Implemented "copySign" for integral types. Removed redundant "indicator"
functions.
Moved "indicator" tests (for floating point arguments) to "FastMathTest",
as the corresponding "copySign" methods are in "FastMath".


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1206274 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2011-11-25 18:02:21 +00:00
parent ec5d9d3772
commit a050013f44
4 changed files with 96 additions and 102 deletions

View File

@ -921,7 +921,7 @@ public class Complex implements FieldElement<Complex>, Serializable {
* where <ul> * where <ul>
* <li>{@code |a| = }{@link Math#abs}(a)</li> * <li>{@code |a| = }{@link Math#abs}(a)</li>
* <li>{@code |a + bi| = }{@link Complex#abs}(a + bi)</li> * <li>{@code |a + bi| = }{@link Complex#abs}(a + bi)</li>
* <li>{@code sign(b) = }{@link MathUtils#indicator}(b) * <li>{@code sign(b) = }{@link FastMath#copySign(double,double) copySign(1d, b)}
* </ul> * </ul>
* <br/> * <br/>
* Returns {@link Complex#NaN} if either real or imaginary part of the * Returns {@link Complex#NaN} if either real or imaginary part of the
@ -957,7 +957,7 @@ public class Complex implements FieldElement<Complex>, Serializable {
return createComplex(t, imaginary / (2.0 * t)); return createComplex(t, imaginary / (2.0 * t));
} else { } else {
return createComplex(FastMath.abs(imaginary) / (2.0 * t), return createComplex(FastMath.abs(imaginary) / (2.0 * t),
MathUtils.indicator(imaginary) * t); FastMath.copySign(1d, imaginary) * t);
} }
} }

View File

@ -82,77 +82,6 @@ public final class MathUtils {
return Arrays.hashCode(value); return Arrays.hashCode(value);
} }
/**
* For a byte value x, this method returns (byte)(+1) if x >= 0 and
* (byte)(-1) if x < 0.
*
* @param x the value, a byte
* @return (byte)(+1) or (byte)(-1), depending on the sign of x
*/
public static byte indicator(final byte x) {
return (x >= ZB) ? PB : NB;
}
/**
* For a double precision value x, this method returns +1.0 if x >= 0 and
* -1.0 if x < 0. Returns {@code NaN} if {@code x} is
* {@code NaN}.
*
* @param x the value, a double
* @return +1.0 or -1.0, depending on the sign of x
*/
public static double indicator(final double x) {
if (Double.isNaN(x)) {
return Double.NaN;
}
return (x >= 0.0) ? 1.0 : -1.0;
}
/**
* For a float value x, this method returns +1.0F if x >= 0 and -1.0F if x <
* 0. Returns {@code NaN} if {@code x} is {@code NaN}.
*
* @param x the value, a float
* @return +1.0F or -1.0F, depending on the sign of x
*/
public static float indicator(final float x) {
if (Float.isNaN(x)) {
return Float.NaN;
}
return (x >= 0.0F) ? 1.0F : -1.0F;
}
/**
* For an int value x, this method returns +1 if x >= 0 and -1 if x < 0.
*
* @param x the value, an int
* @return +1 or -1, depending on the sign of x
*/
public static int indicator(final int x) {
return (x >= 0) ? 1 : -1;
}
/**
* For a long value x, this method returns +1L if x >= 0 and -1L if x < 0.
*
* @param x the value, a long
* @return +1L or -1L, depending on the sign of x
*/
public static long indicator(final long x) {
return (x >= 0L) ? 1L : -1L;
}
/**
* For a short value x, this method returns (short)(+1) if x >= 0 and
* (short)(-1) if x < 0.
*
* @param x the value, a short
* @return (short)(+1) or (short)(-1), depending on the sign of x
*/
public static short indicator(final short x) {
return (x >= ZS) ? PS : NS;
}
/** /**
* Normalize an angle in a 2&pi wide interval around a center value. * Normalize an angle in a 2&pi wide interval around a center value.
* <p>This method has three main uses:</p> * <p>This method has three main uses:</p>
@ -235,6 +164,72 @@ public final class MathUtils {
} }
} }
/**
* Returns the first argument with the sign of the second argument.
*
* @param magnitude Magnitude of the returned value.
* @param sign Sign of the returned value.
* @return a value with magnitude equal to {@code magnitude} and with the
* same sign as the {@code sign} argument.
* @throws MathArithmeticException if {@code magnitude == Short.MIN_VALUE}
* and {@code sign >= 0}.
*/
public static short copySign(short magnitude, short sign) {
if ((magnitude >= 0 && sign >= 0) ||
(magnitude < 0 && sign < 0)) { // Sign is OK.
return magnitude;
} else if (sign >= 0 &&
magnitude == Short.MIN_VALUE) {
throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
} else {
return (short) -magnitude; // Flip sign.
}
}
/**
* Returns the first argument with the sign of the second argument.
*
* @param magnitude Magnitude of the returned value.
* @param sign Sign of the returned value.
* @return a value with magnitude equal to {@code magnitude} and with the
* same sign as the {@code sign} argument.
* @throws MathArithmeticException if {@code magnitude == Integer.MIN_VALUE}
* and {@code sign >= 0}.
*/
public static int copySign(int magnitude, int sign) {
if ((magnitude >= 0 && sign >= 0) ||
(magnitude < 0 && sign < 0)) { // Sign is OK.
return magnitude;
} else if (sign >= 0 &&
magnitude == Integer.MIN_VALUE) {
throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
} else {
return (int) -magnitude; // Flip sign.
}
}
/**
* Returns the first argument with the sign of the second argument.
*
* @param magnitude Magnitude of the returned value.
* @param sign Sign of the returned value.
* @return a value with magnitude equal to {@code magnitude} and with the
* same sign as the {@code sign} argument.
* @throws MathArithmeticException if {@code magnitude == Long.MIN_VALUE}
* and {@code sign >= 0}.
*/
public static long copySign(long magnitude, long sign) {
if ((magnitude >= 0 && sign >= 0) ||
(magnitude < 0 && sign < 0)) { // Sign is OK.
return magnitude;
} else if (sign >= 0 &&
magnitude == Long.MIN_VALUE) {
throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
} else {
return (long) -magnitude; // Flip sign.
}
}
/** /**
* Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a> * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a>
* for int value {@code x}. * for int value {@code x}.

View File

@ -1089,4 +1089,20 @@ public class FastMathTest {
Assert.assertEquals(0, FastMath.log(0, 10), 0); Assert.assertEquals(0, FastMath.log(0, 10), 0);
Assert.assertEquals(Double.NEGATIVE_INFINITY, FastMath.log(10, 0), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, FastMath.log(10, 0), 0);
} }
@Test
public void testIndicatorDouble() {
double delta = 0.0;
Assert.assertEquals(1.0, FastMath.copySign(1d, 2.0), delta);
Assert.assertEquals(1.0, FastMath.copySign(1d, 0.0), delta);
Assert.assertEquals(-1.0, FastMath.copySign(1d, -2.0), delta);
}
@Test
public void testIndicatorFloat() {
float delta = 0.0F;
Assert.assertEquals(1.0F, FastMath.copySign(1d, 2.0F), delta);
Assert.assertEquals(1.0F, FastMath.copySign(1d, 0.0F), delta);
Assert.assertEquals(-1.0F, FastMath.copySign(1d, -2.0F), delta);
}
} }

View File

@ -102,47 +102,30 @@ public final class MathUtilsTest {
@Test @Test
public void testIndicatorByte() { public void testIndicatorByte() {
Assert.assertEquals((byte)1, MathUtils.indicator((byte)2)); Assert.assertEquals((byte)1, MathUtils.copySign((byte)1, (byte)2));
Assert.assertEquals((byte)1, MathUtils.indicator((byte)0)); Assert.assertEquals((byte)1, MathUtils.copySign((byte)1, (byte)0));
Assert.assertEquals((byte)(-1), MathUtils.indicator((byte)(-2))); Assert.assertEquals((byte)(-1), MathUtils.copySign((byte)1, (byte)(-2)));
}
@Test
public void testIndicatorDouble() {
double delta = 0.0;
Assert.assertEquals(1.0, MathUtils.indicator(2.0), delta);
Assert.assertEquals(1.0, MathUtils.indicator(0.0), delta);
Assert.assertEquals(-1.0, MathUtils.indicator(-2.0), delta);
Assert.assertTrue(Double.isNaN(MathUtils.indicator(Double.NaN)));
}
@Test
public void testIndicatorFloat() {
float delta = 0.0F;
Assert.assertEquals(1.0F, MathUtils.indicator(2.0F), delta);
Assert.assertEquals(1.0F, MathUtils.indicator(0.0F), delta);
Assert.assertEquals(-1.0F, MathUtils.indicator(-2.0F), delta);
} }
@Test @Test
public void testIndicatorInt() { public void testIndicatorInt() {
Assert.assertEquals(1, MathUtils.indicator((2))); Assert.assertEquals(1, MathUtils.copySign(1, 2));
Assert.assertEquals(1, MathUtils.indicator((0))); Assert.assertEquals(1, MathUtils.copySign(1, 0));
Assert.assertEquals((-1), MathUtils.indicator((-2))); Assert.assertEquals((-1), MathUtils.copySign(1, -2));
} }
@Test @Test
public void testIndicatorLong() { public void testIndicatorLong() {
Assert.assertEquals(1L, MathUtils.indicator(2L)); Assert.assertEquals(1L, MathUtils.copySign(1L, 2L));
Assert.assertEquals(1L, MathUtils.indicator(0L)); Assert.assertEquals(1L, MathUtils.copySign(1L, 0L));
Assert.assertEquals(-1L, MathUtils.indicator(-2L)); Assert.assertEquals(-1L, MathUtils.copySign(1L, -2L));
} }
@Test @Test
public void testIndicatorShort() { public void testIndicatorShort() {
Assert.assertEquals((short)1, MathUtils.indicator((short)2)); Assert.assertEquals((short)1, MathUtils.copySign((short)1, (short)2));
Assert.assertEquals((short)1, MathUtils.indicator((short)0)); Assert.assertEquals((short)1, MathUtils.copySign((short)1, (short)0));
Assert.assertEquals((short)(-1), MathUtils.indicator((short)(-2))); Assert.assertEquals((short)(-1), MathUtils.copySign((short)1, (short)(-2)));
} }
@Test @Test