Thread overview
Initializing a complex dynamic array (with real part from one array, and imaginary from other array)?
Jul 21, 2021
james.p.leblanc
Jul 21, 2021
drug
Jul 22, 2021
Ali Çehreli
July 21, 2021

I am trying to initialize a complex dynamic array, from two strictly real dynamic arrays (one to be the real part, the other to be the imaginary part.

Here is simple sample of what I have tried:


import std.stdio;
import std.math;
import std.complex;

void main(){
   auto N=2;

   double[] x,y;
   x.length = N;
   y.length = N;

   x[0] = 1.1;
   x[1] = 2.2;
   y[0] = 3.3;
   y[1] = 4.4;

   Complex!double[] z;
   z.length=N;

   z[] = complex(x[],y[]);
   // z = complex(x,y);  // also tried this, did not work
}

-----------------------------------------------------------------

The compile error message is:

rdmd post.d
post.d(22): Error: template `std.complex.complex` cannot deduce function from argument types `!()(double[], double[])`, candidates are:
/home/leblanc/dmd2/linux/bin64/../../src/phobos/std/complex.d(46):        `complex(R)(const R re)`
/home/leblanc/dmd2/linux/bin64/../../src/phobos/std/complex.d(56):        `complex(R, I)(const R re, const I im)`
  with `R = double[],
       I = double[]`
  whose parameters have the following constraints:
  `~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
`  > is(R : double)
  - is(I : double)
`  `~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
post.d(22):        All possible candidates are marked as `deprecated` or `@disable`
  Tip: not satisfied constraints are marked with `>`
Failed: ["/home/leblanc/dmd2/linux/bin64/dmd", "-v", "-o-", "post.d", "-I."]

I understand, I could write a simple function to do this...but was wondering if there is some "standard" way of doing this already?

Thanks,
James

PS Is cdouble (and friends) really going to be deprecated?? I worry that the loss of the built-in complex types eventually might have a downside for syntax and writing. (But, I might very well be wrong about this!!).

July 21, 2021
I wouldn't state it is the best way but you can try something like that:
```D
import std.complex;
import std.range : zip;
import std.algorithm : equal, map;
import std.array : array;

void main(){
    auto N=2;

    double[] x,y;
    x.length = N;
    y.length = N;

    x[0] = 1.1;
    x[1] = 2.2;
    y[0] = 3.3;
    y[1] = 4.4;

    auto z = zip(x, y)                      // concatenate two ranges
        .map!(a=>Complex!double(a[0],a[1])) // take the current first element of the first range as the real part and the current first element of the second range as the imaginary part
        .array;                             // convert the lazy range to a dynamic array, probably you can avoid but this depends on how you use it later

	assert(z.equal([
        Complex!double(1.1, 3.3),
        Complex!double(2.2, 4.4),
    ]));
}
```D

July 22, 2021
On 7/21/21 2:17 AM, drug wrote:

>      auto z = zip(x, y)                      // concatenate two ranges
>          .map!(a=>Complex!double(a[0],a[1])) // take the current first
> element of the first range as the real part and the current first
> element of the second range as the imaginary part
>          .array;                             // convert the lazy range
> to a dynamic array, probably you can avoid but this depends on how you
> use it later

One of the *nonexistent* ;) features of D is automatic tuple expansion, which works only in foreach loops. I think it makes the code much more readable in this case:

       Complex!double[] z;

       import std.range;
       import std.algorithm;

       foreach (re, im; zip(x, y)) {
         z ~= complex(re, im);
       }

An alternative is lockstep:

       foreach (re, im; lockstep(x, y)) {
         z ~= complex(re, im);
       }

Ali