# Complex Coercion

**URL:** <https://chapel.discourse.group/t/complex-coercion/42821>\
**Category:** Users\
**Created:** [May 20, 2025, 4:56am UTC](https://chapel.discourse.group/t/complex-coercion/42821 "2025-05-20T04:56:01Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![damianmoz](https://yyz2.discourse-cdn.com/free1/user_avatar/chapel.discourse.group/damianmoz/32/319_2.png) [@damianmoz](https://chapel.discourse.group/u/damianmoz)\
**Post date:** [May 20, 2025, 4:56am UTC](https://chapel.discourse.group/t/complex-coercion/42821/1 "2025-05-20T04:56:01Z")

</div>

One way to define a **complex** (w) **param** or **const** is

```chapel
param b = 10.5 + 6.23i;

```

But that only works if one is using 64-bit floating point. For those of us who try and avoid the double precision sledgehammer and use 32-bit floating point or those who want to soon use **real** (16) floating point arithmetic and at some stage in the future **real** (128), it gets messier.

```chapel
param b0 = (10.5 + 6.23i):complex(64);
param b1 = 10.5:real(16) + (6.23i):imag(16);
param b2 = (10.5 + 6.23i):complex(256);

```

And where one is using identifiers, the use of the imaginary unit `i` is not feasible

Yes, you can use a coercion like

```chapel
const c0 = (x, y):complex(64);

```

But that won't work with a **param**. And when you want to make that generic:

```chapel
const c1 = (x, y):complex(numBits(x.type)*2));

```

This is really messy, ugly, unreadable, and confusing. You get the drift.

Also, at one stage @bradcray mentioned there were some issues with a type.

And that is a bit weird to people trying to port existing C/C++ or Fortran code which has loads of **CMPLX** , **CMPLXF** , and _CMPLX_\* in C, **cmplx** () and **dcmplx** () and other things in Fortran, and a plethora of ways in C++.

Consider

```chapel
inline proc cmplx(param x : real(?w), param y : real(w)) param
{
    return x + y:imag(w);
}
inline proc cmplx(const x : real(?w), const y : real(w)) const
{
    return x + y:imag(w);
}
inline proc cmplx(param x : real(?w), param y : imag(w)) param
{
    return x + y;
}
inline proc cmplx(const x : real(?w), const y : imag(w)) const
{
    return x + y;
}
inline proc cmplx(param x : imag(?w), param y : real(w)) param
{
    compilerWarning("cmplx: mismatch ordering of param arguments");
    return y + x;
}
inline proc cmplx(const x : imag(?w), const y : real(w)) const
{
    compilerWarning("cmplx: mismatch ordering of const arguments");
    return y + x;
}
inline proc cmplx(param x : real(?w)) param
{
    return x + 0:imag(w);
}
inline proc cmplx(const x : real(?w)) const
{
    return x + 0:imag(w);
}
inline proc cmplx(param y : imag(?w)) param
{
    return 0:real(w) + y;
}
inline proc cmplx(const y : imag(?w)) const
{
    return 0:real(w) + y;
}

```

No need to remember types, **param** and **const** data are handled consistency. Easy to read. Low overhead. You can even have an extra overlead to catch the case of where the imaginary and real components have different precisions.

---

<div class="post-metadata">

**Author:** ![mppf](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@mppf](https://chapel.discourse.group/u/mppf)\
**Post date:** [May 20, 2025, 3:36pm UTC](https://chapel.discourse.group/t/complex-coercion/42821/2 "2025-05-20T15:36:21Z")

</div>

> [@damianmoz](#):
>
> Yes, you can use a coercion like
> 
> ```Chapel
> const c0 = (x, y):complex(64);
> 
> ```
> 
> But that won't work with a **param**. And when you want to make that generic:

This ought to work, but doesn't today, for implementation reasons (namely: we don't have a way of representing param tuples within the compiler).

FWIW your suggestion of `cmplx` procedures seems reasonable to me & I think it is a good candidate for addition to the Math module since you find it useful.

---

<div class="post-metadata">

**Author:** ![bradcray](https://yyz2.discourse-cdn.com/free1/user_avatar/chapel.discourse.group/bradcray/32/72_2.png) [@bradcray](https://chapel.discourse.group/u/bradcray)\
**Post date:** [May 20, 2025, 4:35pm UTC](https://chapel.discourse.group/t/complex-coercion/42821/3 "2025-05-20T16:35:25Z")

</div>

I generally like the idea of these convenience functions, but if they were  
to end up in a standard module, I would personally prefer to stylize them  
as 'new complex(1.2, 3.4)' rather than 'cmplx()', mostly to avoid having  
two things 'complex' and 'cmplx') that look very similar but have  
different roles. A more self-descriptive name like 'createComplex(1.2,  
3.4)' would also do the trick for me (and a user could rename it to  
something like 'cmplx' on importing/using the module if desired).

Unfortunately for my preferred approach, the compiler prevents us from  
defining initializers on 'complex' today, but it may not take much worse  
to loosen that restriction.

Damian, I'd be curious if the extra characters in either solution felt  
off-putting to you (and how much).

-Brad

---

<div class="post-metadata">

**Author:** ![damianmoz](https://yyz2.discourse-cdn.com/free1/user_avatar/chapel.discourse.group/damianmoz/32/319_2.png) [@damianmoz](https://chapel.discourse.group/u/damianmoz)\
**Post date:** [May 21, 2025, 2:06am UTC](https://chapel.discourse.group/t/complex-coercion/42821/4 "2025-05-21T02:06:46Z")

</div>

Thanks for the feedback Brad.

I used **cmplx** () because

a) It followed non-controversial industry proven accepted practice

```
- nobody had to learn any new concepts
- it was written the way it was done in Fortran and C and C++
- existing practice showed no risk of confusion with the type name
- the subtle name difference with the type reflected their roles
-- close enough to be remembered but different enough to be very clear

```

b) It was better than Fortran or C or C++ - clock one up for Chapel!!

```
- it was truly generic
-- no cmplx/dcmplx like Fortran for single/double precision
-- no CMPLXF/CMPLX like C for single/double precision
- it was better than C++ which was a bit mixed up

```

c) The ease with which the need was satisfied in Chapel was obvious

```
- it highlighted the flexibility of the language
- it was another case where the choice of Chapel was vindicated

```

d) It was superior to (x, y):complex(w) because

```
- you did not have to remember the precise type
- the type was inherited from the context of its arguments
- I thought tuples at the time had a high overhead

```

e) It required no changes to Chapel

