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/04 17:57:08 UTC

[commons-numbers] branch master updated (e163c0f -> 152c0eb)

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

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


    from e163c0f  Update coveralls config from 3.1.0 to 4.3.0.
     new 694e8d8  commons-rng 1.2 -> 1.3
     new 152c0eb  Complex: Increase ISO C99 compliance.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/commons/numbers/complex/Complex.java    | 579 +++++++++++---------
 .../commons/numbers/complex/CStandardTest.java     | 600 ++++++++++++++-------
 pom.xml                                            |   2 +-
 3 files changed, 740 insertions(+), 441 deletions(-)


[commons-numbers] 02/02: Complex: Increase ISO C99 compliance.

Posted by ah...@apache.org.
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 152c0eb8c715964e2f35091e374add68ea6bb887
Author: aherbert <ah...@apache.org>
AuthorDate: Wed Dec 4 17:52:47 2019 +0000

    Complex: Increase ISO C99 compliance.
    
    Explicit testing of the conjugate equalities. These are implemented for
    zero and +/- infinity for the imaginary part.
---
 .../apache/commons/numbers/complex/Complex.java    | 579 +++++++++++---------
 .../commons/numbers/complex/CStandardTest.java     | 600 ++++++++++++++-------
 2 files changed, 739 insertions(+), 440 deletions(-)

diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
index d218a6a..4ced624 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
@@ -882,34 +882,53 @@ public final class Complex implements Serializable  {
      * @return the inverse cosine of this complex number.
      */
     public Complex acos() {
-        if (real == 0 &&
-            Double.isNaN(imaginary)) {
-            return new Complex(PI_OVER_2, Double.NaN);
-        } else if (neitherInfiniteNorZeroNorNaN(real) &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(PI_OVER_2, Double.NEGATIVE_INFINITY);
-        } else if (real == Double.NEGATIVE_INFINITY &&
-                   imaginary == 1) {
-            return new Complex(Math.PI, Double.NEGATIVE_INFINITY);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   imaginary == 1) {
-            return new Complex(0, Double.NEGATIVE_INFINITY);
-        } else if (real == Double.NEGATIVE_INFINITY &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(PI_3_OVER_4, Double.NEGATIVE_INFINITY);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(PI_OVER_4, Double.NEGATIVE_INFINITY);
-        } else if (Double.isInfinite(real) &&
-                   Double.isNaN(imaginary)) {
+        if (Double.isFinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                // Special case for zero
+                if (real == 0 && imaginary == 0) {
+                    return new Complex(PI_OVER_2, Math.copySign(0, -imaginary));
+                }
+                // ISO C99: Preserve the equality
+                // acos(conj(z)) = conj(acos(z))
+                Complex z;
+                ComplexConstructor constructor;
+                if (negative(imaginary)) {
+                    z = conj();
+                    constructor = Complex::ofCartesianConjugate;
+                } else {
+                    z = this;
+                    constructor = Complex::ofCartesian;
+                }
+                return z.add(z.sqrt1z().multiplyByI()).log().multiplyByNegI(constructor);
+            }
+            if (Double.isInfinite(imaginary)) {
+                return new Complex(PI_OVER_2, Math.copySign(Double.POSITIVE_INFINITY, -imaginary));
+            }
+            // imaginary is NaN
+            // Special case for real == 0
+            return real == 0 ? new Complex(PI_OVER_2, Double.NaN) : NAN;
+        }
+        if (Double.isInfinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                final double re = real == Double.NEGATIVE_INFINITY ? Math.PI : 0;
+                return new Complex(re, Math.copySign(Double.POSITIVE_INFINITY, -imaginary));
+            }
+            if (Double.isInfinite(imaginary)) {
+                final double re = real == Double.NEGATIVE_INFINITY ? PI_3_OVER_4 : PI_OVER_4;
+                return new Complex(re, Math.copySign(Double.POSITIVE_INFINITY, -imaginary));
+            }
+            // imaginary is NaN
             // Swap real and imaginary
             return new Complex(Double.NaN, real);
-        } else if (Double.isNaN(real) &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(Double.NaN, Double.NEGATIVE_INFINITY);
         }
-        return add(sqrt1z().multiplyByI()).log().multiplyByNegI();
+        // real is NaN
+        if (Double.isInfinite(imaginary)) {
+            return new Complex(Double.NaN, -imaginary);
+        }
+        // optionally raises the ‘‘invalid’’ floating-point exception, for finite y.
+        return NAN;
     }
+
     /**
      * Compute the
      * <a href="http://mathworld.wolfram.com/InverseSine.html">
@@ -974,6 +993,16 @@ public final class Complex implements Serializable  {
     }
 
     /**
+     * Multiply the Complex by -I and create the result using the constructor.
+     *
+     * @param constructor Constructor
+     * @return the result (-iz)
+     */
+    private Complex multiplyByNegI(ComplexConstructor constructor) {
+        return constructor.create(imaginary, -real);
+    }
+
+    /**
      * Compute the
      * <a href="http://mathworld.wolfram.com/InverseHyperbolicSine.html">
      * inverse hyperbolic sine</a> of this complex number.
@@ -985,26 +1014,43 @@ public final class Complex implements Serializable  {
      * @return the inverse hyperbolic sine of this complex number
      */
     public Complex asinh() {
-        if (neitherInfiniteNorZeroNorNaN(real) &&
-            imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(Double.POSITIVE_INFINITY, PI_OVER_2);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   Double.isFinite(imaginary)) {
-            return new Complex(Double.POSITIVE_INFINITY, 0);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(Double.POSITIVE_INFINITY, PI_OVER_4);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   Double.isNaN(imaginary)) {
-            return new Complex(Double.POSITIVE_INFINITY,  Double.NaN);
-        } else if (Double.isNaN(real) &&
-                   imaginary == 0) {
-            return new Complex(Double.NaN, 0);
-        } else if (Double.isNaN(real) &&
-                   imaginary == Double.POSITIVE_INFINITY) {
+        if (Double.isFinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                // Special case for zero
+                if (real == 0 && imaginary == 0) {
+                    return this;
+                }
+                // ISO C99: Preserve the equality
+                // asinh(conj(z)) = conj(asinh(z))
+                final Complex z = negative(imaginary) ? conjugate() : this;
+                final Complex result = z.square().add(ONE).sqrt().add(z).log();
+                return z == this ? result : result.conjugate();
+            }
+            if (Double.isInfinite(imaginary)) {
+                return new Complex(Double.POSITIVE_INFINITY, Math.copySign(PI_OVER_2, imaginary));
+            }
+            // imaginary is NaN
+            return NAN;
+        }
+        if (Double.isInfinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                return new Complex(real, Math.copySign(0, imaginary));
+            }
+            if (Double.isInfinite(imaginary)) {
+                return new Complex(real, Math.copySign(PI_OVER_4, imaginary));
+            }
+            // imaginary is NaN
+            return new Complex(real, Double.NaN);
+        }
+        // real is NaN
+        if (imaginary == 0) {
+            return new Complex(Double.NaN, Math.copySign(0, imaginary));
+        }
+        if (Double.isInfinite(imaginary)) {
             return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
         }
