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 2020/01/02 15:04:44 UTC
[commons-numbers] 02/04: Update C99 standard for acosh and tanh
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 f1b8cc31888aa284e39249708787b37164c5d436
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Wed Jan 1 22:49:41 2020 +0000
Update C99 standard for acosh and tanh
See:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1892.htm#dr_471
---
.../apache/commons/numbers/complex/Complex.java | 31 ++++++++++++++++------
.../commons/numbers/complex/CStandardTest.java | 17 +++++++++---
2 files changed, 37 insertions(+), 11 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 5b710a2..79b2408 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
@@ -1785,7 +1785,8 @@ public final class Complex implements Serializable {
* <li>{@code z.conj().acosh() == z.acosh().conj()}.
* <li>If {@code z} is ±0 + i0, returns +0 + iπ/2.
* <li>If {@code z} is x + i∞ for finite x, returns +∞ + iπ/2.
- * <li>If {@code z} is x + iNaN for finite x, returns NaN + iNaN.
+ * <li>If {@code z} is 0 + iNaN, returns NaN + iπ/2 <sup>[1]</sup>.
+ * <li>If {@code z} is x + iNaN for finite non-zero x, returns NaN + iNaN.
* <li>If {@code z} is −∞ + iy for positive-signed finite y, returns +∞ + iπ.
* <li>If {@code z} is +∞ + iy for positive-signed finite y, returns +∞ + i0.
* <li>If {@code z} is −∞ + i∞, returns +∞ + i3π/4.
@@ -1796,6 +1797,10 @@ public final class Complex implements Serializable {
* <li>If {@code z} is NaN + iNaN, returns NaN + iNaN.
* </ul>
*
+ * <p>[1] This has been updated as per
+ * <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1892.htm#dr_471">
+ * DR 471: Complex math functions cacosh and ctanh</a>.
+ *
* <p>This function is computed using the trigonomic identity:
*
* <p>\[ \cosh^{-1}(z) = \pm i \cos^{-1}(z) \]
@@ -1809,11 +1814,13 @@ public final class Complex implements Serializable {
public Complex acosh() {
// Define in terms of acos
// acosh(z) = +-i acos(z)
- // Handle special case:
+ // Note the special case:
// acos(+-0 + iNaN) = π/2 + iNaN
- // acosh(x + iNaN) = NaN + iNaN for all finite x (including zero)
- if (Double.isNaN(imaginary) && Double.isFinite(real)) {
- return NAN;
+ // acosh(0 + iNaN) = NaN + iπ/2
+ // will not appropriately multiply by I to maintain positive imaginary if
+ // acos() imaginary computes as NaN. So do this explicitly.
+ if (Double.isNaN(imaginary) && real == 0) {
+ return new Complex(Double.NaN, PI_OVER_2);
}
return acos(real, imaginary, (re, im) ->
// Set the sign appropriately for real >= 0
@@ -2517,6 +2524,8 @@ public final class Complex implements Serializable {
return tanh(-imaginary, real, Complex::multiplyNegativeI);
}
+ // TODO
+
/**
* Returns the
* <a href="http://mathworld.wolfram.com/HyperbolicTangent.html">
@@ -2535,8 +2544,10 @@ public final class Complex implements Serializable {
* <li>{@code z.conj().tanh() == z.tanh().conj()}.
* <li>This is an odd function: \( \tanh(z) = -\tanh(-z) \).
* <li>If {@code z} is +0 + i0, returns +0 + i0.
- * <li>If {@code z} is x + i∞ for finite x, returns NaN + iNaN.
- * <li>If {@code z} is x + iNaN for finite x, returns NaN + iNaN.
+ * <li>If {@code z} is 0 + i∞, returns 0 + iNaN.
+ * <li>If {@code z} is x + i∞ for finite non-zero x, returns NaN + iNaN.
+ * <li>If {@code z} is 0 + iNaN, returns 0 + iNAN.
+ * <li>If {@code z} is x + iNaN for finite non-zero x, returns NaN + iNaN.
* <li>If {@code z} is +∞ + iy for positive-signed finite y, returns 1 + i0 sin(2y).
* <li>If {@code z} is +∞ + i∞, returns 1 ± i0 (where the sign of the imaginary part of the result is unspecified).
* <li>If {@code z} is +∞ + iNaN, returns 1 ± i0 (where the sign of the imaginary part of the result is unspecified).
@@ -2545,6 +2556,10 @@ public final class Complex implements Serializable {
* <li>If {@code z} is NaN + iNaN, returns NaN + iNaN.
* </ul>
*
+ * <p>[1] This has been updated as per
+ * <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1892.htm#dr_471">
+ * DR 471: Complex math functions cacosh and ctanh</a>.
+ *
* <p>This is implemented using real \( x \) and imaginary \( y \) parts:
*
* <p>\[ \tan(x + iy) = \frac{\sinh(2x)}{\cosh(2x)+\cos(2y)} + i \frac{\sin(2y)}{\cosh(2x)+\cos(2y)} \]
@@ -2581,7 +2596,7 @@ public final class Complex implements Serializable {
// Identity: sin x / (1 + cos x) = tan(x/2)
return constructor.create(real, Math.tan(imaginary));
}
- return constructor.create(Double.NaN, Double.NaN);
+ return constructor.create(real, Double.NaN);
}
if (imaginary == 0) {
if (Double.isNaN(real)) {
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 b47ec5e..374d565 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
@@ -65,6 +65,7 @@ public class CStandardTest {
private static final Complex nanInf = complex(nan, inf);
private static final Complex nanNegInf = complex(nan, negInf);
private static final Complex nanZero = complex(nan, 0);
+ private static final Complex nanPiTwo = complex(nan, piOverTwo);
private static final Complex piTwoNaN = complex(piOverTwo, nan);
private static final Complex piNegInf = complex(Math.PI, negInf);
private static final Complex piTwoNegInf = complex(piOverTwo, negInf);
@@ -819,6 +820,9 @@ public class CStandardTest {
/**
* ISO C Standard G.6.2.1.
+ *
+ * @see <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1892.htm#dr_471">
+ * Complex math functions cacosh and ctanh</a>
*/
@Test
public void testAcosh() {
@@ -829,7 +833,9 @@ public class CStandardTest {
for (double x : finite) {
assertComplex(complex(x, inf), operation, infPiTwo);
}
- for (double x : finite) {
+ assertComplex(zeroNaN, operation, nanPiTwo);
+ assertComplex(negZeroNaN, operation, nanPiTwo);
+ for (double x : nonZeroFinite) {
assertComplex(complex(x, nan), operation, NAN);
}
for (double y : positiveFinite) {
@@ -974,6 +980,9 @@ public class CStandardTest {
/**
* ISO C Standard G.6.2.6.
+ *
+ * @see <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1892.htm#dr_471">
+ * Complex math functions cacosh and ctanh</a>
*/
@Test
public void testTanh() {
@@ -982,10 +991,12 @@ public class CStandardTest {
assertConjugateEquality(operation);
assertFunctionType(operation, type);
assertComplex(Complex.ZERO, operation, Complex.ZERO, type);
- for (double x : finite) {
+ assertComplex(zeroInf, operation, zeroNaN, type);
+ for (double x : nonZeroFinite) {
assertComplex(complex(x, inf), operation, NAN, type);
}
- for (double x : finite) {
+ assertComplex(zeroNaN, operation, zeroNaN, type);
+ for (double x : nonZeroFinite) {
assertComplex(complex(x, nan), operation, NAN, type);
}
for (double y : positiveFinite) {