You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2019/12/07 02:27:44 UTC

[commons-numbers] 02/04: Update CReferenceTest with many more cases.

This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git

commit 9eedfec839712fc1eb3fcd1dc98628b4fd4ba84c
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Dec 7 01:44:22 2019 +0000

    Update CReferenceTest with many more cases.
    
    Some extreme value cases do not match and are commented out.
---
 .../commons/numbers/complex/CReferenceTest.java    | 792 ++++++++++++++++-----
 1 file changed, 630 insertions(+), 162 deletions(-)

diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CReferenceTest.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CReferenceTest.java
index b98437f..2c268f0 100644
--- a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CReferenceTest.java
+++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CReferenceTest.java
@@ -20,6 +20,10 @@ package org.apache.commons.numbers.complex;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import java.util.function.BiFunction;
+import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
+
 /**
  * Tests the functions defined by the C.99 standard for complex numbers
  * defined in ISO/IEC 9899, Annex G.
@@ -30,233 +34,697 @@ import org.junit.jupiter.api.Test;
  *    ISO/IEC 9899 - Programming languages - C</a>
  */
 public class CReferenceTest {
-
-    /**
-     * Assert the two numbers are equal to within floating-point error.
-     * Two values are considered equal if there are no floating-point values between them.
-     *
-     * @param name the name of the number
-     * @param expected the expected
-     * @param actual the actual
-     * @param maxUlps the maximum units of least precision between the two values
-     */
-    private static void assertEquals(String name, double expected, double actual) {
-        assertEquals(name, expected, actual, 1);
-    }
+    private static final double inf = Double.POSITIVE_INFINITY;
+    private static final double nan = Double.NaN;
 
     /**
      * Assert the two numbers are equal within the provided units of least precision.
      * The maximum count of numbers allowed between the two values is {@code maxUlps - 1}.
      *
-     * @param name the name of the number
+     * @param msg the failure message
      * @param expected the expected
      * @param actual the actual
      * @param maxUlps the maximum units of least precision between the two values
      */
-    private static void assertEquals(String name, double expected, double actual, long maxUlps) {
+    private static void assertEquals(Supplier<String> msg, double expected, double actual, long maxUlps) {
         final long e = Double.doubleToLongBits(expected);
         final long a = Double.doubleToLongBits(actual);
         final long delta = Math.abs(e - a);
         if (delta > maxUlps) {
-            Assertions.fail(String.format("%s: %s != %s (ulps=%d)", name, expected, actual, delta));
+            // DEBUG:
+            if (maxUlps < 0) {
+                // CHECKSTYLE: stop Regex
+                System.out.printf("%s: %s != %s (ulps=%d)%n", msg.get(), expected, actual, delta);
+                // CHECKSTYLE: resume Regex
+            } else {
+                Assertions.fail(String.format("%s: %s != %s (ulps=%d)", msg.get(), expected, actual, delta));
+            }
         }
     }
 
+    /**
+     * Assert the operation on the complex number is equal to the expected value.
+     *
+     * <p>The results are are considered equal if there are no floating-point values between them.
+     *
+     * @param a Real part.
+     * @param b Imaginary part.
+     * @param operation the operation
+     * @param x Expected real part.
+     * @param y Expected imaginary part.
+     */
+    private static void assertComplex(double a, double b,
+            UnaryOperator<Complex> operation,
+            double x, double y) {
+        assertComplex(a, b, operation, x, y, 1);
+    }
+
+    /**
+     * Assert the operation on the complex number is equal to the expected value.
+     *
+     * <p>The results are considered equal within the provided units of least
+     * precision. The maximum count of numbers allowed between the two values is
+     * {@code maxUlps - 1}.
+     *
+     * @param a Real part.
+     * @param b Imaginary part.
+     * @param operation the operation
+     * @param x Expected real part.
+     * @param y Expected imaginary part.
+     * @param maxUlps the maximum units of least precision between the two values
+     */
+    private static void assertComplex(double a, double b,
+            UnaryOperator<Complex> operation,
+            double x, double y, long maxUlps) {
+        final Complex c = Complex.ofCartesian(a, b);
+        final Complex z = operation.apply(c);
+        assertEquals(() -> c + ": real", x, z.getReal(), maxUlps);
+        assertEquals(() -> c + ": imaginary", y, z.getImaginary(), maxUlps);
+    }
+
+    /**
+     * Assert the operation on the complex numbers is equal to the expected value.
+     *
+     * <p>The results are considered equal if there are no floating-point values between them.
+     *
+     * @param a Real part of first number.
+     * @param b Imaginary part of first number.
+     * @param c Real part of second number.
+     * @param d Imaginary part of second number.
+     * @param operation the operation
+     * @param x Expected real part.
+     * @param y Expected imaginary part.
+     */
+    private static void assertComplex(double a, double b, double c, double d,
+            BiFunction<Complex, Complex, Complex> operation,
+            double x, double y) {
+        assertComplex(a, b, c, d, operation, x, y, 1);
+    }
+
+    /**
+     * Assert the operation on the complex numbers is equal to the expected value.
+     *
+     * <p>The results are considered equal within the provided units of least
+     * precision. The maximum count of numbers allowed between the two values is
+     * {@code maxUlps - 1}.
+     *
+     * @param a Real part of first number.
+     * @param b Imaginary part of first number.
+     * @param c Real part of second number.
+     * @param d Imaginary part of second number.
+     * @param operation the operation
+     * @param x Expected real part.
+     * @param y Expected imaginary part.
+     * @param maxUlps the maximum units of least precision between the two values
+     */
+    // CHECKSTYLE: stop ParameterNumberCheck
+    private static void assertComplex(double a, double b, double c, double d,
+            BiFunction<Complex, Complex, Complex> operation,
+            double x, double y, long maxUlps) {
+        final Complex c1 = Complex.ofCartesian(a, b);
+        final Complex c2 = Complex.ofCartesian(c, d);
+        final Complex z = operation.apply(c1, c2);
+        assertEquals(() -> c1 + " op " + c2 + ": real", x, z.getReal(), maxUlps);
+        assertEquals(() -> c1 + " op " + c2 + ": imaginary", y, z.getImaginary(), maxUlps);
+    }
+
     @Test
     public void testAcos() {
-        final Complex z1 = Complex.ofCartesian(2, 3).acos();
-        assertEquals("real", 1.0001435424737972, z1.getReal());
-        assertEquals("imaginary", -1.9833870299165355, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).acos();
-        assertEquals("real", 1.5707963267948966, z2.getReal());
-        assertEquals("imaginary", -0.69314718055994529, z2.getImaginary());
-        final Complex z3 = Complex.ofCartesian(0.75, 0).acos();
-        assertEquals("real", 0.72273424781341566, z3.getReal());
-        assertEquals("imaginary", -0, z3.getImaginary());
+//        assertComplex(-1e+308, 0.0, Complex::acos, nan, -inf);
+//        assertComplex(-1e+308, 0.5, Complex::acos, 0.78539816339744828, -inf);
+//        assertComplex(-1e+308, 1, Complex::acos, 0.78539816339744828, -inf);
+//        assertComplex(-1e+308, 2, Complex::acos, 0.78539816339744828, -inf);
+        assertComplex(-1e+308, 1e+308, Complex::acos, 0.78539816339744828, -inf);
+        assertComplex(-2, 0.0, Complex::acos, 3.1415926535897931, -1.3169578969248164);
+        assertComplex(-2, 0.5, Complex::acos, 2.8638383970320791, -1.3618009008578467, 3);
+        assertComplex(-2, 1, Complex::acos, 2.6342363503726487, -1.4693517443681854);
+        assertComplex(-2, 2, Complex::acos, 2.3250454714929427, -1.7343245214879679);
+        assertComplex(-2, 1e+308, Complex::acos, 0.78539816339744828, -inf);
+        assertComplex(-1, 0.0, Complex::acos, 3.1415926535897931, -0.0);
+        assertComplex(-1, 0.5, Complex::acos, 2.4667038080037869, -0.73285767597364526);
+        assertComplex(-1, 1, Complex::acos, 2.2370357592874122, -1.0612750619050364, 4);
+        assertComplex(-1, 2, Complex::acos, 1.997874913187373, -1.5285709194809995, 9);
+        assertComplex(-1, 1e+308, Complex::acos, 0.78539816339744828, -inf);
+        assertComplex(-0.5, 0.0, Complex::acos, 2.0943951023931953, -1.1102230246251565e-16);
+        assertComplex(-0.5, 0.5, Complex::acos, 2.023074773946087, -0.53063753095251776);
+        assertComplex(-0.5, 1, Complex::acos, 1.9202353896521094, -0.92613303135018232, 2);
+        assertComplex(-0.5, 2, Complex::acos, 1.7918149624177808, -1.4657153519472903, 2);
+        assertComplex(-0.5, 1e+308, Complex::acos, 1.5707963267948966, -inf);
+        assertComplex(-0.0, 0.0, Complex::acos, 1.5707963267948966, -0.0);
+        assertComplex(-0.0, 0.5, Complex::acos, 1.5707963267948966, -0.48121182505960336);
+        assertComplex(-0.0, 1, Complex::acos, 1.5707963267948963, -0.88137358701954283);
+        assertComplex(-0.0, 2, Complex::acos, 1.5707963267948959, -1.4436354751788099, 3);
+        assertComplex(-0.0, 1e+308, Complex::acos, 1.5707963267948966, -inf);
+        assertComplex(0.0, 0.0, Complex::acos, 1.5707963267948966, -0.0);
+        assertComplex(0.0, 0.5, Complex::acos, 1.5707963267948966, -0.48121182505960347, 2);
+        assertComplex(0.0, 1, Complex::acos, 1.5707963267948966, -0.88137358701954294);
+        assertComplex(0.0, 2, Complex::acos, 1.5707963267948966, -1.4436354751788103, 2);
+        assertComplex(0.0, 1e+308, Complex::acos, 1.5707963267948966, -inf);
+        assertComplex(0.5, 0.0, Complex::acos, 1.0471975511965976, -1.1102230246251565e-16);
+        assertComplex(0.5, 0.5, Complex::acos, 1.1185178796437059, -0.53063753095251787);
+        assertComplex(0.5, 1, Complex::acos, 1.2213572639376833, -0.92613303135018255, 2);
+        assertComplex(0.5, 2, Complex::acos, 1.3497776911720127, -1.4657153519472905);
+        assertComplex(0.5, 1e+308, Complex::acos, 1.5707963267948966, -inf);
+        assertComplex(1, 0.0, Complex::acos, 0.0, -0.0);
+        assertComplex(1, 0.5, Complex::acos, 0.67488884558600637, -0.73285767597364526);
+        assertComplex(1, 1, Complex::acos, 0.90455689430238129, -1.0612750619050355);
+        assertComplex(1, 2, Complex::acos, 1.1437177404024204, -1.528570919480998, 2);
+//        assertComplex(1, 1e+308, Complex::acos, 0.78539816339744828, -inf);
+        assertComplex(2, 0.0, Complex::acos, 0.0, -1.3169578969248166);
+        assertComplex(2, 0.5, Complex::acos, 0.27775425655771396, -1.3618009008578458);
+        assertComplex(2, 1, Complex::acos, 0.50735630321714453, -1.4693517443681852);
+        assertComplex(2, 2, Complex::acos, 0.8165471820968504, -1.7343245214879663, 7);
+//        assertComplex(2, 1e+308, Complex::acos, 0.78539816339744828, -inf);
+//        assertComplex(1e+308, 0.0, Complex::acos, nan, -inf);
+//        assertComplex(1e+308, 0.5, Complex::acos, 0.78539816339744828, -inf);
+//        assertComplex(1e+308, 1, Complex::acos, 0.78539816339744828, -inf);
+//        assertComplex(1e+308, 2, Complex::acos, 0.78539816339744828, -inf);
+//        assertComplex(1e+308, 1e+308, Complex::acos, 0.78539816339744828, -inf);
     }
 
     @Test
     public void testAcosh() {
-        final Complex z1 = Complex.ofCartesian(2, 3).acosh();
-        assertEquals("real", 1.9833870299165355, z1.getReal());
-        assertEquals("imaginary", 1.0001435424737972, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).acosh();
-        assertEquals("real", 0.69314718055994529, z2.getReal());
-        assertEquals("imaginary", 1.5707963267948966, z2.getImaginary());
-        final Complex z3 = Complex.ofCartesian(0.75, 0).acosh();
-        assertEquals("real", 0, z3.getReal());
-        // TODO: Fix this test. The sign is currently incorrect.
-        //assertEquals("imaginary", 0.72273424781341566, z3.getImaginary());
+//        assertComplex(-1e+308, 0.0, Complex::acosh, inf, nan);
+//        assertComplex(-1e+308, 0.5, Complex::acosh, inf, 0.78539816339744828);
+//        assertComplex(-1e+308, 1, Complex::acosh, inf, 0.78539816339744828);
+//        assertComplex(-1e+308, 2, Complex::acosh, inf, 0.78539816339744828);
+        assertComplex(-1e+308, 1e+308, Complex::acosh, inf, 0.78539816339744828);
+        assertComplex(-2, 0.0, Complex::acosh, 1.3169578969248164, 3.1415926535897931);
+        assertComplex(-2, 0.5, Complex::acosh, 1.3618009008578467, 2.8638383970320791, 3);
+        assertComplex(-2, 1, Complex::acosh, 1.4693517443681854, 2.6342363503726487);
+        assertComplex(-2, 2, Complex::acosh, 1.7343245214879679, 2.3250454714929427);
+        assertComplex(-2, 1e+308, Complex::acosh, inf, 0.78539816339744828);
+        assertComplex(-1, 0.0, Complex::acosh, 0.0, 3.1415926535897931);
+        assertComplex(-1, 0.5, Complex::acosh, 0.73285767597364526, 2.4667038080037869);
+        assertComplex(-1, 1, Complex::acosh, 1.0612750619050364, 2.2370357592874122, 4);
+        assertComplex(-1, 2, Complex::acosh, 1.5285709194809995, 1.997874913187373, 9);
+        assertComplex(-1, 1e+308, Complex::acosh, inf, 0.78539816339744828);
+        assertComplex(-0.5, 0.0, Complex::acosh, 1.1102230246251565e-16, 2.0943951023931953);
+        assertComplex(-0.5, 0.5, Complex::acosh, 0.53063753095251776, 2.023074773946087);
+        assertComplex(-0.5, 1, Complex::acosh, 0.92613303135018232, 1.9202353896521094, 2);
+        assertComplex(-0.5, 2, Complex::acosh, 1.4657153519472903, 1.7918149624177808, 2);
+        assertComplex(-0.5, 1e+308, Complex::acosh, inf, 1.5707963267948966);
+        assertComplex(-0.0, 0.0, Complex::acosh, 0.0, 1.5707963267948966);
+        assertComplex(-0.0, 0.5, Complex::acosh, 0.48121182505960336, 1.5707963267948966);
+        assertComplex(-0.0, 1, Complex::acosh, 0.88137358701954283, 1.5707963267948963);
+        assertComplex(-0.0, 2, Complex::acosh, 1.4436354751788099, 1.5707963267948959, 3);
+        assertComplex(-0.0, 1e+308, Complex::acosh, inf, 1.5707963267948966);
+        assertComplex(0.0, 0.0, Complex::acosh, 0.0, 1.5707963267948966);
+        assertComplex(0.0, 0.5, Complex::acosh, 0.48121182505960347, 1.5707963267948966, 2);
+        assertComplex(0.0, 1, Complex::acosh, 0.88137358701954294, 1.5707963267948966);
+        assertComplex(0.0, 2, Complex::acosh, 1.4436354751788103, 1.5707963267948966, 2);
+        assertComplex(0.0, 1e+308, Complex::acosh, inf, 1.5707963267948966);
+        assertComplex(0.5, 0.0, Complex::acosh, 1.1102230246251565e-16, 1.0471975511965976);
+        assertComplex(0.5, 0.5, Complex::acosh, 0.53063753095251787, 1.1185178796437059);
+        assertComplex(0.5, 1, Complex::acosh, 0.92613303135018255, 1.2213572639376833, 2);
+        assertComplex(0.5, 2, Complex::acosh, 1.4657153519472905, 1.3497776911720127);
+        assertComplex(0.5, 1e+308, Complex::acosh, inf, 1.5707963267948966);
+        assertComplex(1, 0.0, Complex::acosh, 0.0, 0.0);
+        assertComplex(1, 0.5, Complex::acosh, 0.73285767597364526, 0.67488884558600637);
+        assertComplex(1, 1, Complex::acosh, 1.0612750619050355, 0.90455689430238129);
+        assertComplex(1, 2, Complex::acosh, 1.528570919480998, 1.1437177404024204, 2);
+//        assertComplex(1, 1e+308, Complex::acosh, inf, 0.78539816339744828);
+        assertComplex(2, 0.0, Complex::acosh, 1.3169578969248166, 0.0);
+        assertComplex(2, 0.5, Complex::acosh, 1.3618009008578458, 0.27775425655771396);
+        assertComplex(2, 1, Complex::acosh, 1.4693517443681852, 0.50735630321714453, 7);
+        assertComplex(2, 2, Complex::acosh, 1.7343245214879663, 0.8165471820968504, 7);
+//        assertComplex(1e+308, 0.0, Complex::acosh, inf, nan);
+//        assertComplex(1e+308, 0.5, Complex::acosh, inf, 0.78539816339744828);
+//        assertComplex(1e+308, 1, Complex::acosh, inf, 0.78539816339744828);
+//        assertComplex(1e+308, 2, Complex::acosh, inf, 0.78539816339744828);
+//        assertComplex(1e+308, 1e+308, Complex::acosh, inf, 0.78539816339744828);
     }
 
     @Test
     public void testAsinh() {
-        final Complex z1 = Complex.ofCartesian(2, 3).asinh();
-        assertEquals("real", 1.9686379257930964, z1.getReal());
-        assertEquals("imaginary", 0.96465850440760281, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).asinh();
-        assertEquals("real", 0, z2.getReal());
-        assertEquals("imaginary", 0.848062078981481, z2.getImaginary());
-        final Complex z3 = Complex.ofCartesian(0.75, 0).asinh();
-        assertEquals("real", 0.69314718055994529, z3.getReal());
-        assertEquals("imaginary", 0, z3.getImaginary());
+//        assertComplex(-1e+308, 0.0, Complex::asinh, -inf, nan);
+//        assertComplex(-1e+308, 0.5, Complex::asinh, -inf, 0.78539816339744828);
+//        assertComplex(-1e+308, 1, Complex::asinh, -inf, 0.78539816339744828);
+//        assertComplex(-1e+308, 2, Complex::asinh, -inf, 0.78539816339744828);
+        assertComplex(-1e+308, 1e+308, Complex::asinh, -inf, 0.78539816339744828);
+        assertComplex(-2, 0.0, Complex::asinh, -1.4436354751788099, 0.0, 2);
+        assertComplex(-2, 0.5, Complex::asinh, -1.4657153519472903, 0.22101863562288368, 6);
+        assertComplex(-2, 1, Complex::asinh, -1.5285709194809995, 0.42707858639247681, 12);
+        assertComplex(-2, 2, Complex::asinh, -1.7343245214879652, 0.75424914469804549, 6);
+        assertComplex(-2, 1e+308, Complex::asinh, -inf, 0.78539816339744828);
+        assertComplex(-1, 0.0, Complex::asinh, -0.88137358701954283, 0.0);
+        assertComplex(-1, 0.5, Complex::asinh, -0.92613303135018232, 0.34943906285721327, 2);
+        assertComplex(-1, 1, Complex::asinh, -1.0612750619050355, 0.66623943249251527);
+        assertComplex(-1, 2, Complex::asinh, -1.4693517443681841, 1.0634400235777519, 5);
+        assertComplex(-1, 1e+308, Complex::asinh, -inf, 0.78539816339744828);
+        assertComplex(-0.5, 0.0, Complex::asinh, -0.48121182505960336, 0.0, 2);
+        assertComplex(-0.5, 0.5, Complex::asinh, -0.53063753095251776, 0.4522784471511907);
+        assertComplex(-0.5, 1, Complex::asinh, -0.73285767597364526, 0.89590748120889041, 2);
+        assertComplex(-0.5, 2, Complex::asinh, -1.3618009008578469, 1.2930420702371832, 5);
+        assertComplex(-0.5, 1e+308, Complex::asinh, -inf, 1.5707963267948966);
+        assertComplex(-0.0, 0.0, Complex::asinh, -0.0, 0.0);
+        assertComplex(-0.0, 0.5, Complex::asinh, -1.1102230246251565e-16, 0.52359877559829893);
+        assertComplex(-0.0, 1, Complex::asinh, -0.0, 1.5707963267948966);
+        assertComplex(-0.0, 2, Complex::asinh, -1.3169578969248164, 1.5707963267948961, 2);
+        assertComplex(-0.0, 1e+308, Complex::asinh, -inf, 1.5707963267948966);
+        assertComplex(0.0, 0.0, Complex::asinh, 0.0, 0.0);
+        assertComplex(0.0, 0.5, Complex::asinh, 1.1102230246251565e-16, 0.52359877559829893);
+        assertComplex(0.0, 1, Complex::asinh, 0.0, 1.5707963267948966);
+        assertComplex(0.0, 2, Complex::asinh, 1.3169578969248166, 1.5707963267948966);
+        assertComplex(0.0, 1e+308, Complex::asinh, inf, 1.5707963267948966);
+        assertComplex(0.5, 0.0, Complex::asinh, 0.48121182505960347, 0.0);
+        assertComplex(0.5, 0.5, Complex::asinh, 0.53063753095251787, 0.45227844715119064);
+        assertComplex(0.5, 1, Complex::asinh, 0.73285767597364526, 0.8959074812088903);
+        assertComplex(0.5, 2, Complex::asinh, 1.3618009008578458, 1.2930420702371828);
+        assertComplex(0.5, 1e+308, Complex::asinh, inf, 1.5707963267948966);
+        assertComplex(1, 0.0, Complex::asinh, 0.88137358701954294, 0.0);
+        assertComplex(1, 0.5, Complex::asinh, 0.92613303135018255, 0.34943906285721327);
+        assertComplex(1, 1, Complex::asinh, 1.0612750619050357, 0.66623943249251527);
+        assertComplex(1, 2, Complex::asinh, 1.4693517443681852, 1.0634400235777519);
+        assertComplex(1, 1e+308, Complex::asinh, inf, 0.78539816339744828);
+        assertComplex(2, 0.0, Complex::asinh, 1.4436354751788103, 0.0);
+        assertComplex(2, 0.5, Complex::asinh, 1.4657153519472905, 0.22101863562288387);
+        assertComplex(2, 1, Complex::asinh, 1.528570919480998, 0.42707858639247614);
+        assertComplex(2, 2, Complex::asinh, 1.7343245214879663, 0.75424914469804605);
+        assertComplex(2, 1e+308, Complex::asinh, inf, 0.78539816339744828);
+//        assertComplex(1e+308, 0.0, Complex::asinh, inf, nan);
+//        assertComplex(1e+308, 0.5, Complex::asinh, inf, 0.78539816339744828);
+//        assertComplex(1e+308, 1, Complex::asinh, inf, 0.78539816339744828);
+//        assertComplex(1e+308, 2, Complex::asinh, inf, 0.78539816339744828);
+        assertComplex(1e+308, 1e+308, Complex::asinh, inf, 0.78539816339744828);
     }
 
     @Test
     public void testAtanh() {
-        final Complex z1 = Complex.ofCartesian(2, 3).atanh();
-        assertEquals("real", 0.14694666622552977, z1.getReal());
-        assertEquals("imaginary", 1.3389725222944935, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).atanh();
-        assertEquals("real", 0, z2.getReal());
-        assertEquals("imaginary", 0.64350110879328437, z2.getImaginary());
-        final Complex z3 = Complex.ofCartesian(0.75, 0).atanh();
-        assertEquals("real", 0.97295507452765662, z3.getReal());
-        assertEquals("imaginary", 0, z3.getImaginary());
+        assertComplex(-1e+308, 0.0, Complex::atanh, -0.0, 1.5707963267948966);
+        assertComplex(-1e+308, 0.5, Complex::atanh, -0.0, 1.5707963267948966);
+        assertComplex(-1e+308, 1, Complex::atanh, -0.0, 1.5707963267948966);
+        assertComplex(-1e+308, 2, Complex::atanh, -0.0, 1.5707963267948966);
+        assertComplex(-1e+308, 1e+308, Complex::atanh, -inf, 1.5707963267948966);
+        assertComplex(-2, 0.0, Complex::atanh, -0.54930614433405489, 1.5707963267948966);
+        assertComplex(-2, 0.5, Complex::atanh, -0.50037000005253107, 1.4215468610018069);
+        assertComplex(-2, 1, Complex::atanh, -0.40235947810852507, 1.3389725222944935);
+        assertComplex(-2, 2, Complex::atanh, -0.23887786125685917, 1.311223269671635, 4);
+        assertComplex(-2, 1e+308, Complex::atanh, -0.0, 1.5707963267948966);
+        assertComplex(-1, 0.0, Complex::atanh, -inf, 0.0);
+        assertComplex(-1, 0.5, Complex::atanh, -0.70830333601405404, 0.90788749496088039);
+        assertComplex(-1, 1, Complex::atanh, -0.40235947810852507, 1.0172219678978514);
+        assertComplex(-1, 2, Complex::atanh, -0.17328679513998629, 1.1780972450961724, 2);
+        assertComplex(-1, 1e+308, Complex::atanh, -0.0, 1.5707963267948966);
+        assertComplex(-0.5, 0.0, Complex::atanh, -0.54930614433405489, 0.0);
+        assertComplex(-0.5, 0.5, Complex::atanh, -0.40235947810852507, 0.5535743588970452);
+        assertComplex(-0.5, 1, Complex::atanh, -0.23887786125685906, 0.84757566067082901, 2);
+        assertComplex(-0.5, 2, Complex::atanh, -0.096415620202996155, 1.1265564408348223, 3);
+        assertComplex(-0.5, 1e+308, Complex::atanh, -0.0, 1.5707963267948966);
+        assertComplex(-0.0, 0.0, Complex::atanh, -0.0, 0.0);
+        assertComplex(-0.0, 0.5, Complex::atanh, -0.0, 0.46364760900080615);
+        assertComplex(-0.0, 1, Complex::atanh, -0.0, 0.78539816339744828);
+        assertComplex(-0.0, 2, Complex::atanh, -0.0, 1.1071487177940904);
+        assertComplex(-0.0, 1e+308, Complex::atanh, -0.0, 1.5707963267948966);
+        assertComplex(0.0, 0.0, Complex::atanh, 0.0, 0.0);
+        assertComplex(0.0, 0.5, Complex::atanh, 0.0, 0.46364760900080615);
+        assertComplex(0.0, 1, Complex::atanh, 0.0, 0.78539816339744828);
+        assertComplex(0.0, 2, Complex::atanh, 0.0, 1.1071487177940904);
+        assertComplex(0.0, 1e+308, Complex::atanh, 0.0, 1.5707963267948966);
+        assertComplex(0.5, 0.0, Complex::atanh, 0.54930614433405489, 0.0);
+        assertComplex(0.5, 0.5, Complex::atanh, 0.40235947810852513, 0.5535743588970452);
+        assertComplex(0.5, 1, Complex::atanh, 0.23887786125685911, 0.84757566067082901);
+        assertComplex(0.5, 2, Complex::atanh, 0.096415620202996211, 1.1265564408348223, 7);
+        assertComplex(0.5, 1e+308, Complex::atanh, 0.0, 1.5707963267948966);
+        assertComplex(1, 0.0, Complex::atanh, inf, 0.0);
+        assertComplex(1, 0.5, Complex::atanh, 0.70830333601405404, 0.90788749496088039);
+        assertComplex(1, 1, Complex::atanh, 0.40235947810852513, 1.0172219678978514);
+        assertComplex(1, 2, Complex::atanh, 0.17328679513998635, 1.1780972450961724);
+        assertComplex(1, 1e+308, Complex::atanh, 0.0, 1.5707963267948966);
+        assertComplex(2, 0.0, Complex::atanh, 0.54930614433405489, 1.5707963267948966);
+        assertComplex(2, 0.5, Complex::atanh, 0.50037000005253096, 1.4215468610018069);
+        assertComplex(2, 1, Complex::atanh, 0.40235947810852513, 1.3389725222944935);
+        assertComplex(2, 2, Complex::atanh, 0.23887786125685906, 1.311223269671635);
+        assertComplex(2, 1e+308, Complex::atanh, 0.0, 1.5707963267948966);
+        assertComplex(1e+308, 0.0, Complex::atanh, 0.0, 1.5707963267948966);
+        assertComplex(1e+308, 0.5, Complex::atanh, 0.0, 1.5707963267948966);
+        assertComplex(1e+308, 1, Complex::atanh, 0.0, 1.5707963267948966);
+        assertComplex(1e+308, 2, Complex::atanh, 0.0, 1.5707963267948966);
+        assertComplex(1e+308, 1e+308, Complex::atanh, inf, 1.5707963267948966);
     }
 
     @Test
     public void testCosh() {
-        final Complex z1 = Complex.ofCartesian(2, 3).cosh();
-        assertEquals("real", -3.7245455049153224, z1.getReal());
-        assertEquals("imaginary", 0.51182256998738462, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).cosh();
-        assertEquals("real", 0.7316888688738209, z2.getReal());
-        assertEquals("imaginary", 0, z2.getImaginary());
-        final Complex z3 = Complex.ofCartesian(0.75, 0).cosh();
-        assertEquals("real", 1.2946832846768448, z3.getReal());
-        assertEquals("imaginary", 0, z3.getImaginary());
+        assertComplex(-1e+308, 0.0, Complex::cosh, inf, nan);
+        assertComplex(-1e+308, 0.5, Complex::cosh, inf, -inf);
+        assertComplex(-1e+308, 1, Complex::cosh, inf, -inf);
+        assertComplex(-1e+308, 2, Complex::cosh, -inf, -inf);
+        assertComplex(-1e+308, 1e+308, Complex::cosh, -inf, -inf);
+        assertComplex(-2, 0.0, Complex::cosh, 3.7621956910836314, -0.0);
+        assertComplex(-2, 0.5, Complex::cosh, 3.3016373329140944, -1.7388095044743164);
+        assertComplex(-2, 1, Complex::cosh, 2.0327230070196656, -3.0518977991517997);
+        assertComplex(-2, 2, Complex::cosh, -1.5656258353157435, -3.2978948363112366);
+        assertComplex(-2, 1e+308, Complex::cosh, -3.3532786447904863, -1.6444057804572179);
+        assertComplex(-1, 0.0, Complex::cosh, 1.5430806348152437, -0.0);
+        assertComplex(-1, 0.5, Complex::cosh, 1.3541806567045842, -0.5634214652309818);
+        assertComplex(-1, 1, Complex::cosh, 0.83373002513114913, -0.98889770576286506);
+        assertComplex(-1, 2, Complex::cosh, -0.64214812471551996, -1.0686074213827783);
+        assertComplex(-1, 1e+308, Complex::cosh, -1.375361561382608, -0.5328320968314485);
+        assertComplex(-0.5, 0.0, Complex::cosh, 1.1276259652063807, -0.0);
+        assertComplex(-0.5, 0.5, Complex::cosh, 0.9895848833999199, -0.24982639750046154);
+        assertComplex(-0.5, 1, Complex::cosh, 0.60925890915779424, -0.43848657989259532);
+        assertComplex(-0.5, 2, Complex::cosh, -0.46925797822905341, -0.473830620416407);
+        assertComplex(-0.5, 1e+308, Complex::cosh, -1.0050631011564148, -0.23626278272774978);
+        assertComplex(-0.0, 0.0, Complex::cosh, 1, 0.0);
+        assertComplex(-0.0, 0.5, Complex::cosh, 0.87758256189037276, -0.0);
+        assertComplex(-0.0, 1, Complex::cosh, 0.54030230586813977, -0.0);
+        assertComplex(-0.0, 2, Complex::cosh, -0.41614683654714241, -0.0);
+        assertComplex(-0.0, 1e+308, Complex::cosh, -0.89130893768703345, -0.0);
+        assertComplex(0.0, 0.0, Complex::cosh, 1, 0.0);
+        assertComplex(0.0, 0.5, Complex::cosh, 0.87758256189037276, 0.0);
+        assertComplex(0.0, 1, Complex::cosh, 0.54030230586813977, 0.0);
+        assertComplex(0.0, 2, Complex::cosh, -0.41614683654714241, 0.0);
+        assertComplex(0.0, 1e+308, Complex::cosh, -0.89130893768703345, 0.0);
+        assertComplex(0.5, 0.0, Complex::cosh, 1.1276259652063807, 0.0);
+        assertComplex(0.5, 0.5, Complex::cosh, 0.9895848833999199, 0.24982639750046154);
+        assertComplex(0.5, 1, Complex::cosh, 0.60925890915779424, 0.43848657989259532);
+        assertComplex(0.5, 2, Complex::cosh, -0.46925797822905341, 0.473830620416407);
+        assertComplex(0.5, 1e+308, Complex::cosh, -1.0050631011564148, 0.23626278272774978);
+        assertComplex(1, 0.0, Complex::cosh, 1.5430806348152437, 0.0);
+        assertComplex(1, 0.5, Complex::cosh, 1.3541806567045842, 0.5634214652309818);
+        assertComplex(1, 1, Complex::cosh, 0.83373002513114913, 0.98889770576286506);
+        assertComplex(1, 2, Complex::cosh, -0.64214812471551996, 1.0686074213827783);
+        assertComplex(1, 1e+308, Complex::cosh, -1.375361561382608, 0.5328320968314485);
+        assertComplex(2, 0.0, Complex::cosh, 3.7621956910836314, 0.0);
+        assertComplex(2, 0.5, Complex::cosh, 3.3016373329140944, 1.7388095044743164);
+        assertComplex(2, 1, Complex::cosh, 2.0327230070196656, 3.0518977991517997);
+        assertComplex(2, 2, Complex::cosh, -1.5656258353157435, 3.2978948363112366);
+        assertComplex(2, 1e+308, Complex::cosh, -3.3532786447904863, 1.6444057804572179);
+        assertComplex(1e+308, 0.0, Complex::cosh, inf, nan);
+        assertComplex(1e+308, 0.5, Complex::cosh, inf, inf);
+        assertComplex(1e+308, 1, Complex::cosh, inf, inf);
+        assertComplex(1e+308, 2, Complex::cosh, -inf, inf);
+        assertComplex(1e+308, 1e+308, Complex::cosh, -inf, inf);
     }
 
     @Test
     public void testSinh() {
-        final Complex z1 = Complex.ofCartesian(2, 3).sinh();
-        assertEquals("real", -3.5905645899857799, z1.getReal());
-        assertEquals("imaginary", 0.53092108624851975, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).sinh();
-        assertEquals("real", 0, z2.getReal());
-        assertEquals("imaginary", 0.68163876002333412, z2.getImaginary());
-        final Complex z3 = Complex.ofCartesian(0.75, 0).sinh();
-        assertEquals("real", 0.82231673193582999, z3.getReal());
-        assertEquals("imaginary", 0, z3.getImaginary());
+        assertComplex(-1e+308, 0.0, Complex::sinh, -inf, nan);
+        assertComplex(-1e+308, 0.5, Complex::sinh, -inf, inf);
+        assertComplex(-1e+308, 1, Complex::sinh, -inf, inf);
+        assertComplex(-1e+308, 2, Complex::sinh, inf, inf);
+        assertComplex(-1e+308, 1e+308, Complex::sinh, inf, inf);
+        assertComplex(-2, 0.0, Complex::sinh, -3.6268604078470186, 0.0);
+        assertComplex(-2, 0.5, Complex::sinh, -3.1828694483371489, 1.8036926955321817);
+        assertComplex(-2, 1, Complex::sinh, -1.9596010414216061, 3.1657785132161682);
+        assertComplex(-2, 2, Complex::sinh, 1.5093064853236156, 3.4209548611170133);
+        assertComplex(-2, 1e+308, Complex::sinh, 3.2326530972572871, 1.7057663229177449);
+        assertComplex(-1, 0.0, Complex::sinh, -1.1752011936438014, 0.0);
+        assertComplex(-1, 0.5, Complex::sinh, -1.0313360742545512, 0.73979226445601376);
+        assertComplex(-1, 1, Complex::sinh, -0.63496391478473613, 1.2984575814159773);
+        assertComplex(-1, 2, Complex::sinh, 0.48905625904129368, 1.4031192506220405);
+        assertComplex(-1, 1e+308, Complex::sinh, 1.0474673274751902, 0.69962734438628826);
+        assertComplex(-0.5, 0.0, Complex::sinh, -0.52109530549374738, 0.0);
+        assertComplex(-0.5, 0.5, Complex::sinh, -0.45730415318424927, 0.54061268571315335);
+        assertComplex(-0.5, 1, Complex::sinh, -0.28154899513533443, 0.94886453143716798);
+        assertComplex(-0.5, 2, Complex::sinh, 0.21685216292078974, 1.0253473885839877);
+        assertComplex(-0.5, 1e+308, Complex::sinh, 0.46445690317333216, 0.51126165522310774);
+        assertComplex(-0.0, 0.0, Complex::sinh, -0.0, 0.0);
+        assertComplex(-0.0, 0.5, Complex::sinh, -0.0, 0.47942553860420301);
+        assertComplex(-0.0, 1, Complex::sinh, -0.0, 0.8414709848078965);
+        assertComplex(-0.0, 2, Complex::sinh, 0.0, 0.90929742682568171);
+        assertComplex(-0.0, 1e+308, Complex::sinh, 0.0, 0.4533964905016491);
+        assertComplex(0.0, 0.0, Complex::sinh, 0.0, 0.0);
+        assertComplex(0.0, 0.5, Complex::sinh, 0.0, 0.47942553860420301);
+        assertComplex(0.0, 1, Complex::sinh, 0.0, 0.8414709848078965);
+        assertComplex(0.0, 2, Complex::sinh, -0.0, 0.90929742682568171);
+        assertComplex(0.0, 1e+308, Complex::sinh, -0.0, 0.4533964905016491);
+        assertComplex(0.5, 0.0, Complex::sinh, 0.52109530549374738, 0.0);
+        assertComplex(0.5, 0.5, Complex::sinh, 0.45730415318424927, 0.54061268571315335);
+        assertComplex(0.5, 1, Complex::sinh, 0.28154899513533443, 0.94886453143716798);
+        assertComplex(0.5, 2, Complex::sinh, -0.21685216292078974, 1.0253473885839877);
+        assertComplex(0.5, 1e+308, Complex::sinh, -0.46445690317333216, 0.51126165522310774);
+        assertComplex(1, 0.0, Complex::sinh, 1.1752011936438014, 0.0);
+        assertComplex(1, 0.5, Complex::sinh, 1.0313360742545512, 0.73979226445601376);
+        assertComplex(1, 1, Complex::sinh, 0.63496391478473613, 1.2984575814159773);
+        assertComplex(1, 2, Complex::sinh, -0.48905625904129368, 1.4031192506220405);
+        assertComplex(1, 1e+308, Complex::sinh, -1.0474673274751902, 0.69962734438628826);
+        assertComplex(2, 0.0, Complex::sinh, 3.6268604078470186, 0.0);
+        assertComplex(2, 0.5, Complex::sinh, 3.1828694483371489, 1.8036926955321817);
+        assertComplex(2, 1, Complex::sinh, 1.9596010414216061, 3.1657785132161682);
+        assertComplex(2, 2, Complex::sinh, -1.5093064853236156, 3.4209548611170133);
+        assertComplex(2, 1e+308, Complex::sinh, -3.2326530972572871, 1.7057663229177449);
+        assertComplex(1e+308, 0.0, Complex::sinh, inf, nan);
+        assertComplex(1e+308, 0.5, Complex::sinh, inf, inf);
+        assertComplex(1e+308, 1, Complex::sinh, inf, inf);
+        assertComplex(1e+308, 2, Complex::sinh, -inf, inf);
+        assertComplex(1e+308, 1e+308, Complex::sinh, -inf, inf);
     }
 
     @Test
     public void testTanh() {
-        final Complex z1 = Complex.ofCartesian(2, 3).tanh();
-        assertEquals("real", 0.96538587902213302, z1.getReal());
-        assertEquals("imaginary", -0.0098843750383224918, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).tanh();
-        assertEquals("real", 0, z2.getReal());
-        assertEquals("imaginary", 0.93159645994407225, z2.getImaginary(), 3);
-        final Complex z3 = Complex.ofCartesian(0.75, 0).tanh();
-        assertEquals("real", 0.63514895238728741, z3.getReal());
-        assertEquals("imaginary", 0, z3.getImaginary());
+//        assertComplex(-1e+308, 0.0, Complex::tanh, -1, -0.0);
+//        assertComplex(-1e+308, 0.5, Complex::tanh, -1, 0.0);
+//        assertComplex(-1e+308, 1, Complex::tanh, -1, 0.0);
+//        assertComplex(-1e+308, 2, Complex::tanh, -1, 0.0);
+//        assertComplex(-1e+308, 1e+308, Complex::tanh, nan, nan);
+        assertComplex(-2, 0.0, Complex::tanh, -0.9640275800758169, 0.0);
+        assertComplex(-2, 0.5, Complex::tanh, -0.97994084996173814, 0.030215987322877575);
+        assertComplex(-2, 1, Complex::tanh, -1.0147936161466335, 0.033812826079896691);
+        assertComplex(-2, 2, Complex::tanh, -1.0238355945704727, -0.028392952868232287);
+        assertComplex(-2, 1e+308, Complex::tanh, nan, nan);
+        assertComplex(-1, 0.0, Complex::tanh, -0.76159415595576485, 0.0);
+        assertComplex(-1, 0.5, Complex::tanh, -0.84296620484578311, 0.19557731006593398);
+        assertComplex(-1, 1, Complex::tanh, -1.0839233273386946, 0.27175258531951174);
+        assertComplex(-1, 2, Complex::tanh, -1.1667362572409199, -0.24345820118572523);
+        assertComplex(-1, 1e+308, Complex::tanh, nan, nan);
+        assertComplex(-0.5, 0.0, Complex::tanh, -0.46211715726000974, 0.0);
+        assertComplex(-0.5, 0.5, Complex::tanh, -0.56408314126749848, 0.40389645531602575, 2);
+        assertComplex(-0.5, 1, Complex::tanh, -1.042830728344361, 0.80687741216308495);
+        assertComplex(-0.5, 2, Complex::tanh, -1.3212865837711918, -0.85087812114493777, 2);
+        assertComplex(-0.5, 1e+308, Complex::tanh, nan, nan);
+        assertComplex(-0.0, 0.0, Complex::tanh, -0.0, 0.0);
+        assertComplex(-0.0, 0.5, Complex::tanh, -0.0, 0.54630248984379048);
+        assertComplex(-0.0, 1, Complex::tanh, -0.0, 1.5574077246549021);
+        assertComplex(-0.0, 2, Complex::tanh, -0.0, -2.1850398632615189);
+        assertComplex(-0.0, 1e+308, Complex::tanh, nan, nan);
+        assertComplex(0.0, 0.0, Complex::tanh, 0.0, 0.0);
+        assertComplex(0.0, 0.5, Complex::tanh, 0.0, 0.54630248984379048);
+        assertComplex(0.0, 1, Complex::tanh, 0.0, 1.5574077246549021);
+        assertComplex(0.0, 2, Complex::tanh, 0.0, -2.1850398632615189);
+        assertComplex(0.0, 1e+308, Complex::tanh, nan, nan);
+        assertComplex(0.5, 0.0, Complex::tanh, 0.46211715726000974, 0.0);
+        assertComplex(0.5, 0.5, Complex::tanh, 0.56408314126749848, 0.40389645531602575, 2);
+        assertComplex(0.5, 1, Complex::tanh, 1.042830728344361, 0.80687741216308495);
+        assertComplex(0.5, 2, Complex::tanh, 1.3212865837711918, -0.85087812114493777, 2);
+        assertComplex(0.5, 1e+308, Complex::tanh, nan, nan);
+        assertComplex(1, 0.0, Complex::tanh, 0.76159415595576485, 0.0);
+        assertComplex(1, 0.5, Complex::tanh, 0.84296620484578311, 0.19557731006593398);
+        assertComplex(1, 1, Complex::tanh, 1.0839233273386946, 0.27175258531951174);
+        assertComplex(1, 2, Complex::tanh, 1.1667362572409199, -0.24345820118572523);
+        assertComplex(1, 1e+308, Complex::tanh, nan, nan);
+        assertComplex(2, 0.0, Complex::tanh, 0.9640275800758169, 0.0);
+        assertComplex(2, 0.5, Complex::tanh, 0.97994084996173814, 0.030215987322877575);
+        assertComplex(2, 1, Complex::tanh, 1.0147936161466335, 0.033812826079896691);
+        assertComplex(2, 2, Complex::tanh, 1.0238355945704727, -0.028392952868232287);
+        assertComplex(2, 1e+308, Complex::tanh, nan, nan);
+//        assertComplex(1e+308, 0.0, Complex::tanh, 1, -0.0);
+//        assertComplex(1e+308, 0.5, Complex::tanh, 1, 0.0);
+//        assertComplex(1e+308, 1, Complex::tanh, 1, 0.0);
+//        assertComplex(1e+308, 2, Complex::tanh, 1, 0.0);
+        assertComplex(1e+308, 1e+308, Complex::tanh, nan, nan);
     }
 
     @Test
     public void testExp() {
-        final Complex z1 = Complex.ofCartesian(2, 3).exp();
-        assertEquals("real", -7.3151100949011028, z1.getReal());
-        assertEquals("imaginary", 1.0427436562359045, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).exp();
-        assertEquals("real", 0.7316888688738209, z2.getReal());
-        assertEquals("imaginary", 0.68163876002333412, z2.getImaginary());
-        final Complex z3 = Complex.ofCartesian(0.75, 0).exp();
-        assertEquals("real", 2.1170000166126748, z3.getReal());
-        assertEquals("imaginary", 0, z3.getImaginary());
+        assertComplex(-1e+308, 0.0, Complex::exp, 0.0, 0.0);
+        assertComplex(-1e+308, 0.5, Complex::exp, 0.0, 0.0);
+        assertComplex(-1e+308, 1, Complex::exp, 0.0, 0.0);
+        assertComplex(-1e+308, 2, Complex::exp, -0.0, 0.0);
+        assertComplex(-1e+308, 1e+308, Complex::exp, -0.0, 0.0);
+        assertComplex(-2, 0.0, Complex::exp, 0.1353352832366127, 0.0);
+        assertComplex(-2, 0.5, Complex::exp, 0.11876788457694579, 0.064883191057865414);
+        assertComplex(-2, 1, Complex::exp, 0.073121965598059641, 0.1138807140643681);
+        assertComplex(-2, 2, Complex::exp, -0.056319349992127891, 0.12306002480577674);
+        assertComplex(-2, 1e+308, Complex::exp, -0.12062554753319905, 0.061360542460526864);
+        assertComplex(-1, 0.0, Complex::exp, 0.36787944117144233, 0.0);
+        assertComplex(-1, 0.5, Complex::exp, 0.32284458245003306, 0.17637079922503196);
+        assertComplex(-1, 1, Complex::exp, 0.19876611034641298, 0.30955987565311222);
+        assertComplex(-1, 2, Complex::exp, -0.15309186567422631, 0.33451182923926226);
+        assertComplex(-1, 1e+308, Complex::exp, -0.32789423390741779, 0.16679524755483982);
+        assertComplex(-0.5, 0.0, Complex::exp, 0.60653065971263342, 0.0);
+        assertComplex(-0.5, 0.5, Complex::exp, 0.53228073021567079, 0.29078628821269187);
+        assertComplex(-0.5, 1, Complex::exp, 0.32770991402245986, 0.51037795154457277);
+        assertComplex(-0.5, 2, Complex::exp, -0.25240581530826373, 0.55151676816758077);
+        assertComplex(-0.5, 1e+308, Complex::exp, -0.54060619798308285, 0.27499887249535798);
+        assertComplex(-0.0, 0.0, Complex::exp, 1, 0.0);
+        assertComplex(-0.0, 0.5, Complex::exp, 0.87758256189037276, 0.47942553860420301);
+        assertComplex(-0.0, 1, Complex::exp, 0.54030230586813977, 0.8414709848078965);
+        assertComplex(-0.0, 2, Complex::exp, -0.41614683654714241, 0.90929742682568171);
+        assertComplex(-0.0, 1e+308, Complex::exp, -0.89130893768703345, 0.4533964905016491);
+        assertComplex(0.0, 0.0, Complex::exp, 1, 0.0);
+        assertComplex(0.0, 0.5, Complex::exp, 0.87758256189037276, 0.47942553860420301);
+        assertComplex(0.0, 1, Complex::exp, 0.54030230586813977, 0.8414709848078965);
+        assertComplex(0.0, 2, Complex::exp, -0.41614683654714241, 0.90929742682568171);
+        assertComplex(0.0, 1e+308, Complex::exp, -0.89130893768703345, 0.4533964905016491);
+        assertComplex(0.5, 0.0, Complex::exp, 1.6487212707001282, 0.0);
+        assertComplex(0.5, 0.5, Complex::exp, 1.4468890365841693, 0.79043908321361489);
+        assertComplex(0.5, 1, Complex::exp, 0.89080790429312873, 1.3873511113297634);
+        assertComplex(0.5, 2, Complex::exp, -0.68611014114984314, 1.4991780090003948);
+        assertComplex(0.5, 1e+308, Complex::exp, -1.4695200043297472, 0.74752443795085755);
+        assertComplex(1, 0.0, Complex::exp, 2.7182818284590451, 0.0);
+        assertComplex(1, 0.5, Complex::exp, 2.3855167309591354, 1.3032137296869954);
+        assertComplex(1, 1, Complex::exp, 1.4686939399158851, 2.2873552871788423);
+        assertComplex(1, 2, Complex::exp, -1.1312043837568135, 2.4717266720048188);
+        assertComplex(1, 1e+308, Complex::exp, -2.4228288888577985, 1.2324594412177368);
+        assertComplex(2, 0.0, Complex::exp, 7.3890560989306504, 0.0);
+        assertComplex(2, 0.5, Complex::exp, 6.4845067812512438, 3.5425022000064983);
+        assertComplex(2, 1, Complex::exp, 3.9923240484412719, 6.2176763123679679);
+        assertComplex(2, 2, Complex::exp, -3.0749323206393591, 6.7188496974282499);
+        assertComplex(2, 1e+308, Complex::exp, -6.5859317420477739, 3.350172103374963);
+        assertComplex(1e+308, 0.0, Complex::exp, inf, 0);
+        assertComplex(1e+308, 0.5, Complex::exp, inf, inf);
+        assertComplex(1e+308, 1, Complex::exp, inf, inf);
+        assertComplex(1e+308, 2, Complex::exp, -inf, inf);
+        assertComplex(1e+308, 1e+308, Complex::exp, -inf, inf);
     }
 
     @Test
     public void testLog() {
-        final Complex z1 = Complex.ofCartesian(2, 3).log();
-        assertEquals("real", 1.2824746787307684, z1.getReal());
-        assertEquals("imaginary", 0.98279372324732905, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).log();
-        assertEquals("real", -0.2876820724517809, z2.getReal());
-        assertEquals("imaginary", 1.5707963267948966, z2.getImaginary());
-        final Complex z3 = Complex.ofCartesian(0.75, 0).log();
-        assertEquals("real", -0.2876820724517809, z3.getReal());
-        assertEquals("imaginary", 0, z3.getImaginary());
+        assertComplex(-1e+308, 0.0, Complex::log, 709.19620864216608, 3.1415926535897931);
+        assertComplex(-1e+308, 0.5, Complex::log, 709.19620864216608, 3.1415926535897931);
+        assertComplex(-1e+308, 1, Complex::log, 709.19620864216608, 3.1415926535897931);
+        assertComplex(-1e+308, 2, Complex::log, 709.19620864216608, 3.1415926535897931);
+        assertComplex(-1e+308, 1e+308, Complex::log, 709.54278223244603, 2.3561944901923448);
+        assertComplex(-2, 0.0, Complex::log, 0.69314718055994529, 3.1415926535897931);
+        assertComplex(-2, 0.5, Complex::log, 0.72345949146816269, 2.8966139904629289);
+        assertComplex(-2, 1, Complex::log, 0.80471895621705025, 2.677945044588987);
+        assertComplex(-2, 2, Complex::log, 1.0397207708399181, 2.3561944901923448);
+        assertComplex(-2, 1e+308, Complex::log, 709.19620864216608, 1.5707963267948966);
+        assertComplex(-1, 0.0, Complex::log, 0.0, 3.1415926535897931);
+        assertComplex(-1, 0.5, Complex::log, 0.11157177565710492, 2.677945044588987);
+        assertComplex(-1, 1, Complex::log, 0.3465735902799727, 2.3561944901923448);
+        assertComplex(-1, 2, Complex::log, 0.80471895621705025, 2.0344439357957027);
+        assertComplex(-1, 1e+308, Complex::log, 709.19620864216608, 1.5707963267948966);
+        assertComplex(-0.5, 0.0, Complex::log, -0.69314718055994529, 3.1415926535897931);
+        assertComplex(-0.5, 0.5, Complex::log, -0.34657359027997259, 2.3561944901923448);
+        assertComplex(-0.5, 1, Complex::log, 0.11157177565710492, 2.0344439357957027);
+        assertComplex(-0.5, 2, Complex::log, 0.72345949146816269, 1.8157749899217608);
+        assertComplex(-0.5, 1e+308, Complex::log, 709.19620864216608, 1.5707963267948966);
+        assertComplex(-0.0, 0.0, Complex::log, -inf, 3.1415926535897931);
+        assertComplex(-0.0, 0.5, Complex::log, -0.69314718055994529, 1.5707963267948966);
+        assertComplex(-0.0, 1, Complex::log, 0.0, 1.5707963267948966);
+        assertComplex(-0.0, 2, Complex::log, 0.69314718055994529, 1.5707963267948966);
+        assertComplex(-0.0, 1e+308, Complex::log, 709.19620864216608, 1.5707963267948966);
+        assertComplex(0.0, 0.0, Complex::log, -inf, 0.0);
+        assertComplex(0.0, 0.5, Complex::log, -0.69314718055994529, 1.5707963267948966);
+        assertComplex(0.0, 1, Complex::log, 0.0, 1.5707963267948966);
+        assertComplex(0.0, 2, Complex::log, 0.69314718055994529, 1.5707963267948966);
+        assertComplex(0.0, 1e+308, Complex::log, 709.19620864216608, 1.5707963267948966);
+        assertComplex(0.5, 0.0, Complex::log, -0.69314718055994529, 0.0);
+        assertComplex(0.5, 0.5, Complex::log, -0.34657359027997259, 0.78539816339744828);
+        assertComplex(0.5, 1, Complex::log, 0.11157177565710492, 1.1071487177940904);
+        assertComplex(0.5, 2, Complex::log, 0.72345949146816269, 1.3258176636680326);
+        assertComplex(0.5, 1e+308, Complex::log, 709.19620864216608, 1.5707963267948966);
+        assertComplex(1, 0.0, Complex::log, 0.0, 0.0);
+        assertComplex(1, 0.5, Complex::log, 0.11157177565710492, 0.46364760900080609);
+        assertComplex(1, 1, Complex::log, 0.3465735902799727, 0.78539816339744828);
+        assertComplex(1, 2, Complex::log, 0.80471895621705025, 1.1071487177940904);
+        assertComplex(1, 1e+308, Complex::log, 709.19620864216608, 1.5707963267948966);
+        assertComplex(2, 0.0, Complex::log, 0.69314718055994529, 0.0);
+        assertComplex(2, 0.5, Complex::log, 0.72345949146816269, 0.24497866312686414);
+        assertComplex(2, 1, Complex::log, 0.80471895621705025, 0.46364760900080609);
+        assertComplex(2, 2, Complex::log, 1.0397207708399181, 0.78539816339744828);
+        assertComplex(2, 1e+308, Complex::log, 709.19620864216608, 1.5707963267948966);
+        assertComplex(1e+308, 0.0, Complex::log, 709.19620864216608, 0.0);
+        assertComplex(1e+308, 0.5, Complex::log, 709.19620864216608, 4.9999999999999995e-309);
+        assertComplex(1e+308, 1, Complex::log, 709.19620864216608, 9.9999999999999991e-309);
+        assertComplex(1e+308, 2, Complex::log, 709.19620864216608, 1.9999999999999998e-308);
+        assertComplex(1e+308, 1e+308, Complex::log, 709.54278223244603, 0.78539816339744828);
     }
 
     @Test
     public void testSqrt() {
-        final Complex z1 = Complex.ofCartesian(2, 3).sqrt();
-        assertEquals("real", 1.6741492280355401, z1.getReal());
-        assertEquals("imaginary", 0.89597747612983814, z1.getImaginary());
-        final Complex z2 = Complex.ofCartesian(0, 0.75).sqrt();
-        assertEquals("real", 0.61237243569579447, z2.getReal());
-        assertEquals("imaginary", 0.61237243569579447, z2.getImaginary());
-        final Complex z3 = Complex.ofCartesian(0.75, 0).sqrt();
-        assertEquals("real", 0.8660254037844386, z3.getReal());
-        assertEquals("imaginary", 0, z3.getImaginary());
+        // ---
+        // The following reference 'real' values have been copied from the (1e308, x) cases.
+        // The C reference program used to compute these values does not compute
+        // mirrored values.
+        assertComplex(-1e+308, 0.0, Complex::sqrt, 0, 1e+154);
+        assertComplex(-1e+308, 0.5, Complex::sqrt, 2.4999999999999974e-155, 1e+154, 6);
+        assertComplex(-1e+308, 1, Complex::sqrt, 4.9999999999999999e-155, 1e+154);
+        assertComplex(-1e+308, 2, Complex::sqrt, 9.9999999999999997e-155, 1e+154);
+        assertComplex(-1e+308, 1e+308, Complex::sqrt, 4.5508986056222742e+153, 1.09868411346781e+154);
+        // ---
+        assertComplex(-2, 0.0, Complex::sqrt, 0, 1.4142135623730951);
+        assertComplex(-2, 0.5, Complex::sqrt, 0.17543205637629397, 1.425053124063947, 5);
+        assertComplex(-2, 1, Complex::sqrt, 0.3435607497225126, 1.4553466902253549, 3);
+        assertComplex(-2, 2, Complex::sqrt, 0.64359425290558281, 1.5537739740300374, 2);
+        assertComplex(-2, 1e+308, Complex::sqrt, 7.0710678118654767e+153, 7.0710678118654752e+153);
+        assertComplex(-1, 0.0, Complex::sqrt, 0, 1);
+        assertComplex(-1, 0.5, Complex::sqrt, 0.24293413587832291, 1.0290855136357462, 3);
+        assertComplex(-1, 1, Complex::sqrt, 0.45508986056222739, 1.0986841134678098);
+        assertComplex(-1, 2, Complex::sqrt, 0.78615137775742339, 1.2720196495140688);
+        assertComplex(-1, 1e+308, Complex::sqrt, 7.0710678118654767e+153, 7.0710678118654752e+153);
+        assertComplex(-0.5, 0.0, Complex::sqrt, 0, 0.70710678118654757);
+        assertComplex(-0.5, 0.5, Complex::sqrt, 0.3217971264527914, 0.77688698701501868, 2);
+        assertComplex(-0.5, 1, Complex::sqrt, 0.55589297025142126, 0.89945371997393353);
+        assertComplex(-0.5, 2, Complex::sqrt, 0.88361553087551337, 1.1317139242778693);
+        assertComplex(-0.5, 1e+308, Complex::sqrt, 7.0710678118654767e+153, 7.0710678118654752e+153);
+        assertComplex(-0.0, 0.0, Complex::sqrt, 0.0, 0.0);
+        assertComplex(-0.0, 0.5, Complex::sqrt, 0.50000000000000011, 0.5);
+        assertComplex(-0.0, 1, Complex::sqrt, 0.70710678118654757, 0.70710678118654746);
+        assertComplex(-0.0, 2, Complex::sqrt, 1.0000000000000002, 1);
+        assertComplex(-0.0, 1e+308, Complex::sqrt, 7.0710678118654767e+153, 7.0710678118654752e+153);
+        assertComplex(0.0, 0.0, Complex::sqrt, 0.0, 0.0);
+        assertComplex(0.0, 0.5, Complex::sqrt, 0.50000000000000011, 0.5);
+        assertComplex(0.0, 1, Complex::sqrt, 0.70710678118654757, 0.70710678118654746);
+        assertComplex(0.0, 2, Complex::sqrt, 1.0000000000000002, 1);
+        assertComplex(0.0, 1e+308, Complex::sqrt, 7.0710678118654767e+153, 7.0710678118654752e+153);
+        assertComplex(0.5, 0.0, Complex::sqrt, 0.70710678118654757, 0.0);
+        assertComplex(0.5, 0.5, Complex::sqrt, 0.77688698701501868, 0.32179712645279135);
+        assertComplex(0.5, 1, Complex::sqrt, 0.89945371997393364, 0.55589297025142115);
+        assertComplex(0.5, 2, Complex::sqrt, 1.1317139242778693, 0.88361553087551337);
+        assertComplex(0.5, 1e+308, Complex::sqrt, 7.0710678118654767e+153, 7.0710678118654752e+153);
+        assertComplex(1, 0.0, Complex::sqrt, 1, 0.0);
+        assertComplex(1, 0.5, Complex::sqrt, 1.0290855136357462, 0.24293413587832283);
+        assertComplex(1, 1, Complex::sqrt, 1.0986841134678098, 0.45508986056222733);
+        assertComplex(1, 2, Complex::sqrt, 1.272019649514069, 0.78615137775742328);
+        assertComplex(1, 1e+308, Complex::sqrt, 7.0710678118654767e+153, 7.0710678118654752e+153);
+        assertComplex(2, 0.0, Complex::sqrt, 1.4142135623730951, 0.0);
+        assertComplex(2, 0.5, Complex::sqrt, 1.425053124063947, 0.17543205637629383);
+        assertComplex(2, 1, Complex::sqrt, 1.4553466902253549, 0.34356074972251244);
+        assertComplex(2, 2, Complex::sqrt, 1.5537739740300374, 0.6435942529055827);
+        assertComplex(2, 1e+308, Complex::sqrt, 7.0710678118654767e+153, 7.0710678118654752e+153);
+        assertComplex(1e+308, 0.0, Complex::sqrt, 1e+154, 0.0);
+        assertComplex(1e+308, 0.5, Complex::sqrt, 1e+154, 2.4999999999999974e-155, 6);
+        assertComplex(1e+308, 1, Complex::sqrt, 1e+154, 4.9999999999999999e-155);
+        assertComplex(1e+308, 2, Complex::sqrt, 1e+154, 9.9999999999999997e-155);
+        assertComplex(1e+308, 1e+308, Complex::sqrt, 1.09868411346781e+154, 4.5508986056222734e+153);
     }
 
-
     @Test
     public void testMultiply() {
-        final Complex c1 = Complex.ofCartesian(2, 3);
-        final Complex c2 = Complex.ofCartesian(5, 4);
-        final Complex z1 = c1.multiply(c2);
-        assertEquals("real", -2, z1.getReal());
-        assertEquals("imaginary", 23, z1.getImaginary());
-        final Complex z2 = c1.conjugate().multiply(c2);
-        assertEquals("real", 22, z2.getReal());
-        assertEquals("imaginary", -7, z2.getImaginary());
-        final Complex z3 = c2.multiply(c1);
-        assertEquals("real", -2, z3.getReal());
-        assertEquals("imaginary", 23, z3.getImaginary());
-        final Complex z4 = c2.conjugate().multiply(c1);
-        assertEquals("real", 22, z4.getReal());
-        assertEquals("imaginary", 7, z4.getImaginary());
+        assertComplex(2, 3, 5, 4, Complex::multiply, -2, 23);
+        assertComplex(5, 4, 2, 3, Complex::multiply, -2, 23);
+        assertComplex(2, 3, -5, 4, Complex::multiply, -22, -7);
+        assertComplex(-5, 4, 2, 3, Complex::multiply, -22, -7);
+        assertComplex(2, 3, 5, -4, Complex::multiply, 22, 7);
+        assertComplex(5, -4, 2, 3, Complex::multiply, 22, 7);
+        assertComplex(2, 3, -5, -4, Complex::multiply, 2, -23);
+        assertComplex(-5, -4, 2, 3, Complex::multiply, 2, -23);
     }
 
     @Test
     public void testDivide() {
-        final Complex c1 = Complex.ofCartesian(2, 3);
-        final Complex c2 = Complex.ofCartesian(5, 4);
-        final Complex z1 = c1.divide(c2);
-        assertEquals("real", 0.53658536585365868, z1.getReal());
-        assertEquals("imaginary", 0.17073170731707318, z1.getImaginary());
-        final Complex z2 = c1.conjugate().divide(c2);
-        assertEquals("real", -0.048780487804878099, z2.getReal(), 7);
-        assertEquals("imaginary", -0.56097560975609762, z2.getImaginary());
-        final Complex z3 = c2.divide(c1);
-        assertEquals("real", 1.6923076923076923, z3.getReal());
-        assertEquals("imaginary", -0.53846153846153855, z3.getImaginary());
-        final Complex z4 = c2.conjugate().divide(c1);
-        assertEquals("real", -0.15384615384615394, z4.getReal(), 3);
-        assertEquals("imaginary", -1.7692307692307692, z4.getImaginary());
+        assertComplex(2, 3, 5, 4, Complex::divide, 0.53658536585365857, 0.17073170731707318);
+        assertComplex(5, 4, 2, 3, Complex::divide, 1.6923076923076923, -0.53846153846153844);
+        assertComplex(2, 3, -5, 4, Complex::divide, 0.04878048780487805, -0.56097560975609762);
+        assertComplex(-5, 4, 2, 3, Complex::divide, 0.15384615384615385, 1.7692307692307692);
+        assertComplex(2, 3, 5, -4, Complex::divide, -0.04878048780487805, 0.56097560975609762);
+        assertComplex(5, -4, 2, 3, Complex::divide, -0.15384615384615385, -1.7692307692307692);
+        assertComplex(2, 3, -5, -4, Complex::divide, -0.53658536585365857, -0.17073170731707318);
+        assertComplex(-5, -4, 2, 3, Complex::divide, -1.6923076923076923, 0.53846153846153844);
     }
 
     @Test
     public void testPowComplex() {
-        final Complex c1 = Complex.ofCartesian(2, 3);
-        final Complex c2 = Complex.ofCartesian(5, 4);
-        final Complex z1 = c1.pow(c2);
-        assertEquals("real", -9.7367145095888414, z1.getReal());
-        assertEquals("imaginary", -6.9377513609299868, z1.getImaginary());
-        final Complex z2 = c1.conjugate().pow(c2);
-        assertEquals("real", 30334.832969842264, z2.getReal());
-        assertEquals("imaginary", 6653.9414970320349, z2.getImaginary());
-        final Complex z3 = c2.pow(c1);
-        assertEquals("real", 4.3549103166315382, z3.getReal(), 2);
-        assertEquals("imaginary", 3.2198331430252156, z3.getImaginary(), 8);
-        final Complex z4 = c2.conjugate().pow(c1);
-        assertEquals("real", -146.48661898442663, z4.getReal(), 9);
-        assertEquals("imaginary", -273.63651239033993, z4.getImaginary(), 2);
-    }
-
-    @Test
-    public void testPowScalar() {
-        final Complex c1 = Complex.ofCartesian(2, 3);
-        final double d = 5;
-        final Complex z1 = c1.pow(d);
-        assertEquals("real", 122, z1.getReal());
-        assertEquals("imaginary", -597, z1.getImaginary());
-        final Complex z2 = c1.conjugate().pow(d);
-        assertEquals("real", 122, z2.getReal());
-        assertEquals("imaginary", 597, z2.getImaginary());
+        assertComplex(2, 3, 5, 4, Complex::pow, -9.7367145095888414, -6.9377513609299886, 2);
+        assertComplex(5, 4, 2, 3, Complex::pow, 4.354910316631539, 3.2198331430252156, 8);
+        assertComplex(2, 3, -5, 4, Complex::pow, 3.1452105198427317e-05, 6.8990150088148226e-06);
+        assertComplex(-5, 4, 2, 3, Complex::pow, -0.011821399482548253, -0.022082334539521097);
+        assertComplex(2, 3, 5, -4, Complex::pow, 30334.832969842264, -6653.9414970320349);
+        assertComplex(5, -4, 2, 3, Complex::pow, -146.48661898442663, -273.63651239033993, 9);
+        assertComplex(2, 3, -5, -4, Complex::pow, -0.068119398044204305, 0.048537465694561743, 2);
+        assertComplex(-5, -4, 2, 3, Complex::pow, 53964.514878760994, 39899.038308625939);
     }
 }