-        return square().add(ONE).sqrt().add(this).log();
+        // optionally raises the ‘‘invalid’’ floating-point exception, for finite y.
+        return NAN;
     }
 
     /**
@@ -1019,29 +1065,44 @@ public final class Complex implements Serializable  {
      * @return the inverse hyperbolic tangent of this complex number
      */
     public Complex atanh() {
-        if (real == 0 &&
-            Double.isNaN(imaginary)) {
-            return new Complex(0, Double.NaN);
-        } else if (neitherInfiniteNorZeroNorNaN(real) &&
-                   imaginary == 0) {
-            return new Complex(Double.POSITIVE_INFINITY, 0);
-        } else if (neitherInfiniteNorZeroNorNaN(real) &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(0, PI_OVER_2);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   neitherInfiniteNorZeroNorNaN(imaginary)) {
-            return new Complex(0, PI_OVER_2);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(0, PI_OVER_2);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   Double.isNaN(imaginary)) {
-            return new Complex(0, Double.NaN);
-        } else if (Double.isNaN(real) &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(0, PI_OVER_2);
+        if (Double.isFinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                // Special case for zero
+                if (imaginary == 0) {
+                    if (real == 0) {
+                        return this;
+                    }
+                    if (Math.abs(real) == 1) {
+                        // raises the ‘‘divide-by-zero’’ floating-point exception.
+                        return new Complex(Math.copySign(Double.POSITIVE_INFINITY, real), imaginary);
+                    }
+                }
+                // ISO C99: Preserve the equality
+                // atanh(conj(z)) = conj(atanh(z))
+                final Complex z = negative(imaginary) ? conjugate() : this;
+                final Complex result = z.add(ONE).divide(ONE.subtract(z)).log().multiply(0.5);
+                return z == this ? result : result.conjugate();
+            }
+            if (Double.isInfinite(imaginary)) {
+                return new Complex(Math.copySign(0, real), Math.copySign(PI_OVER_2, imaginary));
+            }
+            // imaginary is NaN
+            // Special case for real == 0
+            return real == 0 ? new Complex(real, Double.NaN) : NAN;
         }
-        return add(ONE).divide(ONE.subtract(this)).log().multiply(0.5);
+        if (Double.isInfinite(real)) {
+            if (Double.isNaN(imaginary)) {
+                return new Complex(Math.copySign(0, real), Double.NaN);
+            }
+            // imaginary is finite or infinite
+            return new Complex(Math.copySign(0, real), Math.copySign(PI_OVER_2, imaginary));
+        }
+        // real is NaN
+        if (Double.isInfinite(imaginary)) {
+            return new Complex(0, Math.copySign(PI_OVER_2, imaginary));
+        }
+        // optionally raises the ‘‘invalid’’ floating-point exception, for finite y.
+        return NAN;
     }
 
     /**
@@ -1057,47 +1118,41 @@ public final class Complex implements Serializable  {
      */
     public Complex acosh() {
         if (Double.isFinite(real)) {
-            if (real == 0 &&
-                imaginary == 0) {
-                return new Complex(0, PI_OVER_2);
-            }
-            if (imaginary == Double.POSITIVE_INFINITY) {
-                return new Complex(Double.POSITIVE_INFINITY, PI_OVER_2);
-            }
-            if (Double.isNaN(imaginary)) {
-                return NAN;
-            }
-        } else if (Double.isInfinite(real)) {
-            if (real == Double.NEGATIVE_INFINITY &&
-                positiveSignedFinite(imaginary)) {
-                return new Complex(Double.POSITIVE_INFINITY, Math.PI);
-            }
-            if (real == Double.POSITIVE_INFINITY &&
-                positiveSignedFinite(imaginary)) {
-                return new Complex(Double.POSITIVE_INFINITY, 0);
+            if (Double.isFinite(imaginary)) {
+                // Special case for zero
+                if (real == 0 && imaginary == 0) {
+                    return new Complex(real, Math.copySign(PI_OVER_2, imaginary));
+                }
+                // ISO C99: Preserve the equality
+                // acosh(conj(z)) = conj(acosh(z))
+                final Complex z = negative(imaginary) ? conjugate() : this;
+                final Complex result = z.square().subtract(ONE).sqrt().add(z).log();
+                return z == this ? result : result.conjugate();
             }
-            if (real == Double.NEGATIVE_INFINITY &&
-                imaginary == Double.POSITIVE_INFINITY) {
-                return new Complex(Double.POSITIVE_INFINITY, PI_3_OVER_4);
+            if (Double.isInfinite(imaginary)) {
+                return new Complex(Double.POSITIVE_INFINITY, Math.copySign(PI_OVER_2, imaginary));
             }
-            if (real == Double.POSITIVE_INFINITY &&
-                imaginary == Double.POSITIVE_INFINITY) {
-                return new Complex(Double.POSITIVE_INFINITY, PI_OVER_4);
-            }
-            if (Double.isNaN(imaginary)) {
-                return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
-            }
-        } else if (Double.isNaN(real)) {
-            if (imaginary == Double.POSITIVE_INFINITY) {
-                return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
+            // imaginary is NaN
+            return NAN;
+        }
+        if (Double.isInfinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                final double im = real == Double.NEGATIVE_INFINITY ? Math.PI : 0;
+                return new Complex(Double.POSITIVE_INFINITY, Math.copySign(im, imaginary));
             }
-            if (Double.isFinite(imaginary) || Double.isNaN(imaginary)) {
-                // optionally raises the ‘‘invalid’’ floating-point exception, for finite y.
-                // No condition for imaginary as negative infinity
-                return NAN;
+            if (Double.isInfinite(imaginary)) {
+                final double im = real == Double.NEGATIVE_INFINITY ? PI_3_OVER_4 : PI_OVER_4;
+                return new Complex(Double.POSITIVE_INFINITY, Math.copySign(im, imaginary));
             }
+            // imaginary is NaN
+            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
+        }
+        // real is NaN
+        if (Double.isInfinite(imaginary)) {
+            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
         }
-        return square().subtract(ONE).sqrt().add(this).log();
+        // optionally raises the ‘‘invalid’’ floating-point exception, for finite y.
+        return NAN;
     }
 
     /**
@@ -1165,25 +1220,36 @@ public final class Complex implements Serializable  {
      * @return the hyperbolic cosine of this complex number
      */
     private static Complex cosh(double real, double imaginary, ComplexConstructor constructor) {
-        if (real == 0 &&
-            imaginary == Double.POSITIVE_INFINITY) {
-            return constructor.create(Double.NaN, 0);
-        } else if (real == 0 &&
-                   Double.isNaN(imaginary)) {
-            return constructor.create(Double.NaN, 0);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   imaginary == 0) {
-            return constructor.create(Double.POSITIVE_INFINITY, 0);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   (imaginary == Double.POSITIVE_INFINITY || Double.isNaN(imaginary))) {
+        if (Double.isFinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                return constructor.create(Math.cosh(real) * Math.cos(imaginary),
+                                          Math.sinh(real) * Math.sin(imaginary));
+            }
+            // Special case for real == 0
+            final double im = real == 0 ? Math.copySign(0, imaginary) : Double.NaN;
+            return constructor.create(Double.NaN, im);
+        }
+        if (Double.isInfinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                if (imaginary == 0) {
+                    // Determine sign
+                    final double im = real > 0 ? imaginary : -imaginary;
+                    return constructor.create(Double.POSITIVE_INFINITY, im);
+                }
+                // inf * cis(y)
+                final double re = real * Math.cos(imaginary);
+                final double im = real * Math.sin(imaginary);
+                return constructor.create(re, im);
+            }
+            // imaginary is infinite or NaN
             return constructor.create(Double.POSITIVE_INFINITY, Double.NaN);
-        } else if (Double.isNaN(real) &&
-                   imaginary == 0) {
-            return constructor.create(Double.NaN, 0);
         }
-
-        return constructor.create(Math.cosh(real) * Math.cos(imaginary),
-                                  Math.sinh(real) * Math.sin(imaginary));
+        // real is NaN
+        if (imaginary == 0) {
+            return constructor.create(Double.NaN, Math.copySign(0, imaginary));
+        }
+        // optionally raises the ‘‘invalid’’ floating-point exception, for nonzero y.
+        return NAN;
     }
 
     /**
@@ -1201,25 +1267,48 @@ public final class Complex implements Serializable  {
      * @return <code><i>e</i><sup>this</sup></code>.
      */
     public Complex exp() {
-        if (real == Double.POSITIVE_INFINITY &&
-            imaginary == 0) {
-            return new Complex(Double.POSITIVE_INFINITY, 0);
-        } else if (real == Double.NEGATIVE_INFINITY &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return Complex.ZERO;
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   (imaginary == Double.POSITIVE_INFINITY || Double.isNaN(imaginary))) {
-            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
-        } else if (real == Double.NEGATIVE_INFINITY &&
-                   Double.isNaN(imaginary)) {
-            return Complex.ZERO;
-        } else if (Double.isNaN(real) &&
-                   imaginary == 0) {
-            return new Complex(Double.NaN, 0);
+        if (Double.isFinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                final double expReal = Math.exp(real);
+                if (imaginary == 0) {
+                    // Preserve sign for conjugate equality
+                    return new Complex(expReal, imaginary);
+                }
+                return new Complex(expReal * Math.cos(imaginary),
+                                   expReal * Math.sin(imaginary));
+            }
+            // Imaginary is infinite or nan
+            return NAN;
+        }
+        if (Double.isInfinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                if (real == Double.POSITIVE_INFINITY) {
+                    if (imaginary == 0) {
+                        return this;
+                    }
+                    // inf * cis(y)
+                    final double re = Double.POSITIVE_INFINITY * Math.cos(imaginary);
+                    final double im = Double.POSITIVE_INFINITY * Math.sin(imaginary);
+                    return new Complex(re, im);
+                }
+                // +0 * cis(y)
+                final double re = 0.0 * Math.cos(imaginary);
+                final double im = 0.0 * Math.sin(imaginary);
+                return new Complex(re, im);
+            }
+            // imaginary is infinite or NaN
+            if (real == Double.POSITIVE_INFINITY) {
+                return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
+            }
+            // Preserve sign for conjugate equality
+            return new Complex(0, Math.copySign(0, imaginary));
+        }
+        // real is NaN
+        if (imaginary == 0) {
+            return new Complex(Double.NaN, Math.copySign(0, imaginary));
         }
-        final double expReal = Math.exp(real);
-        return new Complex(expReal *  Math.cos(imaginary),
-                           expReal * Math.sin(imaginary));
+        // optionally raises the ‘‘invalid’’ floating-point exception, for finite y.
+        return NAN;
     }
 
     /**
@@ -1231,22 +1320,13 @@ public final class Complex implements Serializable  {
      *   log(a + bi) = ln(|a + bi|) + arg(a + bi)i
      * </pre>
      * where ln on the right hand side is {@link Math#log},
-     * {@code |a + bi|} is the modulus, {@link Complex#abs},  and
+     * {@code |a + bi|} is the modulus, {@link Complex#abs}, and
      * {@code arg(a + bi) = }{@link Math#atan2}(b, a).
      *
-     * @return the value <code>ln &nbsp; this</code>, the natural logarithm
-     * of {@code this}.
+     * @return the natural logarithm of {@code this}.
      */
     public Complex log() {
-        if (real == Double.POSITIVE_INFINITY &&
-            imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(Double.POSITIVE_INFINITY, PI_OVER_4);
-        } else if ((real == Double.POSITIVE_INFINITY &&
-                    Double.isNaN(imaginary)) ||
-                   (Double.isNaN(real) &&
-                    imaginary == Double.POSITIVE_INFINITY)) {
-            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
-        }
+        // All edge cases satisfied by the Math library
         return new Complex(Math.log(abs()),
                            Math.atan2(imaginary, real));
     }
@@ -1255,21 +1335,19 @@ public final class Complex implements Serializable  {
      * Compute the base 10 or
      * <a href="http://mathworld.wolfram.com/CommonLogarithm.html">
      * common logarithm</a> of this complex number.
+     * Implements the formula:
+     * <pre>
+     *   log10(a + bi) = log(|a + bi|) + arg(a + bi)i
+     * </pre>
+     * where log on the right hand side is {@link Math#log10},
+     * {@code |a + bi|} is the modulus, {@link Complex#abs}, and
+     * {@code arg(a + bi) = }{@link Math#atan2}(b, a).
      *
-     * @return the base 10 logarithm of <code>this</code>.
+     * @return the base 10 logarithm of {@code this}.
      */
     public Complex log10() {
-        // Same edge cases as log()
-        if (real == Double.POSITIVE_INFINITY &&
-            imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(Double.POSITIVE_INFINITY, PI_OVER_4);
-        } else if ((real == Double.POSITIVE_INFINITY &&
-                    Double.isNaN(imaginary)) ||
-                   (Double.isNaN(real) &&
-                    imaginary == Double.POSITIVE_INFINITY)) {
-            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
-        }
-        return new Complex(Math.log(abs()) / Math.log(10),
+        // All edge cases satisfied by the Math library
+        return new Complex(Math.log10(abs()),
                            Math.atan2(imaginary, real));
     }
 
@@ -1380,33 +1458,34 @@ public final class Complex implements Serializable  {
      * @return the hyperbolic sine of this complex number
      */
     private static Complex sinh(double real, double imaginary, ComplexConstructor constructor) {
-        if (real == 0 &&
-            imaginary == 0) {
-            // Ignore the constructor.
-            // It is used in trignomic identities to multiply the result by -i.
-            // Here the result would still be zero.
-            return Complex.ZERO;
-        } else if (real == 0 &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return constructor.create(0, Double.NaN);
-        } else if (real == 0 &&
-                   Double.isNaN(imaginary)) {
-            return constructor.create(0, Double.NaN);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   imaginary == 0) {
-            return constructor.create(Double.POSITIVE_INFINITY, 0);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return constructor.create(Double.POSITIVE_INFINITY, Double.NaN);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   Double.isNaN(imaginary)) {
+        if (Double.isFinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                return constructor.create(Math.sinh(real) * Math.cos(imaginary),
+                                          Math.cosh(real) * Math.sin(imaginary));
+            }
+            // Special case for real == 0
+            final double re = real == 0 ? real : Double.NaN;
+            return constructor.create(re, Double.NaN);
+        }
+        if (Double.isInfinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                if (imaginary == 0) {
+                    return constructor.create(real, imaginary);
+                }
+                // inf * cis(y)
+                final double re = real * Math.cos(imaginary);
+                final double im = real * Math.sin(imaginary);
+                return constructor.create(re, im);
+            }
+            // imaginary is infinite or NaN
             return constructor.create(Double.POSITIVE_INFINITY, Double.NaN);
-        } else if (Double.isNaN(real) &&
-                   imaginary == 0) {
-            return constructor.create(Double.NaN, 0);
         }
-        return constructor.create(Math.sinh(real) * Math.cos(imaginary),
-                                  Math.cosh(real) * Math.sin(imaginary));
+        // real is NaN
+        if (imaginary == 0) {
+            return constructor.create(Double.NaN, Math.copySign(0, imaginary));
+        }
+        // optionally raises the ‘‘invalid’’ floating-point exception, for nonzero y.
+        return NAN;
     }
 
     /**
@@ -1427,29 +1506,37 @@ public final class Complex implements Serializable  {
      * @return the square root of {@code this}.
      */
     public Complex sqrt() {
-        if (real == 0 &&
-            imaginary == 0) {
-            return ZERO;
-        } else if (neitherInfiniteNorZeroNorNaN(real) &&
-                   imaginary == Double.POSITIVE_INFINITY) {
-            return new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
-        } else if (real == Double.NEGATIVE_INFINITY &&
-                   neitherInfiniteNorZeroNorNaN(imaginary)) {
-            return new Complex(0, Double.NaN);
-        } else if (real == Double.NEGATIVE_INFINITY &&
-                   Double.isNaN(imaginary)) {
-            return new Complex(Double.NaN, Double.POSITIVE_INFINITY);
-        } else if (real == Double.POSITIVE_INFINITY &&
-                   Double.isNaN(imaginary)) {
-            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
+        // Special case for infinite imaginary for all real including nan
+        if (Double.isInfinite(imaginary)) {
+            return new Complex(Double.POSITIVE_INFINITY, imaginary);
         }
-
-        final double t = Math.sqrt((Math.abs(real) + abs()) / 2);
-        if (real >= 0) {
-            return new Complex(t, imaginary / (2 * t));
+        if (Double.isFinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                // Handle zero
+                if (real == 0 && imaginary == 0) {
+                    return new Complex(0, imaginary);
+                }
+                final double t = Math.sqrt((Math.abs(real) + abs()) / 2);
+                if (real >= 0) {
+                    return new Complex(t, imaginary / (2 * t));
+                }
+                return new Complex(Math.abs(imaginary) / (2 * t),
+                                   Math.copySign(1d, imaginary) * t);
+            }
+            // Imaginary is nan
+            return NAN;
+        }
+        if (Double.isInfinite(real)) {
+            // imaginary is finite or NaN
+            final double part = Double.isNaN(imaginary) ? Double.NaN : 0;
+            if (real == Double.NEGATIVE_INFINITY) {
+                return new Complex(part, Math.copySign(Double.POSITIVE_INFINITY, imaginary));
+            }
+            return new Complex(Double.POSITIVE_INFINITY, Math.copySign(part, imaginary));
         }
-        return new Complex(Math.abs(imaginary) / (2 * t),
-                           Math.copySign(1d, imaginary) * t);
+        // real is NaN
+        // optionally raises the ‘‘invalid’’ floating-point exception, for finite y.
+        return NAN;
     }
 
     /**
@@ -1530,19 +1617,30 @@ public final class Complex implements Serializable  {
         // Math.cosh returns positive infinity for infinity.
         // Math.sinh returns the input infinity for infinity.
 
-        if (real == Double.POSITIVE_INFINITY &&
-            (imaginary == Double.POSITIVE_INFINITY || Double.isNaN(imaginary))) {
-            return constructor.create(1, 0);
-        } else if (Double.isNaN(real) &&
-                   imaginary == 0) {
-            return constructor.create(Double.NaN, 0);
-        }
-        final double real2 = 2 * real;
-        final double imaginary2 = 2 * imaginary;
-        final double d = Math.cosh(real2) + Math.cos(imaginary2);
+        if (Double.isFinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                final double real2 = 2 * real;
+                final double imaginary2 = 2 * imaginary;
+                final double d = Math.cosh(real2) + Math.cos(imaginary2);
 
-        return constructor.create(Math.sinh(real2) / d,
-                                  Math.sin(imaginary2) / d);
+                return constructor.create(Math.sinh(real2) / d,
+                                          Math.sin(imaginary2) / d);
+            }
+            return NAN;
+        }
+        if (Double.isInfinite(real)) {
+            if (Double.isFinite(imaginary)) {
+                return constructor.create(Math.copySign(1, real), Math.copySign(0, Math.sin(2 * imaginary)));
+            }
+            // imaginary is infinite or NaN
+            return constructor.create(Math.copySign(1, real), Math.copySign(0, imaginary));
+        }
+        // real is NaN
+        if (imaginary == 0) {
+            return constructor.create(Double.NaN, Math.copySign(0, imaginary));
+        }
+        // optionally raises the ‘‘invalid’’ floating-point exception, for nonzero y.
+        return NAN;
     }
 
    /**
@@ -1647,37 +1745,19 @@ public final class Complex implements Serializable  {
     }
 
     /**
-     * Check that a value meets all the following conditions.
-     * <ul>
-     *  <li>it is not {@code NaN},</li>
-     *  <li>it is not infinite,</li>
-     *  <li>it is not zero,</li>
-     * </ul>
-     *
-     * @param d Value.
-     * @return {@code true} if {@code d} meets all the conditions and
-     * {@code false} otherwise.
-     */
-    private static boolean neitherInfiniteNorZeroNorNaN(double d) {
-        return Double.isFinite(d) && d != 0;
-    }
-
-    /**
-     * Check that a value meets all the following conditions.
+     * Check that a value is negative. It must meet all the following conditions:
      * <ul>
      *  <li>it is not {@code NaN},</li>
-     *  <li>it is not infinite,</li>
-     *  <li>it is positive signed,</li>
+     *  <li>it is negative signed,</li>
      * </ul>
      *
-     * <p>Note: This is false for negative zero.</p>
+     * <p>Note: This is true for negative zero.</p>
      *
      * @param d Value.
-     * @return {@code true} if {@code d} meets all the conditions and
-     * {@code false} otherwise.
+     * @return {@code true} if {@code d} is negative.
      */
-    private static boolean positiveSignedFinite(double d) {
-        return (Double.isFinite(d) && d > 0) || Double.doubleToLongBits(d) == 0;
+    private static boolean negative(double d) {
+        return d < 0 || equals(d, -0.0);
     }
 
     /**
@@ -1697,6 +1777,23 @@ public final class Complex implements Serializable  {
         return new Complex(imaginary, -real);
     }
 
+    /**
+     * Create the conjugate of a complex number given the real and imaginary parts.
+     * This is used in functions that implement conjugate identities. It is the functional
+     * equivalent of:
+     *
+     * <pre>
+     *   z = new Complex(real, imaginary).conjugate();
+     * </pre>
+     *
+     * @param real Real part.
+     * @param imaginary Imaginary part.
+     * @return {@code Complex} object
+     */
+    private static Complex ofCartesianConjugate(double real, double imaginary) {
+        return new Complex(real, -imaginary);
+    }
+
      /** See {@link #parse(String)}. */
     private static class ComplexParsingException extends NumberFormatException {
         /** Serializable version identifier. */
diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java
index 269ab74..cddf068 100644
--- a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java
+++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.commons.numbers.complex;
 
-import org.apache.commons.numbers.core.Precision;
 import org.apache.commons.rng.UniformRandomProvider;
 import org.apache.commons.rng.simple.RandomSource;
 import org.junit.jupiter.api.Assertions;
@@ -26,6 +25,7 @@ import org.junit.jupiter.api.Test;
 import java.util.ArrayList;
 import java.util.function.BiFunction;
 import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
 
 /**
  * Tests the standards defined by the C.99 standard for complex numbers
@@ -43,15 +43,19 @@ public class CStandardTest {
     private static final double piOverFour = Math.PI / 4.0;
     private static final double piOverTwo = Math.PI / 2.0;
     private static final double threePiOverFour = 3.0 * Math.PI / 4.0;
-    private static final Complex oneOne = complex(1, 1);
     private static final Complex oneZero = complex(1, 0);
     private static final Complex oneInf = complex(1, inf);
     private static final Complex oneNaN = complex(1, nan);
+    private static final Complex oneNegZero = complex(1, -0.0);
     private static final Complex zeroInf = complex(0, inf);
     private static final Complex zeroNegInf = complex(0, negInf);
+    private static final Complex zeroNegZero = complex(0, -0.0);
     private static final Complex zeroNaN = complex(0, nan);
     private static final Complex zeroPiTwo = complex(0.0, piOverTwo);
+    private static final Complex negZeroPiTwo = complex(-0.0, piOverTwo);
     private static final Complex negZeroZero = complex(-0.0, 0);
+    private static final Complex negZeroNegZero = complex(-0.0, -0.0);
+    private static final Complex negZeroNaN = complex(-0.0, nan);
     private static final Complex negI = complex(0.0, -1.0);
     private static final Complex infOne = complex(inf, 1);
     private static final Complex infZero = complex(inf, 0);
@@ -61,12 +65,16 @@ public class CStandardTest {
     private static final Complex infThreePiFour = complex(inf, threePiOverFour);
     private static final Complex infPiFour = complex(inf, piOverFour);
     private static final Complex infPi = complex(inf, Math.PI);
+    private static final Complex infNegZero = complex(inf, -0.0);
+    private static final Complex negOneZero = complex(-1, 0);
+    private static final Complex negOneNegZero = complex(-1, -0.0);
     private static final Complex negInfInf = complex(negInf, inf);
     private static final Complex negInfZero = complex(negInf, 0);
+    private static final Complex negInfNegZero = complex(negInf, -0.0);
     private static final Complex negInfOne = complex(negInf, 1);
     private static final Complex negInfNaN = complex(negInf, nan);
-    private static final Complex negInfPosInf = complex(negInf, inf);
     private static final Complex negInfPi = complex(negInf, Math.PI);
+    private static final Complex negInfPiFour = complex(negInf, piOverFour);
     private static final Complex nanInf = complex(nan, inf);
     private static final Complex nanNegInf = complex(nan, negInf);
     private static final Complex nanZero = complex(nan, 0);
@@ -83,33 +91,16 @@ public class CStandardTest {
     private static final Complex nanMax = complex(nan, max);
 
     /**
-     * Assert the two complex numbers have their real and imaginary components within
-     * the given tolerance.
-     *
-     * @param c1 the first complex
-     * @param c2 the second complex
-     * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
-     * values between the real (resp. imaginary) parts of {@code x} and
-     * {@code y}.
-     */
-    public void assertComplex(Complex c1, Complex c2, int maxUlps) {
-        if (!Precision.equals(c1.getReal(), c2.getReal(), maxUlps) ||
-            !Precision.equals(c1.getImaginary(), c2.getImaginary(), maxUlps)) {
-            Assertions.fail(c1 + " != " + c2);
-        }
-    }
-
-    /**
      * Assert the two complex numbers have equivalent real and imaginary components as
      * defined by the {@code ==} operator.
      *
-     * @param c1 the first complex
-     * @param c2 the second complex
+     * @param c1 the first complex (actual)
+     * @param c2 the second complex (expected)
      */
-    public void assertComplex(Complex c1, Complex c2) {
+    private static void assertComplex(Complex c1, Complex c2) {
         // Use a delta of zero to allow comparison of -0.0 to 0.0
-        Assertions.assertEquals(c1.getReal(), c2.getReal(), 0.0, "real");
-        Assertions.assertEquals(c1.getImaginary(), c2.getImaginary(), 0.0, "imaginary");
+        Assertions.assertEquals(c2.getReal(), c1.getReal(), 0.0, "real");
+        Assertions.assertEquals(c2.getImaginary(), c1.getImaginary(), 0.0, "imaginary");
     }
 
     /**
@@ -131,6 +122,109 @@ public class CStandardTest {
     }
 
     /**
+     * Assert the operation on the complex number satisfies the conjugate equality.
+     *
+     * <pre>
+     * op(conj(z)) = conj(op(z))
+     * </pre>
+     *
+     * <p>The results must be binary equal. This includes the sign of zero.
+     *
+     * @param operation the operation
+     */
+    private static void assertConjugateEquality(UnaryOperator<Complex> operation) {
+        // Edge cases
+        final double[] parts = {Double.NEGATIVE_INFINITY, -1, -0.0, 0.0, 1,
+                                Double.POSITIVE_INFINITY, Double.NaN};
+        for (final double x : parts) {
+            for (final double y : parts) {
+                // No conjugate for imaginary NaN
+                if (!Double.isNaN(y)) {
+                    assertConjugateEquality(x, y, operation);
+                }
+            }
+        }
+        // Random numbers
+        final UniformRandomProvider rng = RandomSource.create(RandomSource.SPLIT_MIX_64);
+        for (int i = 0; i < 100; i++) {
+            final double x = next(rng);
+            final double y = next(rng);
+            assertConjugateEquality(x, y, operation);
+        }
+    }
+
+    /**
+     * Assert the operation on the complex number satisfies the conjugate equality.
+     *
+     * <pre>
+     * op(conj(z)) = conj(op(z))
+     * </pre>
+     *
+     * <p>The results must be binary equal. This includes the sign of zero.
+     *
+     * @param re the real component
+     * @param im the imaginary component
+     * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
+     * values between the real (resp. imaginary) parts of {@code x} and
+     * {@code y}.
+     * @param operation the operation
+     */
+    private static void assertConjugateEquality(double re, double im,
+            UnaryOperator<Complex> operation) {
+        final Complex z = complex(re, im);
+        final Complex c1 = operation.apply(z.conj());
+        final Complex c2 = operation.apply(z).conj();
+
+        // Test for binary equality
+        if (!equals(c1.getReal(), c2.getReal()) ||
+            !equals(c1.getImaginary(), c2.getImaginary())) {
+            Assertions.fail(String.format("Conjugate equality failed (z=%s). Expected: %s but was: %s",
+                                          z, c2, c1));
+        }
+    }
+
+    /**
+     * Assert the operation on the complex number is equal to the expected value.
+     * If the imaginary part is not NaN the operation must also satisfy the conjugate equality.
+     *
+     * <pre>
+     * op(conj(z)) = conj(op(z))
+     * </pre>
+     *
+     * <p>The results must be binary equal. This includes the sign of zero.
+     *
+     * @param z the complex
+     * @param operation the operation
+     * @param expected the expected
+     */
+    private static void assertComplex(Complex z,
+            UnaryOperator<Complex> operation, Complex expected) {
+        // Test the operation
+        final Complex c1 = operation.apply(z);
+        if (!equals(c1.getReal(), expected.getReal()) ||
+            !equals(c1.getImaginary(), expected.getImaginary())) {
+            Assertions.fail(String.format("Operation failed (z=%s). Expected: %s but was: %s",
+                                          z, expected, c1));
+        }
+
+        if (!Double.isNaN(z.getImaginary())) {
+            assertConjugateEquality(z.getReal(), z.getImaginary(), operation);
+        }
+    }
+
+    /**
+     * Returns {@code true} if the values are equal according to semantics of
+     * {@link Double#equals(Object)}.
+     *
+     * @param x Value
+     * @param y Value
+     * @return {@code Double.valueof(x).equals(Double.valueOf(y))}
+     */
+    private static boolean equals(double x, double y) {
+        return Double.doubleToLongBits(x) == Double.doubleToLongBits(y);
+    }
+
+    /**
      * Utility to create a Complex.
      *
      * @param real the real
@@ -191,8 +285,8 @@ public class CStandardTest {
      */
     private static ArrayList<Complex> createCombinations(final double[] values, Predicate<Complex> condition) {
         final ArrayList<Complex> list = new ArrayList<>();
-        for (double re : values) {
-            for (double im : values) {
+        for (final double re : values) {
+            for (final double im : values) {
                 final Complex z = complex(re, im);
                 if (condition.test(z)) {
                     list.add(z);
@@ -230,18 +324,18 @@ public class CStandardTest {
 
         // "if one operand is an infinity and the other operand is a nonzero finite number or an
         // infinity, then the result of the * operator is an infinity;"
-        for (Complex z : infinites) {
-            for (Complex w : infinites) {
+        for (final Complex z : infinites) {
+            for (final Complex w : infinites) {
                 assertOperation(z, w, Complex::multiply, "*", Complex::isInfinite, "Inf");
                 assertOperation(w, z, Complex::multiply, "*", Complex::isInfinite, "Inf");
             }
-            for (Complex w : nonZeroFinites) {
+            for (final Complex w : nonZeroFinites) {
                 assertOperation(z, w, Complex::multiply, "*", Complex::isInfinite, "Inf");
                 assertOperation(w, z, Complex::multiply, "*", Complex::isInfinite, "Inf");
             }
             // C.99 refers to non-zero finites.
             // Infer that Complex multiplication of zero with infinites is not defined.
-            for (Complex w : zeroFinites) {
+            for (final Complex w : zeroFinites) {
                 assertOperation(z, w, Complex::multiply, "*", Complex::isNaN, "NaN");
                 assertOperation(w, z, Complex::multiply, "*", Complex::isNaN, "NaN");
             }
@@ -258,7 +352,7 @@ public class CStandardTest {
 
         // Check multiply with (NaN,NaN) is not corrected
         final double[] values = {0, 1, inf, negInf, nan};
-        for (Complex z : createCombinations(values, c -> true)) {
+        for (final Complex z : createCombinations(values, c -> true)) {
             assertOperation(z, NAN, Complex::multiply, "*", Complex::isNaN, "NaN");
             assertOperation(NAN, z, Complex::multiply, "*", Complex::isNaN, "NaN");
         }
@@ -285,34 +379,34 @@ public class CStandardTest {
 
         // "if the first operand is an infinity and the second operand is a finite number, then the
         // result of the / operator is an infinity;"
-        for (Complex z : infinites) {
-            for (Complex w : nonZeroFinites) {
+        for (final Complex z : infinites) {
+            for (final Complex w : nonZeroFinites) {
                 assertOperation(z, w, Complex::divide, "/", Complex::isInfinite, "Inf");
             }
-            for (Complex w : zeroFinites) {
+            for (final Complex w : zeroFinites) {
                 assertOperation(z, w, Complex::divide, "/", Complex::isInfinite, "Inf");
             }
             // Check inf/inf cannot be done
-            for (Complex w : infinites) {
+            for (final Complex w : infinites) {
                 assertOperation(z, w, Complex::divide, "/", Complex::isNaN, "NaN");
             }
         }
 
         // "if the first operand is a finite number and the second operand is an infinity, then the
         // result of the / operator is a zero;"
-        for (Complex z : finites) {
-            for (Complex w : infinites) {
+        for (final Complex z : finites) {
+            for (final Complex w : infinites) {
                 assertOperation(z, w, Complex::divide, "/", CStandardTest::isZero, "Zero");
             }
         }
 
         // "if the first operand is a nonzero finite number or an infinity and the second operand is
         // a zero, then the result of the / operator is an infinity."
-        for (Complex w : zeroFinites) {
-            for (Complex z : nonZeroFinites) {
+        for (final Complex w : zeroFinites) {
+            for (final Complex z : nonZeroFinites) {
                 assertOperation(z, w, Complex::divide, "/", Complex::isInfinite, "Inf");
             }
-            for (Complex z : infinites) {
+            for (final Complex z : infinites) {
                 assertOperation(z, w, Complex::divide, "/", Complex::isInfinite, "Inf");
             }
         }
@@ -320,20 +414,20 @@ public class CStandardTest {
         // ISO C Standard in Annex G is missing an explicit definition of how to handle NaNs.
         // The reference implementation does not correct for divide by NaN components unless
         // infinite.
-        for (Complex w : nans) {
-            for (Complex z : finites) {
+        for (final Complex w : nans) {
+            for (final Complex z : finites) {
                 assertOperation(z, w, Complex::divide, "/", c -> NAN.equals(c), "(NaN,NaN)");
             }
-            for (Complex z : infinites) {
+            for (final Complex z : infinites) {
                 assertOperation(z, w, Complex::divide, "/", c -> NAN.equals(c), "(NaN,NaN)");
             }
         }
 
         // Check (NaN,NaN) divide is not corrected for the edge case of divide by zero or infinite
-        for (Complex w : zeroFinites) {
+        for (final Complex w : zeroFinites) {
             assertOperation(NAN, w, Complex::divide, "/", Complex::isNaN, "NaN");
         }
-        for (Complex w : infinites) {
+        for (final Complex w : infinites) {
             assertOperation(NAN, w, Complex::divide, "/", Complex::isNaN, "NaN");
         }
     }
@@ -367,13 +461,13 @@ public class CStandardTest {
     }
 
     /**
-     * Create a number in the range {@code (-1,1)}.
+     * Create a number in the range {@code (-5,5)}.
      *
      * @param rng the random generator
      * @return the number
      */
     private static double next(UniformRandomProvider rng) {
-        return rng.nextDouble() * (rng.nextBoolean() ? -1 : 1);
+        return rng.nextDouble() * (rng.nextBoolean() ? -5 : 5);
     }
 
     /**
@@ -402,21 +496,23 @@ public class CStandardTest {
      */
     @Test
     public void testAcos() {
-        assertComplex(oneOne.acos().conj(), oneOne.conj().acos(), 1);
-        assertComplex(Complex.ZERO.acos(), piTwoNegZero);
-        assertComplex(negZeroZero.acos(), piTwoNegZero);
-        assertComplex(zeroNaN.acos(), piTwoNaN);
-        assertComplex(oneInf.acos(), piTwoNegInf);
-        assertComplex(oneNaN.acos(), NAN);
-        assertComplex(negInfOne.acos(), piNegInf);
-        assertComplex(infOne.acos(), zeroNegInf);
-        assertComplex(negInfPosInf.acos(), threePiFourNegInf);
-        assertComplex(infInf.acos(), piFourNegInf);
-        assertComplex(infNaN.acos(), nanInf);
-        assertComplex(negInfNaN.acos(), nanNegInf);
-        assertComplex(nanOne.acos(), NAN);
-        assertComplex(nanInf.acos(), nanNegInf);
-        assertComplex(NAN.acos(), NAN);
+        assertConjugateEquality(Complex::acos);
+        assertComplex(Complex.ZERO, Complex::acos, piTwoNegZero);
+        assertComplex(negZeroZero, Complex::acos, piTwoNegZero);
+        assertComplex(zeroNaN, Complex::acos, piTwoNaN);
+        assertComplex(oneNaN, Complex::acos, NAN);
+        assertComplex(oneInf, Complex::acos, piTwoNegInf);
+        assertComplex(negInfZero, Complex::acos, piNegInf);
+        assertComplex(negInfOne, Complex::acos, piNegInf);
+        assertComplex(infZero, Complex::acos, zeroNegInf);
+        assertComplex(infOne, Complex::acos, zeroNegInf);
+        assertComplex(negInfInf, Complex::acos, threePiFourNegInf);
+        assertComplex(infInf, Complex::acos, piFourNegInf);
+        assertComplex(infNaN, Complex::acos, nanInf);
+        assertComplex(negInfNaN, Complex::acos, nanNegInf);
+        assertComplex(nanOne, Complex::acos, NAN);
+        assertComplex(nanInf, Complex::acos, nanNegInf);
+        assertComplex(NAN, Complex::acos, NAN);
     }
 
     /**
@@ -424,51 +520,51 @@ public class CStandardTest {
      */
     @Test
     public void testAcosh() {
-        assertComplex(oneOne.acosh().conj(), oneOne.conj().acosh(), 1);
-        assertComplex(Complex.ZERO.acosh(), zeroPiTwo);
-        assertComplex(negZeroZero.acosh(), zeroPiTwo);
-        assertComplex(oneInf.acosh(), infPiTwo);
-        assertComplex(zeroNaN.acosh(), NAN);
-        assertComplex(oneNaN.acosh(), NAN);
-        assertComplex(negInfOne.acosh(), infPi);
-        assertComplex(negInfZero.acosh(), infPi);
-        assertComplex(infOne.acosh(), infZero);
-        assertComplex(infZero.acosh(), infZero);
-        assertComplex(negInfPosInf.acosh(), infThreePiFour);
-        assertComplex(infInf.acosh(), infPiFour);
-        assertComplex(infNaN.acosh(), infNaN);
-        assertComplex(negInfNaN.acosh(), infNaN);
-        assertComplex(nanOne.acosh(), NAN);
-        assertComplex(nanInf.acosh(), infNaN);
-        assertComplex(NAN.acosh(), NAN);
-        // The standard mentions positive-signed y
-        Assertions.assertThrows(AssertionError.class, () -> {
-            // Not −∞ + iy, positive signed y
-            assertComplex(complex(negInf, -0.0).acosh(), infPi);
-        });
-        Assertions.assertThrows(AssertionError.class, () -> {
-            // Not ∞ + iy, positive signed y
-            assertComplex(complex(inf, -0.0).acosh(), infPi);
-        });
+        assertConjugateEquality(Complex::acosh);
+        assertComplex(Complex.ZERO, Complex::acosh, zeroPiTwo);
+        assertComplex(negZeroZero, Complex::acosh, negZeroPiTwo);
+        assertComplex(zeroNaN, Complex::acosh, NAN);
+        assertComplex(oneNaN, Complex::acosh, NAN);
+        assertComplex(oneInf, Complex::acosh, infPiTwo);
+        assertComplex(negInfZero, Complex::acosh, infPi);
+        assertComplex(negInfOne, Complex::acosh, infPi);
+        assertComplex(infZero, Complex::acosh, infZero);
+        assertComplex(infOne, Complex::acosh, infZero);
+        assertComplex(negInfInf, Complex::acosh, infThreePiFour);
+        assertComplex(infInf, Complex::acosh, infPiFour);
+        assertComplex(infNaN, Complex::acosh, infNaN);
+        assertComplex(negInfNaN, Complex::acosh, infNaN);
+        assertComplex(nanOne, Complex::acosh, NAN);
+        assertComplex(nanInf, Complex::acosh, infNaN);
+        assertComplex(NAN, Complex::acosh, NAN);
     }
 
+    // TODO: test the 'IS ODD/ EVEN' specification
+
     /**
      * ISO C Standard G.6.2.2.
      */
     @Test
     public void testAsinh() {
-        // TODO: test for which Asinh is odd
-        assertComplex(oneOne.conj().asinh(), oneOne.asinh().conj());
-        assertComplex(Complex.ZERO.asinh(), Complex.ZERO);
-        assertComplex(oneInf.asinh(), infPiTwo);
-        assertComplex(oneNaN.asinh(), NAN);
-        assertComplex(infOne.asinh(), infZero);
-        assertComplex(infInf.asinh(), infPiFour);
-        assertComplex(infNaN.asinh(), infNaN);
-        assertComplex(nanZero.asinh(), nanZero);
-        assertComplex(nanOne.asinh(), NAN);
-        assertComplex(nanInf.asinh(), infNaN);
-        assertComplex(NAN, NAN);
+        assertConjugateEquality(Complex::asinh);
+        // AND ASINH IS ODD
+        assertComplex(Complex.ZERO, Complex::asinh, Complex.ZERO);
+        assertComplex(negZeroZero, Complex::asinh, negZeroZero);
+        assertComplex(zeroNaN, Complex::asinh, NAN);
+        assertComplex(oneNaN, Complex::asinh, NAN);
+        assertComplex(oneInf, Complex::asinh, infPiTwo);
+        assertComplex(negInfZero, Complex::asinh, negInfZero);
+        assertComplex(negInfOne, Complex::asinh, negInfZero);
+        assertComplex(infZero, Complex::asinh, infZero);
+        assertComplex(infOne, Complex::asinh, infZero);
+        assertComplex(negInfInf, Complex::asinh, negInfPiFour);
+        assertComplex(infInf, Complex::asinh, infPiFour);
+        assertComplex(infNaN, Complex::asinh, infNaN);
+        assertComplex(negInfNaN, Complex::asinh, negInfNaN);
+        assertComplex(nanZero, Complex::asinh, nanZero);
+        assertComplex(nanOne, Complex::asinh, NAN);
+        assertComplex(nanInf, Complex::asinh, infNaN);
+        assertComplex(NAN, Complex::asinh, NAN);
     }
 
     /**
@@ -476,18 +572,26 @@ public class CStandardTest {
      */
     @Test
     public void testAtanh() {
-        assertComplex(oneOne.conj().atanh(), oneOne.atanh().conj());
-        assertComplex(Complex.ZERO.atanh(), Complex.ZERO);
-        assertComplex(zeroNaN.atanh(), zeroNaN);
-        assertComplex(oneZero.atanh(), infZero);
-        assertComplex(oneInf.atanh(), zeroPiTwo);
-        assertComplex(oneNaN.atanh(), NAN);
-        assertComplex(infOne.atanh(), zeroPiTwo);
-        assertComplex(infInf.atanh(), zeroPiTwo);
-        assertComplex(infNaN.atanh(), zeroNaN);
-        assertComplex(nanOne.atanh(), NAN);
-        assertComplex(nanInf.atanh(), zeroPiTwo);
-        assertComplex(NAN.atanh(), NAN);
+        assertConjugateEquality(Complex::atanh);
+        // AND ATANH IS ODD
+        assertComplex(Complex.ZERO, Complex::atanh, Complex.ZERO);
+        assertComplex(negZeroZero, Complex::atanh, negZeroZero);
+        assertComplex(zeroNaN, Complex::atanh, zeroNaN);
+        assertComplex(oneNaN, Complex::atanh, NAN);
+        assertComplex(oneZero, Complex::atanh, infZero);
+        assertComplex(oneInf, Complex::atanh, zeroPiTwo);
+        assertComplex(negInfZero, Complex::atanh, negZeroPiTwo);
+        assertComplex(negInfOne, Complex::atanh, negZeroPiTwo);
+        assertComplex(infZero, Complex::atanh, zeroPiTwo);
+        assertComplex(infOne, Complex::atanh, zeroPiTwo);
+        assertComplex(negInfInf, Complex::atanh, negZeroPiTwo);
+        assertComplex(infInf, Complex::atanh, zeroPiTwo);
+        assertComplex(infNaN, Complex::atanh, zeroNaN);
+        assertComplex(negInfNaN, Complex::atanh, negZeroNaN);
+        assertComplex(nanZero, Complex::atanh, NAN);
+        assertComplex(nanOne, Complex::atanh, NAN);
+        assertComplex(nanInf, Complex::atanh, zeroPiTwo);
+        assertComplex(NAN, Complex::atanh, NAN);
     }
 
     /**
@@ -495,21 +599,38 @@ public class CStandardTest {
      */
     @Test
     public void testCosh() {
-        assertComplex(oneOne.cosh().conj(), oneOne.conj().cosh());
-        assertComplex(Complex.ZERO.cosh(), Complex.ONE);
-        assertComplex(zeroInf.cosh(), nanZero);
-        assertComplex(zeroNaN.cosh(), nanZero);
-        assertComplex(oneInf.cosh(), NAN);
-        assertComplex(oneNaN.cosh(), NAN);
-        assertComplex(infZero.cosh(), infZero);
-        // the next test does not appear to make sense:
-        // (inf + iy) = inf + cis(y)
-        // skipped
-        assertComplex(infInf.cosh(), infNaN);
-        assertComplex(infNaN.cosh(), infNaN);
-        assertComplex(nanZero.cosh(), nanZero);
-        assertComplex(nanOne.cosh(), NAN);
-        assertComplex(NAN.cosh(), NAN);
+        assertConjugateEquality(Complex::cosh);
+        // AND CCOSH IS EVEN
+        assertComplex(Complex.ZERO, Complex::cosh, Complex.ONE);
+        assertComplex(negZeroZero, Complex::cosh, oneNegZero);
+        assertComplex(zeroInf, Complex::cosh, nanZero);
+        assertComplex(oneInf, Complex::cosh, NAN);
+        assertComplex(zeroNaN, Complex::cosh, nanZero);
+        assertComplex(oneNaN, Complex::cosh, NAN);
+        // (inf + iy) = inf * cis(y)
+        // where cis(y) = cos(y) + i sin(y), and y is finite non-zero
+        //
+        // Note that y == 0: complex(1, 0).multiply(inf) = (inf, NaN)
+        // But the cosh is (inf, 0). This result is computed by g++ and we test it separately.
+        assertComplex(negInfNegZero, Complex::cosh, infZero);
+        assertComplex(negInfZero, Complex::cosh, infNegZero);
+        assertComplex(infNegZero, Complex::cosh, infNegZero);
+        assertComplex(infZero, Complex::cosh, infZero);
+        for (int i = 1; i < 10; i++) {
+            final double y = i * 0.5;
+            assertComplex(complex(inf, y), Complex::cosh, Complex.ofCis(y).multiply(inf));
+            assertComplex(complex(inf, -y), Complex::cosh, Complex.ofCis(-y).multiply(inf));
+            assertComplex(complex(-inf, y), Complex::cosh, Complex.ofCis(y).multiply(-inf));
+            assertComplex(complex(-inf, -y), Complex::cosh, Complex.ofCis(-y).multiply(-inf));
+        }
+        assertComplex(negInfInf, Complex::cosh, infNaN);
+        assertComplex(infInf, Complex::cosh, infNaN);
+        assertComplex(infNaN, Complex::cosh, infNaN);
+        assertComplex(negInfNaN, Complex::cosh, infNaN);
+        assertComplex(nanZero, Complex::cosh, nanZero);
+        assertComplex(nanOne, Complex::cosh, NAN);
+        assertComplex(nanInf, Complex::cosh, NAN);
+        assertComplex(NAN, Complex::cosh, NAN);
     }
 
     /**
@@ -517,19 +638,38 @@ public class CStandardTest {
      */
     @Test
     public void testSinh() {
-        assertComplex(oneOne.sinh().conj(), oneOne.conj().sinh()); // AND CSINH IS ODD
-        assertComplex(Complex.ZERO.sinh(), Complex.ZERO);
-        assertComplex(zeroInf.sinh(), zeroNaN);
-        assertComplex(zeroNaN.sinh(), zeroNaN);
-        assertComplex(oneInf.sinh(), NAN);
-        assertComplex(oneNaN.sinh(), NAN);
-        assertComplex(infZero.sinh(), infZero);
-        // skipped test similar to previous section
-        assertComplex(infInf.sinh(), infNaN);
-        assertComplex(infNaN.sinh(), infNaN);
-        assertComplex(nanZero.sinh(), nanZero);
-        assertComplex(nanOne.sinh(), NAN);
-        assertComplex(NAN.sinh(), NAN);
+        assertConjugateEquality(Complex::sinh);
+        // AND CSINH IS ODD
+        assertComplex(Complex.ZERO, Complex::sinh, Complex.ZERO);
+        assertComplex(negZeroZero, Complex::sinh, negZeroZero);
+        assertComplex(zeroInf, Complex::sinh, zeroNaN);
+        assertComplex(oneInf, Complex::sinh, NAN);
+        assertComplex(zeroNaN, Complex::sinh, zeroNaN);
+        assertComplex(oneNaN, Complex::sinh, NAN);
+        // (inf + iy) = inf * cis(y)
+        // where cis(y) = cos(y) + i sin(y), and y is finite non-zero
+        //
+        // Note that y == 0: complex(1, 0).multiply(inf) = (inf, NaN)
+        // But the sinh is (inf, 0). This result is computed by g++ and we test it separately.
+        assertComplex(negInfNegZero, Complex::sinh, negInfNegZero);
+        assertComplex(negInfZero, Complex::sinh, negInfZero);
+        assertComplex(infNegZero, Complex::sinh, infNegZero);
+        assertComplex(infZero, Complex::sinh, infZero);
+        for (int i = 1; i < 10; i++) {
+            final double y = i * 0.5;
+            assertComplex(complex(inf, y), Complex::sinh, Complex.ofCis(y).multiply(inf));
+            assertComplex(complex(inf, -y), Complex::sinh, Complex.ofCis(-y).multiply(inf));
+            assertComplex(complex(-inf, y), Complex::sinh, Complex.ofCis(y).multiply(-inf));
+            assertComplex(complex(-inf, -y), Complex::sinh, Complex.ofCis(-y).multiply(-inf));
+        }
+        assertComplex(negInfInf, Complex::sinh, infNaN);
+        assertComplex(infInf, Complex::sinh, infNaN);
+        assertComplex(infNaN, Complex::sinh, infNaN);
+        assertComplex(negInfNaN, Complex::sinh, infNaN);
+        assertComplex(nanZero, Complex::sinh, nanZero);
+        assertComplex(nanOne, Complex::sinh, NAN);
+        assertComplex(nanInf, Complex::sinh, NAN);
+        assertComplex(NAN, Complex::sinh, NAN);
     }
 
     /**
@@ -537,16 +677,36 @@ public class CStandardTest {
      */
     @Test
     public void testTanh() {
-        assertComplex(oneOne.tanh().conj(), oneOne.conj().tanh()); // AND CSINH IS ODD
-        assertComplex(Complex.ZERO.tanh(), Complex.ZERO);
-        assertComplex(oneInf.tanh(), NAN);
-        assertComplex(oneNaN.tanh(), NAN);
-        //Do Not Understand the Next Test
-        assertComplex(infInf.tanh(), oneZero);
-        assertComplex(infNaN.tanh(), oneZero);
-        assertComplex(nanZero.tanh(), nanZero);
-        assertComplex(nanOne.tanh(), NAN);
-        assertComplex(NAN.tanh(), NAN);
+        assertConjugateEquality(Complex::tanh);
+        // AND TANH IS ODD
+        assertComplex(Complex.ZERO, Complex::tanh, Complex.ZERO);
+        assertComplex(negZeroZero, Complex::tanh, negZeroZero);
+        assertComplex(zeroInf, Complex::tanh, NAN);
+        assertComplex(oneInf, Complex::tanh, NAN);
+        assertComplex(zeroNaN, Complex::tanh, NAN);
+        assertComplex(oneNaN, Complex::tanh, NAN);
+        // (inf + iy) = 1 + i0 sin(2y), and y is positive-signed finite
+        // Note: no specification for other -inf and/or negative y.
+        // g++ returns the result using (+/-1, i0 sin(2y)) where the sign of the 1 is from the inf.
+        assertComplex(negInfNegZero, Complex::tanh, negOneNegZero);
+        assertComplex(negInfZero, Complex::tanh, negOneZero);
+        assertComplex(infNegZero, Complex::tanh, oneNegZero);
+        assertComplex(infZero, Complex::tanh, oneZero);
+        for (int i = 1; i < 10; i++) {
+            final double y = i * 0.5;
+            assertComplex(complex(inf, y), Complex::tanh, complex(1.0, Math.copySign(0, Math.sin(2 * y))));
+            assertComplex(complex(inf, -y), Complex::tanh, complex(1.0, Math.copySign(0, Math.sin(2 * -y))));
+            assertComplex(complex(-inf, y), Complex::tanh, complex(-1.0, Math.copySign(0, Math.sin(2 * y))));
+            assertComplex(complex(-inf, -y), Complex::tanh, complex(-1.0, Math.copySign(0, Math.sin(2 * -y))));
+        }
+        assertComplex(negInfInf, Complex::tanh, negOneZero);
+        assertComplex(infInf, Complex::tanh, oneZero);
+        assertComplex(infNaN, Complex::tanh, oneZero);
+        assertComplex(negInfNaN, Complex::tanh, negOneZero);
+        assertComplex(nanZero, Complex::tanh, nanZero);
+        assertComplex(nanOne, Complex::tanh, NAN);
+        assertComplex(nanInf, Complex::tanh, NAN);
+        assertComplex(NAN, Complex::tanh, NAN);
     }
 
     /**
@@ -554,20 +714,37 @@ public class CStandardTest {
      */
     @Test
     public void testExp() {
-        assertComplex(oneOne.conj().exp(), oneOne.exp().conj());
-        assertComplex(Complex.ZERO.exp(), oneZero);
-        assertComplex(negZeroZero.exp(), oneZero);
-        assertComplex(oneInf.exp(), NAN);
-        assertComplex(oneNaN.exp(), NAN);
-        assertComplex(infZero.exp(), infZero);
-        // Do not understand next test
-        assertComplex(negInfInf.exp(), Complex.ZERO);
-        assertComplex(infInf.exp(), infNaN);
-        assertComplex(negInfNaN.exp(), Complex.ZERO);
-        assertComplex(infNaN.exp(), infNaN);
-        assertComplex(nanZero.exp(), nanZero);
-        assertComplex(nanOne.exp(), NAN);
-        assertComplex(NAN.exp(), NAN);
+        assertConjugateEquality(Complex::exp);
+        assertComplex(Complex.ZERO, Complex::exp, oneZero);
+        assertComplex(negZeroZero, Complex::exp, oneZero);
+        assertComplex(zeroInf, Complex::exp, NAN);
+        assertComplex(oneInf, Complex::exp, NAN);
+        assertComplex(zeroNaN, Complex::exp, NAN);
+        assertComplex(oneNaN, Complex::exp, NAN);
+        assertComplex(infNegZero, Complex::exp, infNegZero);
+        assertComplex(infZero, Complex::exp, infZero);
+        // (-inf + iy) = +0 cis(y)
+        // where cis(y) = cos(y) + i sin(y), and y is finite
+        for (int i = 0; i < 10; i++) {
+            final double y = i * 0.5;
+            assertComplex(complex(-inf, y), Complex::exp, Complex.ofCis(y).multiply(0.0));
+            assertComplex(complex(-inf, -y), Complex::exp, Complex.ofCis(-y).multiply(0.0));
+        }
+        // (inf + iy) = +inf cis(y)
+        // where cis(y) = cos(y) + i sin(y), and y is non-zero finite
+        for (int i = 1; i < 10; i++) {
+            final double y = i * 0.5;
+            assertComplex(complex(inf, y), Complex::exp, Complex.ofCis(y).multiply(inf));
+            assertComplex(complex(inf, -y), Complex::exp, Complex.ofCis(-y).multiply(inf));
+        }
+        assertComplex(negInfInf, Complex::exp, Complex.ZERO);
+        assertComplex(infInf, Complex::exp, infNaN);
+        assertComplex(negInfNaN, Complex::exp, Complex.ZERO);
+        assertComplex(infNaN, Complex::exp, infNaN);
+        assertComplex(nanZero, Complex::exp, nanZero);
+        assertComplex(nanOne, Complex::exp, NAN);
+        assertComplex(nanInf, Complex::exp, NAN);
+        assertComplex(NAN, Complex::exp, NAN);
     }
 
     /**
@@ -575,38 +752,52 @@ public class CStandardTest {
      */
     @Test
     public void testLog() {
-        assertComplex(oneOne.log().conj(), oneOne.conj().log());
-        assertComplex(negZeroZero.log(), negInfPi);
-        assertComplex(Complex.ZERO.log(), negInfZero);
-        assertComplex(oneInf.log(), infPiTwo);
-        assertComplex(oneNaN.log(), NAN);
-        assertComplex(negInfOne.log(), infPi);
-        assertComplex(infOne.log(), infZero);
-        assertComplex(infInf.log(), infPiFour);
-        assertComplex(infNaN.log(), infNaN);
-        assertComplex(nanOne.log(), NAN);
-        assertComplex(nanInf.log(), infNaN);
-        assertComplex(NAN.log(), NAN);
+        assertConjugateEquality(Complex::log);
+        assertComplex(negZeroZero, Complex::log, negInfPi);
+        assertComplex(Complex.ZERO, Complex::log, negInfZero);
+        assertComplex(zeroInf, Complex::log, infPiTwo);
+        assertComplex(oneInf, Complex::log, infPiTwo);
+        assertComplex(zeroNaN, Complex::log, NAN);
+        assertComplex(oneNaN, Complex::log, NAN);
+        assertComplex(negInfZero, Complex::log, infPi);
+        assertComplex(negInfOne, Complex::log, infPi);
+        assertComplex(infZero, Complex::log, infZero);
+        assertComplex(infOne, Complex::log, infZero);
+        assertComplex(negInfInf, Complex::log, infThreePiFour);
+        assertComplex(infInf, Complex::log, infPiFour);
+        assertComplex(negInfNaN, Complex::log, infNaN);
+        assertComplex(infNaN, Complex::log, infNaN);
+        assertComplex(nanZero, Complex::log, NAN);
+        assertComplex(nanOne, Complex::log, NAN);
+        assertComplex(nanInf, Complex::log, infNaN);
+        assertComplex(NAN, Complex::log, NAN);
     }
 
     /**
-     * Same edge cases as log() since the real component is divided by Math.log(10) whic
+     * Same edge cases as log() since the real component is divided by Math.log(10) which
      * has no effect on infinite or nan.
      */
     @Test
     public void testLog10() {
-        assertComplex(oneOne.log10().conj(), oneOne.conj().log10());
-        assertComplex(negZeroZero.log10(), negInfPi);
-        assertComplex(Complex.ZERO.log10(), negInfZero);
-        assertComplex(oneInf.log10(), infPiTwo);
-        assertComplex(oneNaN.log10(), NAN);
-        assertComplex(negInfOne.log10(), infPi);
-        assertComplex(infOne.log10(), infZero);
-        assertComplex(infInf.log10(), infPiFour);
-        assertComplex(infNaN.log10(), infNaN);
-        assertComplex(nanOne.log10(), NAN);
-        assertComplex(nanInf.log10(), infNaN);
-        assertComplex(NAN.log10(), NAN);
+        assertConjugateEquality(Complex::log10);
+        assertComplex(negZeroZero, Complex::log10, negInfPi);
+        assertComplex(Complex.ZERO, Complex::log10, negInfZero);
+        assertComplex(zeroInf, Complex::log10, infPiTwo);
+        assertComplex(oneInf, Complex::log10, infPiTwo);
+        assertComplex(zeroNaN, Complex::log10, NAN);
+        assertComplex(oneNaN, Complex::log10, NAN);
+        assertComplex(negInfZero, Complex::log10, infPi);
+        assertComplex(negInfOne, Complex::log10, infPi);
+        assertComplex(infZero, Complex::log10, infZero);
+        assertComplex(infOne, Complex::log10, infZero);
+        assertComplex(negInfInf, Complex::log10, infThreePiFour);
+        assertComplex(infInf, Complex::log10, infPiFour);
+        assertComplex(negInfNaN, Complex::log10, infNaN);
+        assertComplex(infNaN, Complex::log10, infNaN);
+        assertComplex(nanZero, Complex::log10, NAN);
+        assertComplex(nanOne, Complex::log10, NAN);
+        assertComplex(nanInf, Complex::log10, infNaN);
+        assertComplex(NAN, Complex::log10, NAN);
     }
 
     /**
@@ -614,14 +805,25 @@ public class CStandardTest {
      */
     @Test
     public void testSqrt2() {
-        assertComplex(oneOne.sqrt().conj(), oneOne.conj().sqrt());
-        assertComplex(Complex.ZERO.sqrt(), Complex.ZERO);
-        assertComplex(oneInf.sqrt(), infInf);
-        assertComplex(negInfOne.sqrt(), zeroNaN);
-        assertComplex(infOne.sqrt(), infZero);
-        assertComplex(negInfNaN.sqrt(), nanInf);
-        assertComplex(infNaN.sqrt(), infNaN);
-        assertComplex(nanOne.sqrt(), NAN);
-        assertComplex(NAN.sqrt(), NAN);
+        assertConjugateEquality(Complex::sqrt);
+        assertComplex(negZeroZero, Complex::sqrt, Complex.ZERO);
+        assertComplex(Complex.ZERO, Complex::sqrt, Complex.ZERO);
+        assertComplex(zeroNegZero, Complex::sqrt, zeroNegZero);
+        assertComplex(negZeroNegZero, Complex::sqrt, zeroNegZero);
+        assertComplex(zeroInf, Complex::sqrt, infInf);
+        assertComplex(oneInf, Complex::sqrt, infInf);
+        assertComplex(infInf, Complex::sqrt, infInf);
+        assertComplex(nanInf, Complex::sqrt, infInf);
+        assertComplex(zeroNaN, Complex::sqrt, NAN);
+        assertComplex(oneNaN, Complex::sqrt, NAN);
+        assertComplex(negInfZero, Complex::sqrt, zeroInf);
+        assertComplex(negInfOne, Complex::sqrt, zeroInf);
+        assertComplex(infZero, Complex::sqrt, infZero);
+        assertComplex(infOne, Complex::sqrt, infZero);
+        assertComplex(negInfNaN, Complex::sqrt, nanInf);
+        assertComplex(infNaN, Complex::sqrt, infNaN);
+        assertComplex(nanZero, Complex::sqrt, NAN);
+        assertComplex(nanOne, Complex::sqrt, NAN);
+        assertComplex(NAN, Complex::sqrt, NAN);
     }
 }


[commons-numbers] 01/02: commons-rng 1.2 -> 1.3

Posted by ah...@apache.org.
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 694e8d81231da3efbd7068731694fa146b91b4cb
Author: aherbert <ah...@apache.org>
AuthorDate: Wed Dec 4 10:11:21 2019 +0000

    commons-rng 1.2 -> 1.3
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 77c64c5..a7a1f54 100644
--- a/pom.xml
+++ b/pom.xml
@@ -63,7 +63,7 @@
     <numbers.mathjax.version>2.7.2</numbers.mathjax.version>
     <numbers.junit.bom.version>5.4.2</numbers.junit.bom.version>
     <numbers.commons.math3.version>3.6.1</numbers.commons.math3.version>
-    <numbers.commons.rng.version>1.2</numbers.commons.rng.version>
+    <numbers.commons.rng.version>1.3</numbers.commons.rng.version>
     <!-- Workaround to avoid duplicating config files. -->
     <numbers.parent.dir>${basedir}</numbers.parent.dir>