Fixing the imaginary/complex mess

bearophile bearophileHUGS at lycos.com
Sun Jun 12 15:37:37 PDT 2011


Andrei:

> Don, instead of this fix, could be at best phase everything built-in 
> about complex out?

Two usages of complex numbers in the RosettaCode site.

Acommon place where you find complex numbers is to plot  Mandelbrot/Julia sets:
http://rosettacode.org/wiki/Mandelbrot_set#D

import std.stdio, std.math;

void main() {
    enum maxIter = 1000;
    foreach (y; -39 .. 39) {
        foreach (x; -39 .. 39) {
            auto c = y/40.0 - 0.5 + x/40.0i,
                 z = 0.0 + 0.0i,
                 i = 0;
            for (; i < maxIter && abs(z) < 4; i++)
                z = z ^^ 2 + c;
            write(i == maxIter ? '#' : ' ');
        }
        writeln();
    }
}



Version using std.complex:

import std.stdio, std.complex;

void main() {
    enum maxIter = 1000;
    foreach (y; -39 .. 39) {
        foreach (x; -39 .. 39) {
            auto c = Complex!double(y/40.0 - 0.5, x/40.0),
                 z = Complex!double(0, 0),
                 i = 0;
            for (; i < maxIter && z.abs() < 4; i++)
                z = z ^^ 2 + c;
            write(i == maxIter ? '#' : ' ');
        }
        writeln();
    }
}


I think it's worth adding to std.complex module few examples of usage, plus a complex() function so you are allowed to write (the imaginary part defaults to zero if the real part is set to zero):
auto z = complex(5);

Instead of:
auto z = Complex!double(5, 0);


complex(5) probably has to create a Complex!double and not a Complex!int (that is not even supported, std.complex.Complex support floating point values only).

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

Another common usage of D complex numbers is to represent generic 2D points.
http://rosettacode.org/wiki/Constrained_random_points_on_a_circle#D

Original code (to plot some points in a circle):

import std.stdio, std.random, std.math;
 
void main() {
    char[31][31] table = ' ';
 
    foreach (i; 0 .. 100) {
        int x, y;
        do {
            x = uniform(-15, 16);
            y = uniform(-15, 16);
        } while(abs(12.5 - abs(x + y * 1i)) > 2.5);
        table[x + 15][y + 15] = '*';
    }
 
    foreach (row; table)
        writeln(row);
}


Version using std.complex:

import std.stdio, std.random, std.complex, std.math;

void main() {
    char[31][31] table = ' ';

    foreach (i; 0 .. 100) {
        int x, y;
        do {
            x = uniform(-15, 16);
            y = uniform(-15, 16);
        } while(abs(12.5 - Complex!double(x, y).abs) > 2.5);
        table[x + 15][y + 15] = '*';
    }

    foreach (row; table)
        writeln(row);
}

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

Regarding the printing of Complex values, this program:

import std.stdio, std.complex;
void main() {
    writeln(Complex!double(0, -1));
}


Prints:
0-1i


While Python prints the same complex number as:

>>> 0-1j
-1j

Bye,
bearophile


More information about the Digitalmars-d mailing list