```
- we did not have to impose on the Chapel team (for which I feel guilty)
-- it was after a time where I had asked for fixes to real(32)
-- it was while I contemplated asking for a transmute feature
--- as it transpired - I waited a long while before I pushed that harder

```

f) Nobody onto whom I was pushing this complained. Always a good sign.

I originally only used it as a **const** routine. I was pleasantly surprised much later when my approach worked very nicely when it came to a **param**. This further vindicated my approach.

I still get confused as to when I need to use **new** in Chapel. Any time I do not need to use **new** is a huge bonus. I hated using it in C++ too.

The cmplx() intrinsic of Fortran and CMPLX of C has been saying 'create a complex instance' for 50+ and 25+ years respectively. Why use a new name?

Forcing people to import 'createComplex' with the name 'cmplx' is just complicating the experience. Why rock the boat?

The 'createComplex' approach is different to long established practice. It means learning something new for a user or re-educating programmers for managers. I cannot see a programmer preferring a new 13-character name against using a 5-character name which has become second nature.

The 13 letters of _createComplex_ dominates any mathematical expression in which it appears. This long word with a capital letter detracts from

a) the clarity/tautness of the expression within the Chapel code, and  
b) the ability of the Chapel language to reflect the actual mathematics

This makes it harder to debug for Chapel users and confusing to read by non-Chapel users trying to learn the code and those verifying/QA'ing the code for mathematical correctness

Algol68 has the dyadic operator **I** , i.e. uppercase 'i', which for real `x` or `y`, allows you to to create a complex number anywhere and with ease as

```Chapel
       x I y

```

But it is obtuse, looks nothing like a complex number in Mathematics, and is nothing like accepted practice. So I would object to this Algl68 feature on similar grounds to your idea of _createComplex_. Mind you, once people got used to it, they loved using the operator **I**. Weaning them off it during a move to C++ was tough!!

Note that our usage of complex numbers is only for things like the dynamic behavior of structures and my debugging complex linear algebra routines for clients. We need feedback from people like electrical engineers who eat, sleep and drink this stuff.

Thanks for listening.
