Improved speed of FastMath copysign methods.

JIRA: MATH-951

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1459887 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2013-03-22 16:25:17 +00:00
parent 787684869d
commit 5c14a29c69
4 changed files with 28 additions and 6 deletions

View File

@ -162,6 +162,9 @@
<contributor> <contributor>
<name>Dan Checkoway</name> <name>Dan Checkoway</name>
</contributor> </contributor>
<contributor>
<name>Charles Cooper</name>
</contributor>
<contributor> <contributor>
<name>Paul Cowan</name> <name>Paul Cowan</name>
</contributor> </contributor>

View File

@ -55,6 +55,9 @@ This is a minor release: It combines bug fixes and new features.
Changes to existing features were made in a backwards-compatible Changes to existing features were made in a backwards-compatible
way such as to allow drop-in replacement of the v3.1[.1] JAR file. way such as to allow drop-in replacement of the v3.1[.1] JAR file.
"> ">
<action dev="luc" type="update" issue="MATH-951" due-to="Charles Cooper">
Improved speed of FastMath copysign methods.
</action>
<action dev="erans" type="add" issue="MATH-817" due-to="Jared Becksfort"> <action dev="erans" type="add" issue="MATH-817" due-to="Jared Becksfort">
Added Multivariate Normal Mixture Model Fitting by Expectation Maximization. Added Multivariate Normal Mixture Model Fitting by Expectation Maximization.
</action> </action>

View File

@ -3630,9 +3630,13 @@ public class FastMath {
* @return the magnitude with the same sign as the {@code sign} argument * @return the magnitude with the same sign as the {@code sign} argument
*/ */
public static double copySign(double magnitude, double sign){ public static double copySign(double magnitude, double sign){
long m = Double.doubleToLongBits(magnitude); // The highest order bit is going to be zero if the
long s = Double.doubleToLongBits(sign); // highest order bit of m and s is the same and one otherwise.
if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK // So (m^s) will be positive if both m and s have the same sign
// and negative otherwise.
final long m = Double.doubleToLongBits(magnitude);
final long s = Double.doubleToLongBits(sign);
if ((m^s) >= 0) {
return magnitude; return magnitude;
} }
return -magnitude; // flip sign return -magnitude; // flip sign
@ -3647,9 +3651,13 @@ public class FastMath {
* @return the magnitude with the same sign as the {@code sign} argument * @return the magnitude with the same sign as the {@code sign} argument
*/ */
public static float copySign(float magnitude, float sign){ public static float copySign(float magnitude, float sign){
int m = Float.floatToIntBits(magnitude); // The highest order bit is going to be zero if the
int s = Float.floatToIntBits(sign); // highest order bit of m and s is the same and one otherwise.
if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK // So (m^s) will be positive if both m and s have the same sign
// and negative otherwise.
final int m = Float.floatToIntBits(magnitude);
final int s = Float.floatToIntBits(sign);
if ((m^s) >= 0) {
return magnitude; return magnitude;
} }
return -magnitude; // flip sign return -magnitude; // flip sign

View File

@ -1149,6 +1149,10 @@ public class FastMathTest {
double delta = 0.0; double delta = 0.0;
Assert.assertEquals(1.0, FastMath.copySign(1d, 2.0), delta); 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, 0.0), delta);
Assert.assertEquals(-1.0, FastMath.copySign(1d, -0.0), delta);
Assert.assertEquals(1.0, FastMath.copySign(1d, Double.POSITIVE_INFINITY), delta);
Assert.assertEquals(-1.0, FastMath.copySign(1d, Double.NEGATIVE_INFINITY), delta);
Assert.assertEquals(1.0, FastMath.copySign(1d, Double.NaN), delta);
Assert.assertEquals(-1.0, FastMath.copySign(1d, -2.0), delta); Assert.assertEquals(-1.0, FastMath.copySign(1d, -2.0), delta);
} }
@ -1157,6 +1161,10 @@ public class FastMathTest {
float delta = 0.0F; float delta = 0.0F;
Assert.assertEquals(1.0F, FastMath.copySign(1d, 2.0F), delta); 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, 0.0F), delta);
Assert.assertEquals(-1.0F, FastMath.copySign(1d, -0.0F), delta);
Assert.assertEquals(1.0F, FastMath.copySign(1d, Float.POSITIVE_INFINITY), delta);
Assert.assertEquals(-1.0F, FastMath.copySign(1d, Float.NEGATIVE_INFINITY), delta);
Assert.assertEquals(1.0F, FastMath.copySign(1d, Float.NaN), delta);
Assert.assertEquals(-1.0F, FastMath.copySign(1d, -2.0F), delta); Assert.assertEquals(-1.0F, FastMath.copySign(1d, -2.0F), delta);
} }