1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.numbers.complex;
19
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.List;
23 import java.util.function.BiFunction;
24 import java.util.function.DoubleFunction;
25 import java.util.function.Supplier;
26
27 import org.apache.commons.rng.UniformRandomProvider;
28 import org.apache.commons.rng.simple.RandomSource;
29 import org.junit.jupiter.api.Assertions;
30 import org.junit.jupiter.api.Disabled;
31 import org.junit.jupiter.api.Test;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 class ComplexTest {
47
48 private static final double inf = Double.POSITIVE_INFINITY;
49 private static final double neginf = Double.NEGATIVE_INFINITY;
50 private static final double nan = Double.NaN;
51 private static final double pi = Math.PI;
52 private static final Complex oneInf = Complex.ofCartesian(1, inf);
53 private static final Complex oneNegInf = Complex.ofCartesian(1, neginf);
54 private static final Complex infOne = Complex.ofCartesian(inf, 1);
55 private static final Complex infZero = Complex.ofCartesian(inf, 0);
56 private static final Complex infNegZero = Complex.ofCartesian(inf, -0.0);
57 private static final Complex infNegInf = Complex.ofCartesian(inf, neginf);
58 private static final Complex infInf = Complex.ofCartesian(inf, inf);
59 private static final Complex negInfInf = Complex.ofCartesian(neginf, inf);
60 private static final Complex negInfOne = Complex.ofCartesian(neginf, 1);
61 private static final Complex negInfNegInf = Complex.ofCartesian(neginf, neginf);
62 private static final Complex oneNan = Complex.ofCartesian(1, nan);
63 private static final Complex zeroInf = Complex.ofCartesian(0, inf);
64 private static final Complex zeroNan = Complex.ofCartesian(0, nan);
65 private static final Complex nanZero = Complex.ofCartesian(nan, 0);
66 private static final Complex NAN = Complex.ofCartesian(nan, nan);
67 private static final Complex INF = Complex.ofCartesian(inf, inf);
68
69
70
71
72 private enum NumberType {
73 NAN, INFINITE, FINITE
74 }
75
76
77
78
79
80
81
82 private static Complex ofReal(double real) {
83 return Complex.ofCartesian(real, 0);
84 }
85
86
87
88
89
90
91
92 private static Complex ofImaginary(double imaginary) {
93 return Complex.ofCartesian(0, imaginary);
94 }
95
96 @Test
97 @Disabled("Used to output the java environment")
98 @SuppressWarnings("squid:S2699")
99 void testJava() {
100
101 System.out.println(">>testJava()");
102
103
104
105
106 System.out.println("Math.exp=" + Math.exp(Double.NEGATIVE_INFINITY));
107 final String[] props = {"java.version",
108 "java.vendor",
109 "java.vm.specification.version",
110 "java.vm.specification.vendor",
111 "java.vm.specification.name",
112 "java.vm.version",
113 "java.vm.vendor",
114 "java.vm.name",
115 "java.specification.version",
116
117 "java.specification.vendor",
118 "java.specification.name",
119 "java.class.version",
120 };
121 for (final String t : props) {
122 System.out.println(t + "=" + System.getProperty(t));
123 }
124 System.out.println("<<testJava()");
125
126 }
127
128 @Test
129 void testCartesianConstructor() {
130 final Complex z = Complex.ofCartesian(3.0, 4.0);
131 Assertions.assertEquals(3.0, z.getReal());
132 Assertions.assertEquals(4.0, z.getImaginary());
133 }
134
135 @Test
136 void testPolarConstructor() {
137 final double r = 98765;
138 final double theta = 0.12345;
139 final Complex z = Complex.ofPolar(r, theta);
140 final Complex y = Complex.ofCis(theta);
141 Assertions.assertEquals(r * y.getReal(), z.getReal());
142 Assertions.assertEquals(r * y.getImaginary(), z.getImaginary());
143
144
145
146 Assertions.assertEquals(NAN, Complex.ofPolar(1, -inf));
147 Assertions.assertEquals(NAN, Complex.ofPolar(1, inf));
148 Assertions.assertEquals(NAN, Complex.ofPolar(1, nan));
149
150
151 Assertions.assertEquals(NAN, Complex.ofPolar(inf, nan));
152
153 Assertions.assertEquals(NAN, Complex.ofPolar(-inf, 1));
154 Assertions.assertEquals(NAN, Complex.ofPolar(-0.0, 1));
155 Assertions.assertEquals(NAN, Complex.ofPolar(nan, 1));
156
157
158
159 Assertions.assertEquals(NAN, Complex.ofPolar(-0.0, 0.0));
160 Assertions.assertEquals(Complex.ofCartesian(0.0, 0.0), Complex.ofPolar(0.0, 0.0));
161 Assertions.assertEquals(Complex.ofCartesian(1.0, 0.0), Complex.ofPolar(1.0, 0.0));
162 Assertions.assertEquals(Complex.ofCartesian(-1.0, Math.sin(pi)), Complex.ofPolar(1.0, pi));
163 Assertions.assertEquals(Complex.ofCartesian(-inf, inf), Complex.ofPolar(inf, pi));
164 Assertions.assertEquals(Complex.ofCartesian(inf, nan), Complex.ofPolar(inf, 0.0));
165 Assertions.assertEquals(Complex.ofCartesian(inf, -inf), Complex.ofPolar(inf, -pi / 4));
166 Assertions.assertEquals(Complex.ofCartesian(-inf, -inf), Complex.ofPolar(inf, 5 * pi / 4));
167 }
168
169 @Test
170 void testPolarConstructorAbsArg() {
171
172
173 final UniformRandomProvider rng = RandomSource.SPLIT_MIX_64.create(678678638L);
174 for (int i = 0; i < 10; i++) {
175 final double rho = rng.nextDouble();
176
177 final double theta = pi - rng.nextDouble() * 2 * pi;
178 final Complex z = Complex.ofPolar(rho, theta);
179
180 Assertions.assertEquals(rho, z.abs(), Math.ulp(rho));
181 Assertions.assertEquals(theta, z.arg(), Math.ulp(theta));
182 }
183 }
184
185 @Test
186 void testCisConstructor() {
187 final double x = 0.12345;
188 final Complex z = Complex.ofCis(x);
189 Assertions.assertEquals(Math.cos(x), z.getReal());
190 Assertions.assertEquals(Math.sin(x), z.getImaginary());
191 }
192
193
194
195
196 @Test
197 void testParseAndToString() {
198 final double[] parts = {Double.NEGATIVE_INFINITY, -1, -0.0, 0.0, 1, Math.PI, Double.POSITIVE_INFINITY,
199 Double.NaN};
200 for (final double x : parts) {
201 for (final double y : parts) {
202 final Complex z = Complex.ofCartesian(x, y);
203 Assertions.assertEquals(z, Complex.parse(z.toString()));
204 }
205 }
206 final UniformRandomProvider rng = RandomSource.SPLIT_MIX_64.create();
207 for (int i = 0; i < 10; i++) {
208 final double x = -1 + rng.nextDouble() * 2;
209 final double y = -1 + rng.nextDouble() * 2;
210 final Complex z = Complex.ofCartesian(x, y);
211 Assertions.assertEquals(z, Complex.parse(z.toString()));
212 }
213
214
215 Assertions.assertEquals(Complex.ofPolar(2, pi), Complex.parse(Complex.ofPolar(2, pi).toString()));
216 Assertions.assertEquals(Complex.ofCis(pi), Complex.parse(Complex.ofCis(pi).toString()));
217 }
218
219 @Test
220 void testParseNull() {
221 Assertions.assertThrows(NullPointerException.class, () -> Complex.parse(null));
222 }
223
224 @Test
225 void testParseEmpty() {
226 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse(""));
227 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse(" "));
228 }
229
230 @Test
231 void testParseWrongStart() {
232 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("1.0,2.0)"));
233 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("[1.0,2.0)"));
234 }
235
236 @Test
237 void testParseWrongEnd() {
238 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(1.0,2.0"));
239 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(1.0,2.0]"));
240 }
241
242 @Test
243 void testParseWrongSeparator() {
244 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(1.0 2.0)"));
245 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(1.0:2.0)"));
246 }
247
248 @Test
249 void testParseSeparatorOutsideStartAndEnd() {
250 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(1.0,2.0),"));
251 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse(",(1.0,2.0)"));
252 }
253
254 @Test
255 void testParseExtraSeparator() {
256 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(1.0,,2.0)"));
257 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(1.0,2.0,)"));
258 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(,1.0,2.0)"));
259 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(1.0,2,0)"));
260 }
261
262 @Test
263 void testParseInvalidRe() {
264 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(I.0,2.0)"));
265 }
266
267 @Test
268 void testParseInvalidIm() {
269 Assertions.assertThrows(NumberFormatException.class, () -> Complex.parse("(1.0,2.G)"));
270 }
271
272 @Test
273 void testParseSpaceAllowedAroundNumbers() {
274 final double re = 1.234;
275 final double im = 5.678;
276 final Complex z = Complex.ofCartesian(re, im);
277 Assertions.assertEquals(z, Complex.parse("(" + re + "," + im + ")"));
278 Assertions.assertEquals(z, Complex.parse("( " + re + "," + im + ")"));
279 Assertions.assertEquals(z, Complex.parse("(" + re + " ," + im + ")"));
280 Assertions.assertEquals(z, Complex.parse("(" + re + ", " + im + ")"));
281 Assertions.assertEquals(z, Complex.parse("(" + re + "," + im + " )"));
282 Assertions.assertEquals(z, Complex.parse("( " + re + " , " + im + " )"));
283 }
284
285 @Test
286 void testCGrammar() {
287 final UniformRandomProvider rng = RandomSource.SPLIT_MIX_64.create();
288 for (int i = 0; i < 10; i++) {
289 final Complex z = Complex.ofCartesian(rng.nextDouble(), rng.nextDouble());
290 Assertions.assertEquals(z.getReal(), z.real(), "real");
291 Assertions.assertEquals(z.getImaginary(), z.imag(), "imag");
292 }
293 }
294
295 @Test
296 void testAbs() {
297 final Complex z = Complex.ofCartesian(3.0, 4.0);
298 Assertions.assertEquals(5.0, z.abs());
299 }
300
301 @Test
302 void testAbsNaN() {
303
304 Assertions.assertEquals(nan, NAN.abs());
305 Assertions.assertEquals(nan, Complex.ofCartesian(3.0, nan).abs());
306 Assertions.assertEquals(nan, Complex.ofCartesian(nan, 3.0).abs());
307
308 Assertions.assertEquals(inf, Complex.ofCartesian(inf, nan).abs());
309 Assertions.assertEquals(inf, Complex.ofCartesian(-inf, nan).abs());
310 Assertions.assertEquals(inf, Complex.ofCartesian(nan, inf).abs());
311 Assertions.assertEquals(inf, Complex.ofCartesian(nan, -inf).abs());
312 Assertions.assertEquals(inf, Complex.ofCartesian(inf, 3.0).abs());
313 Assertions.assertEquals(inf, Complex.ofCartesian(-inf, 3.0).abs());
314 Assertions.assertEquals(inf, Complex.ofCartesian(3.0, inf).abs());
315 Assertions.assertEquals(inf, Complex.ofCartesian(3.0, -inf).abs());
316 }
317
318
319
320
321 @Test
322 void testArg() {
323 Complex z = Complex.ofCartesian(1, 0);
324 assertArgument(0.0, z, 1.0e-12);
325
326 z = Complex.ofCartesian(1, 1);
327 assertArgument(Math.PI / 4, z, 1.0e-12);
328
329 z = Complex.ofCartesian(0, 1);
330 assertArgument(Math.PI / 2, z, 1.0e-12);
331
332 z = Complex.ofCartesian(-1, 1);
333 assertArgument(3 * Math.PI / 4, z, 1.0e-12);
334
335 z = Complex.ofCartesian(-1, 0);
336 assertArgument(Math.PI, z, 1.0e-12);
337
338 z = Complex.ofCartesian(-1, -1);
339 assertArgument(-3 * Math.PI / 4, z, 1.0e-12);
340
341 z = Complex.ofCartesian(0, -1);
342 assertArgument(-Math.PI / 2, z, 1.0e-12);
343
344 z = Complex.ofCartesian(1, -1);
345 assertArgument(-Math.PI / 4, z, 1.0e-12);
346 }
347
348
349
350
351 @Test
352 void testArgInf() {
353 assertArgument(Math.PI / 4, infInf, 1.0e-12);
354 assertArgument(Math.PI / 2, oneInf, 1.0e-12);
355 assertArgument(0.0, infOne, 1.0e-12);
356 assertArgument(Math.PI / 2, zeroInf, 1.0e-12);
357 assertArgument(0.0, infZero, 1.0e-12);
358 assertArgument(Math.PI, negInfOne, 1.0e-12);
359 assertArgument(-3.0 * Math.PI / 4, negInfNegInf, 1.0e-12);
360 assertArgument(-Math.PI / 2, oneNegInf, 1.0e-12);
361 }
362
363
364
365
366 @Test
367 void testArgNaN() {
368 assertArgument(Double.NaN, nanZero, 0);
369 assertArgument(Double.NaN, zeroNan, 0);
370 assertArgument(Double.NaN, NAN, 0);
371 }
372
373 private static void assertArgument(double expected, Complex complex, double delta) {
374 final double actual = complex.arg();
375 Assertions.assertEquals(expected, actual, delta);
376 Assertions.assertEquals(actual, complex.arg(), delta);
377 }
378
379 @Test
380 void testNorm() {
381 final Complex z = Complex.ofCartesian(3.0, 4.0);
382 Assertions.assertEquals(25.0, z.norm());
383 }
384
385 @Test
386 void testNormNaN() {
387
388 Assertions.assertEquals(nan, NAN.norm());
389 Assertions.assertEquals(nan, Complex.ofCartesian(3.0, nan).norm());
390 Assertions.assertEquals(nan, Complex.ofCartesian(nan, 3.0).norm());
391
392 Assertions.assertEquals(inf, Complex.ofCartesian(inf, nan).norm());
393 Assertions.assertEquals(inf, Complex.ofCartesian(-inf, nan).norm());
394 Assertions.assertEquals(inf, Complex.ofCartesian(nan, inf).norm());
395 Assertions.assertEquals(inf, Complex.ofCartesian(nan, -inf).norm());
396 }
397
398
399
400
401 @Test
402 void testNumberType() {
403 assertNumberType(0, 0, NumberType.FINITE);
404 assertNumberType(1, 0, NumberType.FINITE);
405 assertNumberType(0, 1, NumberType.FINITE);
406
407 assertNumberType(inf, 0, NumberType.INFINITE);
408 assertNumberType(-inf, 0, NumberType.INFINITE);
409 assertNumberType(0, inf, NumberType.INFINITE);
410 assertNumberType(0, -inf, NumberType.INFINITE);
411
412
413
414 assertNumberType(inf, nan, NumberType.INFINITE);
415 assertNumberType(-inf, nan, NumberType.INFINITE);
416 assertNumberType(nan, inf, NumberType.INFINITE);
417 assertNumberType(nan, -inf, NumberType.INFINITE);
418
419 assertNumberType(nan, 0, NumberType.NAN);
420 assertNumberType(0, nan, NumberType.NAN);
421 assertNumberType(nan, nan, NumberType.NAN);
422 }
423
424
425
426
427
428
429
430
431
432 private static void assertNumberType(double real, double imaginary, NumberType type) {
433 final Complex z = Complex.ofCartesian(real, imaginary);
434 final boolean isNaN = z.isNaN();
435 final boolean isInfinite = z.isInfinite();
436 final boolean isFinite = z.isFinite();
437
438 int count = isNaN ? 1 : 0;
439 count += isInfinite ? 1 : 0;
440 count += isFinite ? 1 : 0;
441 Assertions.assertEquals(1, count,
442 () -> String.format("Complex can be only one type: isNaN=%s, isInfinite=%s, isFinite=%s: %s", isNaN,
443 isInfinite, isFinite, z));
444 switch (type) {
445 case FINITE:
446 Assertions.assertTrue(isFinite, () -> "not finite: " + z);
447 break;
448 case INFINITE:
449 Assertions.assertTrue(isInfinite, () -> "not infinite: " + z);
450 break;
451 case NAN:
452 Assertions.assertTrue(isNaN, () -> "not nan: " + z);
453 break;
454 default:
455 Assertions.fail("Unknown number type");
456 }
457 }
458
459 @Test
460 void testConjugate() {
461 final Complex x = Complex.ofCartesian(3.0, 4.0);
462 final Complex z = x.conj();
463 Assertions.assertEquals(3.0, z.getReal());
464 Assertions.assertEquals(-4.0, z.getImaginary());
465 }
466
467 @Test
468 void testConjugateNaN() {
469 final Complex z = NAN.conj();
470 Assertions.assertTrue(z.isNaN());
471 }
472
473 @Test
474 void testConjugateInfinite() {
475 Complex z = Complex.ofCartesian(0, inf);
476 Assertions.assertEquals(neginf, z.conj().getImaginary());
477 z = Complex.ofCartesian(0, neginf);
478 Assertions.assertEquals(inf, z.conj().getImaginary());
479 }
480
481 @Test
482 void testNegate() {
483 final Complex x = Complex.ofCartesian(3.0, 4.0);
484 final Complex z = x.negate();
485 Assertions.assertEquals(-3.0, z.getReal());
486 Assertions.assertEquals(-4.0, z.getImaginary());
487 }
488
489 @Test
490 void testNegateNaN() {
491 final Complex z = NAN.negate();
492 Assertions.assertTrue(z.isNaN());
493 }
494
495 @Test
496 void testProj() {
497 final Complex z = Complex.ofCartesian(3.0, 4.0);
498 Assertions.assertSame(z, z.proj());
499
500 TestUtils.assertSame(infZero, Complex.ofCartesian(inf, 4.0).proj());
501 TestUtils.assertSame(infZero, Complex.ofCartesian(inf, inf).proj());
502 TestUtils.assertSame(infZero, Complex.ofCartesian(inf, nan).proj());
503 TestUtils.assertSame(infZero, Complex.ofCartesian(3.0, inf).proj());
504 TestUtils.assertSame(infZero, Complex.ofCartesian(nan, inf).proj());
505 TestUtils.assertSame(infNegZero, Complex.ofCartesian(inf, -4.0).proj());
506 TestUtils.assertSame(infNegZero, Complex.ofCartesian(inf, -inf).proj());
507 TestUtils.assertSame(infNegZero, Complex.ofCartesian(3.0, -inf).proj());
508 TestUtils.assertSame(infNegZero, Complex.ofCartesian(nan, -inf).proj());
509 }
510
511 @Test
512 void testAdd() {
513 final Complex x = Complex.ofCartesian(3.0, 4.0);
514 final Complex y = Complex.ofCartesian(5.0, 6.0);
515 final Complex z = x.add(y);
516 Assertions.assertEquals(8.0, z.getReal());
517 Assertions.assertEquals(10.0, z.getImaginary());
518 }
519
520 @Test
521 void testAddInf() {
522 Complex x = Complex.ofCartesian(1, 1);
523 final Complex z = Complex.ofCartesian(inf, 0);
524 final Complex w = x.add(z);
525 Assertions.assertEquals(1, w.getImaginary());
526 Assertions.assertEquals(inf, w.getReal());
527
528 x = Complex.ofCartesian(neginf, 0);
529 Assertions.assertTrue(Double.isNaN(x.add(z).getReal()));
530 }
531
532 @Test
533 void testAddReal() {
534 final Complex x = Complex.ofCartesian(3.0, 4.0);
535 final double y = 5.0;
536 final Complex z = x.add(y);
537 Assertions.assertEquals(8.0, z.getReal());
538 Assertions.assertEquals(4.0, z.getImaginary());
539
540 Assertions.assertEquals(z, x.add(ofReal(y)));
541 }
542
543 @Test
544 void testAddRealNaN() {
545 final Complex x = Complex.ofCartesian(3.0, 4.0);
546 final double y = nan;
547 final Complex z = x.add(y);
548 Assertions.assertEquals(nan, z.getReal());
549 Assertions.assertEquals(4.0, z.getImaginary());
550
551 Assertions.assertEquals(z, x.add(ofReal(y)));
552 }
553
554 @Test
555 void testAddRealInf() {
556 final Complex x = Complex.ofCartesian(3.0, 4.0);
557 final double y = inf;
558 final Complex z = x.add(y);
559 Assertions.assertEquals(inf, z.getReal());
560 Assertions.assertEquals(4.0, z.getImaginary());
561
562 Assertions.assertEquals(z, x.add(ofReal(y)));
563 }
564
565 @Test
566 void testAddRealWithNegZeroImaginary() {
567 final Complex x = Complex.ofCartesian(3.0, -0.0);
568 final double y = 5.0;
569 final Complex z = x.add(y);
570 Assertions.assertEquals(8.0, z.getReal());
571 Assertions.assertEquals(-0.0, z.getImaginary(), "Expected sign preservation");
572
573 final Complex z2 = x.add(ofReal(y));
574 Assertions.assertEquals(8.0, z2.getReal());
575 Assertions.assertEquals(0.0, z2.getImaginary(), "Expected no-sign preservation");
576 }
577
578 @Test
579 void testAddImaginary() {
580 final Complex x = Complex.ofCartesian(3.0, 4.0);
581 final double y = 5.0;
582 final Complex z = x.addImaginary(y);
583 Assertions.assertEquals(3.0, z.getReal());
584 Assertions.assertEquals(9.0, z.getImaginary());
585
586 Assertions.assertEquals(z, x.add(ofImaginary(y)));
587 }
588
589 @Test
590 void testAddImaginaryNaN() {
591 final Complex x = Complex.ofCartesian(3.0, 4.0);
592 final double y = nan;
593 final Complex z = x.addImaginary(y);
594 Assertions.assertEquals(3.0, z.getReal());
595 Assertions.assertEquals(nan, z.getImaginary());
596
597 Assertions.assertEquals(z, x.add(ofImaginary(y)));
598 }
599
600 @Test
601 void testAddImaginaryInf() {
602 final Complex x = Complex.ofCartesian(3.0, 4.0);
603 final double y = inf;
604 final Complex z = x.addImaginary(y);
605 Assertions.assertEquals(3.0, z.getReal());
606 Assertions.assertEquals(inf, z.getImaginary());
607
608 Assertions.assertEquals(z, x.add(ofImaginary(y)));
609 }
610
611 @Test
612 void testAddImaginaryWithNegZeroReal() {
613 final Complex x = Complex.ofCartesian(-0.0, 4.0);
614 final double y = 5.0;
615 final Complex z = x.addImaginary(y);
616 Assertions.assertEquals(-0.0, z.getReal(), "Expected sign preservation");
617 Assertions.assertEquals(9.0, z.getImaginary());
618
619 final Complex z2 = x.add(ofImaginary(y));
620 Assertions.assertEquals(0.0, z2.getReal(), "Expected no-sign preservation");
621 Assertions.assertEquals(9.0, z2.getImaginary());
622 }
623
624 @Test
625 void testSubtract() {
626 final Complex x = Complex.ofCartesian(3.0, 4.0);
627 final Complex y = Complex.ofCartesian(5.0, 7.0);
628 final Complex z = x.subtract(y);
629 Assertions.assertEquals(-2.0, z.getReal());
630 Assertions.assertEquals(-3.0, z.getImaginary());
631 }
632
633 @Test
634 void testSubtractInf() {
635 final Complex x = Complex.ofCartesian(3.0, 4.0);
636 final Complex y = Complex.ofCartesian(inf, 7.0);
637 Complex z = x.subtract(y);
638 Assertions.assertEquals(neginf, z.getReal());
639 Assertions.assertEquals(-3.0, z.getImaginary());
640
641 z = y.subtract(y);
642 Assertions.assertEquals(nan, z.getReal());
643 Assertions.assertEquals(0.0, z.getImaginary());
644 }
645
646 @Test
647 void testSubtractReal() {
648 final Complex x = Complex.ofCartesian(3.0, 4.0);
649 final double y = 5.0;
650 final Complex z = x.subtract(y);
651 Assertions.assertEquals(-2.0, z.getReal());
652 Assertions.assertEquals(4.0, z.getImaginary());
653
654 Assertions.assertEquals(z, x.subtract(ofReal(y)));
655 }
656
657 @Test
658 void testSubtractRealNaN() {
659 final Complex x = Complex.ofCartesian(3.0, 4.0);
660 final double y = nan;
661 final Complex z = x.subtract(y);
662 Assertions.assertEquals(nan, z.getReal());
663 Assertions.assertEquals(4.0, z.getImaginary());
664
665 Assertions.assertEquals(z, x.subtract(ofReal(y)));
666 }
667
668 @Test
669 void testSubtractRealInf() {
670 final Complex x = Complex.ofCartesian(3.0, 4.0);
671 final double y = inf;
672 final Complex z = x.subtract(y);
673 Assertions.assertEquals(-inf, z.getReal());
674 Assertions.assertEquals(4.0, z.getImaginary());
675
676 Assertions.assertEquals(z, x.subtract(ofReal(y)));
677 }
678
679 @Test
680 void testSubtractRealWithNegZeroImaginary() {
681 final Complex x = Complex.ofCartesian(3.0, -0.0);
682 final double y = 5.0;
683 final Complex z = x.subtract(y);
684 Assertions.assertEquals(-2.0, z.getReal());
685 Assertions.assertEquals(-0.0, z.getImaginary());
686
687
688 Assertions.assertEquals(z, x.subtract(ofReal(y)));
689 }
690
691 @Test
692 void testSubtractImaginary() {
693 final Complex x = Complex.ofCartesian(3.0, 4.0);
694 final double y = 5.0;
695 final Complex z = x.subtractImaginary(y);
696 Assertions.assertEquals(3.0, z.getReal());
697 Assertions.assertEquals(-1.0, z.getImaginary());
698
699 Assertions.assertEquals(z, x.subtract(ofImaginary(y)));
700 }
701
702 @Test
703 void testSubtractImaginaryNaN() {
704 final Complex x = Complex.ofCartesian(3.0, 4.0);
705 final double y = nan;
706 final Complex z = x.subtractImaginary(y);
707 Assertions.assertEquals(3.0, z.getReal());
708 Assertions.assertEquals(nan, z.getImaginary());
709
710 Assertions.assertEquals(z, x.subtract(ofImaginary(y)));
711 }
712
713 @Test
714 void testSubtractImaginaryInf() {
715 final Complex x = Complex.ofCartesian(3.0, 4.0);
716 final double y = inf;
717 final Complex z = x.subtractImaginary(y);
718 Assertions.assertEquals(3.0, z.getReal());
719 Assertions.assertEquals(-inf, z.getImaginary());
720
721 Assertions.assertEquals(z, x.subtract(ofImaginary(y)));
722 }
723
724 @Test
725 void testSubtractImaginaryWithNegZeroReal() {
726 final Complex x = Complex.ofCartesian(-0.0, 4.0);
727 final double y = 5.0;
728 final Complex z = x.subtractImaginary(y);
729 Assertions.assertEquals(-0.0, z.getReal());
730 Assertions.assertEquals(-1.0, z.getImaginary());
731
732
733 Assertions.assertEquals(z, x.subtract(ofImaginary(y)));
734 }
735
736 @Test
737 void testSubtractFromReal() {
738 final Complex x = Complex.ofCartesian(3.0, 4.0);
739 final double y = 5.0;
740 final Complex z = x.subtractFrom(y);
741 Assertions.assertEquals(2.0, z.getReal());
742 Assertions.assertEquals(-4.0, z.getImaginary());
743
744 Assertions.assertEquals(z, ofReal(y).subtract(x));
745 }
746
747 @Test
748 void testSubtractFromRealNaN() {
749 final Complex x = Complex.ofCartesian(3.0, 4.0);
750 final double y = nan;
751 final Complex z = x.subtractFrom(y);
752 Assertions.assertEquals(nan, z.getReal());
753 Assertions.assertEquals(-4.0, z.getImaginary());
754
755 Assertions.assertEquals(z, ofReal(y).subtract(x));
756 }
757
758 @Test
759 void testSubtractFromRealInf() {
760 final Complex x = Complex.ofCartesian(3.0, 4.0);
761 final double y = inf;
762 final Complex z = x.subtractFrom(y);
763 Assertions.assertEquals(inf, z.getReal());
764 Assertions.assertEquals(-4.0, z.getImaginary());
765
766 Assertions.assertEquals(z, ofReal(y).subtract(x));
767 }
768
769 @Test
770 void testSubtractFromRealWithPosZeroImaginary() {
771 final Complex x = Complex.ofCartesian(3.0, 0.0);
772 final double y = 5.0;
773 final Complex z = x.subtractFrom(y);
774 Assertions.assertEquals(2.0, z.getReal());
775 Assertions.assertEquals(-0.0, z.getImaginary(), "Expected sign inversion");
776
777 Assertions.assertNotEquals(z, ofReal(y).subtract(x));
778 }
779
780 @Test
781 void testSubtractFromImaginary() {
782 final Complex x = Complex.ofCartesian(3.0, 4.0);
783 final double y = 5.0;
784 final Complex z = x.subtractFromImaginary(y);
785 Assertions.assertEquals(-3.0, z.getReal());
786 Assertions.assertEquals(1.0, z.getImaginary());
787
788 Assertions.assertEquals(z, ofImaginary(y).subtract(x));
789 }
790
791 @Test
792 void testSubtractFromImaginaryNaN() {
793 final Complex x = Complex.ofCartesian(3.0, 4.0);
794 final double y = nan;
795 final Complex z = x.subtractFromImaginary(y);
796 Assertions.assertEquals(-3.0, z.getReal());
797 Assertions.assertEquals(nan, z.getImaginary());
798
799 Assertions.assertEquals(z, ofImaginary(y).subtract(x));
800 }
801
802 @Test
803 void testSubtractFromImaginaryInf() {
804 final Complex x = Complex.ofCartesian(3.0, 4.0);
805 final double y = inf;
806 final Complex z = x.subtractFromImaginary(y);
807 Assertions.assertEquals(-3.0, z.getReal());
808 Assertions.assertEquals(inf, z.getImaginary());
809
810 Assertions.assertEquals(z, ofImaginary(y).subtract(x));
811 }
812
813 @Test
814 void testSubtractFromImaginaryWithPosZeroReal() {
815 final Complex x = Complex.ofCartesian(0.0, 4.0);
816 final double y = 5.0;
817 final Complex z = x.subtractFromImaginary(y);
818 Assertions.assertEquals(-0.0, z.getReal(), "Expected sign inversion");
819 Assertions.assertEquals(1.0, z.getImaginary());
820
821 Assertions.assertNotEquals(z, ofImaginary(y).subtract(x));
822 }
823
824 @Test
825 void testMultiply() {
826 final Complex x = Complex.ofCartesian(3.0, 4.0);
827 final Complex y = Complex.ofCartesian(5.0, 6.0);
828 final Complex z = x.multiply(y);
829 Assertions.assertEquals(-9.0, z.getReal());
830 Assertions.assertEquals(38.0, z.getImaginary());
831 }
832
833 @Test
834 void testMultiplyInfInf() {
835 final Complex z = infInf.multiply(infInf);
836
837 Assertions.assertTrue(z.isInfinite());
838
839
840 Assertions.assertEquals(Complex.ofCartesian(nan, inf), infInf.multiply(infInf));
841 Assertions.assertEquals(Complex.ofCartesian(inf, nan), infInf.multiply(infNegInf));
842 Assertions.assertEquals(Complex.ofCartesian(-inf, nan), infInf.multiply(negInfInf));
843 Assertions.assertEquals(Complex.ofCartesian(nan, -inf), infInf.multiply(negInfNegInf));
844 }
845
846 @Test
847 void testMultiplyReal() {
848 final Complex x = Complex.ofCartesian(3.0, 4.0);
849 final double y = 2.0;
850 Complex z = x.multiply(y);
851 Assertions.assertEquals(6.0, z.getReal());
852 Assertions.assertEquals(8.0, z.getImaginary());
853
854 Assertions.assertEquals(z, x.multiply(ofReal(y)));
855
856 z = x.multiply(-y);
857 Assertions.assertEquals(-6.0, z.getReal());
858 Assertions.assertEquals(-8.0, z.getImaginary());
859
860 Assertions.assertEquals(z, x.multiply(ofReal(-y)));
861 }
862
863 @Test
864 void testMultiplyRealNaN() {
865 final Complex x = Complex.ofCartesian(3.0, 4.0);
866 final double y = nan;
867 final Complex z = x.multiply(y);
868 Assertions.assertEquals(nan, z.getReal());
869 Assertions.assertEquals(nan, z.getImaginary());
870
871 Assertions.assertEquals(z, x.multiply(ofReal(y)));
872 }
873
874 @Test
875 void testMultiplyRealInf() {
876 final Complex x = Complex.ofCartesian(3.0, 4.0);
877 final double y = inf;
878 Complex z = x.multiply(y);
879 Assertions.assertEquals(inf, z.getReal());
880 Assertions.assertEquals(inf, z.getImaginary());
881
882 Assertions.assertEquals(z, x.multiply(ofReal(y)));
883
884 z = x.multiply(-y);
885 Assertions.assertEquals(-inf, z.getReal());
886 Assertions.assertEquals(-inf, z.getImaginary());
887
888 Assertions.assertEquals(z, x.multiply(ofReal(-y)));
889 }
890
891 @Test
892 void testMultiplyRealZero() {
893 final Complex x = Complex.ofCartesian(3.0, 4.0);
894 final double y = 0.0;
895 Complex z = x.multiply(y);
896 Assertions.assertEquals(0.0, z.getReal());
897 Assertions.assertEquals(0.0, z.getImaginary());
898
899 Assertions.assertEquals(z, x.multiply(ofReal(y)));
900
901 z = x.multiply(-y);
902 Assertions.assertEquals(-0.0, z.getReal());
903 Assertions.assertEquals(-0.0, z.getImaginary());
904
905 final Complex z2 = x.multiply(ofReal(-y));
906 Assertions.assertEquals(-0.0, z2.getReal());
907 Assertions.assertEquals(0.0, z2.getImaginary(), "Expected no sign preservation");
908 }
909
910 @Test
911 void testMultiplyImaginary() {
912 final Complex x = Complex.ofCartesian(3.0, 4.0);
913 final double y = 2.0;
914 Complex z = x.multiplyImaginary(y);
915 Assertions.assertEquals(-8.0, z.getReal());
916 Assertions.assertEquals(6.0, z.getImaginary());
917
918 Assertions.assertEquals(z, x.multiply(ofImaginary(y)));
919
920 z = x.multiplyImaginary(-y);
921 Assertions.assertEquals(8.0, z.getReal());
922 Assertions.assertEquals(-6.0, z.getImaginary());
923
924 Assertions.assertEquals(z, x.multiply(ofImaginary(-y)));
925 }
926
927 @Test
928 void testMultiplyImaginaryNaN() {
929 final Complex x = Complex.ofCartesian(3.0, 4.0);
930 final double y = nan;
931 final Complex z = x.multiplyImaginary(y);
932 Assertions.assertEquals(nan, z.getReal());
933 Assertions.assertEquals(nan, z.getImaginary());
934
935 Assertions.assertEquals(z, x.multiply(ofImaginary(y)));
936 }
937
938 @Test
939 void testMultiplyImaginaryInf() {
940 final Complex x = Complex.ofCartesian(3.0, 4.0);
941 final double y = inf;
942 Complex z = x.multiplyImaginary(y);
943 Assertions.assertEquals(-inf, z.getReal());
944 Assertions.assertEquals(inf, z.getImaginary());
945
946 Assertions.assertEquals(z, x.multiply(ofImaginary(y)));
947
948 z = x.multiplyImaginary(-y);
949 Assertions.assertEquals(inf, z.getReal());
950 Assertions.assertEquals(-inf, z.getImaginary());
951
952 Assertions.assertEquals(z, x.multiply(ofImaginary(-y)));
953 }
954
955 @Test
956 void testMultiplyImaginaryZero() {
957 final Complex x = Complex.ofCartesian(3.0, 4.0);
958 final double y = 0.0;
959 Complex z = x.multiplyImaginary(y);
960 Assertions.assertEquals(-0.0, z.getReal());
961 Assertions.assertEquals(0.0, z.getImaginary());
962
963 Complex z2 = x.multiply(ofImaginary(y));
964 Assertions.assertEquals(0.0, z2.getReal(), "Expected no sign preservation");
965 Assertions.assertEquals(0.0, z2.getImaginary());
966
967 z = x.multiplyImaginary(-y);
968 Assertions.assertEquals(0.0, z.getReal());
969 Assertions.assertEquals(-0.0, z.getImaginary());
970
971 z2 = x.multiply(ofImaginary(-y));
972 Assertions.assertEquals(0.0, z2.getReal());
973 Assertions.assertEquals(0.0, z2.getImaginary(), "Expected no sign preservation");
974 }
975
976 @Test
977 void testNonZeroMultiplyI() {
978 final double[] parts = {3.0, 4.0};
979 for (final double a : parts) {
980 for (final double b : parts) {
981 final Complex c = Complex.ofCartesian(a, b);
982 final Complex x = c.multiplyImaginary(1.0);
983
984 Assertions.assertEquals(-b, x.getReal());
985 Assertions.assertEquals(a, x.getImaginary());
986 final Complex z = c.multiply(Complex.I);
987 Assertions.assertEquals(x, z);
988 }
989 }
990 }
991
992 @Test
993 void testNonZeroMultiplyNegativeI() {
994
995 final double[] parts = {3.0, 4.0};
996 final Complex[] negIs = {Complex.ofCartesian(-0.0, -1), Complex.ofCartesian(0.0, -1)};
997 for (final double a : parts) {
998 for (final double b : parts) {
999 final Complex c = Complex.ofCartesian(a, b);
1000 final Complex x = c.multiplyImaginary(-1.0);
1001
1002 Assertions.assertEquals(b, x.getReal());
1003 Assertions.assertEquals(-a, x.getImaginary());
1004 for (final Complex negI : negIs) {
1005 final Complex z = c.multiply(negI);
1006 Assertions.assertEquals(x, z);
1007 }
1008 }
1009 }
1010 }
1011
1012 @Test
1013 void testMultiplyZeroByI() {
1014 final double[] zeros = {-0.0, 0.0};
1015 for (final double a : zeros) {
1016 for (final double b : zeros) {
1017 final Complex c = Complex.ofCartesian(a, b);
1018 final Complex x = c.multiplyImaginary(1.0);
1019
1020 Assertions.assertEquals(-b, x.getReal());
1021 Assertions.assertEquals(a, x.getImaginary());
1022 final Complex z = c.multiply(Complex.I);
1023
1024 if (Double.compare(b, 0.0) == 0) {
1025
1026
1027
1028 Assertions.assertEquals(0, z.getReal(), 0.0);
1029 Assertions.assertEquals(0, z.getImaginary(), 0.0);
1030 Assertions.assertNotEquals(x, z);
1031 } else {
1032 Assertions.assertEquals(x, z);
1033 }
1034 }
1035 }
1036 }
1037
1038 @Test
1039 void testMultiplyZeroByNegativeI() {
1040
1041
1042 final Complex negI = Complex.I.negate();
1043 final double[] zeros = {-0.0, 0.0};
1044 for (final double a : zeros) {
1045 for (final double b : zeros) {
1046 final Complex c = Complex.ofCartesian(a, b);
1047 final Complex x = c.multiplyImaginary(-1.0);
1048
1049 Assertions.assertEquals(b, x.getReal());
1050 Assertions.assertEquals(-a, x.getImaginary());
1051 final Complex z = c.multiply(negI);
1052 final Complex z2 = c.multiply(Complex.I).negate();
1053
1054 if (Double.compare(b, -0.0) == 0) {
1055
1056
1057
1058 Assertions.assertEquals(0, z.getReal(), 0.0);
1059 Assertions.assertEquals(0, z.getImaginary(), 0.0);
1060 Assertions.assertNotEquals(x, z);
1061
1062
1063 Assertions.assertEquals(x, z2);
1064 } else {
1065 Assertions.assertEquals(x, z);
1066
1067
1068 Assertions.assertNotEquals(x, z2);
1069 }
1070 }
1071 }
1072 }
1073
1074 @Test
1075 void testDivide() {
1076 final Complex x = Complex.ofCartesian(3.0, 4.0);
1077 final Complex y = Complex.ofCartesian(5.0, 6.0);
1078 final Complex z = x.divide(y);
1079 Assertions.assertEquals(39.0 / 61.0, z.getReal());
1080 Assertions.assertEquals(2.0 / 61.0, z.getImaginary());
1081 }
1082
1083 @Test
1084 void testDivideZero() {
1085 final Complex x = Complex.ofCartesian(3.0, 4.0);
1086 final Complex z = x.divide(Complex.ZERO);
1087 Assertions.assertEquals(INF, z);
1088 }
1089
1090 @Test
1091 void testDivideZeroZero() {
1092 final Complex x = Complex.ofCartesian(0.0, 0.0);
1093 final Complex z = x.divide(Complex.ZERO);
1094 Assertions.assertEquals(NAN, z);
1095 }
1096
1097 @Test
1098 void testDivideNaN() {
1099 final Complex x = Complex.ofCartesian(3.0, 4.0);
1100 final Complex z = x.divide(NAN);
1101 Assertions.assertTrue(z.isNaN());
1102 }
1103
1104 @Test
1105 void testDivideNanInf() {
1106 Complex z = oneInf.divide(Complex.ONE);
1107 Assertions.assertTrue(Double.isNaN(z.getReal()));
1108 Assertions.assertEquals(inf, z.getImaginary());
1109
1110 z = negInfNegInf.divide(oneNan);
1111 Assertions.assertTrue(Double.isNaN(z.getReal()));
1112 Assertions.assertTrue(Double.isNaN(z.getImaginary()));
1113
1114 z = negInfInf.divide(Complex.ONE);
1115 Assertions.assertTrue(Double.isInfinite(z.getReal()));
1116 Assertions.assertTrue(Double.isInfinite(z.getImaginary()));
1117 }
1118
1119 @Test
1120 void testDivideReal() {
1121 final Complex x = Complex.ofCartesian(3.0, 4.0);
1122 final double y = 2.0;
1123 Complex z = x.divide(y);
1124 Assertions.assertEquals(1.5, z.getReal());
1125 Assertions.assertEquals(2.0, z.getImaginary());
1126
1127 Assertions.assertEquals(z, x.divide(ofReal(y)));
1128
1129 z = x.divide(-y);
1130 Assertions.assertEquals(-1.5, z.getReal());
1131 Assertions.assertEquals(-2.0, z.getImaginary());
1132
1133 Assertions.assertEquals(z, x.divide(ofReal(-y)));
1134 }
1135
1136 @Test
1137 void testDivideRealNaN() {
1138 final Complex x = Complex.ofCartesian(3.0, 4.0);
1139 final double y = nan;
1140 final Complex z = x.divide(y);
1141 Assertions.assertEquals(nan, z.getReal());
1142 Assertions.assertEquals(nan, z.getImaginary());
1143
1144 Assertions.assertEquals(z, x.divide(ofReal(y)));
1145 }
1146
1147 @Test
1148 void testDivideRealInf() {
1149 final Complex x = Complex.ofCartesian(3.0, 4.0);
1150 final double y = inf;
1151 Complex z = x.divide(y);
1152 Assertions.assertEquals(0.0, z.getReal());
1153 Assertions.assertEquals(0.0, z.getImaginary());
1154
1155 Assertions.assertEquals(z, x.divide(ofReal(y)));
1156
1157 z = x.divide(-y);
1158 Assertions.assertEquals(-0.0, z.getReal());
1159 Assertions.assertEquals(-0.0, z.getImaginary());
1160
1161 Assertions.assertEquals(z, x.divide(ofReal(-y)));
1162 }
1163
1164 @Test
1165 void testDivideRealZero() {
1166 final Complex x = Complex.ofCartesian(3.0, 4.0);
1167 final double y = 0.0;
1168 Complex z = x.divide(y);
1169 Assertions.assertEquals(inf, z.getReal());
1170 Assertions.assertEquals(inf, z.getImaginary());
1171
1172 Assertions.assertEquals(z, x.divide(ofReal(y)));
1173
1174 z = x.divide(-y);
1175 Assertions.assertEquals(-inf, z.getReal());
1176 Assertions.assertEquals(-inf, z.getImaginary());
1177
1178 Assertions.assertEquals(z, x.divide(ofReal(-y)));
1179 }
1180
1181 @Test
1182 void testDivideImaginary() {
1183 final Complex x = Complex.ofCartesian(3.0, 4.0);
1184 final double y = 2.0;
1185 Complex z = x.divideImaginary(y);
1186 Assertions.assertEquals(2.0, z.getReal());
1187 Assertions.assertEquals(-1.5, z.getImaginary());
1188
1189 Assertions.assertEquals(z, x.divide(ofImaginary(y)));
1190
1191 z = x.divideImaginary(-y);
1192 Assertions.assertEquals(-2.0, z.getReal());
1193 Assertions.assertEquals(1.5, z.getImaginary());
1194
1195 Assertions.assertEquals(z, x.divide(ofImaginary(-y)));
1196 }
1197
1198 @Test
1199 void testDivideImaginaryNaN() {
1200 final Complex x = Complex.ofCartesian(3.0, 4.0);
1201 final double y = nan;
1202 final Complex z = x.divideImaginary(y);
1203 Assertions.assertEquals(nan, z.getReal());
1204 Assertions.assertEquals(nan, z.getImaginary());
1205
1206 Assertions.assertEquals(z, x.divide(ofImaginary(y)));
1207 }
1208
1209 @Test
1210 void testDivideImaginaryInf() {
1211 final Complex x = Complex.ofCartesian(3.0, 4.0);
1212 final double y = inf;
1213 Complex z = x.divideImaginary(y);
1214 Assertions.assertEquals(0.0, z.getReal());
1215 Assertions.assertEquals(-0.0, z.getImaginary());
1216
1217 Assertions.assertEquals(z, x.divide(ofImaginary(y)));
1218
1219 z = x.divideImaginary(-y);
1220 Assertions.assertEquals(-0.0, z.getReal());
1221 Assertions.assertEquals(0.0, z.getImaginary());
1222
1223 Assertions.assertEquals(z, x.divide(ofImaginary(-y)));
1224 }
1225
1226 @Test
1227 void testDivideImaginaryZero() {
1228 final Complex x = Complex.ofCartesian(3.0, 4.0);
1229 final double y = 0.0;
1230 Complex z = x.divideImaginary(y);
1231 Assertions.assertEquals(inf, z.getReal());
1232 Assertions.assertEquals(-inf, z.getImaginary());
1233
1234 Complex z2 = x.divide(ofImaginary(y));
1235 Assertions.assertEquals(inf, z2.getReal());
1236 Assertions.assertEquals(inf, z2.getImaginary(), "Expected no sign preservation");
1237
1238 z = x.divideImaginary(-y);
1239 Assertions.assertEquals(-inf, z.getReal());
1240 Assertions.assertEquals(inf, z.getImaginary());
1241
1242 z2 = x.divide(ofImaginary(-y));
1243 Assertions.assertEquals(inf, z2.getReal(), "Expected no sign preservation");
1244 Assertions.assertEquals(inf, z2.getImaginary());
1245 }
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255 @Test
1256 void testSignedArithmetic() {
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282 assertSignedZeroArithmetic("addReal", Complex::add, ComplexTest::ofReal, Complex::add,
1283 0b1111000000000000111100000000000011110000000000001111L);
1284
1285 assertSignedZeroArithmetic("addImaginary", Complex::addImaginary, ComplexTest::ofImaginary, Complex::add,
1286 0b1111111111111111L);
1287
1288 assertSignedZeroArithmetic("subtractReal", Complex::subtract, ComplexTest::ofReal, Complex::subtract, 0);
1289
1290 assertSignedZeroArithmetic("subtractImaginary", Complex::subtractImaginary, ComplexTest::ofImaginary,
1291 Complex::subtract, 0);
1292
1293 assertSignedZeroArithmetic("subtractFromReal", Complex::subtractFrom, ComplexTest::ofReal,
1294 (y, z) -> z.subtract(y), 0b11110000000000001111000000000000111100000000000011110000L);
1295
1296 assertSignedZeroArithmetic("subtractFromImaginary", Complex::subtractFromImaginary, ComplexTest::ofImaginary,
1297 (y, z) -> z.subtract(y), 0b11111111111111110000000000000000L);
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307 assertSignedZeroArithmetic("multiplyReal", Complex::multiply, ComplexTest::ofReal, Complex::multiply,
1308 0b1001101011011000000100000001000010111010111110000101000001010L);
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318 assertSignedZeroArithmetic("multiplyImaginary", Complex::multiplyImaginary, ComplexTest::ofImaginary,
1319 Complex::multiply, 0b11000110110101001000000010000001110001111101011010000010100000L);
1320
1321
1322
1323
1324
1325 assertSignedZeroArithmetic("divideReal", Complex::divide, ComplexTest::ofReal, Complex::divide,
1326 0b100100001000000010000001000000011001000L);
1327
1328
1329
1330 }
1331
1332 private static void assertSignedZeroArithmetic(String name, BiFunction<Complex, Double, Complex> doubleOperation,
1333 DoubleFunction<Complex> doubleToComplex, BiFunction<Complex, Complex, Complex> complexOperation,
1334 long expectedFailures) {
1335
1336 final double[] arguments = {-0.0, 0.0, -2, 3};
1337 for (final double a : arguments) {
1338 for (final double b : arguments) {
1339 final Complex c = Complex.ofCartesian(a, b);
1340 for (final double arg : arguments) {
1341 final Complex y = doubleOperation.apply(c, arg);
1342 final Complex z = complexOperation.apply(c, doubleToComplex.apply(arg));
1343 final boolean expectedFailure = (expectedFailures & 0x1) == 1;
1344 expectedFailures >>>= 1;
1345
1346 Assertions.assertEquals(y.getReal(), z.getReal(), 0, () -> c + " " + name + " " + arg + ": real");
1347 Assertions.assertEquals(y.getImaginary(), z.getImaginary(), 0,
1348 () -> c + " " + name + " " + arg + ": imaginary");
1349 Assertions.assertEquals(expectedFailure, !y.equals(z),
1350 () -> c + " " + name + " " + arg + ": sign-difference");
1351 }
1352 }
1353 }
1354 }
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364 @Test
1365 void testSignedDivideImaginaryArithmetic() {
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377 long expectedFailures = 0b11001101111011001100110011001110110011110010000111001101000000L;
1378
1379 final double[] arguments = {-0.0, 0.0, -2, 3};
1380 for (final double a : arguments) {
1381 for (final double b : arguments) {
1382 final Complex c = Complex.ofCartesian(a, b);
1383 for (final double arg : arguments) {
1384 final Complex y = c.divideImaginary(arg);
1385 Complex z = c.divide(ofImaginary(arg));
1386 final boolean expectedFailure = (expectedFailures & 0x1) == 1;
1387 expectedFailures >>>= 1;
1388
1389
1390 if (arg == 0) {
1391
1392
1393 z = z.multiplyImaginary(1);
1394 final double ya = expectedFailure ? Math.abs(y.getReal()) : y.getReal();
1395 final double yb = expectedFailure ? Math.abs(y.getImaginary()) : y.getImaginary();
1396 final double za = expectedFailure ? Math.abs(z.getReal()) : z.getReal();
1397 final double zb = expectedFailure ? Math.abs(z.getImaginary()) : z.getImaginary();
1398 Assertions.assertEquals(ya, za, () -> c + " divideImaginary " + arg + ": real");
1399 Assertions.assertEquals(yb, zb, () -> c + " divideImaginary " + arg + ": imaginary");
1400 } else {
1401
1402 Assertions.assertEquals(y.getReal(), z.getReal(), 0,
1403 () -> c + " divideImaginary " + arg + ": real");
1404 Assertions.assertEquals(y.getImaginary(), z.getImaginary(), 0,
1405 () -> c + " divideImaginary " + arg + ": imaginary");
1406 Assertions.assertEquals(expectedFailure, !y.equals(z),
1407 () -> c + " divideImaginary " + arg + ": sign-difference");
1408 }
1409 }
1410 }
1411 }
1412 }
1413
1414 @Test
1415 void testLog10() {
1416 final double ln10 = Math.log(10);
1417 final UniformRandomProvider rng = RandomSource.SPLIT_MIX_64.create();
1418 for (int i = 0; i < 10; i++) {
1419 final Complex z = Complex.ofCartesian(rng.nextDouble() * 2, rng.nextDouble() * 2);
1420 final Complex lnz = z.log();
1421 final Complex log10z = z.log10();
1422
1423 Assertions.assertEquals(lnz.getReal() / ln10, log10z.getReal(), 1e-12, "real");
1424
1425 Assertions.assertEquals(lnz.getImaginary(), log10z.getImaginary(), "imag");
1426 }
1427 }
1428
1429 @Test
1430 void testPow() {
1431 final Complex x = Complex.ofCartesian(3, 4);
1432 final double yDouble = 5.0;
1433 final Complex yComplex = ofReal(yDouble);
1434 Assertions.assertEquals(x.pow(yComplex), x.pow(yDouble));
1435 }
1436
1437 @Test
1438 void testPowComplexRealZero() {
1439
1440 final Complex x = Complex.ofCartesian(0, 1);
1441 final Complex z = Complex.ofCartesian(2, 3);
1442 final Complex c = x.pow(z);
1443
1444 Assertions.assertEquals(-0.008983291021129429, c.getReal());
1445 Assertions.assertEquals(1.1001358594835313e-18, c.getImaginary());
1446 }
1447
1448 @Test
1449 void testPowComplexZeroBase() {
1450 final double x = Double.MIN_VALUE;
1451 assertPowComplexZeroBase(0, 0, NAN);
1452 assertPowComplexZeroBase(0, x, NAN);
1453 assertPowComplexZeroBase(x, x, NAN);
1454 assertPowComplexZeroBase(x, 0, Complex.ZERO);
1455 }
1456
1457 private static void assertPowComplexZeroBase(double re, double im, Complex expected) {
1458 final Complex z = Complex.ofCartesian(re, im);
1459 final Complex c = Complex.ZERO.pow(z);
1460 Assertions.assertEquals(expected, c);
1461 }
1462
1463 @Test
1464 void testPowScalerRealZero() {
1465
1466 final Complex x = Complex.ofCartesian(0, 1);
1467 final Complex c = x.pow(2);
1468
1469 Assertions.assertEquals(-1, c.getReal());
1470 Assertions.assertEquals(1.2246467991473532e-16, c.getImaginary());
1471 }
1472
1473 @Test
1474 void testPowScalarZeroBase() {
1475 final double x = Double.MIN_VALUE;
1476 assertPowScalarZeroBase(0, NAN);
1477 assertPowScalarZeroBase(x, Complex.ZERO);
1478 }
1479
1480 private static void assertPowScalarZeroBase(double exp, Complex expected) {
1481 final Complex c = Complex.ZERO.pow(exp);
1482 Assertions.assertEquals(expected, c);
1483 }
1484
1485 @Test
1486 void testPowNanBase() {
1487 final Complex x = NAN;
1488 final double yDouble = 5.0;
1489 final Complex yComplex = ofReal(yDouble);
1490 Assertions.assertEquals(x.pow(yComplex), x.pow(yDouble));
1491 }
1492
1493 @Test
1494 void testPowNanExponent() {
1495 final Complex x = Complex.ofCartesian(3, 4);
1496 final double yDouble = Double.NaN;
1497 final Complex yComplex = ofReal(yDouble);
1498 Assertions.assertEquals(x.pow(yComplex), x.pow(yDouble));
1499 }
1500
1501 @Test
1502 void testSqrtPolar() {
1503 final double tol = 1e-12;
1504 double r = 1;
1505 for (int i = 0; i < 5; i++) {
1506 r += i;
1507 double theta = 0;
1508 for (int j = 0; j < 11; j++) {
1509 theta += pi / 12;
1510 final Complex z = Complex.ofPolar(r, theta);
1511 final Complex sqrtz = Complex.ofPolar(Math.sqrt(r), theta / 2);
1512 TestUtils.assertEquals(sqrtz, z.sqrt(), tol);
1513 }
1514 }
1515 }
1516
1517 @Test
1518 void testZerothRootThrows() {
1519 final Complex c = Complex.ofCartesian(1, 1);
1520 Assertions.assertThrows(IllegalArgumentException.class, () -> c.nthRoot(0),
1521 "zeroth root should not be allowed");
1522 }
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536 @Test
1537 void testNthRootNormalThirdRoot() {
1538
1539 final Complex z = Complex.ofCartesian(-2, 2);
1540
1541 final Complex[] thirdRootsOfZ = z.nthRoot(3).toArray(new Complex[0]);
1542
1543 Assertions.assertEquals(3, thirdRootsOfZ.length);
1544
1545 Assertions.assertEquals(1.0, thirdRootsOfZ[0].getReal(), 1.0e-5);
1546 Assertions.assertEquals(1.0, thirdRootsOfZ[0].getImaginary(), 1.0e-5);
1547
1548 Assertions.assertEquals(-1.3660254037844386, thirdRootsOfZ[1].getReal(), 1.0e-5);
1549 Assertions.assertEquals(0.36602540378443843, thirdRootsOfZ[1].getImaginary(), 1.0e-5);
1550
1551 Assertions.assertEquals(0.366025403784439, thirdRootsOfZ[2].getReal(), 1.0e-5);
1552 Assertions.assertEquals(-1.3660254037844384, thirdRootsOfZ[2].getImaginary(), 1.0e-5);
1553 }
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568 @Test
1569 void testNthRootNormalFourthRoot() {
1570
1571 final Complex z = Complex.ofCartesian(5, -2);
1572
1573 final Complex[] fourthRootsOfZ = z.nthRoot(4).toArray(new Complex[0]);
1574
1575 Assertions.assertEquals(4, fourthRootsOfZ.length);
1576
1577 Assertions.assertEquals(1.5164629308487783, fourthRootsOfZ[0].getReal(), 1.0e-5);
1578 Assertions.assertEquals(-0.14469266210702247, fourthRootsOfZ[0].getImaginary(), 1.0e-5);
1579
1580 Assertions.assertEquals(0.14469266210702256, fourthRootsOfZ[1].getReal(), 1.0e-5);
1581 Assertions.assertEquals(1.5164629308487783, fourthRootsOfZ[1].getImaginary(), 1.0e-5);
1582
1583 Assertions.assertEquals(-1.5164629308487783, fourthRootsOfZ[2].getReal(), 1.0e-5);
1584 Assertions.assertEquals(0.14469266210702267, fourthRootsOfZ[2].getImaginary(), 1.0e-5);
1585
1586 Assertions.assertEquals(-0.14469266210702275, fourthRootsOfZ[3].getReal(), 1.0e-5);
1587 Assertions.assertEquals(-1.5164629308487783, fourthRootsOfZ[3].getImaginary(), 1.0e-5);
1588 }
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602 @Test
1603 void testNthRootCornercaseThirdRootImaginaryPartEmpty() {
1604
1605
1606 final Complex z = Complex.ofCartesian(8, 0);
1607
1608 final Complex[] thirdRootsOfZ = z.nthRoot(3).toArray(new Complex[0]);
1609
1610 Assertions.assertEquals(3, thirdRootsOfZ.length);
1611
1612 Assertions.assertEquals(2.0, thirdRootsOfZ[0].getReal(), 1.0e-5);
1613 Assertions.assertEquals(0.0, thirdRootsOfZ[0].getImaginary(), 1.0e-5);
1614
1615 Assertions.assertEquals(-1.0, thirdRootsOfZ[1].getReal(), 1.0e-5);
1616 Assertions.assertEquals(1.7320508075688774, thirdRootsOfZ[1].getImaginary(), 1.0e-5);
1617
1618 Assertions.assertEquals(-1.0, thirdRootsOfZ[2].getReal(), 1.0e-5);
1619 Assertions.assertEquals(-1.732050807568877, thirdRootsOfZ[2].getImaginary(), 1.0e-5);
1620 }
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634 @Test
1635 void testNthRootCornercaseThirdRootRealPartZero() {
1636
1637 final Complex z = Complex.ofCartesian(0, 2);
1638
1639 final Complex[] thirdRootsOfZ = z.nthRoot(3).toArray(new Complex[0]);
1640
1641 Assertions.assertEquals(3, thirdRootsOfZ.length);
1642
1643 Assertions.assertEquals(1.0911236359717216, thirdRootsOfZ[0].getReal(), 1.0e-5);
1644 Assertions.assertEquals(0.6299605249474365, thirdRootsOfZ[0].getImaginary(), 1.0e-5);
1645
1646 Assertions.assertEquals(-1.0911236359717216, thirdRootsOfZ[1].getReal(), 1.0e-5);
1647 Assertions.assertEquals(0.6299605249474365, thirdRootsOfZ[1].getImaginary(), 1.0e-5);
1648
1649 Assertions.assertEquals(-2.3144374213981936E-16, thirdRootsOfZ[2].getReal(), 1.0e-5);
1650 Assertions.assertEquals(-1.2599210498948732, thirdRootsOfZ[2].getImaginary(), 1.0e-5);
1651 }
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668 @Test
1669 void testNthRootNegativeArg() {
1670
1671 final Complex z = Complex.ofCartesian(1, 0);
1672
1673 Complex[] fourthRootsOfZ = z.nthRoot(4).toArray(new Complex[0]);
1674
1675 Assertions.assertEquals(1, fourthRootsOfZ[0].getReal(), 1.0e-5);
1676 Assertions.assertEquals(0, fourthRootsOfZ[0].getImaginary(), 1.0e-5);
1677
1678 Assertions.assertEquals(0, fourthRootsOfZ[1].getReal(), 1.0e-5);
1679 Assertions.assertEquals(1, fourthRootsOfZ[1].getImaginary(), 1.0e-5);
1680
1681 Assertions.assertEquals(-1, fourthRootsOfZ[2].getReal(), 1.0e-5);
1682 Assertions.assertEquals(0, fourthRootsOfZ[2].getImaginary(), 1.0e-5);
1683
1684 Assertions.assertEquals(0, fourthRootsOfZ[3].getReal(), 1.0e-5);
1685 Assertions.assertEquals(-1, fourthRootsOfZ[3].getImaginary(), 1.0e-5);
1686
1687 fourthRootsOfZ = z.nthRoot(-4).toArray(new Complex[0]);
1688
1689 Assertions.assertEquals(1, fourthRootsOfZ[0].getReal(), 1.0e-5);
1690 Assertions.assertEquals(0, fourthRootsOfZ[0].getImaginary(), 1.0e-5);
1691
1692 Assertions.assertEquals(0, fourthRootsOfZ[1].getReal(), 1.0e-5);
1693 Assertions.assertEquals(-1, fourthRootsOfZ[1].getImaginary(), 1.0e-5);
1694
1695 Assertions.assertEquals(-1, fourthRootsOfZ[2].getReal(), 1.0e-5);
1696 Assertions.assertEquals(0, fourthRootsOfZ[2].getImaginary(), 1.0e-5);
1697
1698 Assertions.assertEquals(0, fourthRootsOfZ[3].getReal(), 1.0e-5);
1699 Assertions.assertEquals(1, fourthRootsOfZ[3].getImaginary(), 1.0e-5);
1700 }
1701
1702 @Test
1703 void testNthRootNan() {
1704 final int n = 3;
1705 final Complex z = ofReal(Double.NaN);
1706 final List<Complex> r = z.nthRoot(n);
1707 Assertions.assertEquals(n, r.size());
1708 for (final Complex c : r) {
1709 Assertions.assertTrue(Double.isNaN(c.getReal()));
1710 Assertions.assertTrue(Double.isNaN(c.getImaginary()));
1711 }
1712 }
1713
1714 @Test
1715 void testNthRootInf() {
1716 final int n = 3;
1717 final Complex z = ofReal(Double.NEGATIVE_INFINITY);
1718 final List<Complex> r = z.nthRoot(n);
1719 Assertions.assertEquals(n, r.size());
1720 }
1721
1722 @Test
1723 void testEqualsWithNull() {
1724 final Complex x = Complex.ofCartesian(3.0, 4.0);
1725 Assertions.assertNotEquals(x, null);
1726 }
1727
1728 @Test
1729 void testEqualsWithAnotherClass() {
1730 final Complex x = Complex.ofCartesian(3.0, 4.0);
1731 Assertions.assertNotEquals(x, new Object());
1732 }
1733
1734 @Test
1735 void testEqualsWithSameObject() {
1736 final Complex x = Complex.ofCartesian(3.0, 4.0);
1737 Assertions.assertEquals(x, x);
1738 }
1739
1740 @Test
1741 void testEqualsWithCopyObject() {
1742 final Complex x = Complex.ofCartesian(3.0, 4.0);
1743 final Complex y = Complex.ofCartesian(3.0, 4.0);
1744 Assertions.assertEquals(x, y);
1745 }
1746
1747 @Test
1748 void testEqualsWithRealDifference() {
1749 final Complex x = Complex.ofCartesian(0.0, 0.0);
1750 final Complex y = Complex.ofCartesian(0.0 + Double.MIN_VALUE, 0.0);
1751 Assertions.assertNotEquals(x, y);
1752 }
1753
1754 @Test
1755 void testEqualsWithImaginaryDifference() {
1756 final Complex x = Complex.ofCartesian(0.0, 0.0);
1757 final Complex y = Complex.ofCartesian(0.0, 0.0 + Double.MIN_VALUE);
1758 Assertions.assertNotEquals(x, y);
1759 }
1760
1761
1762
1763
1764
1765
1766 @Test
1767 void testEqualsIsConsistentWithArraysEquals() {
1768
1769 assertEqualsIsConsistentWithArraysEquals(Complex.ofCartesian(Double.NaN, 0.0),
1770 Complex.ofCartesian(Double.NaN, 1.0), "NaN real and different non-NaN imaginary");
1771 assertEqualsIsConsistentWithArraysEquals(Complex.ofCartesian(0.0, Double.NaN),
1772 Complex.ofCartesian(1.0, Double.NaN), "Different non-NaN real and NaN imaginary");
1773 assertEqualsIsConsistentWithArraysEquals(Complex.ofCartesian(0.0, 0.0), Complex.ofCartesian(-0.0, 0.0),
1774 "Different real zeros");
1775 assertEqualsIsConsistentWithArraysEquals(Complex.ofCartesian(0.0, 0.0), Complex.ofCartesian(0.0, -0.0),
1776 "Different imaginary zeros");
1777
1778
1779 final double[] values = {Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, -1, 0, 1};
1780 final ArrayList<Complex> list = createCombinations(values);
1781
1782 for (final Complex c : list) {
1783 final double real = c.getReal();
1784 final double imag = c.getImaginary();
1785
1786
1787 assertEqualsIsConsistentWithArraysEquals(c, Complex.ofCartesian(real, imag), "Copy complex");
1788
1789
1790 final double realDelta = smallestChange(real);
1791 final double imagDelta = smallestChange(imag);
1792 Assertions.assertNotEquals(real, realDelta, "Real was not changed");
1793 Assertions.assertNotEquals(imag, imagDelta, "Imaginary was not changed");
1794
1795 assertEqualsIsConsistentWithArraysEquals(c, Complex.ofCartesian(realDelta, imag), "Delta real");
1796 assertEqualsIsConsistentWithArraysEquals(c, Complex.ofCartesian(real, imagDelta), "Delta imaginary");
1797 }
1798 }
1799
1800
1801
1802
1803
1804 @Test
1805 void testEqualsWithDifferentNaNs() {
1806
1807 final double[] values = {Double.NaN, 0, 1};
1808 final ArrayList<Complex> list = createCombinations(values);
1809
1810
1811
1812
1813
1814 for (int i = 0; i < list.size(); i++) {
1815 final Complex c1 = list.get(i);
1816 final Complex copy = Complex.ofCartesian(c1.getReal(), c1.getImaginary());
1817 assertEqualsIsConsistentWithArraysEquals(c1, copy, "Copy is not equal");
1818 for (int j = i + 1; j < list.size(); j++) {
1819 final Complex c2 = list.get(j);
1820 assertEqualsIsConsistentWithArraysEquals(c1, c2, "Different NaNs should not be equal");
1821 }
1822 }
1823 }
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833 private static void assertEqualsIsConsistentWithArraysEquals(Complex c1, Complex c2, String msg) {
1834 final boolean expected = Arrays.equals(new double[] {c1.getReal(), c1.getImaginary()},
1835 new double[] {c2.getReal(), c2.getImaginary()});
1836 final boolean actual = c1.equals(c2);
1837 Assertions.assertEquals(expected, actual,
1838 () -> String.format("equals(Object) is not consistent with Arrays.equals: %s. %s vs %s", msg, c1, c2));
1839 }
1840
1841
1842
1843
1844
1845
1846
1847 @Test
1848 void testHashCode() {
1849
1850 final double[] values = {Double.NaN, Double.NEGATIVE_INFINITY, -3.45, -1, -0.0, 0.0, Double.MIN_VALUE, 1, 3.45,
1851 Double.POSITIVE_INFINITY};
1852 final ArrayList<Complex> list = createCombinations(values);
1853
1854 final String msg = "'equals' not compatible with 'hashCode'";
1855
1856 for (final Complex c : list) {
1857 final double real = c.getReal();
1858 final double imag = c.getImaginary();
1859 final int expected = Arrays.hashCode(new double[] {real, imag});
1860 final int hash = c.hashCode();
1861 Assertions.assertEquals(expected, hash, "hashCode does not match Arrays.hashCode({re, im})");
1862
1863
1864
1865 final Complex copy = Complex.ofCartesian(real, imag);
1866 Assertions.assertEquals(hash, copy.hashCode(), "Copy hash code is not equal");
1867
1868
1869
1870
1871
1872
1873 final double realDelta = smallestChange(real);
1874 final double imagDelta = smallestChange(imag);
1875 Assertions.assertNotEquals(real, realDelta, "Real was not changed");
1876 Assertions.assertNotEquals(imag, imagDelta, "Imaginary was not changed");
1877
1878 final Complex cRealDelta = Complex.ofCartesian(realDelta, imag);
1879 final Complex cImagDelta = Complex.ofCartesian(real, imagDelta);
1880 if (hash != cRealDelta.hashCode()) {
1881 Assertions.assertNotEquals(c, cRealDelta, () -> "real+delta: " + msg);
1882 }
1883 if (hash != cImagDelta.hashCode()) {
1884 Assertions.assertNotEquals(c, cImagDelta, () -> "imaginary+delta: " + msg);
1885 }
1886 }
1887 }
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900 @Test
1901 void testHashCodeWithDifferentZeros() {
1902 final double[] values = {-0.0, 0.0};
1903 final ArrayList<Complex> list = createCombinations(values);
1904
1905
1906
1907 for (int i = 0; i < list.size(); i++) {
1908 final Complex c1 = list.get(i);
1909 for (int j = i + 1; j < list.size(); j++) {
1910 final Complex c2 = list.get(j);
1911 if (c1.hashCode() != c2.hashCode()) {
1912 Assertions.assertNotEquals(c1, c2, "'equals' not compatible with 'hashCode'");
1913 }
1914 }
1915 }
1916 }
1917
1918
1919
1920
1921
1922
1923
1924
1925 private static ArrayList<Complex> createCombinations(final double[] values) {
1926 final ArrayList<Complex> list = new ArrayList<>(values.length * values.length);
1927 for (final double re : values) {
1928 for (final double im : values) {
1929 list.add(Complex.ofCartesian(re, im));
1930 }
1931 }
1932 return list;
1933 }
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944 private static double smallestChange(double x) {
1945 if (Double.isNaN(x)) {
1946 return 0;
1947 }
1948 return x == Double.POSITIVE_INFINITY ? Math.nextDown(x) : Math.nextUp(x);
1949 }
1950
1951 @Test
1952 void testAtanhEdgeConditions() {
1953
1954 final Complex c = Complex.ofCartesian(2, 0).atanh();
1955
1956 Assertions.assertEquals(0.54930614433405489, c.getReal());
1957 Assertions.assertEquals(1.5707963267948966, c.getImaginary());
1958 }
1959
1960 @Test
1961 void testAtanhAssumptions() {
1962
1963 final double safeUpper = Math.sqrt(Double.MAX_VALUE) / 2;
1964 final double safeLower = Math.sqrt(Double.MIN_NORMAL) * 2;
1965
1966
1967 Assertions.assertEquals(safeUpper, 1 + safeUpper);
1968
1969 Assertions.assertEquals(-safeUpper, 1 - safeUpper);
1970
1971 Assertions.assertEquals(0, safeLower * safeLower / safeUpper);
1972
1973 Assertions.assertEquals(safeUpper, 1 / safeUpper + safeUpper);
1974
1975 Assertions.assertEquals(4, 4 + safeLower * safeLower);
1976
1977 Assertions.assertEquals(1, (1 - safeLower) * (1 - safeLower));
1978
1979 Assertions.assertEquals(1, 1 - safeLower * safeLower);
1980
1981
1982 final double result = 4 * safeLower / safeUpper / safeUpper;
1983 Assertions.assertEquals(result, Math.log1p(result));
1984 Assertions.assertEquals(result, result - result * result / 2, "Expected log1p Taylor series to be redundant");
1985
1986 Assertions.assertNotEquals(0, 1 - Math.nextUp(1));
1987 Assertions.assertNotEquals(0, 1 - Math.nextDown(1));
1988 }
1989
1990 @Test
1991 void testCoshSinhTanhAssumptions() {
1992
1993 final double safeExpMax = 708;
1994
1995 final double big = Math.exp(safeExpMax);
1996 final double small = Math.exp(-safeExpMax);
1997
1998
1999 Assertions.assertTrue(Double.isFinite(big));
2000 Assertions.assertTrue(Double.isInfinite(Math.exp(safeExpMax + 2)));
2001
2002
2003 Assertions.assertEquals(big + small, big);
2004 Assertions.assertEquals(Math.cosh(safeExpMax), big / 2);
2005 Assertions.assertEquals(Math.cosh(-safeExpMax), big / 2);
2006
2007
2008 Assertions.assertEquals(big - small, big);
2009 Assertions.assertEquals(small - big, -big);
2010 Assertions.assertEquals(Math.sinh(safeExpMax), big / 2);
2011 Assertions.assertEquals(Math.sinh(-safeExpMax), -big / 2);
2012
2013
2014
2015 Assertions.assertTrue(Double.isFinite(Math.sinh(safeExpMax / 2) * Math.cosh(safeExpMax / 2)));
2016 Assertions.assertTrue(Double.isFinite(Math.sinh(safeExpMax / 2) * Math.sinh(safeExpMax / 2)));
2017
2018
2019 Assertions.assertNotEquals(0.0, 2.0 / big);
2020 Assertions.assertEquals(0.0, 2.0 / big / big);
2021
2022
2023
2024 Assertions.assertTrue(Double.isFinite(0.5 * big * Double.MIN_VALUE * big));
2025 Assertions.assertTrue(Double.isInfinite(0.5 * big * Double.MIN_VALUE * big * big));
2026
2027
2028 for (final double y : new double[] {Math.PI / 2, Math.PI / 4, 1.0, 0.5, 0.0}) {
2029 Assertions.assertEquals(Math.signum(Math.sin(2 * y)), Math.signum(Math.sin(y) * Math.cos(y)));
2030 Assertions.assertEquals(Math.signum(Math.sin(2 * -y)), Math.signum(Math.sin(-y) * Math.cos(-y)));
2031 }
2032
2033
2034
2035 Assertions.assertTrue(2.0 / Double.MAX_VALUE > 0);
2036 }
2037
2038
2039
2040
2041
2042 @Test
2043 void testSinCosLinearAssumptions() {
2044
2045
2046 Assertions.assertEquals(1.0, Math.cos(Double.MIN_NORMAL));
2047 Assertions.assertEquals(Double.MIN_NORMAL, Math.sin(Double.MIN_NORMAL));
2048
2049
2050
2051 Assertions.assertEquals(1.0, Math.cosh(Double.MIN_NORMAL));
2052 Assertions.assertEquals(Double.MIN_NORMAL, Math.sinh(Double.MIN_NORMAL));
2053 }
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065 @Test
2066 void testAbsVsSqrt() {
2067 final UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_128_PP.create();
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081 assertAbsVsSqrt(1000,
2082 () -> Complex.ofCartesian(createFixedExponentNumber(rng, 1000), createFixedExponentNumber(rng, 1000)));
2083 assertAbsVsSqrt(1000,
2084 () -> Complex.ofCartesian(createFixedExponentNumber(rng, -1000), createFixedExponentNumber(rng, -1000)));
2085 }
2086
2087 private static void assertAbsVsSqrt(int samples, Supplier<Complex> supplier) {
2088
2089
2090
2091
2092 for (int i = 0; i < samples; i++) {
2093 final Complex z = supplier.get();
2094 final double abs = z.abs();
2095 final double x = Math.abs(z.getReal());
2096 final double y = Math.abs(z.getImaginary());
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107 final Complex c = z.sqrt();
2108 final double t = Math.sqrt(2 * (x + abs));
2109 if (z.getReal() >= 0) {
2110 Assertions.assertEquals(t / 2, c.getReal());
2111 Assertions.assertEquals(z.getImaginary() / t, c.getImaginary());
2112 } else {
2113 Assertions.assertEquals(y / t, c.getReal());
2114 Assertions.assertEquals(Math.copySign(t / 2, z.getImaginary()), c.getImaginary());
2115 }
2116 }
2117 }
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129 @Test
2130 void testAbsVsLog() {
2131 final UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_128_PP.create();
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147 assertAbsVsLog(100,
2148 () -> Complex.ofCartesian(createFixedExponentNumber(rng, 1022), createFixedExponentNumber(rng, 1022)));
2149 assertAbsVsLog(100,
2150 () -> Complex.ofCartesian(createFixedExponentNumber(rng, -1022), createFixedExponentNumber(rng, -1022)));
2151 }
2152
2153 private static void assertAbsVsLog(int samples, Supplier<Complex> supplier) {
2154
2155
2156
2157
2158 for (int i = 0; i < samples; i++) {
2159 final Complex z = supplier.get();
2160 final double abs = z.abs();
2161 final double x = Math.abs(z.getReal());
2162 final double y = Math.abs(z.getImaginary());
2163
2164
2165
2166 final Complex c = z.log();
2167 Assertions.assertEquals(Math.log(abs), c.getReal());
2168 }
2169 }
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179 private static double createFixedExponentNumber(UniformRandomProvider rng, int exponent) {
2180 return Double.longBitsToDouble((rng.nextLong() >>> 12) | ((1023L + exponent) << 52));
2181 }
2182 }