Added a fast implementation of IEEEremainder in FastMath.

This commit is contained in:
Luc Maisonobe 2015-05-16 14:22:46 +02:00
parent 83c61da2c9
commit 15a24dc0fc
3 changed files with 54 additions and 6 deletions

View File

@ -54,6 +54,9 @@ If the output is not quite correct, check for invisible trailing spaces!
</release>
<release version="4.0" date="XXXX-XX-XX" description="">
<action dev="luc" type="add" >
Added a fast implementation of IEEEremainder in FastMath.
</action>
<action dev="luc" type="fix" issue="MATH-1222" due-to="Benedikt Ritter">
Use Double.isNaN rather than x != x in FastMath.
</action>

View File

@ -3628,13 +3628,24 @@ public class FastMath {
* <li>If the dividend is finite and the divisor is an infinity, the result equals the dividend.</li>
* <li>If the dividend is a zero and the divisor is finite, the result equals the dividend.</li>
* </ul>
* <p><b>Note:</b> this implementation currently delegates to {@link StrictMath#IEEEremainder}
* @param dividend the number to be divided
* @param divisor the number by which to divide
* @return the remainder, rounded
*/
public static double IEEEremainder(double dividend, double divisor) {
return StrictMath.IEEEremainder(dividend, divisor); // TODO provide our own implementation
public static double IEEEremainder(final double dividend, final double divisor) {
if (getExponent(dividend) == 1024 || getExponent(divisor) == 1024 || divisor == 0.0) {
// we are in one of the special cases
if (Double.isInfinite(divisor) && !Double.isInfinite(dividend)) {
return dividend;
} else {
return Double.NaN;
}
} else {
// we are in the general case
final double n = FastMath.rint(dividend / divisor);
final double remainder = Double.isInfinite(n) ? 0.0 : dividend - divisor * n;
return (remainder == 0) ? FastMath.copySign(remainder, dividend) : remainder;
}
}
/** Convert a long to interger, detecting overflows

View File

@ -28,9 +28,9 @@ public class FastMathTestPerformance {
private static final double F1 = 1d / RUNS;
// Header format
private static final String FMT_HDR = "%-5s %13s %13s %13s Runs=%d Java %s (%s) %s (%s)";
private static final String FMT_HDR = "%-13s %13s %13s %13s Runs=%d Java %s (%s) %s (%s)";
// Detail format
private static final String FMT_DTL = "%-5s %6d %6.1f %6d %6.4f %6d %6.4f";
private static final String FMT_DTL = "%-13s %6d %6.1f %6d %6.4f %6d %6.4f";
public static void main(String[] args) {
System.out.println(String.format(FMT_HDR,
@ -60,6 +60,7 @@ public class FastMathTestPerformance {
testSqrt();
testTan();
testTanh();
testIEEEremainder();
}
@ -429,7 +430,40 @@ public class FastMathTestPerformance {
report("hypot",strictTime,fastTime,mathTime);
assertTrue(!Double.isNaN(x));
}
private static void testIEEEremainder() {
double x = 0;
long time = System.nanoTime();
int max = (int) FastMath.floor(FastMath.sqrt(RUNS));
for (int i = 0; i < max; i++) {
for (int j = 0; j < max; j++) {
x += StrictMath.IEEEremainder((i - max/2) * (100.0 / max), (j + 1) * (100.0 / max));
}
}
long strictTime = System.nanoTime() - time;
x = 0;
time = System.nanoTime();
for (int i = 0; i < max; i++) {
for (int j = 0; j < max; j++) {
x += FastMath.IEEEremainder((i - max/2) * (100.0 / max), (j + 1) * (100.0 / max));
}
}
long fastTime = System.nanoTime() - time;
x = 0;
time = System.nanoTime();
for (int i = 0; i < max; i++) {
for (int j = 0; j < max; j++) {
x += Math.IEEEremainder((i - max/2) * (100.0 / max), (j + 1) * (100.0 / max));
}
}
long mathTime = System.nanoTime() - time;
report("IEEEremainder",strictTime,fastTime,mathTime);
assertTrue(!Double.isNaN(x));
}
private static void testCbrt() {
double x = 0;
long time = System.nanoTime();