complex arithmetic in D: multiple questions
J-S Caux
js at gmail.com
Fri Mar 9 12:34:40 UTC 2018
Please bear with me, this is a long question!
To explain, I'm a scientist considering switching from C++ to D,
but before I do, I need to ensure that I can:
- achieve execution speeds comparable to C++ (for the same
accuracy; I can accept a slight slowdown, call it 30%, to get a
few more digits (which I typically don't need))
- easily perform all standard mathematical operations on complex
numbers
- (many other things not relevant here: memory use,
parallelization, etc).
In the two files linked below, I compare execution speed/accuracy
between D and C++ when using log on complex variables:
https://www.dropbox.com/s/hfw7nkwg25mk37u/test_cx.d?dl=0
https://www.dropbox.com/s/hfw7nkwg25mk37u/test_cx.d?dl=0
The idea is simple: let a complex variable be uniformly
distributed around the unit circle. Summing the logs should give
zero.
In the D code, I've defined an "own" version of the log, log_cx,
since std.complex (tragically!) does not provide this function
(and many others, see recent threads
https://forum.dlang.org/post/dewzhtnpqkaqkzxwpkrs@forum.dlang.org
and
https://forum.dlang.org/thread/lsnuevdefktulxltoqpj@forum.dlang.org, and issue https://issues.dlang.org/show_bug.cgi?id=18571).
First, speed/accuracy (times for 1M points in all cases):
D:
dmd, no flags:
Complex!real: re, im (should be 0):
-9.24759400999786151942e-15 6.26324079407839123978e-14
time for 1000000 pts: 190 ms, 508 μs, and 9 hnsecs
Complex!double: re, im (should be 0):
-1.96986871259241524967e-12 5.46260919029144254022e-09
time for 1000000 pts: 455 ms, 888 μs, and 7 hnsecs
dmd -release -inline -O:
Complex!real: re, im (should be 0):
-9.24759400999786151942e-15 6.26324079407839123978e-14
time for 1000000 pts: 175 ms, 352 μs, and 3 hnsecs
Complex!double: re, im (should be 0):
-4.23880765557105362133e-14 5.46260919029144254022e-09
time for 1000000 pts: 402 ms, 965 μs, and 7 hnsecs
ldc2, no flags:
Complex!real: re, im (should be 0):
-9.24759400999786151942e-15 6.26324079407839123978e-14
time for 1000000 pts: 184 ms, 353 μs, and 9 hnsecs
Complex!double: re, im (should be 0):
-1.96986871259241524967e-12 5.46260919029144254022e-09
time for 1000000 pts: 436 ms, 526 μs, and 8 hnsecs
ldc2 -release -O:
Complex!real: re, im (should be 0):
-9.24759400999786151942e-15 6.26324079407839123978e-14
time for 1000000 pts: 108 ms and 966 μs
Complex!double: re, im (should be 0):
-1.96986871259241524967e-12 5.46260919029144254022e-09
time for 1000000 pts: 330 ms, 421 μs, and 8 hnsecs
As expected accuracy with Complex!real is about 4 digits better,
and the best combo is ldc2 with flags.
Now C++:
GCC 7.1.0, -O3:
complex<double>: re, im (should be 0):
(8.788326118779445e-13,1.433519814600731e-11)
time for 1000000 pts: 0.042751 seconds.
Apple LLVM version 9.0.0 (clang-900.0.39.2), -O3:
complex<double>: re, im (should be 0):
(-3.0160318686967e-12,1.433519814600731e-11)
time for 1000000 pts: 0.038715 seconds.
So simple C++ is thrice as fast as the best-achieved D I managed.
Now for my questions:
- I would expect the D `Complex!double` case to work faster than
the `real` one. Why is it the other way around? [I can accept
(and use) D with Complex!real running 1/3 the speed of C++ (but
with increased accuracy), but I'd also love to be able to run D
with `Complex!double` at C++ speeds, since the tradeoff might be
worth it for some calculations]
- what is the best way to correct the unfortunate (to be polite)
omission of many standard mathematical functions from
std.complex? [if I may be frank, this is a real pain for us
scientists] There exists
https://gist.github.com/Biotronic/17af645c2c9b7913de1f04980cd22b37 but can this be integrated (after improvements) in the language, or should I (re)build my own?
- for my education, why was the decision made to go from the
built-in types `creal` etc to the `Complex` type?
[related questions:
More information about the Digitalmars-d-learn
mailing list