root/trunk/docsrc/cppcomplex.dd

Revision 2040, 5.0 kB (checked in by walter, 1 year ago)

typography

  • Property svn:eol-style set to native
Line 
1 Ddoc
2
3 $(COMMUNITY D Complex Types and C++ std::complex,
4
5     How do D's complex numbers compare with C++'s std::complex class?
6
7 <h3>Syntactical Aesthetics</h3>
8
9     In C++, the complex types are:
10
11 $(CCODE
12 complex&lt;float&gt;
13 complex&lt;double&gt;
14 complex&lt;long double&gt;
15 )
16
17     C++ has no distinct imaginary type. D has 3 complex types and 3
18     imaginary types:
19
20 ------------
21 cfloat
22 cdouble
23 creal
24 ifloat
25 idouble
26 ireal
27 ------------
28
29     A C++ complex number can interact with an arithmetic literal, but
30     since there is no imaginary type, imaginary numbers can only be
31     created with the constructor syntax:
32
33 $(CCODE
34 complex&lt;long double&gt; a = 5;       // a = 5 + 0i
35 complex&lt;long double&gt; b(0,7);      // b = 0 + 7i
36 c = a + b + complex&lt;long double&gt;(0,7);    // c = 5 + 14i
37 )
38
39     In D, an imaginary numeric literal has the $(SINGLEQUOTE i) suffix.
40     The corresponding code would be the more natural:
41
42 ------------
43 creal a = 5;        // a = 5 + 0i
44 ireal b = 7i;       // b = 7i
45 c = a + b + 7i;     // c = 5 + 14i
46 ------------
47
48     For more involved expressions involving constants:
49
50 ------------
51 c = (6 + 2i - 1 + 3i) / 3i;
52 ------------
53
54     In C++, this would be:
55
56 $(CCODE
57 c = (complex&lt;double&gt;(6,2) + complex&lt;double&gt;(-1,3)) / complex&lt;double&gt;(0,3);
58 )
59
60     or if an imaginary class were added to C++ it might be:
61
62 $(CCODE
63 c = (6 + imaginary&lt;double&gt;(2) - 1 + imaginary&lt;double&gt;(3)) / imaginary&lt;double&gt;(3);
64 )
65
66     In other words, an imaginary number $(I nn) can be represented with
67     just $(I nn)i rather than writing a constructor call
68     complex&lt;long double&gt;(0,$(I nn)).
69
70 <h3>Efficiency</h3>
71
72     The lack of an imaginary type in C++ means that operations on
73     imaginary numbers wind up with a lot of extra computations done
74     on the 0 real part. For example, adding two imaginary numbers
75     in D is one add:
76
77 ------------
78 ireal a, b, c;
79 c = a + b;
80 ------------
81
82     In C++, it is two adds, as the real parts get added too:
83
84 $(CCODE
85 c.re = a.re + b.re;
86 c.im = a.im + b.im;
87 )
88
89     Multiply is worse, as 4 multiplies and two adds are done instead of
90     one multiply:
91
92 $(CCODE
93 c.re = a.re * b.re - a.im * b.im;
94 c.im = a.im * b.re + a.re * b.im;
95 )
96
97     Divide is the worst - D has one divide, whereas C++ implements
98     complex division with typically one comparison, 3 divides,
99     3 multiplies and 3 additions:
100
101 $(CCODE
102 if (fabs(b.re) < fabs(b.im))
103 {
104     r = b.re / b.im;
105     den = b.im + r * b.re;
106     c.re = (a.re * r + a.im) / den;
107     c.im = (a.im * r - a.re) / den;
108 }
109 else
110 {
111     r = b.im / b.re;
112     den = b.re + r * b.im;
113     c.re = (a.re + r * a.im) / den;
114     c.im = (a.im - r * a.re) / den;
115 }
116 )
117
118     To avoid these efficiency concerns in C++, one could simulate
119     an imaginary number using a double. For example, given the D:
120
121 ------------
122 cdouble c;
123 idouble im;
124 c *= im;
125 ------------
126
127     it could be written in C++ as:
128
129 $(CCODE
130 complex&lt;double&gt; c;
131 double im;
132 c = complex&lt;double&gt;(-c.imag() * im, c.real() * im);
133 )
134
135     but then the advantages of complex being a library type integrated
136     in with the arithmetic operators have been lost.
137
138 <h3>Semantics</h3>
139
140     Worst of all, the lack of an imaginary type can cause the wrong
141     answer to be inadvertently produced.
142     To quote <a href="http://www.cs.berkeley.edu/~wkahan/">
143     Prof. Kahan</a>:
144
145     $(BLOCKQUOTE
146     "A streamline goes astray when the complex functions SQRT and LOG
147     are implemented, as is necessary in Fortran and in libraries
148     currently distributed with C/C++ compilers, in a way that
149     disregards the sign of 0.0 in IEEE 754 arithmetic and consequently
150     violates identities like SQRT( CONJ( Z ) ) = CONJ( SQRT( Z ) ) and
151     LOG( CONJ( Z ) ) = CONJ( LOG( Z ) ) whenever the COMPLEX variable Z
152     takes negative real values. Such anomalies are unavoidable if
153     Complex Arithmetic operates on pairs (x, y) instead of notional
154     sums x + i*y of real and imaginary
155     variables. The language of pairs is $(I incorrect) for Complex
156     Arithmetic; it needs the Imaginary type."
157     )
158
159     The semantic problems are:
160
161     $(UL
162     $(LI Consider the formula (1 - infinity*$(I i)) * $(I i) which
163     should produce (infinity + $(I i)). However, if instead the second
164     factor is (0 + $(I i)) rather than just $(I i), the result is
165     (infinity + NaN*$(I i)), a spurious NaN was generated.
166     )
167
168     $(LI A distinct imaginary type preserves the sign of 0, necessary
169     for calculations involving branch cuts.
170     )
171     )
172
173     Appendix G of the C99 standard has recommendations for dealing
174     with this problem. However, those recommendations are not part
175     of the C++98 standard, and so cannot be portably relied upon.
176
177 <h3>References</h3>
178
179     <a href="http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf">
180     How Java's Floating-Point Hurts Everyone Everywhere</a>
181     Prof. W. Kahan and Joseph D. Darcy
182     <p>
183
184     <a href="http://www.cs.berkeley.edu/~wkahan/Curmudge.pdf">
185     The Numerical Analyst as Computer Science Curmudgeon</a>
186     by Prof. W. Kahan
187     <p>
188
189     $(DOUBLEQUOTE Branch Cuts for Complex Elementary Functions,
190     or Much Ado About Nothing's Sign Bit)
191     by W. Kahan, ch.<br>
192     7 in The State of the Art in Numerical Analysis (1987)
193     ed. by M. Powell and A. Iserles for Oxford U.P.
194
195 )
196
197 Macros:
198     TITLE=D Complex Types vs C++ std::complex
199     WIKI=CPPcomplex
Note: See TracBrowser for help on using the browser.