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 2022/07/28 09:33:31 UTC
[commons-numbers] branch complex-gsoc-2022 updated: NUMBERS-188: Refactor complex scalar binary functions to static methods
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch complex-gsoc-2022
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
The following commit(s) were added to refs/heads/complex-gsoc-2022 by this push:
new 9510b535 NUMBERS-188: Refactor complex scalar binary functions to static methods
9510b535 is described below
commit 9510b535cb466171d686d846dc8d8c2c9b4c6433
Author: sumanth-rajkumar <53...@users.noreply.github.com>
AuthorDate: Thu Jul 28 05:33:25 2022 -0400
NUMBERS-188: Refactor complex scalar binary functions to static methods
Refactored binary methods accepting a scalar double as the second argument.
---
.../numbers/complex/ComplexBinaryOperator.java | 8 +-
.../commons/numbers/complex/ComplexFunctions.java | 334 ++++++++++++++++++++-
...aryOperator.java => ComplexScalarFunction.java} | 23 +-
.../numbers/complex/ComplexUnaryOperator.java | 5 +-
.../commons/numbers/complex/CStandardTest.java | 48 +--
.../commons/numbers/complex/ComplexTest.java | 327 +++++++++++---------
.../apache/commons/numbers/complex/TestUtils.java | 66 ++++
7 files changed, 623 insertions(+), 188 deletions(-)
diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexBinaryOperator.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexBinaryOperator.java
index 6714e78e..d30ee297 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexBinaryOperator.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexBinaryOperator.java
@@ -38,10 +38,10 @@ public interface ComplexBinaryOperator<R> {
*
* @param real1 Real part \( a \) of the first complex number \( (a +ib) \).
* @param imaginary1 Imaginary part \( b \) of the first complex number \( (a +ib) \).
- * @param real2 Real part \( a \) of the second complex number \( (a +ib) \).
- * @param imaginary2 Imaginary part \( b \) of the second complex number \( (a +ib) \).
- * @param out Consumer for the complex result.
+ * @param real2 Real part \( c \) of the second complex number \( (c +id) \).
+ * @param imaginary2 Imaginary part \( d \) of the second complex number \( (c +id) \).
+ * @param action Consumer for the complex result.
* @return the object returned by the provided consumer.
*/
- R apply(double real1, double imaginary1, double real2, double imaginary2, ComplexSink<R> out);
+ R apply(double real1, double imaginary1, double real2, double imaginary2, ComplexSink<R> action);
}
diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexFunctions.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexFunctions.java
index 1b7445f4..1917aa1b 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexFunctions.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexFunctions.java
@@ -228,7 +228,7 @@ public final class ComplexFunctions {
* Returns the argument of the complex number.
*
* <p>The argument is the angle phi between the positive real axis and
- * the point representing this number in the complex plane.
+ * the point representing the number in the complex plane.
* The value returned is between \( -\pi \) (not inclusive)
* and \( \pi \) (inclusive), with negative values returned for numbers with
* negative imaginary parts.
@@ -406,8 +406,8 @@ public final class ComplexFunctions {
*
* @param real1 Real part \( a \) of the first complex number \( (a +ib) \).
* @param imaginary1 Imaginary part \( b \) of the first complex number \( (a +ib) \).
- * @param real2 Real part \( a \) of the second complex number \( (a +ib) \).
- * @param imaginary2 Imaginary part \( b \) of the second complex number \( (a +ib) \).
+ * @param real2 Real part \( c \) of the second complex number \( (c +id) \).
+ * @param imaginary2 Imaginary part \( d \) of the second complex number \( (a +id) \).
* @param action Consumer for the addition result.
* @param <R> the return type of the supplied action.
* @return the object returned by the supplied action.
@@ -420,6 +420,58 @@ public final class ComplexFunctions {
imaginary1 + imaginary2);
}
+ /**
+ * Computes the result of the addition of a complex number and a real number.
+ * Implements the formula:
+ *
+ * <p>\[ (a + i b) + c = (a + c) + i b \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * real-only and complex numbers.</p>
+ *
+ * <p>Note: This method preserves the sign of the imaginary component \( b \) if it is {@code -0.0}.
+ * The sign would be lost if adding \( (c + i 0) \) using
+ * {@link #add(double, double, double, double, ComplexSink) add(real, imaginary, addend, 0, action)} since
+ * {@code -0.0 + 0.0 = 0.0}.
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param addend Value to be added to the complex number.
+ * @param action Consumer for the addition result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #add(double, double, double, double, ComplexSink)
+ */
+ public static <R> R add(double real, double imaginary, double addend, ComplexSink<R> action) {
+ return action.apply(real + addend, imaginary);
+ }
+
+ /**
+ * Computes the result of the addition of a complex number and an imaginary number.
+ * Implements the formula:
+ *
+ * <p>\[ (a + i b) + i d = a + i (b + d) \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * imaginary-only and complex numbers.</p>
+ *
+ * <p>Note: This method preserves the sign of the real component \( a \) if it is {@code -0.0}.
+ * The sign would be lost if adding \( (0 + i d) \) using
+ * {@link #add(double, double, double, double, ComplexSink) add(real, imaginary, 0, addend, action)} since
+ * {@code -0.0 + 0.0 = 0.0}.
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param addend Value to be added to the complex number.
+ * @param action Consumer for the addition result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #add(double, double, double, double, ComplexSink)
+ */
+ public static <R> R addImaginary(double real, double imaginary, double addend, ComplexSink<R> action) {
+ return action.apply(real, imaginary + addend);
+ }
+
/**
* Returns a {@code Object} whose value is {@code (real1 - real2, imaginary1 - imaginary2)}.
* Implements the formula:
@@ -428,8 +480,8 @@ public final class ComplexFunctions {
*
* @param real1 Real part \( a \) of the first complex number \( (a +ib) \).
* @param imaginary1 Imaginary part \( b \) of the first complex number \( (a +ib) \).
- * @param real2 Real part \( a \) of the second complex number \( (a +ib) \).
- * @param imaginary2 Imaginary part \( b \) of the second complex number \( (a +ib) \).
+ * @param real2 Real part \( c \) of the second complex number \( (c +id) \).
+ * @param imaginary2 Imaginary part \( d \) of the second complex number \( (c +id) \).
* @param action Consumer for the subtraction result.
* @param <R> the return type of the supplied action.
* @return the object returned by the supplied action.
@@ -442,6 +494,99 @@ public final class ComplexFunctions {
imaginary1 - imaginary2);
}
+ /**
+ * Returns a {@code Object} whose value is {@code (real - subtrahend, imaginary)},
+ * with {@code subtrahend} interpreted as a real number.
+ * Implements the formula:
+ *
+ * <p>\[ (a + i b) - c = (a - c) + i b \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * real-only and complex numbers.</p>
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param subtrahend Value to be subtracted from the complex number.
+ * @param action Consumer for the subtraction result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #subtract(double, double, double, double, ComplexSink)
+ */
+ public static <R> R subtract(double real, double imaginary, double subtrahend, ComplexSink<R> action) {
+ return action.apply(real - subtrahend, imaginary);
+ }
+
+ /**
+ * Computes the result of the subtraction of an imaginary number from a complex number.
+ * Implements the formula:
+ *
+ * <p>\[ (a + i b) - i d = a + i (b - d) \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * imaginary-only and complex numbers.</p>
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param subtrahend Value to be subtracted from the complex number.
+ * @param action Consumer for the subtraction result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #subtract(double, double, double, double, ComplexSink)
+ */
+ public static <R> R subtractImaginary(double real, double imaginary, double subtrahend, ComplexSink<R> action) {
+ return action.apply(real, imaginary - subtrahend);
+ }
+
+ /**
+ * Computes the result of the subtraction of a complex number from a real number.
+ * Implements the formula:
+ * \[ c - (a + i b) = (c - a) - i b \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * real-only and complex numbers.</p>
+ *
+ * <p>Note: This method inverts the sign of the imaginary component \( b \) if it is {@code 0.0}.
+ * The sign would not be inverted if subtracting from \( c + i 0 \) using
+ * {@link #subtract(double, double, double, double, ComplexSink) subtract(minuend, 0, real, imaginary, action)} since
+ * {@code 0.0 - 0.0 = 0.0}.
+ *
+ * @param minuend Value the complex number is to be subtracted from.
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param action Consumer for the subtraction result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #subtract(double, double, double, double, ComplexSink)
+ */
+ public static <R> R realSubtract(double minuend, double real, double imaginary, ComplexSink<R> action) {
+ return action.apply(minuend - real, -imaginary);
+ }
+
+ /**
+ * Computes the result of the subtraction of a complex number from an imaginary number.
+ * Implements the formula:
+ * \[ i d - (a + i b) = -a + i (d - b) \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * imaginary-only and complex numbers.</p>
+ *
+ * <p>Note: This method inverts the sign of the real component \( a \) if it is {@code 0.0}.
+ * The sign would not be inverted if subtracting from \( 0 + i d \) using
+ * {@link #subtract(double, double, double, double, ComplexSink) subtract(0, minuend, real, imaginary, action)} since
+ * {@code 0.0 - 0.0 = 0.0}.
+ *
+ * @param minuend Value the complex number is to be subtracted from.
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param action Consumer for the subtraction result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #subtract(double, double, double, double, ComplexSink)
+ */
+ public static <R> R imaginarySubtract(double minuend, double real, double imaginary, ComplexSink<R> action) {
+ return action.apply(-real, minuend - imaginary);
+ }
+
/**
* Returns a {@code Object} whose value is {@code (real1 + i*imaginary1) * (real2 + i*imaginary2))}.
* Implements the formula:
@@ -453,7 +598,7 @@ public final class ComplexFunctions {
* @param real1 Real part \( a \) of the first complex number \( (a +ib) \).
* @param imaginary1 Imaginary part \( b \) of the first complex number \( (a +ib) \).
* @param real2 Real part \( a \) of the second complex number \( (a +ib) \).
- * @param imaginary2 Imaginary part \( b \) of the second complex number \( (a +ib) \).
+ * @param imaginary2 Imaginary part \( d \) of the second complex number \( (c +id) \).
* @param action Consumer for the multiplication result.
* @param <R> the return type of the supplied action.
* @return the object returned by the supplied action.
@@ -570,6 +715,70 @@ public final class ComplexFunctions {
return Double.isNaN(value) ? Math.copySign(0.0, value) : value;
}
+ /**
+ * Computes the result of the multiplication of a complex number and a real number.
+ * Implements the formula:
+ *
+ * <p>\[ (a + i b) c = (ac) + i (bc) \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * real-only and complex numbers.</p>
+ *
+ * <p>Note: This method should be preferred over using
+ * {@link #multiply(double, double, double, double, ComplexSink) multiply(a, b, factor, 0, action)}. Multiplication
+ * can generate signed zeros if either the complex has zeros for the real
+ * and/or imaginary component, or if the factor is zero. The summation of signed zeros
+ * in {@link #multiply(double, double, double, double, ComplexSink)} may create zeros in the result that differ in sign
+ * from the equivalent call to multiply by a real-only number.
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param factor Value to be multiplied by the complex number.
+ * @param action Consumer for the multiplication result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action
+ * @see #multiply(double, double, double, double, ComplexSink)
+ */
+ public static <R> R multiply(double real, double imaginary, double factor, ComplexSink<R> action) {
+ return action.apply(real * factor, imaginary * factor);
+ }
+
+ /**
+ * Computes the result of the multiplication of a complex number and an imaginary number.
+ * Implements the formula:
+ *
+ * <p>\[ (a + i b) id = (-bd) + i (ad) \]
+ *
+ * <p>This method can be used to compute the multiplication of the complex number \( z \)
+ * by \( i \) using a factor with magnitude 1.0. This should be used in preference to
+ * {@link #multiply(double, double, double, double, ComplexSink) multiply(Complex.I)} with or without {@link #negate(double, double, ComplexSink) negation}:</p>
+ *
+ * \[ \begin{aligned}
+ * iz &= (-b + i a) \\
+ * -iz &= (b - i a) \end{aligned} \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * imaginary-only and complex numbers.</p>
+ *
+ * <p>Note: This method should be preferred over using
+ * {@link #multiply(double, double, double, double, ComplexSink) multiply(a, b, 0, factor, action)}. Multiplication
+ * can generate signed zeros if either the complex has zeros for the real
+ * and/or imaginary component, or if the factor is zero. The summation of signed zeros
+ * in {@link #multiply(double, double, double, double, ComplexSink)} may create zeros in the result that differ in sign
+ * from the equivalent call to multiply by an imaginary-only number.
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param factor Value to be multiplied by the complex number.
+ * @param action Consumer for the multiplication result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #multiply(double, double, double, double, ComplexSink)
+ */
+ public static <R> R multiplyImaginary(double real, double imaginary, double factor, ComplexSink<R> action) {
+ return action.apply(-imaginary * factor, real * factor);
+ }
+
/**
* Returns a {@code Object} whose value is {@code (real1 + i*imaginary1)/(real2 + i*imaginary2)}.
* Implements the formula:
@@ -579,18 +788,18 @@ public final class ComplexFunctions {
* <p>Re-calculates NaN result values to recover infinities as specified in C99 standard G.5.1.
*
* <p>Note: In the event of divide by zero this method produces the same result
- * as dividing by a real-only zero using (add divide reference)
+ * as dividing by a real-only zero using {@link #divide(double, double, double, ComplexSink)}.
*
* @param real1 Real part \( a \) of the first complex number \( (a +ib) \).
* @param imaginary1 Imaginary part \( b \) of the first complex number \( (a +ib) \).
- * @param real2 Real part \( a \) of the second complex number \( (a +ib) \).
- * @param imaginary2 Imaginary part \( b \) of the second complex number \( (a +ib) \).
+ * @param real2 Real part \( c \) of the second complex number \( (c +id) \).
+ * @param imaginary2 Imaginary part \( d \) of the second complex number \( (c +id) \).
* @param action Consumer for the division result.
* @param <R> the return type of the supplied action.
* @return the object returned by the supplied action.
* @see <a href="http://mathworld.wolfram.com/ComplexDivision.html">Complex Division</a>
+ * @see #divide(double, double, double, ComplexSink)
*/
- //TODO - add divide reference once moved to ComplexFunctions
public static <R> R divide(double real1, double imaginary1,
double real2, double imaginary2,
ComplexSink<R> action) {
@@ -651,6 +860,71 @@ public final class ComplexFunctions {
return action.apply(x, y);
}
+ /**
+ * Computes the result of the division of a complex number by a real number.
+ * Implements the formula:
+ *
+ * <p>\[ \frac{a + i b}{c} = \frac{a}{c} + i \frac{b}{c} \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * real-only and complex numbers.</p>
+ *
+ * <p>Note: This method should be preferred over using
+ * {@link #divide(double, double, double, double, ComplexSink) divide(a, b, divisor, 0, action)}. Division
+ * can generate signed zeros if the complex has zeros for the real
+ * and/or imaginary component, or the divisor is infinite. The summation of signed zeros
+ * in {@link #divide(double, double, double, double, ComplexSink)} may create zeros in the result that differ in sign
+ * from the equivalent call to divide by a real-only number.
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param divisor Value by which the complex number is to be divided.
+ * @param action Consumer for the division result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #divide(double, double, double, double, ComplexSink)
+ */
+ public static <R> R divide(double real, double imaginary, double divisor, ComplexSink<R> action) {
+ return action.apply(real / divisor, imaginary / divisor);
+ }
+
+ /**
+ * Computes the result of the division of a complex number by an imaginary number.
+ * Implements the formula:
+ *
+ * <p>\[ \frac{a + i b}{id} = \frac{b}{d} - i \frac{a}{d} \]
+ *
+ * <p>This method is included for compatibility with ISO C99 which defines arithmetic between
+ * imaginary-only and complex numbers.</p>
+ *
+ * <p>Note: This method should be preferred over using
+ * {@link #divide(double, double, double, double, ComplexSink) divide(a, b, 0, divisor, action)}. Division
+ * can generate signed zeros if the complex has zeros for the real
+ * and/or imaginary component, or the divisor is infinite. The summation of signed zeros
+ * in {@link #divide(double, double, double, double, ComplexSink)} may create zeros in the result that differ in sign
+ * from the equivalent call to divide by an imaginary-only number.
+ *
+ * <p>Warning: This method will generate a different result from
+ * {@link #divide(double, double, double, double, ComplexSink) divide(a, b, 0, divisor, action)} if the divisor is zero.
+ * In this case the divide method using a zero-valued Complex will produce the same result
+ * as dividing by a real-only zero. The output from dividing by imaginary zero will create
+ * infinite and NaN values in the same component parts as the output from
+ * {@code divide(real, imaginary, Complex.ZERO, action).multiplyImaginary(real, imaginary, 1, action)}, however the sign
+ * of some infinite values may be negated.
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param divisor Value by which the complex number is to be divided.
+ * @param action Consumer for the division result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #divide(double, double, double, double, ComplexSink)
+ * @see #divide(double, double, double, ComplexSink)
+ */
+ public static <R> R divideImaginary(double real, double imaginary, double divisor, ComplexSink<R> action) {
+ return action.apply(imaginary / divisor, -real / divisor);
+ }
+
/**
* Returns the
* <a href="http://mathworld.wolfram.com/ExponentialFunction.html">
@@ -945,8 +1219,8 @@ public final class ComplexFunctions {
*
* @param real1 Real part \( a \) of the first complex number \( (a +ib) \).
* @param imaginary1 Imaginary part \( b \) of the first complex number \( (a +ib) \).
- * @param real2 Real part \( a \) of the second complex number \( (a +ib) \).
- * @param imaginary2 Imaginary part \( b \) of the second complex number \( (a +ib) \).
+ * @param real2 Real part \( c \) of the second complex number \( (c +id) \).
+ * @param imaginary2 Imaginary part \( d \) of the second complex number \( (c +id) \).
* @param action Consumer for the power result.
* @param <R> the return type of the supplied action.
* @return the object returned by the supplied action.
@@ -971,6 +1245,42 @@ public final class ComplexFunctions {
return log(real1, imaginary1, (x, y) -> multiply(x, y, real2, imaginary2, (a, b) -> exp(a, b, action)));
}
+ /**
+ * Returns the complex power of the complex number raised to the power of {@code x},
+ * with {@code x} interpreted as a real number.
+ * Implements the formula:
+ *
+ * <p>\[ z^x = e^{x \ln(z)} \]
+ *
+ * <p>If the complex number is zero then this method returns zero if {@code x} is positive;
+ * otherwise it returns NaN + iNaN.
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param x The exponent to which the complex number is to be raised.
+ * @param action Consumer for the power result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ * @see #log(double, double, ComplexSink)
+ * @see #multiply(double, double, double, ComplexSink)
+ * @see #exp(double, double, ComplexSink)
+ * @see #pow(double, double, double, double, ComplexSink)
+ * @see <a href="http://functions.wolfram.com/ElementaryFunctions/Power/">Power</a>
+ */
+ public static <R> R pow(double real, double imaginary, double x, ComplexSink<R> action) {
+ if (real == 0 &&
+ imaginary == 0) {
+ // This value is zero. Test the other.
+ if (x > 0) {
+ // 0 raised to positive number is 0
+ return action.apply(0, 0);
+ }
+ // 0 raised to anything else is NaN
+ return action.apply(Double.NaN, Double.NaN);
+ }
+ return log(real, imaginary, (y, z) -> multiply(y, z, x, (a, b) -> exp(a, b, action)));
+ }
+
/**
* Returns the
* <a href="http://mathworld.wolfram.com/SquareRoot.html">
diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUnaryOperator.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexScalarFunction.java
similarity index 58%
copy from commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUnaryOperator.java
copy to commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexScalarFunction.java
index a9bae229..b339f5a3 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUnaryOperator.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexScalarFunction.java
@@ -18,27 +18,30 @@
package org.apache.commons.numbers.complex;
/**
- * Represents a unary operation on a Cartesian form of a complex number \( a + ib \)
- * where \( a \) and \( b \) are real numbers represented as two {@code double}
- * parts. The operation creates a complex number result; the result is supplied
- * to a terminating consumer function which may return an object representation
- * of the complex result.
+ * Represents a binary operation on a Cartesian form of a complex number \( a + ib \)
+ * and a {@code double} scalar operand, where \( a \) and \( b \) are real numbers represented as two {@code double}
+ * The operation creates a complex number result; the result is supplied to a terminating consumer function
+ * which may return an object representation of the complex result.
*
* <p>This is a functional interface whose functional method is
- * {@link #apply(double, double, ComplexSink)}.
+ * {@link #apply(double, double, double, ComplexSink)}.
*
* @param <R> The type of the complex result
* @since 1.1
*/
@FunctionalInterface
-public interface ComplexUnaryOperator<R> {
+public interface ComplexScalarFunction<R> {
/**
- * Represents an operator that accepts real and imaginary parts of a complex number and supplies the complex result to the provided consumer.
+ * Represents a binary function that accepts a Complex number's real and imaginary parts
+ * and a double operand to produce a Complex result.
+ * The complex result is supplied to the provided consumer.
+ *
* @param real Real part \( a \) of the complex number \( (a +ib) \).
* @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
- * @param out Consumer for the complex result.
+ * @param operand Scalar operand.
+ * @param action Consumer for the complex result.
* @return the object returned by the provided consumer.
*/
- R apply(double real, double imaginary, ComplexSink<R> out);
+ R apply(double real, double imaginary, double operand, ComplexSink<R> action);
}
diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUnaryOperator.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUnaryOperator.java
index a9bae229..dbfc53d6 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUnaryOperator.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUnaryOperator.java
@@ -35,10 +35,11 @@ public interface ComplexUnaryOperator<R> {
/**
* Represents an operator that accepts real and imaginary parts of a complex number and supplies the complex result to the provided consumer.
+ *
* @param real Real part \( a \) of the complex number \( (a +ib) \).
* @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
- * @param out Consumer for the complex result.
+ * @param action Consumer for the complex result.
* @return the object returned by the provided consumer.
*/
- R apply(double real, double imaginary, ComplexSink<R> out);
+ R apply(double real, double imaginary, ComplexSink<R> action);
}
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 620e3a92..b739c359 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
@@ -980,27 +980,27 @@ class CStandardTest {
final double re = next(rng);
final double im = next(rng);
final Complex z = complex(re, im);
- final Complex iz = z.multiplyImaginary(1);
+ final Complex iz = TestUtils.assertSame(z, 1, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
- Complex actual = TestUtils.assertSame(z, "asin", Complex::asin, ComplexFunctions::asin);
- Complex expected = TestUtils.assertSame(iz, "asinh", Complex::asinh, ComplexFunctions::asinh);
- assertComplex(actual, expected.multiplyImaginary(-1));
+ Complex c1 = TestUtils.assertSame(z, "asin", Complex::asin, ComplexFunctions::asin);
+ Complex c2 = TestUtils.assertSame(iz, "asinh", Complex::asinh, ComplexFunctions::asinh);
+ assertComplex(c1, TestUtils.assertSame(c2, -1, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary));
- actual = TestUtils.assertSame(z, "atan", Complex::atan, ComplexFunctions::atan);
- expected = TestUtils.assertSame(iz, "atanh", Complex::atanh, ComplexFunctions::atanh);
- assertComplex(actual, expected.multiplyImaginary(-1));
+ c1 = TestUtils.assertSame(z, "atan", Complex::atan, ComplexFunctions::atan);
+ c2 = TestUtils.assertSame(iz, "atanh", Complex::atanh, ComplexFunctions::atanh);
+ assertComplex(c1, TestUtils.assertSame(c2, -1, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary));
- actual = TestUtils.assertSame(z, "cos", Complex::cos, ComplexFunctions::cos);
- expected = TestUtils.assertSame(iz, "cosh", Complex::cosh, ComplexFunctions::cosh);
- assertComplex(actual, expected);
+ c1 = TestUtils.assertSame(z, "cos", Complex::cos, ComplexFunctions::cos);
+ c2 = TestUtils.assertSame(iz, "cosh", Complex::cosh, ComplexFunctions::cosh);
+ assertComplex(c1, c2);
- actual = TestUtils.assertSame(z, "sin", Complex::sin, ComplexFunctions::sin);
- expected = TestUtils.assertSame(iz, "sinh", Complex::sinh, ComplexFunctions::sinh);
- assertComplex(actual, expected.multiplyImaginary(-1));
+ c1 = TestUtils.assertSame(z, "sin", Complex::sin, ComplexFunctions::sin);
+ c2 = TestUtils.assertSame(iz, "sinh", Complex::sinh, ComplexFunctions::sinh);
+ assertComplex(c1, TestUtils.assertSame(c2, -1, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary));
- actual = TestUtils.assertSame(z, "tan", Complex::tan, ComplexFunctions::tan);
- expected = TestUtils.assertSame(iz, "tanh", Complex::tanh, ComplexFunctions::tanh);
- assertComplex(actual, expected.multiplyImaginary(-1));
+ c1 = TestUtils.assertSame(z, "tan", Complex::tan, ComplexFunctions::tan);
+ c2 = TestUtils.assertSame(iz, "tanh", Complex::tanh, ComplexFunctions::tanh);
+ assertComplex(c1, TestUtils.assertSame(c2, -1, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary));
}
}
@@ -1056,8 +1056,8 @@ class CStandardTest {
{1.40905821964671, 1.4090583434236112},
{1.912164268932753, 1.9121638616231227}}) {
final Complex z = complex(pair[0], pair[1]);
- assertAbs(z.abs(), z.multiplyImaginary(1));
- Assertions.assertEquals(z.abs(), z.multiplyImaginary(1).abs(), "Expected |z| == |iz|");
+ final Complex iz = TestUtils.assertSame(z, 1, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
+ Assertions.assertEquals(z.abs(), iz.abs(), "Expected |z| == |iz|");
}
// Test with a range of numbers.
@@ -1267,7 +1267,8 @@ class CStandardTest {
}
assertComplex(infZero, name, operation1, operation2, infZero, type);
for (final double y : nonZeroFinite) {
- assertComplex(complex(inf, y), name, operation1, operation2, Complex.ofCis(y).multiply(inf), type);
+ final Complex expected = TestUtils.assertSame(Complex.ofCis(y), inf, "multiply", Complex::multiply, ComplexFunctions::multiply);
+ assertComplex(complex(inf, y), name, operation1, operation2, expected, type);
}
assertComplex(infInf, name, operation1, operation2, infNaN, type, UnspecifiedSign.REAL);
assertComplex(infNaN, name, operation1, operation2, infNaN, type);
@@ -1302,7 +1303,8 @@ class CStandardTest {
assertComplex(infZero, name, operation1, operation2, infZero, type);
// Note: Error in the ISO C99 reference to use positive finite y but the zero case is different
for (final double y : nonZeroFinite) {
- assertComplex(complex(inf, y), name, operation1, operation2, Complex.ofCis(y).multiply(inf), type);
+ final Complex expected = TestUtils.assertSame(Complex.ofCis(y), inf, "multiply", Complex::multiply, ComplexFunctions::multiply);
+ assertComplex(complex(inf, y), name, operation1, operation2, expected, type);
}
assertComplex(infInf, name, operation1, operation2, infNaN, type, UnspecifiedSign.REAL);
assertComplex(infNaN, name, operation1, operation2, infNaN, type, UnspecifiedSign.REAL);
@@ -1369,10 +1371,12 @@ class CStandardTest {
}
assertComplex(infZero, name, operation1, operation2, infZero);
for (final double y : finite) {
- assertComplex(complex(-inf, y), name, operation1, operation2, Complex.ofCis(y).multiply(0.0));
+ final Complex expected = TestUtils.assertSame(Complex.ofCis(y), 0.0, "multiply", Complex::multiply, ComplexFunctions::multiply);
+ assertComplex(complex(-inf, y), name, operation1, operation2, expected);
}
for (final double y : nonZeroFinite) {
- assertComplex(complex(inf, y), name, operation1, operation2, Complex.ofCis(y).multiply(inf));
+ final Complex expected = TestUtils.assertSame(Complex.ofCis(y), inf, "multiply", Complex::multiply, ComplexFunctions::multiply);
+ assertComplex(complex(inf, y), name, operation1, operation2, expected);
}
assertComplex(negInfInf, name, operation1, operation2, Complex.ZERO, UnspecifiedSign.REAL_IMAGINARY);
assertComplex(infInf, name, operation1, operation2, infNaN, UnspecifiedSign.REAL);
diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java
index 02653eb6..3d7410e0 100644
--- a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java
+++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java
@@ -553,44 +553,47 @@ class ComplexTest {
void testAddReal() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 5.0;
- final Complex z = x.add(y);
+ final Complex z = TestUtils.assertSame(x, y, "add", Complex::add, ComplexFunctions::add);
Assertions.assertEquals(8.0, z.getReal());
Assertions.assertEquals(4.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.add(ofReal(y)));
+ final Complex actual = TestUtils.assertSame(x, ofReal(y), "add", Complex::add, ComplexFunctions::add);
+ Assertions.assertEquals(z, actual);
}
@Test
void testAddRealNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.add(y);
+ final Complex z = TestUtils.assertSame(x, y, "add", Complex::add, ComplexFunctions::add);
Assertions.assertEquals(nan, z.getReal());
Assertions.assertEquals(4.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.add(ofReal(y)));
+ final Complex actual = TestUtils.assertSame(x, ofReal(y), "add", Complex::add, ComplexFunctions::add);
+ Assertions.assertEquals(z, actual);
}
@Test
void testAddRealInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- final Complex z = x.add(y);
+ final Complex z = TestUtils.assertSame(x, y, "add", Complex::add, ComplexFunctions::add);
Assertions.assertEquals(inf, z.getReal());
Assertions.assertEquals(4.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.add(ofReal(y)));
+ final Complex actual = TestUtils.assertSame(x, ofReal(y), "add", Complex::add, ComplexFunctions::add);
+ Assertions.assertEquals(z, actual);
}
@Test
void testAddRealWithNegZeroImaginary() {
final Complex x = Complex.ofCartesian(3.0, -0.0);
final double y = 5.0;
- final Complex z = x.add(y);
+ final Complex z = TestUtils.assertSame(x, y, "add", Complex::add, ComplexFunctions::add);
Assertions.assertEquals(8.0, z.getReal());
Assertions.assertEquals(-0.0, z.getImaginary(), "Expected sign preservation");
// Sign-preservation is a problem: -0.0 + 0.0 == 0.0
- final Complex z2 = x.add(ofReal(y));
+ final Complex z2 = TestUtils.assertSame(x, ofReal(y), "add", Complex::add, ComplexFunctions::add);
Assertions.assertEquals(8.0, z2.getReal());
Assertions.assertEquals(0.0, z2.getImaginary(), "Expected no-sign preservation");
}
@@ -599,44 +602,47 @@ class ComplexTest {
void testAddImaginary() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 5.0;
- final Complex z = x.addImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "addImaginary", Complex::addImaginary, ComplexFunctions::addImaginary);
Assertions.assertEquals(3.0, z.getReal());
Assertions.assertEquals(9.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.add(ofImaginary(y)));
+ final Complex actual = TestUtils.assertSame(x, ofImaginary(y), "add", Complex::add, ComplexFunctions::add);
+ Assertions.assertEquals(z, actual);
}
@Test
void testAddImaginaryNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.addImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "addImaginary", Complex::addImaginary, ComplexFunctions::addImaginary);
Assertions.assertEquals(3.0, z.getReal());
Assertions.assertEquals(nan, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.add(ofImaginary(y)));
+ final Complex actual = TestUtils.assertSame(x, ofImaginary(y), "add", Complex::add, ComplexFunctions::add);
+ Assertions.assertEquals(z, actual);
}
@Test
void testAddImaginaryInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- final Complex z = x.addImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "addImaginary", Complex::addImaginary, ComplexFunctions::addImaginary);
Assertions.assertEquals(3.0, z.getReal());
Assertions.assertEquals(inf, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.add(ofImaginary(y)));
+ final Complex actual = TestUtils.assertSame(x, ofImaginary(y), "add", Complex::add, ComplexFunctions::add);
+ Assertions.assertEquals(z, actual);
}
@Test
void testAddImaginaryWithNegZeroReal() {
final Complex x = Complex.ofCartesian(-0.0, 4.0);
final double y = 5.0;
- final Complex z = x.addImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "addImaginary", Complex::addImaginary, ComplexFunctions::addImaginary);
Assertions.assertEquals(-0.0, z.getReal(), "Expected sign preservation");
Assertions.assertEquals(9.0, z.getImaginary());
// Sign-preservation is a problem: -0.0 + 0.0 == 0.0
- final Complex z2 = x.add(ofImaginary(y));
+ final Complex z2 = TestUtils.assertSame(x, ofImaginary(y), "add", Complex::add, ComplexFunctions::add);
Assertions.assertEquals(0.0, z2.getReal(), "Expected no-sign preservation");
Assertions.assertEquals(9.0, z2.getImaginary());
}
@@ -667,178 +673,194 @@ class ComplexTest {
void testSubtractReal() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 5.0;
- final Complex z = x.subtract(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtract", Complex::subtract, ComplexFunctions::subtract);
Assertions.assertEquals(-2.0, z.getReal());
Assertions.assertEquals(4.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.subtract(ofReal(y)));
+ final Complex actual = TestUtils.assertSame(x, ofReal(y), "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractRealNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.subtract(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtract", Complex::subtract, ComplexFunctions::subtract);
Assertions.assertEquals(nan, z.getReal());
Assertions.assertEquals(4.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.subtract(ofReal(y)));
+ final Complex actual = TestUtils.assertSame(x, ofReal(y), "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractRealInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- final Complex z = x.subtract(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtract", Complex::subtract, ComplexFunctions::subtract);
Assertions.assertEquals(-inf, z.getReal());
Assertions.assertEquals(4.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.subtract(ofReal(y)));
+ final Complex actual = TestUtils.assertSame(x, ofReal(y), "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractRealWithNegZeroImaginary() {
final Complex x = Complex.ofCartesian(3.0, -0.0);
final double y = 5.0;
- final Complex z = x.subtract(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtract", Complex::subtract, ComplexFunctions::subtract);
Assertions.assertEquals(-2.0, z.getReal());
Assertions.assertEquals(-0.0, z.getImaginary());
// Equivalent
// Sign-preservation is not a problem: -0.0 - 0.0 == -0.0
- Assertions.assertEquals(z, x.subtract(ofReal(y)));
+ final Complex actual = TestUtils.assertSame(x, ofReal(y), "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractImaginary() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 5.0;
- final Complex z = x.subtractImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractImaginary", Complex::subtractImaginary, ComplexFunctions::subtractImaginary);
Assertions.assertEquals(3.0, z.getReal());
Assertions.assertEquals(-1.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.subtract(ofImaginary(y)));
+ final Complex actual = TestUtils.assertSame(x, ofImaginary(y), "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractImaginaryNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.subtractImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractImaginary", Complex::subtractImaginary, ComplexFunctions::subtractImaginary);
Assertions.assertEquals(3.0, z.getReal());
Assertions.assertEquals(nan, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.subtract(ofImaginary(y)));
+ final Complex actual = TestUtils.assertSame(x, ofImaginary(y), "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractImaginaryInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- final Complex z = x.subtractImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractImaginary", Complex::subtractImaginary, ComplexFunctions::subtractImaginary);
Assertions.assertEquals(3.0, z.getReal());
Assertions.assertEquals(-inf, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.subtract(ofImaginary(y)));
+ final Complex actual = TestUtils.assertSame(x, ofImaginary(y), "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractImaginaryWithNegZeroReal() {
final Complex x = Complex.ofCartesian(-0.0, 4.0);
final double y = 5.0;
- final Complex z = x.subtractImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractImaginary", Complex::subtractImaginary, ComplexFunctions::subtractImaginary);
Assertions.assertEquals(-0.0, z.getReal());
Assertions.assertEquals(-1.0, z.getImaginary());
// Equivalent
// Sign-preservation is not a problem: -0.0 - 0.0 == -0.0
- Assertions.assertEquals(z, x.subtract(ofImaginary(y)));
+ final Complex actual = TestUtils.assertSame(x, ofImaginary(y), "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractFromReal() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 5.0;
- final Complex z = x.subtractFrom(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractFrom", Complex::subtractFrom, TestUtils::subtractFrom);
Assertions.assertEquals(2.0, z.getReal());
Assertions.assertEquals(-4.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, ofReal(y).subtract(x));
+ final Complex actual = TestUtils.assertSame(ofReal(y), x, "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractFromRealNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.subtractFrom(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractFrom", Complex::subtractFrom, TestUtils::subtractFrom);
Assertions.assertEquals(nan, z.getReal());
Assertions.assertEquals(-4.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, ofReal(y).subtract(x));
+ final Complex actual = TestUtils.assertSame(ofReal(y), x, "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractFromRealInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- final Complex z = x.subtractFrom(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractFrom", Complex::subtractFrom, TestUtils::subtractFrom);
Assertions.assertEquals(inf, z.getReal());
Assertions.assertEquals(-4.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, ofReal(y).subtract(x));
+ final Complex actual = TestUtils.assertSame(ofReal(y), x, "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractFromRealWithPosZeroImaginary() {
final Complex x = Complex.ofCartesian(3.0, 0.0);
final double y = 5.0;
- final Complex z = x.subtractFrom(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractFrom", Complex::subtractFrom, TestUtils::subtractFrom);
Assertions.assertEquals(2.0, z.getReal());
Assertions.assertEquals(-0.0, z.getImaginary(), "Expected sign inversion");
// Sign-inversion is a problem: 0.0 - 0.0 == 0.0
- Assertions.assertNotEquals(z, ofReal(y).subtract(x));
+ final Complex actual = TestUtils.assertSame(ofReal(y), x, "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertNotEquals(z, actual);
}
@Test
void testSubtractFromImaginary() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 5.0;
- final Complex z = x.subtractFromImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractFromImaginary", Complex::subtractFromImaginary, TestUtils::subtractFromImaginary);
Assertions.assertEquals(-3.0, z.getReal());
Assertions.assertEquals(1.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, ofImaginary(y).subtract(x));
+ final Complex actual = TestUtils.assertSame(ofImaginary(y), x, "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractFromImaginaryNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.subtractFromImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractFromImaginary", Complex::subtractFromImaginary, TestUtils::subtractFromImaginary);
Assertions.assertEquals(-3.0, z.getReal());
Assertions.assertEquals(nan, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, ofImaginary(y).subtract(x));
+ final Complex actual = TestUtils.assertSame(ofImaginary(y), x, "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractFromImaginaryInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- final Complex z = x.subtractFromImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractFromImaginary", Complex::subtractFromImaginary, TestUtils::subtractFromImaginary);
Assertions.assertEquals(-3.0, z.getReal());
Assertions.assertEquals(inf, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, ofImaginary(y).subtract(x));
+ final Complex actual = TestUtils.assertSame(ofImaginary(y), x, "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertEquals(z, actual);
}
@Test
void testSubtractFromImaginaryWithPosZeroReal() {
final Complex x = Complex.ofCartesian(0.0, 4.0);
final double y = 5.0;
- final Complex z = x.subtractFromImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "subtractFromImaginary", Complex::subtractFromImaginary, TestUtils::subtractFromImaginary);
Assertions.assertEquals(-0.0, z.getReal(), "Expected sign inversion");
Assertions.assertEquals(1.0, z.getImaginary());
// Sign-inversion is a problem: 0.0 - 0.0 == 0.0
- Assertions.assertNotEquals(z, ofImaginary(y).subtract(x));
+ final Complex actual = TestUtils.assertSame(ofImaginary(y), x, "subtract", Complex::subtract, ComplexFunctions::subtract);
+ Assertions.assertNotEquals(z, actual);
}
@Test
@@ -872,62 +894,68 @@ class ComplexTest {
void testMultiplyReal() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 2.0;
- Complex z = x.multiply(y);
+ Complex z = TestUtils.assertSame(x, y, "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(6.0, z.getReal());
Assertions.assertEquals(8.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofReal(y)));
+ Complex actual = TestUtils.assertSame(x, ofReal(y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
- z = x.multiply(-y);
+ z = TestUtils.assertSame(x, -y, "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(-6.0, z.getReal());
Assertions.assertEquals(-8.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofReal(-y)));
+ actual = TestUtils.assertSame(x, ofReal(-y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
}
@Test
void testMultiplyRealNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.multiply(y);
+ final Complex z = TestUtils.assertSame(x, y, "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(nan, z.getReal());
Assertions.assertEquals(nan, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofReal(y)));
+ final Complex actual = TestUtils.assertSame(x, ofReal(y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
}
@Test
void testMultiplyRealInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- Complex z = x.multiply(y);
+ Complex z = TestUtils.assertSame(x, y, "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(inf, z.getReal());
Assertions.assertEquals(inf, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofReal(y)));
+ Complex actual = TestUtils.assertSame(x, ofReal(y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
- z = x.multiply(-y);
+ z = TestUtils.assertSame(x, -y, "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(-inf, z.getReal());
Assertions.assertEquals(-inf, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofReal(-y)));
+ actual = TestUtils.assertSame(x, ofReal(-y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
}
@Test
void testMultiplyRealZero() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 0.0;
- Complex z = x.multiply(y);
+ Complex z = TestUtils.assertSame(x, y, "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(0.0, z.getReal());
Assertions.assertEquals(0.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofReal(y)));
+ Complex actual = TestUtils.assertSame(x, ofReal(y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
- z = x.multiply(-y);
+ z = TestUtils.assertSame(x, -y, "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(-0.0, z.getReal());
Assertions.assertEquals(-0.0, z.getImaginary());
// Sign-preservation is a problem for imaginary: 0.0 - -0.0 == 0.0
- final Complex z2 = x.multiply(ofReal(-y));
+ final Complex z2 = TestUtils.assertSame(x, ofReal(-y), "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(-0.0, z2.getReal());
Assertions.assertEquals(0.0, z2.getImaginary(), "Expected no sign preservation");
}
@@ -936,64 +964,69 @@ class ComplexTest {
void testMultiplyImaginary() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 2.0;
- Complex z = x.multiplyImaginary(y);
+ Complex z = TestUtils.assertSame(x, y, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
Assertions.assertEquals(-8.0, z.getReal());
Assertions.assertEquals(6.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofImaginary(y)));
+ Complex actual = TestUtils.assertSame(x, ofImaginary(y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
- z = x.multiplyImaginary(-y);
+ z = TestUtils.assertSame(x, -y, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
Assertions.assertEquals(8.0, z.getReal());
Assertions.assertEquals(-6.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofImaginary(-y)));
+ actual = TestUtils.assertSame(x, ofImaginary(-y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
}
@Test
void testMultiplyImaginaryNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.multiplyImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
Assertions.assertEquals(nan, z.getReal());
Assertions.assertEquals(nan, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofImaginary(y)));
+ final Complex actual = TestUtils.assertSame(x, ofImaginary(y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
}
@Test
void testMultiplyImaginaryInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- Complex z = x.multiplyImaginary(y);
+ Complex z = TestUtils.assertSame(x, y, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
Assertions.assertEquals(-inf, z.getReal());
Assertions.assertEquals(inf, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofImaginary(y)));
+ Complex actual = TestUtils.assertSame(x, ofImaginary(y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
- z = x.multiplyImaginary(-y);
+ z = TestUtils.assertSame(x, -y, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
Assertions.assertEquals(inf, z.getReal());
Assertions.assertEquals(-inf, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.multiply(ofImaginary(-y)));
+ actual = TestUtils.assertSame(x, ofImaginary(-y), "multiply", Complex::multiply, ComplexFunctions::multiply);
+ Assertions.assertEquals(z, actual);
}
@Test
void testMultiplyImaginaryZero() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 0.0;
- Complex z = x.multiplyImaginary(y);
+ Complex z = TestUtils.assertSame(x, y, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
Assertions.assertEquals(-0.0, z.getReal());
Assertions.assertEquals(0.0, z.getImaginary());
// Sign-preservation is a problem for real: 0.0 - -0.0 == 0.0
- Complex z2 = x.multiply(ofImaginary(y));
+ Complex z2 = TestUtils.assertSame(x, ofImaginary(y), "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(0.0, z2.getReal(), "Expected no sign preservation");
Assertions.assertEquals(0.0, z2.getImaginary());
- z = x.multiplyImaginary(-y);
+ z = TestUtils.assertSame(x, -y, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
Assertions.assertEquals(0.0, z.getReal());
Assertions.assertEquals(-0.0, z.getImaginary());
// Sign-preservation is a problem for imaginary: -0.0 - 0.0 == 0.0
- z2 = x.multiply(ofImaginary(-y));
+ z2 = TestUtils.assertSame(x, ofImaginary(-y), "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(0.0, z2.getReal());
Assertions.assertEquals(0.0, z2.getImaginary(), "Expected no sign preservation");
}
@@ -1004,11 +1037,11 @@ class ComplexTest {
for (final double a : parts) {
for (final double b : parts) {
final Complex c = Complex.ofCartesian(a, b);
- final Complex x = c.multiplyImaginary(1.0);
+ final Complex x = TestUtils.assertSame(c, 1.0, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
// Check verses algebra solution
Assertions.assertEquals(-b, x.getReal());
Assertions.assertEquals(a, x.getImaginary());
- final Complex z = c.multiply(Complex.I);
+ final Complex z = TestUtils.assertSame(c, Complex.I, "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(x, z);
}
}
@@ -1022,12 +1055,12 @@ class ComplexTest {
for (final double a : parts) {
for (final double b : parts) {
final Complex c = Complex.ofCartesian(a, b);
- final Complex x = c.multiplyImaginary(-1.0);
+ final Complex x = TestUtils.assertSame(c, -1.0, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
// Check verses algebra solution
Assertions.assertEquals(b, x.getReal());
Assertions.assertEquals(-a, x.getImaginary());
for (final Complex negI : negIs) {
- final Complex z = c.multiply(negI);
+ final Complex z = TestUtils.assertSame(c, negI, "multiply", Complex::multiply, ComplexFunctions::multiply);
Assertions.assertEquals(x, z);
}
}
@@ -1040,11 +1073,11 @@ class ComplexTest {
for (final double a : zeros) {
for (final double b : zeros) {
final Complex c = Complex.ofCartesian(a, b);
- final Complex x = c.multiplyImaginary(1.0);
+ final Complex x = TestUtils.assertSame(c, 1.0, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
// Check verses algebra solution
Assertions.assertEquals(-b, x.getReal());
Assertions.assertEquals(a, x.getImaginary());
- final Complex z = c.multiply(Complex.I);
+ final Complex z = TestUtils.assertSame(c, Complex.I, "multiply", Complex::multiply, ComplexFunctions::multiply);
// Does not work when imaginary part is +0.0.
if (Double.compare(b, 0.0) == 0) {
// (-0.0, 0.0).multiply( (0,1) ) => (-0.0, 0.0) expected (-0.0,-0.0)
@@ -1069,12 +1102,13 @@ class ComplexTest {
for (final double a : zeros) {
for (final double b : zeros) {
final Complex c = Complex.ofCartesian(a, b);
- final Complex x = c.multiplyImaginary(-1.0);
+ final Complex x = TestUtils.assertSame(c, -1.0, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
// Check verses algebra solution
Assertions.assertEquals(b, x.getReal());
Assertions.assertEquals(-a, x.getImaginary());
- final Complex z = c.multiply(negI);
- final Complex z2 = c.multiply(Complex.I).negate();
+ final Complex z = TestUtils.assertSame(c, negI, "multiply", Complex::multiply, ComplexFunctions::multiply);
+ final Complex ci = TestUtils.assertSame(c, Complex.I, "multiply", Complex::multiply, ComplexFunctions::multiply);
+ final Complex z2 = TestUtils.assertSame(ci, "negate", Complex::negate, ComplexFunctions::negate);
// Does not work when imaginary part is -0.0.
if (Double.compare(b, -0.0) == 0) {
// (-0.0,-0.0).multiply( (-0.0,-1) ) => ( 0.0, 0.0) expected (-0.0, 0.0)
@@ -1145,126 +1179,138 @@ class ComplexTest {
void testDivideReal() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 2.0;
- Complex z = x.divide(y);
+ Complex z = TestUtils.assertSame(x, y, "divide", Complex::divide, ComplexFunctions::divide);
Assertions.assertEquals(1.5, z.getReal());
Assertions.assertEquals(2.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofReal(y)));
+ Complex actual = TestUtils.assertSame(x, ofReal(y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
- z = x.divide(-y);
+ z = TestUtils.assertSame(x, -y, "divide", Complex::divide, ComplexFunctions::divide);
Assertions.assertEquals(-1.5, z.getReal());
Assertions.assertEquals(-2.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofReal(-y)));
+ actual = TestUtils.assertSame(x, ofReal(-y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
}
@Test
void testDivideRealNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.divide(y);
+ final Complex z = TestUtils.assertSame(x, y, "divide", Complex::divide, ComplexFunctions::divide);
Assertions.assertEquals(nan, z.getReal());
Assertions.assertEquals(nan, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofReal(y)));
+ final Complex actual = TestUtils.assertSame(x, ofReal(y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
}
@Test
void testDivideRealInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- Complex z = x.divide(y);
+ Complex z = TestUtils.assertSame(x, y, "divide", Complex::divide, ComplexFunctions::divide);
Assertions.assertEquals(0.0, z.getReal());
Assertions.assertEquals(0.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofReal(y)));
+ Complex actual = TestUtils.assertSame(x, ofReal(y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
- z = x.divide(-y);
+ z = TestUtils.assertSame(x, -y, "divide", Complex::divide, ComplexFunctions::divide);
Assertions.assertEquals(-0.0, z.getReal());
Assertions.assertEquals(-0.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofReal(-y)));
+ actual = TestUtils.assertSame(x, ofReal(-y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
}
@Test
void testDivideRealZero() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 0.0;
- Complex z = x.divide(y);
+ Complex z = TestUtils.assertSame(x, y, "divide", Complex::divide, ComplexFunctions::divide);
Assertions.assertEquals(inf, z.getReal());
Assertions.assertEquals(inf, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofReal(y)));
+ Complex actual = TestUtils.assertSame(x, ofReal(y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
- z = x.divide(-y);
+ z = TestUtils.assertSame(x, -y, "divide", Complex::divide, ComplexFunctions::divide);
Assertions.assertEquals(-inf, z.getReal());
Assertions.assertEquals(-inf, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofReal(-y)));
+ actual = TestUtils.assertSame(x, ofReal(-y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
}
@Test
void testDivideImaginary() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 2.0;
- Complex z = x.divideImaginary(y);
+ Complex z = TestUtils.assertSame(x, y, "divideImaginary", Complex::divideImaginary, ComplexFunctions::divideImaginary);
Assertions.assertEquals(2.0, z.getReal());
Assertions.assertEquals(-1.5, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofImaginary(y)));
+ Complex actual = TestUtils.assertSame(x, ofImaginary(y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
- z = x.divideImaginary(-y);
+ z = TestUtils.assertSame(x, -y, "divideImaginary", Complex::divideImaginary, ComplexFunctions::divideImaginary);
Assertions.assertEquals(-2.0, z.getReal());
Assertions.assertEquals(1.5, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofImaginary(-y)));
+ actual = TestUtils.assertSame(x, ofImaginary(-y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
}
@Test
void testDivideImaginaryNaN() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = nan;
- final Complex z = x.divideImaginary(y);
+ final Complex z = TestUtils.assertSame(x, y, "divideImaginary", Complex::divideImaginary, ComplexFunctions::divideImaginary);
Assertions.assertEquals(nan, z.getReal());
Assertions.assertEquals(nan, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofImaginary(y)));
+ final Complex actual = TestUtils.assertSame(x, ofImaginary(y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
}
@Test
void testDivideImaginaryInf() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = inf;
- Complex z = x.divideImaginary(y);
+ Complex z = TestUtils.assertSame(x, y, "divideImaginary", Complex::divideImaginary, ComplexFunctions::divideImaginary);
Assertions.assertEquals(0.0, z.getReal());
Assertions.assertEquals(-0.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofImaginary(y)));
+ Complex actual = TestUtils.assertSame(x, ofImaginary(y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
- z = x.divideImaginary(-y);
+ z = TestUtils.assertSame(x, -y, "divideImaginary", Complex::divideImaginary, ComplexFunctions::divideImaginary);
Assertions.assertEquals(-0.0, z.getReal());
Assertions.assertEquals(0.0, z.getImaginary());
// Equivalent
- Assertions.assertEquals(z, x.divide(ofImaginary(-y)));
+ actual = TestUtils.assertSame(x, ofImaginary(-y), "divide", Complex::divide, ComplexFunctions::divide);
+ Assertions.assertEquals(z, actual);
}
@Test
void testDivideImaginaryZero() {
final Complex x = Complex.ofCartesian(3.0, 4.0);
final double y = 0.0;
- Complex z = x.divideImaginary(y);
+ Complex z = TestUtils.assertSame(x, y, "divideImaginary", Complex::divideImaginary, ComplexFunctions::divideImaginary);
Assertions.assertEquals(inf, z.getReal());
Assertions.assertEquals(-inf, z.getImaginary());
// Sign-preservation is a problem for imaginary: 0.0 - -0.0 == 0.0
- Complex z2 = x.divide(ofImaginary(y));
+ Complex z2 = TestUtils.assertSame(x, ofImaginary(y), "divide", Complex::divide, ComplexFunctions::divide);
Assertions.assertEquals(inf, z2.getReal());
Assertions.assertEquals(inf, z2.getImaginary(), "Expected no sign preservation");
- z = x.divideImaginary(-y);
+ z = TestUtils.assertSame(x, -y, "divideImaginary", Complex::divideImaginary, ComplexFunctions::divideImaginary);
Assertions.assertEquals(-inf, z.getReal());
Assertions.assertEquals(inf, z.getImaginary());
// Sign-preservation is a problem for real: 0.0 + -0.0 == 0.0
- z2 = x.divide(ofImaginary(-y));
+ z2 = TestUtils.assertSame(x, ofImaginary(-y), "divide", Complex::divide, ComplexFunctions::divide);
Assertions.assertEquals(inf, z2.getReal(), "Expected no sign preservation");
Assertions.assertEquals(inf, z2.getImaginary());
}
@@ -1304,22 +1350,22 @@ class ComplexTest {
// and the javadoc in Complex does not break down the actual cases.
// 16: (x,-0.0) + x
- assertSignedZeroArithmetic("addReal", Complex::add, ComplexTest::ofReal, Complex::add,
+ assertSignedZeroArithmetic("addReal", Complex::add, ComplexFunctions::add, ComplexTest::ofReal, Complex::add, ComplexFunctions::add,
0b1111000000000000111100000000000011110000000000001111L);
// 16: (-0.0,x) + x
- assertSignedZeroArithmetic("addImaginary", Complex::addImaginary, ComplexTest::ofImaginary, Complex::add,
+ assertSignedZeroArithmetic("addImaginary", Complex::addImaginary, ComplexFunctions::addImaginary, ComplexTest::ofImaginary, Complex::add, ComplexFunctions::add,
0b1111111111111111L);
// 0:
- assertSignedZeroArithmetic("subtractReal", Complex::subtract, ComplexTest::ofReal, Complex::subtract, 0);
+ assertSignedZeroArithmetic("subtractReal", Complex::subtract, ComplexFunctions::subtract, ComplexTest::ofReal, Complex::subtract, ComplexFunctions::subtract, 0);
// 0:
- assertSignedZeroArithmetic("subtractImaginary", Complex::subtractImaginary, ComplexTest::ofImaginary,
- Complex::subtract, 0);
+ assertSignedZeroArithmetic("subtractImaginary", Complex::subtractImaginary, ComplexFunctions::subtractImaginary, ComplexTest::ofImaginary,
+ Complex::subtract, ComplexFunctions::subtract, 0);
// 16: x - (x,+0.0)
- assertSignedZeroArithmetic("subtractFromReal", Complex::subtractFrom, ComplexTest::ofReal,
- (y, z) -> z.subtract(y), 0b11110000000000001111000000000000111100000000000011110000L);
+ assertSignedZeroArithmetic("subtractFromReal", Complex::subtractFrom, TestUtils::subtractFrom, ComplexTest::ofReal,
+ (y, z) -> z.subtract(y), (a, b, c, d, action) -> ComplexFunctions.subtract(c, d, a, b, action), 0b11110000000000001111000000000000111100000000000011110000L);
// 16: x - (+0.0,x)
- assertSignedZeroArithmetic("subtractFromImaginary", Complex::subtractFromImaginary, ComplexTest::ofImaginary,
- (y, z) -> z.subtract(y), 0b11111111111111110000000000000000L);
+ assertSignedZeroArithmetic("subtractFromImaginary", Complex::subtractFromImaginary, TestUtils::subtractFromImaginary, ComplexTest::ofImaginary,
+ (y, z) -> z.subtract(y), (a, b, c, d, action) -> ComplexFunctions.subtract(c, d, a, b, action), 0b11111111111111110000000000000000L);
// 4: (-0.0,-x) * +x
// 4: (+0.0,-0.0) * x
// 4: (+0.0,x) * -x
@@ -1329,7 +1375,7 @@ class ComplexTest {
// 2: (+y,-x) * -0.0
// 2: (+x,-y) * +0.0
// 2: (+x,+y) * -0.0
- assertSignedZeroArithmetic("multiplyReal", Complex::multiply, ComplexTest::ofReal, Complex::multiply,
+ assertSignedZeroArithmetic("multiplyReal", Complex::multiply, ComplexFunctions::multiply, ComplexTest::ofReal, Complex::multiply, ComplexFunctions::multiply,
0b1001101011011000000100000001000010111010111110000101000001010L);
// 4: (-0.0,+x) * +x
// 2: (+0.0,-0.0) * -x
@@ -1340,31 +1386,33 @@ class ComplexTest {
// 2: (+0.0,+/-y) * -/+0
// 2: (+y,+/-0.0) * +/-y (sign 0.0 matches sign y)
// 2: (+y,+x) * +0.0
- assertSignedZeroArithmetic("multiplyImaginary", Complex::multiplyImaginary, ComplexTest::ofImaginary,
- Complex::multiply, 0b11000110110101001000000010000001110001111101011010000010100000L);
+ assertSignedZeroArithmetic("multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary, ComplexTest::ofImaginary,
+ Complex::multiply, ComplexFunctions::multiply, 0b11000110110101001000000010000001110001111101011010000010100000L);
// 2: (-0.0,0) / +y
// 2: (+0.0,+x) / -y
// 2: (-x,0) / -y
// 1: (-0.0,+y) / +y
// 1: (-y,+0.0) / -y
- assertSignedZeroArithmetic("divideReal", Complex::divide, ComplexTest::ofReal, Complex::divide,
+ assertSignedZeroArithmetic("divideReal", Complex::divide, ComplexFunctions::divide, ComplexTest::ofReal, Complex::divide, ComplexFunctions::divide,
0b100100001000000010000001000000011001000L);
// DivideImaginary has its own test as the result is not always equal ignoring the
// sign.
}
- private static void assertSignedZeroArithmetic(String name, BiFunction<Complex, Double, Complex> doubleOperation,
- DoubleFunction<Complex> doubleToComplex, BiFunction<Complex, Complex, Complex> complexOperation,
- long expectedFailures) {
+ private static void assertSignedZeroArithmetic(String name, BiFunction<Complex, Double, Complex> doubleOperation1,
+ ComplexScalarFunction<ComplexNumber> doubleOperation2,
+ DoubleFunction<Complex> doubleToComplex, BiFunction<Complex, Complex, Complex> complexOperation1,
+ ComplexBinaryOperator<ComplexNumber> complexOperation2,
+ long expectedFailures) {
// With an operation on zero or non-zero arguments
final double[] arguments = {-0.0, 0.0, -2, 3};
for (final double a : arguments) {
for (final double b : arguments) {
final Complex c = Complex.ofCartesian(a, b);
for (final double arg : arguments) {
- final Complex y = doubleOperation.apply(c, arg);
- final Complex z = complexOperation.apply(c, doubleToComplex.apply(arg));
+ final Complex y = TestUtils.assertSame(c, arg, name, doubleOperation1, doubleOperation2);
+ final Complex z = TestUtils.assertSame(c, doubleToComplex.apply(arg), name, complexOperation1, complexOperation2);
final boolean expectedFailure = (expectedFailures & 0x1) == 1;
expectedFailures >>>= 1;
// Check the same answer. Sign is allowed to be different for zero.
@@ -1406,7 +1454,7 @@ class ComplexTest {
for (final double b : arguments) {
final Complex c = Complex.ofCartesian(a, b);
for (final double arg : arguments) {
- final Complex y = c.divideImaginary(arg);
+ final Complex y = TestUtils.assertSame(c, arg, "divideImaginary", Complex::divideImaginary, ComplexFunctions::divideImaginary);
Complex z = TestUtils.assertSame(c, ofImaginary(arg), "divide", Complex::divide, ComplexFunctions::divide);
final boolean expectedFailure = (expectedFailures & 0x1) == 1;
expectedFailures >>>= 1;
@@ -1415,7 +1463,7 @@ class ComplexTest {
if (arg == 0) {
// Same result if multiplied by I. The sign may not match so
// optionally ignore the sign of the infinity.
- z = z.multiplyImaginary(1);
+ z = TestUtils.assertSame(z, 1, "multiplyImaginary", Complex::multiplyImaginary, ComplexFunctions::multiplyImaginary);
final double ya = expectedFailure ? Math.abs(y.getReal()) : y.getReal();
final double yb = expectedFailure ? Math.abs(y.getImaginary()) : y.getImaginary();
final double za = expectedFailure ? Math.abs(z.getReal()) : z.getReal();
@@ -1458,7 +1506,8 @@ class ComplexTest {
final double yDouble = 5.0;
final Complex yComplex = ofReal(yDouble);
final Complex expected = TestUtils.assertSame(x, yComplex, "pow", Complex::pow, ComplexFunctions::pow);
- Assertions.assertEquals(expected, x.pow(yDouble));
+ final Complex actual = TestUtils.assertSame(x, yDouble, "pow", Complex::pow, ComplexFunctions::pow);
+ Assertions.assertEquals(expected, actual);
}
@Test
@@ -1491,7 +1540,7 @@ class ComplexTest {
void testPowScalerRealZero() {
// Hits the edge case when real == 0 but imaginary != 0
final Complex x = Complex.ofCartesian(0, 1);
- final Complex c = x.pow(2);
+ final Complex c = TestUtils.assertSame(x, 2, "pow", Complex::pow, ComplexFunctions::pow);
// Answer from g++
Assertions.assertEquals(-1, c.getReal());
Assertions.assertEquals(1.2246467991473532e-16, c.getImaginary());
@@ -1505,7 +1554,7 @@ class ComplexTest {
}
private static void assertPowScalarZeroBase(double exp, Complex expected) {
- final Complex c = Complex.ZERO.pow(exp);
+ final Complex c = TestUtils.assertSame(Complex.ZERO, exp, "pow", Complex::pow, ComplexFunctions::pow);
Assertions.assertEquals(expected, c);
}
@@ -1515,7 +1564,8 @@ class ComplexTest {
final double yDouble = 5.0;
final Complex yComplex = ofReal(yDouble);
final Complex expected = TestUtils.assertSame(x, yComplex, "pow", Complex::pow, ComplexFunctions::pow);
- Assertions.assertEquals(expected, x.pow(yDouble));
+ final Complex actual = TestUtils.assertSame(x, yDouble, "pow", Complex::pow, ComplexFunctions::pow);
+ Assertions.assertEquals(expected, actual);
}
@Test
@@ -1524,7 +1574,8 @@ class ComplexTest {
final double yDouble = Double.NaN;
final Complex yComplex = ofReal(yDouble);
final Complex expected = TestUtils.assertSame(x, yComplex, "pow", Complex::pow, ComplexFunctions::pow);
- Assertions.assertEquals(expected, x.pow(yDouble));
+ final Complex actual = TestUtils.assertSame(x, yDouble, "pow", Complex::pow, ComplexFunctions::pow);
+ Assertions.assertEquals(expected, actual);
}
@Test
diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/TestUtils.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/TestUtils.java
index e67bec5f..cefe109b 100644
--- a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/TestUtils.java
+++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/TestUtils.java
@@ -457,6 +457,30 @@ public final class TestUtils {
return z;
}
+ /**
+ * Assert the operation on the complex number and double operand is <em>exactly</em> equal to the operation on
+ * complex real and imaginary parts and double operand.
+ *
+ * @param c Input complex number.
+ * @param operand Scalar operand.
+ * @param name Operation name.
+ * @param operation1 Operation on the Complex object and double operand.
+ * @param operation2 Operation on the complex real and imaginary parts and double operand.
+ * @return Result complex number from the given operation.
+ */
+ public static Complex assertSame(Complex c,
+ double operand,
+ String name,
+ BiFunction<Complex, Double, Complex> operation1,
+ ComplexScalarFunction<ComplexNumber> operation2) {
+ final Complex z = operation1.apply(c, operand);
+ // Test operation2 produces the exact same result
+ final ComplexNumber z2 = operation2.apply(c.real(), c.imag(), operand, ComplexNumber::new);
+ Assertions.assertEquals(z.real(), z2.getReal(), () -> "Scalar operator mismatch: " + name + " real");
+ Assertions.assertEquals(z.imag(), z2.getImaginary(), () -> "Scalar operator mismatch: " + name + " imaginary");
+ return z;
+ }
+
/**
* Assert the operation on the complex number is <em>exactly</em> equal to the operation on
* complex real and imaginary parts.
@@ -498,4 +522,46 @@ public final class TestUtils {
Assertions.assertEquals(b1, b2, () -> "Predicate mismatch: " + name);
return b1;
}
+
+ /**
+ * Computes the result of the subtraction of a complex number from an imaginary number.
+ * Implements the formula:
+ * \[ i d - (a + i b) = -a + i (d - b) \]
+ *
+ * <p>This method is a helper to replicate the method signature of the object-orientated
+ * API in Complex (i.e. the complex argument is first) using the equivalent static API
+ * function in ComplexFunctions.
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param minuend Value the complex number is to be subtracted from.
+ * @param action Consumer for the subtraction result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ */
+ public static <R> R subtractFromImaginary(double real, double imaginary, double minuend, ComplexSink<R> action) {
+ // Call the equivalent static API function
+ return ComplexFunctions.imaginarySubtract(minuend, real, imaginary, action);
+ }
+
+ /**
+ * Computes the result of the subtraction of a complex number from a real number.
+ * Implements the formula:
+ * \[ c - (a + i b) = (c - a) - i b \]
+ *
+ * <p>This method is a helper to replicate the method signature of the object-orientated
+ * API in Complex (i.e. the complex argument is first) using the equivalent static API
+ * function in ComplexFunctions.
+ *
+ * @param real Real part \( a \) of the complex number \( (a +ib) \).
+ * @param imaginary Imaginary part \( b \) of the complex number \( (a +ib) \).
+ * @param minuend Value the complex number is to be subtracted from.
+ * @param action Consumer for the subtraction result.
+ * @param <R> the return type of the supplied action.
+ * @return the object returned by the supplied action.
+ */
+ public static <R> R subtractFrom(double real, double imaginary, double minuend, ComplexSink<R> action) {
+ // Call the equivalent static API function
+ return ComplexFunctions.realSubtract(minuend, real, imaginary, action);
+ }
}