View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.numbers.complex;
19  
20  import org.apache.commons.rng.UniformRandomProvider;
21  import org.apache.commons.rng.simple.RandomSource;
22  import org.junit.jupiter.api.Assertions;
23  import org.junit.jupiter.api.Test;
24  
25  import java.math.BigDecimal;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.function.BiFunction;
29  import java.util.function.Predicate;
30  import java.util.function.ToDoubleFunction;
31  import java.util.function.UnaryOperator;
32  
33  /**
34   * Tests the standards defined by the C.99 standard for complex numbers
35   * defined in ISO/IEC 9899, Annex G.
36   *
37   * @see <a href="http://www.open-std.org/JTC1/SC22/WG14/www/standards">
38   *    ISO/IEC 9899 - Programming languages - C</a>
39   */
40  class CStandardTest {
41  
42      private static final double inf = Double.POSITIVE_INFINITY;
43      private static final double negInf = Double.NEGATIVE_INFINITY;
44      private static final double nan = Double.NaN;
45      private static final double max = Double.MAX_VALUE;
46      private static final double piOverFour = Math.PI / 4.0;
47      private static final double piOverTwo = Math.PI / 2.0;
48      private static final double threePiOverFour = 3.0 * Math.PI / 4.0;
49      private static final Complex oneZero = complex(1, 0);
50      private static final Complex zeroInf = complex(0, inf);
51      private static final Complex zeroNegInf = complex(0, negInf);
52      private static final Complex zeroNaN = complex(0, nan);
53      private static final Complex zeroPiTwo = complex(0.0, piOverTwo);
54      private static final Complex negZeroZero = complex(-0.0, 0);
55      private static final Complex negZeroNaN = complex(-0.0, nan);
56      private static final Complex infZero = complex(inf, 0);
57      private static final Complex infNaN = complex(inf, nan);
58      private static final Complex infInf = complex(inf, inf);
59      private static final Complex infPiTwo = complex(inf, piOverTwo);
60      private static final Complex infThreePiFour = complex(inf, threePiOverFour);
61      private static final Complex infPiFour = complex(inf, piOverFour);
62      private static final Complex infPi = complex(inf, Math.PI);
63      private static final Complex negInfInf = complex(negInf, inf);
64      private static final Complex negInfZero = complex(negInf, 0);
65      private static final Complex negInfNaN = complex(negInf, nan);
66      private static final Complex negInfPi = complex(negInf, Math.PI);
67      private static final Complex nanInf = complex(nan, inf);
68      private static final Complex nanNegInf = complex(nan, negInf);
69      private static final Complex nanZero = complex(nan, 0);
70      private static final Complex nanPiTwo = complex(nan, piOverTwo);
71      private static final Complex piTwoNaN = complex(piOverTwo, nan);
72      private static final Complex piNegInf = complex(Math.PI, negInf);
73      private static final Complex piTwoNegInf = complex(piOverTwo, negInf);
74      private static final Complex piTwoNegZero = complex(piOverTwo, -0.0);
75      private static final Complex threePiFourNegInf = complex(threePiOverFour, negInf);
76      private static final Complex piFourNegInf = complex(piOverFour, negInf);
77      private static final Complex NAN = complex(nan, nan);
78      private static final Complex maxMax = complex(max, max);
79      private static final Complex maxNan = complex(max, nan);
80      private static final Complex nanMax = complex(nan, max);
81  
82      /** Finite numbers (positive and negative with zero). */
83      private static final double[] finite;
84      /** Positive finite numbers (with zero). */
85      private static final double[] positiveFinite;
86      /** Non-zero finite numbers (positive and negative). */
87      private static final double[] nonZeroFinite;
88      /** Non-zero positive finite numbers. */
89      private static final double[] nonZeroPositiveFinite;
90      /** Non-zero finite and infinite numbers (positive and negative). */
91      private static final double[] nonZero;
92  
93      static {
94          // Choose a range that covers 2 * Math.PI.
95          // This is important for the functions that use cis(y).
96          final int size = 13;
97          finite = new double[size * 2];
98          positiveFinite = new double[size];
99          for (int i = 0; i < size; i++) {
100             final double v = i * 0.5;
101             finite[i * 2] = -v;
102             finite[i * 2 + 1] = v;
103             positiveFinite[i] = v;
104         }
105 
106         // Copy without zero
107         nonZeroFinite = Arrays.copyOfRange(finite, 2, finite.length);
108         nonZeroPositiveFinite = Arrays.copyOfRange(positiveFinite, 1, positiveFinite.length);
109 
110         nonZero = Arrays.copyOf(nonZeroFinite, nonZeroFinite.length + 2);
111         nonZero[nonZeroFinite.length] = Double.POSITIVE_INFINITY;
112         nonZero[nonZeroFinite.length + 1] = Double.NEGATIVE_INFINITY;
113 
114         // Arrange numerically
115         Arrays.sort(finite);
116         Arrays.sort(nonZeroFinite);
117         Arrays.sort(nonZero);
118     }
119 
120     /**
121      * The function type (e.g. odd or even).
122      */
123     private enum FunctionType {
124         /** Odd: f(z) = -f(-z). */
125         ODD,
126         /** Even: f(z) = f(-z). */
127         EVEN,
128         /** Not Odd or Even. */
129         NONE;
130     }
131 
132     /**
133      * An enum containing functionality to remove the sign from complex parts.
134      */
135     private enum UnspecifiedSign {
136         /** Remove the sign from the real component. */
137         REAL {
138             @Override
139             Complex removeSign(Complex c) {
140                 return negative(c.getReal()) ? complex(-c.getReal(), c.getImaginary()) : c;
141             }
142         },
143         /** Remove the sign from the imaginary component. */
144         IMAGINARY {
145             @Override
146             Complex removeSign(Complex c) {
147                 return negative(c.getImaginary()) ? complex(c.getReal(), -c.getImaginary()) : c;
148             }
149         },
150         /** Remove the sign from the real and imaginary component. */
151         REAL_IMAGINARY {
152             @Override
153             Complex removeSign(Complex c) {
154                 return IMAGINARY.removeSign(REAL.removeSign(c));
155             }
156         },
157         /** Do not remove the sign. */
158         NONE {
159             @Override
160             Complex removeSign(Complex c) {
161                 return c;
162             }
163         };
164 
165         /**
166          * Removes the sign from the complex real and or imaginary parts.
167          *
168          * @param c the complex
169          * @return the complex
170          */
171         abstract Complex removeSign(Complex c);
172 
173         /**
174          * Check that a value is negative. It must meet all the following conditions:
175          * <ul>
176          *  <li>it is not {@code NaN},</li>
177          *  <li>it is negative signed,</li>
178          * </ul>
179          *
180          * <p>Note: This is true for negative zero.</p>
181          *
182          * @param d Value.
183          * @return {@code true} if {@code d} is negative.
184          */
185         private static boolean negative(double d) {
186             return d < 0 || Double.doubleToLongBits(d) == Double.doubleToLongBits(-0.0);
187         }
188     }
189 
190     /**
191      * Assert the two complex numbers have equivalent real and imaginary components as
192      * defined by the {@code ==} operator.
193      *
194      * @param c1 the first complex (actual)
195      * @param c2 the second complex (expected)
196      */
197     private static void assertComplex(Complex c1, Complex c2) {
198         // Use a delta of zero to allow comparison of -0.0 to 0.0
199         Assertions.assertEquals(c2.getReal(), c1.getReal(), 0.0, "real");
200         Assertions.assertEquals(c2.getImaginary(), c1.getImaginary(), 0.0, "imaginary");
201     }
202 
203     /**
204      * Assert the operation on the two complex numbers.
205      *
206      * @param c1 the first complex
207      * @param c2 the second complex
208      * @param operation the operation
209      * @param operationName the operation name
210      * @param expected the expected
211      * @param expectedName the expected name
212      */
213     private static void assertOperation(Complex c1, Complex c2,
214             BiFunction<Complex, Complex, Complex> operation, String operationName,
215             Predicate<Complex> expected, String expectedName) {
216         final Complex z = operation.apply(c1, c2);
217         Assertions.assertTrue(expected.test(z),
218             () -> String.format("%s expected: %s %s %s = %s", expectedName, c1, operationName, c2, z));
219     }
220 
221     /**
222      * Assert the operation on the complex number satisfies the conjugate equality.
223      *
224      * <pre>
225      * op(conj(z)) = conj(op(z))
226      * </pre>
227      *
228      * <p>The results must be binary equal. This includes the sign of zero.
229      *
230      * <h2>ISO C99 equalities</h2>
231      *
232      * <p>Note that this method currently enforces the conjugate equalities for some cases
233      * where the sign of the real/imaginary parts are unspecified in ISO C99. This is
234      * allowed (since they are unspecified). The sign specification is appropriately
235      * handled during testing of odd/even functions. There are some functions where it
236      * is not possible to satisfy the conjugate equality and also the odd/even rule.
237      * The compromise made here is to satisfy only one and the other is allowed to fail
238      * only on the sign of the output result. Known functions where this applies are:
239      *
240      * <ul>
241      *  <li>asinh(NaN, inf)
242      *  <li>atanh(NaN, inf)
243      *  <li>cosh(NaN, 0.0)
244      *  <li>sinh(inf, inf)
245      *  <li>sinh(inf, nan)
246      * </ul>
247      *
248      * @param operation the operation
249      */
250     private static void assertConjugateEquality(UnaryOperator<Complex> operation) {
251         // Edge cases. Inf/NaN are specifically handled in the C99 test cases
252         // but are repeated here to enforce the conjugate equality even when the C99
253         // standard does not specify a sign. This may be revised in the future.
254         final double[] parts = {Double.NEGATIVE_INFINITY, -1, -0.0, 0.0, 1,
255                                 Double.POSITIVE_INFINITY, Double.NaN};
256         for (final double x : parts) {
257             for (final double y : parts) {
258                 // No conjugate for imaginary NaN
259                 if (!Double.isNaN(y)) {
260                     assertConjugateEquality(complex(x, y), operation, UnspecifiedSign.NONE);
261                 }
262             }
263         }
264         // Random numbers
265         final UniformRandomProvider rng = RandomSource.SPLIT_MIX_64.create();
266         for (int i = 0; i < 100; i++) {
267             final double x = next(rng);
268             final double y = next(rng);
269             assertConjugateEquality(complex(x, y), operation, UnspecifiedSign.NONE);
270         }
271     }
272 
273     /**
274      * Assert the operation on the complex number satisfies the conjugate equality.
275      *
276      * <pre>
277      * op(conj(z)) = conj(op(z))
278      * </pre>
279      *
280      * <p>The results must be binary equal; the sign of the complex number is first processed
281      * using the provided sign specification.
282      *
283      * @param z the complex number
284      * @param operation the operation
285      * @param sign the sign specification
286      */
287     private static void assertConjugateEquality(Complex z,
288             UnaryOperator<Complex> operation, UnspecifiedSign sign) {
289         final Complex c1 = operation.apply(z.conj());
290         final Complex c2 = operation.apply(z).conj();
291         final Complex t1 = sign.removeSign(c1);
292         final Complex t2 = sign.removeSign(c2);
293 
294         // Test for binary equality
295         if (!equals(t1.getReal(), t2.getReal()) ||
296             !equals(t1.getImaginary(), t2.getImaginary())) {
297             Assertions.fail(
298                 String.format("Conjugate equality failed (z=%s). Expected: %s but was: %s (Unspecified sign = %s)",
299                               z, c1, c2, sign));
300         }
301     }
302 
303     /**
304      * Assert the operation on the complex number is odd or even.
305      *
306      * <pre>
307      * Odd : f(z) = -f(-z)
308      * Even: f(z) =  f(-z)
309      * </pre>
310      *
311      * <p>The results must be binary equal. This includes the sign of zero.
312      *
313      * @param operation the operation
314      * @param type the type
315      */
316     private static void assertFunctionType(UnaryOperator<Complex> operation, FunctionType type) {
317         // Note: It may not be possible to satisfy the conjugate equality
318         // and be an odd/even function with regard to zero.
319         // The C99 standard allows for these cases to have unspecified sign.
320         // This test ignores parts that can result in unspecified signed results.
321         // The valid edge cases should be tested for each function separately.
322         if (type == FunctionType.NONE) {
323             return;
324         }
325 
326         // Edge cases around zero.
327         final double[] parts = {-2, -1, -0.0, 0.0, 1, 2};
328         for (final double x : parts) {
329             for (final double y : parts) {
330                 assertFunctionType(complex(x, y), operation, type, UnspecifiedSign.NONE);
331             }
332         }
333         // Random numbers
334         final UniformRandomProvider rng = RandomSource.SPLIT_MIX_64.create();
335         for (int i = 0; i < 100; i++) {
336             final double x = next(rng);
337             final double y = next(rng);
338             assertFunctionType(complex(x, y), operation, type, UnspecifiedSign.NONE);
339         }
340     }
341 
342     /**
343      * Assert the operation on the complex number is odd or even.
344      *
345      * <pre>
346      * Odd : f(z) = -f(-z)
347      * Even: f(z) =  f(-z)
348      * </pre>
349      *
350      * <p>The results must be binary equal; the sign of the complex number is first processed
351      * using the provided sign specification.
352      *
353      * @param z the complex number
354      * @param operation the operation
355      * @param type the type (assumed to be ODD/EVEN)
356      * @param sign the sign specification
357      */
358     private static void assertFunctionType(Complex z,
359             UnaryOperator<Complex> operation, FunctionType type, UnspecifiedSign sign) {
360         final Complex c1 = operation.apply(z);
361         Complex c2 = operation.apply(z.negate());
362         if (type == FunctionType.ODD) {
363             c2 = c2.negate();
364         }
365         final Complex t1 = sign.removeSign(c1);
366         final Complex t2 = sign.removeSign(c2);
367 
368         // Test for binary equality
369         if (!equals(t1.getReal(), t2.getReal()) ||
370             !equals(t1.getImaginary(), t2.getImaginary())) {
371             Assertions.fail(
372                 String.format("%s equality failed (z=%s, -z=%s). Expected: %s but was: %s (Unspecified sign = %s)",
373                               type, z, z.negate(), c1, c2, sign));
374             new Exception().printStackTrace();
375         }
376     }
377 
378     /**
379      * Assert the operation on the complex number is equal to the expected value.
380      * If the imaginary part is not NaN the operation must also satisfy the conjugate equality.
381      *
382      * <pre>
383      * op(conj(z)) = conj(op(z))
384      * </pre>
385      *
386      * <p>The results must be binary equal. This includes the sign of zero.
387      *
388      * @param z the complex
389      * @param operation the operation
390      * @param expected the expected
391      */
392     private static void assertComplex(Complex z,
393             UnaryOperator<Complex> operation, Complex expected) {
394         assertComplex(z, operation, expected, FunctionType.NONE, UnspecifiedSign.NONE);
395     }
396 
397     /**
398      * Assert the operation on the complex number is equal to the expected value. If the
399      * imaginary part is not NaN the operation must also satisfy the conjugate equality.
400      *
401      * <pre>
402      * op(conj(z)) = conj(op(z))
403      * </pre>
404      *
405      * <p>The results must be binary equal. This includes the sign of zero.
406      *
407      * @param z the complex
408      * @param operation the operation
409      * @param expected the expected
410      * @param sign the sign specification
411      */
412     private static void assertComplex(Complex z,
413             UnaryOperator<Complex> operation, Complex expected, UnspecifiedSign sign) {
414         assertComplex(z, operation, expected, FunctionType.NONE, sign);
415     }
416 
417     /**
418      * Assert the operation on the complex number is equal to the expected value. If the
419      * imaginary part is not NaN the operation must also satisfy the conjugate equality.
420      *
421      * <pre>
422      * op(conj(z)) = conj(op(z))
423      * </pre>
424      *
425      * <p>If the function type is ODD/EVEN the operation must satisfy the function type equality.
426      *
427      * <pre>
428      * Odd : f(z) = -f(-z)
429      * Even: f(z) =  f(-z)
430      * </pre>
431      *
432      * <p>The results must be binary equal. This includes the sign of zero.
433      *
434      * @param z the complex
435      * @param operation the operation
436      * @param expected the expected
437      * @param type the type
438      */
439     private static void assertComplex(Complex z,
440             UnaryOperator<Complex> operation, Complex expected,
441             FunctionType type) {
442         assertComplex(z, operation, expected, type, UnspecifiedSign.NONE);
443     }
444 
445     /**
446      * Assert the operation on the complex number is equal to the expected value. If the
447      * imaginary part is not NaN the operation must also satisfy the conjugate equality.
448      *
449      * <pre>
450      * op(conj(z)) = conj(op(z))
451      * </pre>
452      *
453      * <p>If the function type is ODD/EVEN the operation must satisfy the function type equality.
454      *
455      * <pre>
456      * Odd : f(z) = -f(-z)
457      * Even: f(z) =  f(-z)
458      * </pre>
459      *
460      * <p>An ODD/EVEN function is also tested that the conjugate equalities hold with {@code -z}.
461      * This effectively enumerates testing: (re, im); (re, -im); (-re, -im); and (-re, im).
462      *
463      * <p>The results must be binary equal; the sign of the complex number is first processed
464      * using the provided sign specification.
465      *
466      * @param z the complex
467      * @param operation the operation
468      * @param expected the expected
469      * @param type the type
470      * @param sign the sign specification
471      */
472     private static void assertComplex(Complex z,
473             UnaryOperator<Complex> operation, Complex expected,
474             FunctionType type, UnspecifiedSign sign) {
475         // Developer note: Set the sign specification to UnspecifiedSign.NONE
476         // to see which equalities fail. They should be for input defined
477         // in ISO C99 with an unspecified output sign, e.g.
478         // sign = UnspecifiedSign.NONE
479 
480         // Test the operation
481         final Complex c = operation.apply(z);
482         final Complex t1 = sign.removeSign(c);
483         final Complex t2 = sign.removeSign(expected);
484         if (!equals(t1.getReal(), t2.getReal()) ||
485             !equals(t1.getImaginary(), t2.getImaginary())) {
486             Assertions.fail(
487                 String.format("Operation failed (z=%s). Expected: %s but was: %s (Unspecified sign = %s)",
488                               z, expected, c, sign));
489         }
490 
491         if (!Double.isNaN(z.getImaginary())) {
492             assertConjugateEquality(z, operation, sign);
493         }
494 
495         if (type != FunctionType.NONE) {
496             assertFunctionType(z, operation, type, sign);
497 
498             // An odd/even function should satisfy the conjugate equality
499             // on the negated complex. This ensures testing the equalities
500             // hold for:
501             // (re, im) =  (re, -im)
502             // (re, im) =  (-re, -im) (even)
503             //          = -(-re, -im) (odd)
504             // (-re, -im) = (-re, im)
505             if (!Double.isNaN(z.getImaginary())) {
506                 assertConjugateEquality(z.negate(), operation, sign);
507             }
508         }
509     }
510 
511     /**
512      * Assert {@link Complex#abs()} is functionally equivalent to using
513      * {@link Math#hypot(double, double)}. If the results differ the true result
514      * is computed with extended precision. The test fails if the result is further
515      * than the provided ULPs from the reference result.
516      *
517      * <p>This can be used to assert that the custom implementation of abs() is no worse than
518      * {@link Math#hypot(double, double)} which aims to be within 1 ULP of the exact result.
519      *
520      * <p>Note: This method will not handle an input complex that is infinite or nan so should
521      * not be used for edge case tests.
522      *
523      * <p>Note: The true result is the sum {@code x^2 + y^2} computed using BigDecimal,
524      * converted to a double and the sqrt computed using standard precision.
525      * This is not the exact result as the BigDecimal
526      * sqrt() function was added in Java 9 and is unavailable for the current build target.
527      * In this case we require a measure of how close you can get to the nearest-double
528      * representing the answer, and the not the exact distance from the answer, so this
529      * is valid assuming {@link Math#sqrt(double)} has no error. The test then becomes a
530      * measure of the accuracy of the high-precision sum {@code x^2 + y^2}.
531      *
532      * @param z the complex
533      * @param ulps the maximum allowed ULPs from the exact result
534      */
535     private static void assertAbs(Complex z, int ulps) {
536         double x = z.getReal();
537         double y = z.getImaginary();
538         // For speed use Math.hypot as the reference, not BigDecimal computation.
539         final double expected = Math.hypot(x, y);
540         final double observed = z.abs();
541         if (expected == observed) {
542             // This condition will occur in the majority of cases.
543             return;
544         }
545         // Compute the 'exact' result.
546         // JDK 9 BigDecimal.sqrt() is not available so compute the standard sqrt of the
547         // high precision sum. Do scaling as the high precision sum may not be in the
548         // range of a double.
549         int scale = 0;
550         x = Math.abs(x);
551         y = Math.abs(y);
552         if (Math.max(x, y) > 0x1.0p+500) {
553             scale = Math.getExponent(Math.max(x, y));
554         } else if (Math.min(x, y) < 0x1.0p-500) {
555             scale = Math.getExponent(Math.min(x, y));
556         }
557         if (scale != 0) {
558             x = Math.scalb(x, -scale);
559             y = Math.scalb(y, -scale);
560         }
561         // Compute and re-scale. 'exact' must be effectively final for use in the
562         // assertion message supplier.
563         final double result = Math.sqrt(new BigDecimal(x).pow(2).add(new BigDecimal(y).pow(2)).doubleValue());
564         final double exact = scale != 0 ? Math.scalb(result, scale) : result;
565         if (exact == observed) {
566             // Different from Math.hypot but matches the 'exact' result
567             return;
568         }
569         // Distance from the 'exact' result should be within tolerance.
570         final long obsBits = Double.doubleToLongBits(observed);
571         final long exactBits = Double.doubleToLongBits(exact);
572         final long obsUlp = Math.abs(exactBits - obsBits);
573         Assertions.assertTrue(obsUlp <= ulps, () -> {
574             // Compute for Math.hypot for reference.
575             final long expBits = Double.doubleToLongBits(expected);
576             final long expUlp = Math.abs(exactBits - expBits);
577             return String.format("%s.abs(). Expected %s, was %s (%d ulps). hypot %s (%d ulps)",
578                 z, exact, observed, obsUlp, expected, expUlp);
579         });
580     }
581 
582     /**
583      * Assert {@link Complex#abs()} functions as per {@link Math#hypot(double, double)}.
584      * The two numbers for {@code z = x + iy} are generated from the two function.
585      *
586      * <p>The functions should not generate numbers that are infinite or nan.
587      *
588      * @param rng Source of randomness
589      * @param fx Function to generate x
590      * @param fy Function to generate y
591      * @param samples Number of samples
592      */
593     private static void assertAbs(UniformRandomProvider rng,
594                                   ToDoubleFunction<UniformRandomProvider> fx,
595                                   ToDoubleFunction<UniformRandomProvider> fy,
596                                   int samples) {
597         for (int i = 0; i < samples; i++) {
598             double x = fx.applyAsDouble(rng);
599             double y = fy.applyAsDouble(rng);
600             assertAbs(Complex.ofCartesian(x, y), 1);
601         }
602     }
603 
604     /**
605      * Creates a sub-normal number with up to 52-bits in the mantissa. The number of bits
606      * to drop must be in the range [0, 51].
607      *
608      * @param rng Source of randomness
609      * @param drop The number of mantissa bits to drop.
610      * @return the number
611      */
612     private static double createSubNormalNumber(UniformRandomProvider rng, int drop) {
613         return Double.longBitsToDouble(rng.nextLong() >>> (12 + drop));
614     }
615 
616     /**
617      * Creates a number in the range {@code [1, 2)} with up to 52-bits in the mantissa.
618      * Then modifies the exponent by the given amount.
619      *
620      * @param rng Source of randomness
621      * @param exponent Amount to change the exponent (in range [-1023, 1023])
622      * @return the number
623      */
624     private static double createFixedExponentNumber(UniformRandomProvider rng, int exponent) {
625         return Double.longBitsToDouble((rng.nextLong() >>> 12) | ((1023L + exponent) << 52));
626     }
627 
628     /**
629      * Returns {@code true} if the values are equal according to semantics of
630      * {@link Double#equals(Object)}.
631      *
632      * @param x Value
633      * @param y Value
634      * @return {@code Double.valueof(x).equals(Double.valueOf(y))}
635      */
636     private static boolean equals(double x, double y) {
637         return Double.doubleToLongBits(x) == Double.doubleToLongBits(y);
638     }
639 
640     /**
641      * Utility to create a Complex.
642      *
643      * @param real the real
644      * @param imaginary the imaginary
645      * @return the complex
646      */
647     private static Complex complex(double real, double imaginary) {
648         return Complex.ofCartesian(real, imaginary);
649     }
650 
651     /**
652      * Creates a list of Complex infinites.
653      *
654      * @return the list
655      */
656     private static ArrayList<Complex> createInfinites() {
657         final double[] values = {0, 1, inf, negInf, nan};
658         return createCombinations(values, Complex::isInfinite);
659     }
660 
661     /**
662      * Creates a list of Complex finites that are not zero.
663      *
664      * @return the list
665      */
666     private static ArrayList<Complex> createNonZeroFinites() {
667         final double[] values = {-1, -0, 0, 1, Double.MAX_VALUE};
668         return createCombinations(values, c -> !CStandardTest.isZero(c));
669     }
670 
671     /**
672      * Creates a list of Complex finites that are zero: [0,0], [-0,0], [0,-0], [-0,-0].
673      *
674      * @return the list
675      */
676     private static ArrayList<Complex> createZeroFinites() {
677         final double[] values = {-0, 0};
678         return createCombinations(values, c -> true);
679     }
680 
681     /**
682      * Creates a list of Complex NaNs.
683      *
684      * @return the list
685      */
686     private static ArrayList<Complex> createNaNs() {
687         final double[] values = {0, 1, nan};
688         return createCombinations(values, Complex::isNaN);
689     }
690 
691     /**
692      * Creates a list of Complex numbers as an all-vs-all combinations that pass the
693      * condition.
694      *
695      * @param values the values
696      * @param condition the condition
697      * @return the list
698      */
699     private static ArrayList<Complex> createCombinations(final double[] values, Predicate<Complex> condition) {
700         final ArrayList<Complex> list = new ArrayList<>();
701         for (final double re : values) {
702             for (final double im : values) {
703                 final Complex z = complex(re, im);
704                 if (condition.test(z)) {
705                     list.add(z);
706                 }
707             }
708         }
709         return list;
710     }
711 
712     /**
713      * Checks if the complex is zero. This method uses the {@code ==} operator and allows
714      * equality between signed zeros: {@code -0.0 == 0.0}.
715      *
716      * @param c the complex
717      * @return true if zero
718      */
719     private static boolean isZero(Complex c) {
720         return c.getReal() == 0 && c.getImaginary() == 0;
721     }
722 
723     /**
724      * ISO C Standard G.5 (4).
725      */
726     @Test
727     void testMultiply() {
728         final ArrayList<Complex> infinites = createInfinites();
729         final ArrayList<Complex> nonZeroFinites = createNonZeroFinites();
730         final ArrayList<Complex> zeroFinites = createZeroFinites();
731 
732         // C.99 refers to non-zero finites.
733         // Standard multiplication of zero with infinites is not defined.
734         Assertions.assertEquals(nan, 0.0 * inf, "0 * inf");
735         Assertions.assertEquals(nan, 0.0 * negInf, "0 * -inf");
736         Assertions.assertEquals(nan, -0.0 * inf, "-0 * inf");
737         Assertions.assertEquals(nan, -0.0 * negInf, "-0 * -inf");
738 
739         // "if one operand is an infinity and the other operand is a nonzero finite number or an
740         // infinity, then the result of the * operator is an infinity;"
741         for (final Complex z : infinites) {
742             for (final Complex w : infinites) {
743                 assertOperation(z, w, Complex::multiply, "*", Complex::isInfinite, "Inf");
744                 assertOperation(w, z, Complex::multiply, "*", Complex::isInfinite, "Inf");
745             }
746             for (final Complex w : nonZeroFinites) {
747                 assertOperation(z, w, Complex::multiply, "*", Complex::isInfinite, "Inf");
748                 assertOperation(w, z, Complex::multiply, "*", Complex::isInfinite, "Inf");
749             }
750             // C.99 refers to non-zero finites.
751             // Infer that Complex multiplication of zero with infinites is not defined.
752             for (final Complex w : zeroFinites) {
753                 assertOperation(z, w, Complex::multiply, "*", Complex::isNaN, "NaN");
754                 assertOperation(w, z, Complex::multiply, "*", Complex::isNaN, "NaN");
755             }
756         }
757 
758         // ISO C Standard in Annex G is missing an explicit definition of how to handle NaNs.
759         // We will assume multiplication by (nan,nan) is not allowed.
760         // It is undefined how to multiply when a complex has only one NaN component.
761         // The reference implementation in Annex G allows it.
762 
763         // The GNU g++ compiler computes:
764         // (1e300 + i 1e300) * (1e30 + i NAN) = inf + i inf
765         // Thus this is allowing some computations with NaN.
766 
767         // Check multiply with (NaN,NaN) is not corrected
768         final double[] values = {0, 1, inf, negInf, nan};
769         for (final Complex z : createCombinations(values, c -> true)) {
770             assertOperation(z, NAN, Complex::multiply, "*", Complex::isNaN, "NaN");
771             assertOperation(NAN, z, Complex::multiply, "*", Complex::isNaN, "NaN");
772         }
773 
774         // Test multiply cases which result in overflow are corrected to infinity
775         assertOperation(maxMax, maxMax, Complex::multiply, "*", Complex::isInfinite, "Inf");
776         assertOperation(maxNan, maxNan, Complex::multiply, "*", Complex::isInfinite, "Inf");
777         assertOperation(nanMax, maxNan, Complex::multiply, "*", Complex::isInfinite, "Inf");
778         assertOperation(maxNan, nanMax, Complex::multiply, "*", Complex::isInfinite, "Inf");
779         assertOperation(nanMax, nanMax, Complex::multiply, "*", Complex::isInfinite, "Inf");
780     }
781 
782     /**
783      * ISO C Standard G.5 (4).
784      */
785     @Test
786     void testDivide() {
787         final ArrayList<Complex> infinites = createInfinites();
788         final ArrayList<Complex> nonZeroFinites = createNonZeroFinites();
789         final ArrayList<Complex> zeroFinites = createZeroFinites();
790         final ArrayList<Complex> nans = createNaNs();
791         final ArrayList<Complex> finites = new ArrayList<>(nonZeroFinites);
792         finites.addAll(zeroFinites);
793 
794         // "if the first operand is an infinity and the second operand is a finite number, then the
795         // result of the / operator is an infinity;"
796         for (final Complex z : infinites) {
797             for (final Complex w : nonZeroFinites) {
798                 assertOperation(z, w, Complex::divide, "/", Complex::isInfinite, "Inf");
799             }
800             for (final Complex w : zeroFinites) {
801                 assertOperation(z, w, Complex::divide, "/", Complex::isInfinite, "Inf");
802             }
803             // Check inf/inf cannot be done
804             for (final Complex w : infinites) {
805                 assertOperation(z, w, Complex::divide, "/", Complex::isNaN, "NaN");
806             }
807         }
808 
809         // "if the first operand is a finite number and the second operand is an infinity, then the
810         // result of the / operator is a zero;"
811         for (final Complex z : finites) {
812             for (final Complex w : infinites) {
813                 assertOperation(z, w, Complex::divide, "/", CStandardTest::isZero, "Zero");
814             }
815         }
816 
817         // "if the first operand is a nonzero finite number or an infinity and the second operand is
818         // a zero, then the result of the / operator is an infinity."
819         for (final Complex w : zeroFinites) {
820             for (final Complex z : nonZeroFinites) {
821                 assertOperation(z, w, Complex::divide, "/", Complex::isInfinite, "Inf");
822             }
823             for (final Complex z : infinites) {
824                 assertOperation(z, w, Complex::divide, "/", Complex::isInfinite, "Inf");
825             }
826         }
827 
828         // ISO C Standard in Annex G is missing an explicit definition of how to handle NaNs.
829         // The reference implementation does not correct for divide by NaN components unless
830         // infinite.
831         for (final Complex w : nans) {
832             for (final Complex z : finites) {
833                 assertOperation(z, w, Complex::divide, "/", c -> NAN.equals(c), "(NaN,NaN)");
834             }
835             for (final Complex z : infinites) {
836                 assertOperation(z, w, Complex::divide, "/", c -> NAN.equals(c), "(NaN,NaN)");
837             }
838         }
839 
840         // Check (NaN,NaN) divide is not corrected for the edge case of divide by zero or infinite
841         for (final Complex w : zeroFinites) {
842             assertOperation(NAN, w, Complex::divide, "/", Complex::isNaN, "NaN");
843         }
844         for (final Complex w : infinites) {
845             assertOperation(NAN, w, Complex::divide, "/", Complex::isNaN, "NaN");
846         }
847     }
848 
849     /**
850      * ISO C Standard G.6 (3).
851      */
852     @Test
853     void testSqrt1() {
854         assertComplex(complex(-2.0, 0.0).sqrt(), complex(0.0, Math.sqrt(2)));
855         assertComplex(complex(-2.0, -0.0).sqrt(), complex(0.0, -Math.sqrt(2)));
856     }
857 
858     /**
859      * ISO C Standard G.6 (7).
860      */
861     @Test
862     void testImplicitTrig() {
863         final UniformRandomProvider rng = RandomSource.SPLIT_MIX_64.create();
864         for (int i = 0; i < 100; i++) {
865             final double re = next(rng);
866             final double im = next(rng);
867             final Complex z = complex(re, im);
868             final Complex iz = z.multiplyImaginary(1);
869             assertComplex(z.asin(), iz.asinh().multiplyImaginary(-1));
870             assertComplex(z.atan(), iz.atanh().multiplyImaginary(-1));
871             assertComplex(z.cos(), iz.cosh());
872             assertComplex(z.sin(), iz.sinh().multiplyImaginary(-1));
873             assertComplex(z.tan(), iz.tanh().multiplyImaginary(-1));
874         }
875     }
876 
877     /**
878      * Create a number in the range {@code [-5,5)}.
879      *
880      * @param rng the random generator
881      * @return the number
882      */
883     private static double next(UniformRandomProvider rng) {
884         // Note: [0, 1) minus 1 is [-1, 0). This occurs half the time to create [-1, 1).
885         return (rng.nextDouble() - rng.nextInt(1)) * 5;
886     }
887 
888     /**
889      * ISO C Standard G.6 (6) for abs().
890      * Functionality is defined by ISO C Standard F.9.4.3 hypot function.
891      */
892     @Test
893     void testAbs() {
894         Assertions.assertEquals(inf, complex(inf, nan).abs());
895         Assertions.assertEquals(inf, complex(negInf, nan).abs());
896         final UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_128_PP.create();
897         for (int i = 0; i < 10; i++) {
898             final double x = next(rng);
899             final double y = next(rng);
900             Assertions.assertEquals(complex(x, y).abs(), complex(y, x).abs());
901             Assertions.assertEquals(complex(x, y).abs(), complex(x, -y).abs());
902             Assertions.assertEquals(Math.abs(x), complex(x, 0.0).abs());
903             Assertions.assertEquals(Math.abs(x), complex(x, -0.0).abs());
904             Assertions.assertEquals(inf, complex(inf, y).abs());
905             Assertions.assertEquals(inf, complex(negInf, y).abs());
906         }
907 
908         // Test verses Math.hypot due to the use of a custom implementation.
909         // First test edge cases. Use negatives to test the sign is correctly removed.
910         final double[] parts = {-0.0, -Double.MIN_VALUE, -Double.MIN_NORMAL, -Double.MAX_VALUE,
911             Double.NEGATIVE_INFINITY, Double.NaN};
912         for (final double x : parts) {
913             for (final double y : parts) {
914                 Assertions.assertEquals(Math.hypot(x, y), complex(x, y).abs());
915             }
916         }
917 
918         // The reference fdlibm hypot implementation orders using the upper 32-bits of the double.
919         // Tests using random numbers that differ in only the lower 32-bits
920         // show a frequency of <1e-9 that the computation is not commutative: f(x, y) != f(y, x)
921         // Test known cases where ordering is required on the lower 32-bits to ensure |z| == |iz|.
922         // These cases would fail a direct fdlibm conversion of this:
923         // https://www.netlib.org/fdlibm/e_hypot.c
924         for (final double[] pair : new double[][] {
925                 {1.3122561682406755, 1.3122565442732959},
926                 {1.40905821964671, 1.4090583434236112},
927                 {1.912164268932753, 1.9121638616231227}}) {
928             final Complex z = complex(pair[0], pair[1]);
929             Assertions.assertEquals(z.abs(), z.multiplyImaginary(1).abs(), "Expected |z| == |iz|");
930         }
931 
932         // Test with a range of numbers.
933         // Sub-normals require special handling so we use different variations of these to
934         // ensure they are handled correctly.
935         // Note:
936         // 1 ULP differences with Math.hypot can be observed due to the different implementations.
937         // For normal numbers observable differences require billions of numbers to show a
938         // few hundred cases of lower ULPs and a magnitude smaller count of higher ULPs.
939         // For sub-normal numbers a few thousand examples can demonstrate
940         // a larger count of 1 ULP improvements than 1 ULP errors verses Math.hypot.
941         // A formal statistical test to demonstrate differences are significant is not implemented.
942         // This test simply asserts the answer is either the same as Math.hypot or else is within
943         // 1 ULP of a high precision computation.
944         final int samples = 100;
945         assertAbs(rng, r -> createSubNormalNumber(r, 0), r -> createSubNormalNumber(r, 0), samples);
946         assertAbs(rng, r -> createSubNormalNumber(r, 0), r -> createSubNormalNumber(r, 1), samples);
947         assertAbs(rng, r -> createSubNormalNumber(r, 0), r -> createSubNormalNumber(r, 2), samples);
948         // Numbers on the same scale (fixed exponent)
949         assertAbs(rng, r -> createFixedExponentNumber(r, 0), r -> createFixedExponentNumber(r, 0), samples);
950         // Numbers on different scales
951         assertAbs(rng, r -> createFixedExponentNumber(r, 0), r -> createFixedExponentNumber(r, 1), samples);
952         assertAbs(rng, r -> createFixedExponentNumber(r, 0), r -> createFixedExponentNumber(r, 2 + r.nextInt(10)), samples);
953         // Intermediate overflow / underflow
954         assertAbs(rng, r -> createFixedExponentNumber(r, 1022), r -> createFixedExponentNumber(r, 1022), samples);
955         assertAbs(rng, r -> createFixedExponentNumber(r, -1022), r -> createFixedExponentNumber(r, -1022), samples);
956         // Complex cis numbers
957         final ToDoubleFunction<UniformRandomProvider> cisGenerator = new ToDoubleFunction<UniformRandomProvider>() {
958             private double tmp = Double.NaN;
959             @Override
960             public double applyAsDouble(UniformRandomProvider rng) {
961                 if (Double.isNaN(tmp)) {
962                     double u = rng.nextDouble() * Math.PI;
963                     tmp = Math.cos(u);
964                     return Math.sin(u);
965                 }
966                 final double r = tmp;
967                 tmp = Double.NaN;
968                 return r;
969             }
970         };
971         assertAbs(rng, cisGenerator, cisGenerator, samples);
972     }
973 
974     /**
975      * ISO C Standard G.6.1.1.
976      */
977     @Test
978     void testAcos() {
979         final UnaryOperator<Complex> operation = Complex::acos;
980         assertConjugateEquality(operation);
981         assertComplex(Complex.ZERO, operation, piTwoNegZero);
982         assertComplex(negZeroZero, operation, piTwoNegZero);
983         assertComplex(zeroNaN, operation, piTwoNaN);
984         assertComplex(negZeroNaN, operation, piTwoNaN);
985         for (double x : finite) {
986             assertComplex(complex(x, inf), operation, piTwoNegInf);
987         }
988         for (double x : nonZeroFinite) {
989             assertComplex(complex(x, nan), operation, NAN);
990         }
991         for (double y : positiveFinite) {
992             assertComplex(complex(-inf, y), operation, piNegInf);
993         }
994         for (double y : positiveFinite) {
995             assertComplex(complex(inf, y), operation, zeroNegInf);
996         }
997         assertComplex(negInfInf, operation, threePiFourNegInf);
998         assertComplex(infInf, operation, piFourNegInf);
999         assertComplex(infNaN, operation, nanInf, UnspecifiedSign.IMAGINARY);
1000         assertComplex(negInfNaN, operation, nanNegInf, UnspecifiedSign.IMAGINARY);
1001         for (double y : finite) {
1002             assertComplex(complex(nan, y), operation, NAN);
1003         }
1004         assertComplex(nanInf, operation, nanNegInf);
1005         assertComplex(NAN, operation, NAN);
1006     }
1007 
1008     /**
1009      * ISO C Standard G.6.2.1.
1010      *
1011      * @see <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1892.htm#dr_471">
1012      *   Complex math functions cacosh and ctanh</a>
1013      */
1014     @Test
1015     void testAcosh() {
1016         final UnaryOperator<Complex> operation = Complex::acosh;
1017         assertConjugateEquality(operation);
1018         assertComplex(Complex.ZERO, operation, zeroPiTwo);
1019         assertComplex(negZeroZero, operation, zeroPiTwo);
1020         for (double x : finite) {
1021             assertComplex(complex(x, inf), operation, infPiTwo);
1022         }
1023         assertComplex(zeroNaN, operation, nanPiTwo);
1024         assertComplex(negZeroNaN, operation, nanPiTwo);
1025         for (double x : nonZeroFinite) {
1026             assertComplex(complex(x, nan), operation, NAN);
1027         }
1028         for (double y : positiveFinite) {
1029             assertComplex(complex(-inf, y), operation, infPi);
1030         }
1031         for (double y : positiveFinite) {
1032             assertComplex(complex(inf, y), operation, infZero);
1033         }
1034         assertComplex(negInfInf, operation, infThreePiFour);
1035         assertComplex(infInf, operation, infPiFour);
1036         assertComplex(infNaN, operation, infNaN);
1037         assertComplex(negInfNaN, operation, infNaN);
1038         for (double y : finite) {
1039             assertComplex(complex(nan, y), operation, NAN);
1040         }
1041         assertComplex(nanInf, operation, infNaN);
1042         assertComplex(NAN, operation, NAN);
1043     }
1044 
1045     /**
1046      * ISO C Standard G.6.2.2.
1047      */
1048     @Test
1049     void testAsinh() {
1050         final UnaryOperator<Complex> operation = Complex::asinh;
1051         final FunctionType type = FunctionType.ODD;
1052         assertConjugateEquality(operation);
1053         assertFunctionType(operation, type);
1054         assertComplex(Complex.ZERO, operation, Complex.ZERO, type);
1055         for (double x : positiveFinite) {
1056             assertComplex(complex(x, inf), operation, infPiTwo, type);
1057         }
1058         for (double x : finite) {
1059             assertComplex(complex(x, nan), operation, NAN, type);
1060         }
1061         for (double y : positiveFinite) {
1062             assertComplex(complex(inf, y), operation, infZero, type);
1063         }
1064         assertComplex(infInf, operation, infPiFour, type);
1065         assertComplex(infNaN, operation, infNaN, type);
1066         assertComplex(nanZero, operation, nanZero, type);
1067         for (double y : nonZeroFinite) {
1068             assertComplex(complex(nan, y), operation, NAN, type);
1069         }
1070         assertComplex(nanInf, operation, infNaN, type, UnspecifiedSign.REAL);
1071         assertComplex(NAN, operation, NAN, type);
1072     }
1073 
1074     /**
1075      * ISO C Standard G.6.2.3.
1076      */
1077     @Test
1078     void testAtanh() {
1079         final UnaryOperator<Complex> operation = Complex::atanh;
1080         final FunctionType type = FunctionType.ODD;
1081         assertConjugateEquality(operation);
1082         assertFunctionType(operation, type);
1083         assertComplex(Complex.ZERO, operation, Complex.ZERO, type);
1084         assertComplex(zeroNaN, operation, zeroNaN, type);
1085         assertComplex(oneZero, operation, infZero, type);
1086         for (double x : positiveFinite) {
1087             assertComplex(complex(x, inf), operation, zeroPiTwo, type);
1088         }
1089         for (double x : nonZeroFinite) {
1090             assertComplex(complex(x, nan), operation, NAN, type);
1091         }
1092         for (double y : positiveFinite) {
1093             assertComplex(complex(inf, y), operation, zeroPiTwo, type);
1094         }
1095         assertComplex(infInf, operation, zeroPiTwo, type);
1096         assertComplex(infNaN, operation, zeroNaN, type);
1097         assertComplex(nanZero, operation, NAN, type);
1098         for (double y : finite) {
1099             assertComplex(complex(nan, y), operation, NAN, type);
1100         }
1101         assertComplex(nanInf, operation, zeroPiTwo, type, UnspecifiedSign.REAL);
1102         assertComplex(NAN, operation, NAN, type);
1103     }
1104 
1105     /**
1106      * ISO C Standard G.6.2.4.
1107      */
1108     @Test
1109     void testCosh() {
1110         final UnaryOperator<Complex> operation = Complex::cosh;
1111         final FunctionType type = FunctionType.EVEN;
1112         assertConjugateEquality(operation);
1113         assertFunctionType(operation, type);
1114         assertComplex(Complex.ZERO, operation, Complex.ONE, type);
1115         assertComplex(zeroInf, operation, nanZero, type, UnspecifiedSign.IMAGINARY);
1116         assertComplex(zeroNaN, operation, nanZero, type, UnspecifiedSign.IMAGINARY);
1117         for (double x : nonZeroFinite) {
1118             assertComplex(complex(x, inf), operation, NAN, type);
1119         }
1120         for (double x : nonZeroFinite) {
1121             assertComplex(complex(x, nan), operation, NAN, type);
1122         }
1123         assertComplex(infZero, operation, infZero, type);
1124         for (double y : nonZeroFinite) {
1125             assertComplex(complex(inf, y), operation, Complex.ofCis(y).multiply(inf), type);
1126         }
1127         assertComplex(infInf, operation, infNaN, type, UnspecifiedSign.REAL);
1128         assertComplex(infNaN, operation, infNaN, type);
1129         assertComplex(nanZero, operation, nanZero, type, UnspecifiedSign.IMAGINARY);
1130         for (double y : nonZero) {
1131             assertComplex(complex(nan, y), operation, NAN, type);
1132         }
1133         assertComplex(NAN, operation, NAN, type);
1134     }
1135 
1136     /**
1137      * ISO C Standard G.6.2.5.
1138      */
1139     @Test
1140     void testSinh() {
1141         final UnaryOperator<Complex> operation = Complex::sinh;
1142         final FunctionType type = FunctionType.ODD;
1143         assertConjugateEquality(operation);
1144         assertFunctionType(operation, type);
1145         assertComplex(Complex.ZERO, operation, Complex.ZERO, type);
1146         assertComplex(zeroInf, operation, zeroNaN, type, UnspecifiedSign.REAL);
1147         assertComplex(zeroNaN, operation, zeroNaN, type, UnspecifiedSign.REAL);
1148         for (double x : nonZeroPositiveFinite) {
1149             assertComplex(complex(x, inf), operation, NAN, type);
1150         }
1151         for (double x : nonZeroFinite) {
1152             assertComplex(complex(x, nan), operation, NAN, type);
1153         }
1154         assertComplex(infZero, operation, infZero, type);
1155         // Note: Error in the ISO C99 reference to use positive finite y but the zero case is different
1156         for (double y : nonZeroFinite) {
1157             assertComplex(complex(inf, y), operation, Complex.ofCis(y).multiply(inf), type);
1158         }
1159         assertComplex(infInf, operation, infNaN, type, UnspecifiedSign.REAL);
1160         assertComplex(infNaN, operation, infNaN, type, UnspecifiedSign.REAL);
1161         assertComplex(nanZero, operation, nanZero, type);
1162         for (double y : nonZero) {
1163             assertComplex(complex(nan, y), operation, NAN, type);
1164         }
1165         assertComplex(NAN, operation, NAN, type);
1166     }
1167 
1168     /**
1169      * ISO C Standard G.6.2.6.
1170      *
1171      * @see <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1892.htm#dr_471">
1172      *   Complex math functions cacosh and ctanh</a>
1173      */
1174     @Test
1175     void testTanh() {
1176         final UnaryOperator<Complex> operation = Complex::tanh;
1177         final FunctionType type = FunctionType.ODD;
1178         assertConjugateEquality(operation);
1179         assertFunctionType(operation, type);
1180         assertComplex(Complex.ZERO, operation, Complex.ZERO, type);
1181         assertComplex(zeroInf, operation, zeroNaN, type);
1182         for (double x : nonZeroFinite) {
1183             assertComplex(complex(x, inf), operation, NAN, type);
1184         }
1185         assertComplex(zeroNaN, operation, zeroNaN, type);
1186         for (double x : nonZeroFinite) {
1187             assertComplex(complex(x, nan), operation, NAN, type);
1188         }
1189         for (double y : positiveFinite) {
1190             assertComplex(complex(inf, y), operation, complex(1.0, Math.copySign(0, Math.sin(2 * y))), type);
1191         }
1192         assertComplex(infInf, operation, oneZero, type, UnspecifiedSign.IMAGINARY);
1193         assertComplex(infNaN, operation, oneZero, type, UnspecifiedSign.IMAGINARY);
1194         assertComplex(nanZero, operation, nanZero, type);
1195         for (double y : nonZero) {
1196             assertComplex(complex(nan, y), operation, NAN, type);
1197         }
1198         assertComplex(NAN, operation, NAN, type);
1199     }
1200 
1201     /**
1202      * ISO C Standard G.6.3.1.
1203      */
1204     @Test
1205     void testExp() {
1206         final UnaryOperator<Complex> operation = Complex::exp;
1207         assertConjugateEquality(operation);
1208         assertComplex(Complex.ZERO, operation, oneZero);
1209         assertComplex(negZeroZero, operation, oneZero);
1210         for (double x : finite) {
1211             assertComplex(complex(x, inf), operation, NAN);
1212         }
1213         for (double x : finite) {
1214             assertComplex(complex(x, nan), operation, NAN);
1215         }
1216         assertComplex(infZero, operation, infZero);
1217         for (double y : finite) {
1218             assertComplex(complex(-inf, y), operation, Complex.ofCis(y).multiply(0.0));
1219         }
1220         for (double y : nonZeroFinite) {
1221             assertComplex(complex(inf, y), operation, Complex.ofCis(y).multiply(inf));
1222         }
1223         assertComplex(negInfInf, operation, Complex.ZERO, UnspecifiedSign.REAL_IMAGINARY);
1224         assertComplex(infInf, operation, infNaN, UnspecifiedSign.REAL);
1225         assertComplex(negInfNaN, operation, Complex.ZERO, UnspecifiedSign.REAL_IMAGINARY);
1226         assertComplex(infNaN, operation, infNaN, UnspecifiedSign.REAL);
1227         assertComplex(nanZero, operation, nanZero);
1228         for (double y : nonZero) {
1229             assertComplex(complex(nan, y), operation, NAN);
1230         }
1231         assertComplex(NAN, operation, NAN);
1232     }
1233 
1234     /**
1235      * ISO C Standard G.6.3.2.
1236      */
1237     @Test
1238     void testLog() {
1239         final UnaryOperator<Complex> operation = Complex::log;
1240         assertConjugateEquality(operation);
1241         assertComplex(negZeroZero, operation, negInfPi);
1242         assertComplex(Complex.ZERO, operation, negInfZero);
1243         for (double x : finite) {
1244             assertComplex(complex(x, inf), operation, infPiTwo);
1245         }
1246         for (double x : finite) {
1247             assertComplex(complex(x, nan), operation, NAN);
1248         }
1249         for (double y : positiveFinite) {
1250             assertComplex(complex(-inf, y), operation, infPi);
1251         }
1252         for (double y : positiveFinite) {
1253             assertComplex(complex(inf, y), operation, infZero);
1254         }
1255         assertComplex(negInfInf, operation, infThreePiFour);
1256         assertComplex(infInf, operation, infPiFour);
1257         assertComplex(negInfNaN, operation, infNaN);
1258         assertComplex(infNaN, operation, infNaN);
1259         for (double y : finite) {
1260             assertComplex(complex(nan, y), operation, NAN);
1261         }
1262         assertComplex(nanInf, operation, infNaN);
1263         assertComplex(NAN, operation, NAN);
1264     }
1265 
1266     /**
1267      * Same edge cases as log() since the real component is divided by Math.log(10) which
1268      * has no effect on infinite or nan.
1269      */
1270     @Test
1271     void testLog10() {
1272         final UnaryOperator<Complex> operation = Complex::log10;
1273         assertConjugateEquality(operation);
1274         assertComplex(negZeroZero, operation, negInfPi);
1275         assertComplex(Complex.ZERO, operation, negInfZero);
1276         for (double x : finite) {
1277             assertComplex(complex(x, inf), operation, infPiTwo);
1278         }
1279         for (double x : finite) {
1280             assertComplex(complex(x, nan), operation, NAN);
1281         }
1282         for (double y : positiveFinite) {
1283             assertComplex(complex(-inf, y), operation, infPi);
1284         }
1285         for (double y : positiveFinite) {
1286             assertComplex(complex(inf, y), operation, infZero);
1287         }
1288         assertComplex(negInfInf, operation, infThreePiFour);
1289         assertComplex(infInf, operation, infPiFour);
1290         assertComplex(negInfNaN, operation, infNaN);
1291         assertComplex(infNaN, operation, infNaN);
1292         for (double y : finite) {
1293             assertComplex(complex(nan, y), operation, NAN);
1294         }
1295         assertComplex(nanInf, operation, infNaN);
1296         assertComplex(NAN, operation, NAN);
1297     }
1298 
1299     /**
1300      * ISO C Standard G.6.4.2.
1301      */
1302     @Test
1303     void testSqrt() {
1304         final UnaryOperator<Complex> operation = Complex::sqrt;
1305         assertConjugateEquality(operation);
1306         assertComplex(negZeroZero, operation, Complex.ZERO);
1307         assertComplex(Complex.ZERO, operation, Complex.ZERO);
1308         for (double x : finite) {
1309             assertComplex(complex(x, inf), operation, infInf);
1310         }
1311         // Include infinity and nan for (x, inf).
1312         assertComplex(infInf, operation, infInf);
1313         assertComplex(negInfInf, operation, infInf);
1314         assertComplex(nanInf, operation, infInf);
1315         for (double x : finite) {
1316             assertComplex(complex(x, nan), operation, NAN);
1317         }
1318         for (double y : positiveFinite) {
1319             assertComplex(complex(-inf, y), operation, zeroInf);
1320         }
1321         for (double y : positiveFinite) {
1322             assertComplex(complex(inf, y), operation, infZero);
1323         }
1324         assertComplex(negInfNaN, operation, nanInf, UnspecifiedSign.IMAGINARY);
1325         assertComplex(infNaN, operation, infNaN);
1326         for (double y : finite) {
1327             assertComplex(complex(nan, y), operation, NAN);
1328         }
1329         assertComplex(NAN, operation, NAN);
1330     }
1331 }