JDK-5039109 : StrictMath/Math pow functions gives wrong answers for large odd integer powers
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2004-04-28
  • Updated: 2004-04-28
  • Resolved: 2004-04-28
Related Reports
Duplicate :  
Description

Name: dk106046			Date: 04/28/2004

OPERATING SYSTEM(S):
Windows 2000

FULL JDK VERSION(S):
1.4.2_04-b05


The StrictMath and Math pow functions give answers which contradicts the
specification given by:
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/StrictMath.html#pow(double,%20double)
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#pow(double,%20double)
If the first argument is finite and less than zero 
if the second argument is a finite even integer, the result is equal to the result of raising the absolute value of the first argument to the power of the second argument 
if the second argument is a finite odd integer, the result is equal to the negative of the result of raising the absolute value of the first argument to the power of the second argument 
if the second argument is finite and not an integer, then the result is NaN. 


The following program:

public class pow {
    static int ln = 0;
    public static double printpow1(double a, double b) {
        double d1 = StrictMath.pow(a, b);
        double d2 = Math.pow(a, b);
        System.out.println((++ln)+" StrictMath.pow("+a+","+b+") = "+d1);
        System.out.println((++ln)+"       Math.pow("+a+","+b+") = "+d2);
        return d1;
    }
    public static double printpow2(double a, double b) {
        double r = printpow1(a, b);
        double r2 = printpow1(-a, b);
        if (!Double.isInfinite(a) && !Double.isNaN(a) && a != 0.0 &&
            !Double.isInfinite(b) && !Double.isNaN(b) &&
            StrictMath.ceil(b) == b &&
            StrictMath.abs(b % 2.0) == 1.0) {
            if (Double.compare(r, -r2) != 0) System.out.println("Error");
        }
        return r;
    }
    public static double printpow3(double a, double b) {
        double r = printpow2(a, b);
        printpow2(a, -b);
        return r;
    }
    public static void main(String args[]) {
        System.out.println((++ln)+" Testing pow method");
        printpow3(1.0000000001, 10000000001.0);
        printpow3(100, 10000000001.0);
        printpow3(0.001, 10000000001.0);
    }
}

gives the following output
1 Testing pow method
2 StrictMath.pow(1.0000000001,1.0000000001E10) = 2.7182820535066154
3       Math.pow(1.0000000001,1.0000000001E10) = 2.7182820535066154
4 StrictMath.pow(-1.0000000001,1.0000000001E10) = -0.0
5       Math.pow(-1.0000000001,1.0000000001E10) = -0.0
Error
6 StrictMath.pow(1.0000000001,-1.0000000001E10) = 0.3678794107145682
7       Math.pow(1.0000000001,-1.0000000001E10) = 0.3678794107145682
8 StrictMath.pow(-1.0000000001,-1.0000000001E10) = -Infinity
9       Math.pow(-1.0000000001,-1.0000000001E10) = -Infinity
Error
10 StrictMath.pow(100.0,1.0000000001E10) = Infinity
11       Math.pow(100.0,1.0000000001E10) = Infinity
12 StrictMath.pow(-100.0,1.0000000001E10) = Infinity
13       Math.pow(-100.0,1.0000000001E10) = Infinity
Error
14 StrictMath.pow(100.0,-1.0000000001E10) = 0.0
15       Math.pow(100.0,-1.0000000001E10) = 0.0
16 StrictMath.pow(-100.0,-1.0000000001E10) = 0.0
17       Math.pow(-100.0,-1.0000000001E10) = 0.0
Error
18 StrictMath.pow(0.0010,1.0000000001E10) = 0.0
19       Math.pow(0.0010,1.0000000001E10) = 0.0
20 StrictMath.pow(-0.0010,1.0000000001E10) = 0.0
21       Math.pow(-0.0010,1.0000000001E10) = 0.0
Error
22 StrictMath.pow(0.0010,-1.0000000001E10) = Infinity
23       Math.pow(0.0010,-1.0000000001E10) = Infinity
24 StrictMath.pow(-0.0010,-1.0000000001E10) = Infinity
25       Math.pow(-0.0010,-1.0000000001E10) = Infinity
Error

The specification for java.lang.StrictMath also says:

To help ensure portability of Java programs, the definitions of many of the numeric functions in this package require that they produce the same results as certain published algorithms. These algorithms are available from the well-known network library netlib as the package "Freely Distributable Math Library" (fdlibm). These algorithms, which are written in the C programming language, are then to be understood as executed with all floating-point operations following the rules of Java floating-point arithmetic. 

The network library may be found on the World Wide Web at: 

   http://metalab.unc.edu/
 The Java math library is defined with respect to the version of fdlibm dated January 4, 1995. Where fdlibm provides more than one definition for a function (such as acos), use the "IEEE 754 core function" version (residing in a file whose name begins with the letter e). 


but this version of fdlibm has some bugs in the pow function (fixed in the latest version) causing the problems above.
I think that Java should meet the special cases as defined in the Java specification, as bit for bit reproducibility of the wrong answer given by fdlibm is not very useful, so java.lang.StrictMath needs to use a fixed version of the fdlibm pow function.


The specification for java.lang.Math says that:
A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic.

The java.lang.Math results break the Java specification and there is not a contradiction in the specification, so the java.lang.Math code should also be fixed.

======================================================================

Comments
EVALUATION Tiger will require use of fdlibm 5.3 instead of 5.2; fdlibm 5.3 has this problem in pow fixed. ###@###.### 2004-04-28
28-04-2004