For obj-c stage-final re-use the checksum from the previous stage
[official-gcc.git] / libphobos / src / std / complex.d
blob8e488db4162b39677abd5e8e53d20746c1f1ad4a
1 // Written in the D programming language.
3 /** This module contains the $(LREF Complex) type, which is used to represent
4 _complex numbers, along with related mathematical operations and functions.
6 $(LREF Complex) will eventually
7 $(DDLINK deprecate, Deprecated Features, replace)
8 the built-in types $(D cfloat), $(D cdouble), $(D creal), $(D ifloat),
9 $(D idouble), and $(D ireal).
11 Authors: Lars Tandle Kyllingstad, Don Clugston
12 Copyright: Copyright (c) 2010, Lars T. Kyllingstad.
13 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0)
14 Source: $(PHOBOSSRC std/_complex.d)
16 module std.complex;
18 import std.traits;
20 /** Helper function that returns a _complex number with the specified
21 real and imaginary parts.
23 Params:
24 R = (template parameter) type of real part of complex number
25 I = (template parameter) type of imaginary part of complex number
27 re = real part of complex number to be constructed
28 im = (optional) imaginary part of complex number, 0 if omitted.
30 Returns:
31 $(D Complex) instance with real and imaginary parts set
32 to the values provided as input. If neither $(D re) nor
33 $(D im) are floating-point numbers, the return type will
34 be $(D Complex!double). Otherwise, the return type is
35 deduced using $(D std.traits.CommonType!(R, I)).
37 auto complex(R)(R re) @safe pure nothrow @nogc
38 if (is(R : double))
40 static if (isFloatingPoint!R)
41 return Complex!R(re, 0);
42 else
43 return Complex!double(re, 0);
46 /// ditto
47 auto complex(R, I)(R re, I im) @safe pure nothrow @nogc
48 if (is(R : double) && is(I : double))
50 static if (isFloatingPoint!R || isFloatingPoint!I)
51 return Complex!(CommonType!(R, I))(re, im);
52 else
53 return Complex!double(re, im);
56 ///
57 @safe pure nothrow unittest
59 auto a = complex(1.0);
60 static assert(is(typeof(a) == Complex!double));
61 assert(a.re == 1.0);
62 assert(a.im == 0.0);
64 auto b = complex(2.0L);
65 static assert(is(typeof(b) == Complex!real));
66 assert(b.re == 2.0L);
67 assert(b.im == 0.0L);
69 auto c = complex(1.0, 2.0);
70 static assert(is(typeof(c) == Complex!double));
71 assert(c.re == 1.0);
72 assert(c.im == 2.0);
74 auto d = complex(3.0, 4.0L);
75 static assert(is(typeof(d) == Complex!real));
76 assert(d.re == 3.0);
77 assert(d.im == 4.0L);
79 auto e = complex(1);
80 static assert(is(typeof(e) == Complex!double));
81 assert(e.re == 1);
82 assert(e.im == 0);
84 auto f = complex(1L, 2);
85 static assert(is(typeof(f) == Complex!double));
86 assert(f.re == 1L);
87 assert(f.im == 2);
89 auto g = complex(3, 4.0L);
90 static assert(is(typeof(g) == Complex!real));
91 assert(g.re == 3);
92 assert(g.im == 4.0L);
96 /** A complex number parametrised by a type $(D T), which must be either
97 $(D float), $(D double) or $(D real).
99 struct Complex(T)
100 if (isFloatingPoint!T)
102 import std.format : FormatSpec;
103 import std.range.primitives : isOutputRange;
105 /** The real part of the number. */
106 T re;
108 /** The imaginary part of the number. */
109 T im;
111 /** Converts the complex number to a string representation.
113 The second form of this function is usually not called directly;
114 instead, it is used via $(REF format, std,string), as shown in the examples
115 below. Supported format characters are 'e', 'f', 'g', 'a', and 's'.
117 See the $(MREF std, format) and $(REF format, std,string)
118 documentation for more information.
120 string toString() const @safe /* TODO: pure nothrow */
122 import std.exception : assumeUnique;
123 char[] buf;
124 buf.reserve(100);
125 auto fmt = FormatSpec!char("%s");
126 toString((const(char)[] s) { buf ~= s; }, fmt);
127 static trustedAssumeUnique(T)(T t) @trusted { return assumeUnique(t); }
128 return trustedAssumeUnique(buf);
131 static if (is(T == double))
133 @safe unittest
135 auto c = complex(1.2, 3.4);
137 // Vanilla toString formatting:
138 assert(c.toString() == "1.2+3.4i");
140 // Formatting with std.string.format specs: the precision and width
141 // specifiers apply to both the real and imaginary parts of the
142 // complex number.
143 import std.format : format;
144 assert(format("%.2f", c) == "1.20+3.40i");
145 assert(format("%4.1f", c) == " 1.2+ 3.4i");
148 /// ditto
149 void toString(Writer, Char)(scope Writer w,
150 FormatSpec!Char formatSpec) const
151 if (isOutputRange!(Writer, const(Char)[]))
153 import std.format : formatValue;
154 import std.math : signbit;
155 import std.range.primitives : put;
156 formatValue(w, re, formatSpec);
157 if (signbit(im) == 0)
158 put(w, "+");
159 formatValue(w, im, formatSpec);
160 put(w, "i");
163 @safe pure nothrow @nogc:
165 /** Construct a complex number with the specified real and
166 imaginary parts. In the case where a single argument is passed
167 that is not complex, the imaginary part of the result will be
168 zero.
170 this(R : T)(Complex!R z)
172 re = z.re;
173 im = z.im;
176 /// ditto
177 this(Rx : T, Ry : T)(Rx x, Ry y)
179 re = x;
180 im = y;
183 /// ditto
184 this(R : T)(R r)
186 re = r;
187 im = 0;
190 // ASSIGNMENT OPERATORS
192 // this = complex
193 ref Complex opAssign(R : T)(Complex!R z)
195 re = z.re;
196 im = z.im;
197 return this;
200 // this = numeric
201 ref Complex opAssign(R : T)(R r)
203 re = r;
204 im = 0;
205 return this;
208 // COMPARISON OPERATORS
210 // this == complex
211 bool opEquals(R : T)(Complex!R z) const
213 return re == z.re && im == z.im;
216 // this == numeric
217 bool opEquals(R : T)(R r) const
219 return re == r && im == 0;
222 // UNARY OPERATORS
224 // +complex
225 Complex opUnary(string op)() const
226 if (op == "+")
228 return this;
231 // -complex
232 Complex opUnary(string op)() const
233 if (op == "-")
235 return Complex(-re, -im);
238 // BINARY OPERATORS
240 // complex op complex
241 Complex!(CommonType!(T,R)) opBinary(string op, R)(Complex!R z) const
243 alias C = typeof(return);
244 auto w = C(this.re, this.im);
245 return w.opOpAssign!(op)(z);
248 // complex op numeric
249 Complex!(CommonType!(T,R)) opBinary(string op, R)(R r) const
250 if (isNumeric!R)
252 alias C = typeof(return);
253 auto w = C(this.re, this.im);
254 return w.opOpAssign!(op)(r);
257 // numeric + complex, numeric * complex
258 Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R r) const
259 if ((op == "+" || op == "*") && (isNumeric!R))
261 return opBinary!(op)(r);
264 // numeric - complex
265 Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R r) const
266 if (op == "-" && isNumeric!R)
268 return Complex(r - re, -im);
271 // numeric / complex
272 Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R r) const
273 if (op == "/" && isNumeric!R)
275 import std.math : fabs;
276 typeof(return) w = void;
277 if (fabs(re) < fabs(im))
279 immutable ratio = re/im;
280 immutable rdivd = r/(re*ratio + im);
282 w.re = rdivd*ratio;
283 w.im = -rdivd;
285 else
287 immutable ratio = im/re;
288 immutable rdivd = r/(re + im*ratio);
290 w.re = rdivd;
291 w.im = -rdivd*ratio;
294 return w;
297 // numeric ^^ complex
298 Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R lhs) const
299 if (op == "^^" && isNumeric!R)
301 import std.math : cos, exp, log, sin, PI;
302 Unqual!(CommonType!(T, R)) ab = void, ar = void;
304 if (lhs >= 0)
306 // r = lhs
307 // theta = 0
308 ab = lhs ^^ this.re;
309 ar = log(lhs) * this.im;
311 else
313 // r = -lhs
314 // theta = PI
315 ab = (-lhs) ^^ this.re * exp(-PI * this.im);
316 ar = PI * this.re + log(-lhs) * this.im;
319 return typeof(return)(ab * cos(ar), ab * sin(ar));
322 // OP-ASSIGN OPERATORS
324 // complex += complex, complex -= complex
325 ref Complex opOpAssign(string op, C)(C z)
326 if ((op == "+" || op == "-") && is(C R == Complex!R))
328 mixin ("re "~op~"= z.re;");
329 mixin ("im "~op~"= z.im;");
330 return this;
333 // complex *= complex
334 ref Complex opOpAssign(string op, C)(C z)
335 if (op == "*" && is(C R == Complex!R))
337 auto temp = re*z.re - im*z.im;
338 im = im*z.re + re*z.im;
339 re = temp;
340 return this;
343 // complex /= complex
344 ref Complex opOpAssign(string op, C)(C z)
345 if (op == "/" && is(C R == Complex!R))
347 import std.math : fabs;
348 if (fabs(z.re) < fabs(z.im))
350 immutable ratio = z.re/z.im;
351 immutable denom = z.re*ratio + z.im;
353 immutable temp = (re*ratio + im)/denom;
354 im = (im*ratio - re)/denom;
355 re = temp;
357 else
359 immutable ratio = z.im/z.re;
360 immutable denom = z.re + z.im*ratio;
362 immutable temp = (re + im*ratio)/denom;
363 im = (im - re*ratio)/denom;
364 re = temp;
366 return this;
369 // complex ^^= complex
370 ref Complex opOpAssign(string op, C)(C z)
371 if (op == "^^" && is(C R == Complex!R))
373 import std.math : exp, log, cos, sin;
374 immutable r = abs(this);
375 immutable t = arg(this);
376 immutable ab = r^^z.re * exp(-t*z.im);
377 immutable ar = t*z.re + log(r)*z.im;
379 re = ab*cos(ar);
380 im = ab*sin(ar);
381 return this;
384 // complex += numeric, complex -= numeric
385 ref Complex opOpAssign(string op, U : T)(U a)
386 if (op == "+" || op == "-")
388 mixin ("re "~op~"= a;");
389 return this;
392 // complex *= numeric, complex /= numeric
393 ref Complex opOpAssign(string op, U : T)(U a)
394 if (op == "*" || op == "/")
396 mixin ("re "~op~"= a;");
397 mixin ("im "~op~"= a;");
398 return this;
401 // complex ^^= real
402 ref Complex opOpAssign(string op, R)(R r)
403 if (op == "^^" && isFloatingPoint!R)
405 import std.math : cos, sin;
406 immutable ab = abs(this)^^r;
407 immutable ar = arg(this)*r;
408 re = ab*cos(ar);
409 im = ab*sin(ar);
410 return this;
413 // complex ^^= int
414 ref Complex opOpAssign(string op, U)(U i)
415 if (op == "^^" && isIntegral!U)
417 switch (i)
419 case 0:
420 re = 1.0;
421 im = 0.0;
422 break;
423 case 1:
424 // identity; do nothing
425 break;
426 case 2:
427 this *= this;
428 break;
429 case 3:
430 auto z = this;
431 this *= z;
432 this *= z;
433 break;
434 default:
435 this ^^= cast(real) i;
437 return this;
441 @safe pure nothrow unittest
443 import std.complex;
444 import std.math;
446 enum EPS = double.epsilon;
447 auto c1 = complex(1.0, 1.0);
449 // Check unary operations.
450 auto c2 = Complex!double(0.5, 2.0);
452 assert(c2 == +c2);
454 assert((-c2).re == -(c2.re));
455 assert((-c2).im == -(c2.im));
456 assert(c2 == -(-c2));
458 // Check complex-complex operations.
459 auto cpc = c1 + c2;
460 assert(cpc.re == c1.re + c2.re);
461 assert(cpc.im == c1.im + c2.im);
463 auto cmc = c1 - c2;
464 assert(cmc.re == c1.re - c2.re);
465 assert(cmc.im == c1.im - c2.im);
467 auto ctc = c1 * c2;
468 assert(approxEqual(abs(ctc), abs(c1)*abs(c2), EPS));
469 assert(approxEqual(arg(ctc), arg(c1)+arg(c2), EPS));
471 auto cdc = c1 / c2;
472 assert(approxEqual(abs(cdc), abs(c1)/abs(c2), EPS));
473 assert(approxEqual(arg(cdc), arg(c1)-arg(c2), EPS));
475 auto cec = c1^^c2;
476 assert(approxEqual(cec.re, 0.11524131979943839881, EPS));
477 assert(approxEqual(cec.im, 0.21870790452746026696, EPS));
479 // Check complex-real operations.
480 double a = 123.456;
482 auto cpr = c1 + a;
483 assert(cpr.re == c1.re + a);
484 assert(cpr.im == c1.im);
486 auto cmr = c1 - a;
487 assert(cmr.re == c1.re - a);
488 assert(cmr.im == c1.im);
490 auto ctr = c1 * a;
491 assert(ctr.re == c1.re*a);
492 assert(ctr.im == c1.im*a);
494 auto cdr = c1 / a;
495 assert(approxEqual(abs(cdr), abs(c1)/a, EPS));
496 assert(approxEqual(arg(cdr), arg(c1), EPS));
498 auto cer = c1^^3.0;
499 assert(approxEqual(abs(cer), abs(c1)^^3, EPS));
500 assert(approxEqual(arg(cer), arg(c1)*3, EPS));
502 auto rpc = a + c1;
503 assert(rpc == cpr);
505 auto rmc = a - c1;
506 assert(rmc.re == a-c1.re);
507 assert(rmc.im == -c1.im);
509 auto rtc = a * c1;
510 assert(rtc == ctr);
512 auto rdc = a / c1;
513 assert(approxEqual(abs(rdc), a/abs(c1), EPS));
514 assert(approxEqual(arg(rdc), -arg(c1), EPS));
516 rdc = a / c2;
517 assert(approxEqual(abs(rdc), a/abs(c2), EPS));
518 assert(approxEqual(arg(rdc), -arg(c2), EPS));
520 auto rec1a = 1.0 ^^ c1;
521 assert(rec1a.re == 1.0);
522 assert(rec1a.im == 0.0);
524 auto rec2a = 1.0 ^^ c2;
525 assert(rec2a.re == 1.0);
526 assert(rec2a.im == 0.0);
528 auto rec1b = (-1.0) ^^ c1;
529 assert(approxEqual(abs(rec1b), std.math.exp(-PI * c1.im), EPS));
530 auto arg1b = arg(rec1b);
531 /* The argument _should_ be PI, but floating-point rounding error
532 * means that in fact the imaginary part is very slightly negative.
534 assert(approxEqual(arg1b, PI, EPS) || approxEqual(arg1b, -PI, EPS));
536 auto rec2b = (-1.0) ^^ c2;
537 assert(approxEqual(abs(rec2b), std.math.exp(-2 * PI), EPS));
538 assert(approxEqual(arg(rec2b), PI_2, EPS));
540 auto rec3a = 0.79 ^^ complex(6.8, 5.7);
541 auto rec3b = complex(0.79, 0.0) ^^ complex(6.8, 5.7);
542 assert(approxEqual(rec3a.re, rec3b.re, EPS));
543 assert(approxEqual(rec3a.im, rec3b.im, EPS));
545 auto rec4a = (-0.79) ^^ complex(6.8, 5.7);
546 auto rec4b = complex(-0.79, 0.0) ^^ complex(6.8, 5.7);
547 assert(approxEqual(rec4a.re, rec4b.re, EPS));
548 assert(approxEqual(rec4a.im, rec4b.im, EPS));
550 auto rer = a ^^ complex(2.0, 0.0);
551 auto rcheck = a ^^ 2.0;
552 static assert(is(typeof(rcheck) == double));
553 assert(feqrel(rer.re, rcheck) == double.mant_dig);
554 assert(isIdentical(rer.re, rcheck));
555 assert(rer.im == 0.0);
557 auto rer2 = (-a) ^^ complex(2.0, 0.0);
558 rcheck = (-a) ^^ 2.0;
559 assert(feqrel(rer2.re, rcheck) == double.mant_dig);
560 assert(isIdentical(rer2.re, rcheck));
561 assert(approxEqual(rer2.im, 0.0, EPS));
563 auto rer3 = (-a) ^^ complex(-2.0, 0.0);
564 rcheck = (-a) ^^ (-2.0);
565 assert(feqrel(rer3.re, rcheck) == double.mant_dig);
566 assert(isIdentical(rer3.re, rcheck));
567 assert(approxEqual(rer3.im, 0.0, EPS));
569 auto rer4 = a ^^ complex(-2.0, 0.0);
570 rcheck = a ^^ (-2.0);
571 assert(feqrel(rer4.re, rcheck) == double.mant_dig);
572 assert(isIdentical(rer4.re, rcheck));
573 assert(rer4.im == 0.0);
575 // Check Complex-int operations.
576 foreach (i; 0 .. 6)
578 auto cei = c1^^i;
579 assert(approxEqual(abs(cei), abs(c1)^^i, EPS));
580 // Use cos() here to deal with arguments that go outside
581 // the (-pi,pi] interval (only an issue for i>3).
582 assert(approxEqual(std.math.cos(arg(cei)), std.math.cos(arg(c1)*i), EPS));
585 // Check operations between different complex types.
586 auto cf = Complex!float(1.0, 1.0);
587 auto cr = Complex!real(1.0, 1.0);
588 auto c1pcf = c1 + cf;
589 auto c1pcr = c1 + cr;
590 static assert(is(typeof(c1pcf) == Complex!double));
591 static assert(is(typeof(c1pcr) == Complex!real));
592 assert(c1pcf.re == c1pcr.re);
593 assert(c1pcf.im == c1pcr.im);
595 auto c1c = c1;
596 auto c2c = c2;
598 c1c /= c1;
599 assert(approxEqual(c1c.re, 1.0, EPS));
600 assert(approxEqual(c1c.im, 0.0, EPS));
602 c1c = c1;
603 c1c /= c2;
604 assert(approxEqual(c1c.re, 0.588235, EPS));
605 assert(approxEqual(c1c.im, -0.352941, EPS));
607 c2c /= c1;
608 assert(approxEqual(c2c.re, 1.25, EPS));
609 assert(approxEqual(c2c.im, 0.75, EPS));
611 c2c = c2;
612 c2c /= c2;
613 assert(approxEqual(c2c.re, 1.0, EPS));
614 assert(approxEqual(c2c.im, 0.0, EPS));
617 @safe pure nothrow unittest
619 // Initialization
620 Complex!double a = 1;
621 assert(a.re == 1 && a.im == 0);
622 Complex!double b = 1.0;
623 assert(b.re == 1.0 && b.im == 0);
624 Complex!double c = Complex!real(1.0, 2);
625 assert(c.re == 1.0 && c.im == 2);
628 @safe pure nothrow unittest
630 // Assignments and comparisons
631 Complex!double z;
633 z = 1;
634 assert(z == 1);
635 assert(z.re == 1.0 && z.im == 0.0);
637 z = 2.0;
638 assert(z == 2.0);
639 assert(z.re == 2.0 && z.im == 0.0);
641 z = 1.0L;
642 assert(z == 1.0L);
643 assert(z.re == 1.0 && z.im == 0.0);
645 auto w = Complex!real(1.0, 1.0);
646 z = w;
647 assert(z == w);
648 assert(z.re == 1.0 && z.im == 1.0);
650 auto c = Complex!float(2.0, 2.0);
651 z = c;
652 assert(z == c);
653 assert(z.re == 2.0 && z.im == 2.0);
657 /* Makes Complex!(Complex!T) fold to Complex!T.
659 The rationale for this is that just like the real line is a
660 subspace of the complex plane, the complex plane is a subspace
661 of itself. Example of usage:
663 Complex!T addI(T)(T x)
665 return x + Complex!T(0.0, 1.0);
668 The above will work if T is both real and complex.
670 template Complex(T)
671 if (is(T R == Complex!R))
673 alias Complex = T;
676 @safe pure nothrow unittest
678 static assert(is(Complex!(Complex!real) == Complex!real));
680 Complex!T addI(T)(T x)
682 return x + Complex!T(0.0, 1.0);
685 auto z1 = addI(1.0);
686 assert(z1.re == 1.0 && z1.im == 1.0);
688 enum one = Complex!double(1.0, 0.0);
689 auto z2 = addI(one);
690 assert(z1 == z2);
695 Params: z = A complex number.
696 Returns: The absolute value (or modulus) of `z`.
698 T abs(T)(Complex!T z) @safe pure nothrow @nogc
700 import std.math : hypot;
701 return hypot(z.re, z.im);
705 @safe pure nothrow unittest
707 static import std.math;
708 assert(abs(complex(1.0)) == 1.0);
709 assert(abs(complex(0.0, 1.0)) == 1.0);
710 assert(abs(complex(1.0L, -2.0L)) == std.math.sqrt(5.0L));
715 Params:
716 z = A complex number.
717 x = A real number.
718 Returns: The squared modulus of `z`.
719 For genericity, if called on a real number, returns its square.
721 T sqAbs(T)(Complex!T z) @safe pure nothrow @nogc
723 return z.re*z.re + z.im*z.im;
727 @safe pure nothrow unittest
729 import std.math;
730 assert(sqAbs(complex(0.0)) == 0.0);
731 assert(sqAbs(complex(1.0)) == 1.0);
732 assert(sqAbs(complex(0.0, 1.0)) == 1.0);
733 assert(approxEqual(sqAbs(complex(1.0L, -2.0L)), 5.0L));
734 assert(approxEqual(sqAbs(complex(-3.0L, 1.0L)), 10.0L));
735 assert(approxEqual(sqAbs(complex(1.0f,-1.0f)), 2.0f));
738 /// ditto
739 T sqAbs(T)(T x) @safe pure nothrow @nogc
740 if (isFloatingPoint!T)
742 return x*x;
745 @safe pure nothrow unittest
747 import std.math;
748 assert(sqAbs(0.0) == 0.0);
749 assert(sqAbs(-1.0) == 1.0);
750 assert(approxEqual(sqAbs(-3.0L), 9.0L));
751 assert(approxEqual(sqAbs(-5.0f), 25.0f));
756 Params: z = A complex number.
757 Returns: The argument (or phase) of `z`.
759 T arg(T)(Complex!T z) @safe pure nothrow @nogc
761 import std.math : atan2;
762 return atan2(z.im, z.re);
766 @safe pure nothrow unittest
768 import std.math;
769 assert(arg(complex(1.0)) == 0.0);
770 assert(arg(complex(0.0L, 1.0L)) == PI_2);
771 assert(arg(complex(1.0L, 1.0L)) == PI_4);
776 Params: z = A complex number.
777 Returns: The complex conjugate of `z`.
779 Complex!T conj(T)(Complex!T z) @safe pure nothrow @nogc
781 return Complex!T(z.re, -z.im);
785 @safe pure nothrow unittest
787 assert(conj(complex(1.0)) == complex(1.0));
788 assert(conj(complex(1.0, 2.0)) == complex(1.0, -2.0));
793 Constructs a complex number given its absolute value and argument.
794 Params:
795 modulus = The modulus
796 argument = The argument
797 Returns: The complex number with the given modulus and argument.
799 Complex!(CommonType!(T, U)) fromPolar(T, U)(T modulus, U argument)
800 @safe pure nothrow @nogc
802 import std.math : sin, cos;
803 return Complex!(CommonType!(T,U))
804 (modulus*cos(argument), modulus*sin(argument));
808 @safe pure nothrow unittest
810 import std.math;
811 auto z = fromPolar(std.math.sqrt(2.0), PI_4);
812 assert(approxEqual(z.re, 1.0L, real.epsilon));
813 assert(approxEqual(z.im, 1.0L, real.epsilon));
818 Trigonometric functions on complex numbers.
820 Params: z = A complex number.
821 Returns: The sine and cosine of `z`, respectively.
823 Complex!T sin(T)(Complex!T z) @safe pure nothrow @nogc
825 import std.math : expi, coshisinh;
826 auto cs = expi(z.re);
827 auto csh = coshisinh(z.im);
828 return typeof(return)(cs.im * csh.re, cs.re * csh.im);
832 @safe pure nothrow unittest
834 static import std.math;
835 import std.math : feqrel;
836 assert(sin(complex(0.0)) == 0.0);
837 assert(sin(complex(2.0, 0)) == std.math.sin(2.0));
838 auto c1 = sin(complex(2.0L, 0));
839 auto c2 = complex(std.math.sin(2.0L), 0);
840 assert(feqrel(c1.re, c2.re) >= real.mant_dig - 1 &&
841 feqrel(c1.im, c2.im) >= real.mant_dig - 1);
845 /// ditto
846 Complex!T cos(T)(Complex!T z) @safe pure nothrow @nogc
848 import std.math : expi, coshisinh;
849 auto cs = expi(z.re);
850 auto csh = coshisinh(z.im);
851 return typeof(return)(cs.re * csh.re, - cs.im * csh.im);
855 @safe pure nothrow unittest
857 static import std.math;
858 import std.math : feqrel;
859 assert(cos(complex(0.0)) == 1.0);
860 assert(cos(complex(1.3)) == std.math.cos(1.3));
861 auto c1 = cos(complex(0, 5.2L));
862 auto c2 = complex(std.math.cosh(5.2L), 0.0L);
863 assert(feqrel(c1.re, c2.re) >= real.mant_dig - 1 &&
864 feqrel(c1.im, c2.im) >= real.mant_dig - 1);
865 auto c3 = cos(complex(1.3L));
866 auto c4 = complex(std.math.cos(1.3L), 0.0L);
867 assert(feqrel(c3.re, c4.re) >= real.mant_dig - 1 &&
868 feqrel(c3.im, c4.im) >= real.mant_dig - 1);
872 Params: y = A real number.
873 Returns: The value of cos(y) + i sin(y).
875 Note:
876 $(D expi) is included here for convenience and for easy migration of code
877 that uses $(REF _expi, std,math). Unlike $(REF _expi, std,math), which uses the
878 x87 $(I fsincos) instruction when possible, this function is no faster
879 than calculating cos(y) and sin(y) separately.
881 Complex!real expi(real y) @trusted pure nothrow @nogc
883 import std.math : cos, sin;
884 return Complex!real(cos(y), sin(y));
888 @safe pure nothrow unittest
890 static import std.math;
892 assert(expi(1.3e5L) == complex(std.math.cos(1.3e5L), std.math.sin(1.3e5L)));
893 assert(expi(0.0L) == 1.0L);
894 auto z1 = expi(1.234);
895 auto z2 = std.math.expi(1.234);
896 assert(z1.re == z2.re && z1.im == z2.im);
901 Params: z = A complex number.
902 Returns: The square root of `z`.
904 Complex!T sqrt(T)(Complex!T z) @safe pure nothrow @nogc
906 static import std.math;
907 typeof(return) c;
908 real x,y,w,r;
910 if (z == 0)
912 c = typeof(return)(0, 0);
914 else
916 real z_re = z.re;
917 real z_im = z.im;
919 x = std.math.fabs(z_re);
920 y = std.math.fabs(z_im);
921 if (x >= y)
923 r = y / x;
924 w = std.math.sqrt(x)
925 * std.math.sqrt(0.5 * (1 + std.math.sqrt(1 + r * r)));
927 else
929 r = x / y;
930 w = std.math.sqrt(y)
931 * std.math.sqrt(0.5 * (r + std.math.sqrt(1 + r * r)));
934 if (z_re >= 0)
936 c = typeof(return)(w, z_im / (w + w));
938 else
940 if (z_im < 0)
941 w = -w;
942 c = typeof(return)(z_im / (w + w), w);
945 return c;
949 @safe pure nothrow unittest
951 static import std.math;
952 assert(sqrt(complex(0.0)) == 0.0);
953 assert(sqrt(complex(1.0L, 0)) == std.math.sqrt(1.0L));
954 assert(sqrt(complex(-1.0L, 0)) == complex(0, 1.0L));
957 @safe pure nothrow unittest
959 import std.math : approxEqual;
961 auto c1 = complex(1.0, 1.0);
962 auto c2 = Complex!double(0.5, 2.0);
964 auto c1s = sqrt(c1);
965 assert(approxEqual(c1s.re, 1.09868411));
966 assert(approxEqual(c1s.im, 0.45508986));
968 auto c2s = sqrt(c2);
969 assert(approxEqual(c2s.re, 1.1317134));
970 assert(approxEqual(c2s.im, 0.8836155));
973 // Issue 10881: support %f formatting of complex numbers
974 @safe unittest
976 import std.format : format;
978 auto x = complex(1.2, 3.4);
979 assert(format("%.2f", x) == "1.20+3.40i");
981 auto y = complex(1.2, -3.4);
982 assert(format("%.2f", y) == "1.20-3.40i");
985 @safe unittest
987 // Test wide string formatting
988 import std.format;
989 wstring wformat(T)(string format, Complex!T c)
991 import std.array : appender;
992 auto w = appender!wstring();
993 auto n = formattedWrite(w, format, c);
994 return w.data;
997 auto x = complex(1.2, 3.4);
998 assert(wformat("%.2f", x) == "1.20+3.40i"w);
1001 @safe unittest
1003 // Test ease of use (vanilla toString() should be supported)
1004 assert(complex(1.2, 3.4).toString() == "1.2+3.4i");