Bug 1380031: Ensure Math.exp(1) returns Math.E. r=arai
authorAndré Bargull <andre.bargull@gmail.com>
Mon, 25 Mar 2019 09:15:27 +0000
changeset 466229 0808c449b0156fc7adbdddba77f4a1d2eff11040
parent 466228 13c0d857bf3c7cb5b21f25e2c35e1f2f3a57a4e2
child 466230 fd9b6ab6d5647258849e9f09949ac3399585f87e
push id35762
push usercsabou@mozilla.com
push dateWed, 27 Mar 2019 04:44:00 +0000
treeherdermozilla-central@bc572aee49b6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1380031
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1380031: Ensure Math.exp(1) returns Math.E. r=arai Differential Revision: https://phabricator.services.mozilla.com/D24354
js/src/tests/non262/Math/exp-exact.js
modules/fdlibm/patches/17_exp_exact_result_for_positive_one.patch
modules/fdlibm/src/e_exp.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/tests/non262/Math/exp-exact.js
@@ -0,0 +1,29 @@
+// Properties of Math.exp that are guaranteed by the spec.
+
+// If x is NaN, the result is NaN.
+assertEq(Math.exp(NaN), NaN);
+
+// If x is +0, the result is 1.
+assertEq(Math.exp(+0), 1);
+
+// If x is −0, the result is 1.
+assertEq(Math.exp(-0), 1);
+
+// If x is +∞, the result is +∞.
+assertEq(Math.exp(Infinity), Infinity);
+
+// If x is −∞, the result is +0.
+assertEq(Math.exp(-Infinity), +0);
+
+
+// Not guaranteed by the specification, but generally assumed to hold.
+
+// If x is 1, the result is Math.E.
+assertEq(Math.exp(1), Math.E);
+
+// If x is -1, the result is 1/Math.E.
+assertEq(Math.exp(-1), 1 / Math.E);
+
+
+if (typeof reportCompare === "function")
+    reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/modules/fdlibm/patches/17_exp_exact_result_for_positive_one.patch
@@ -0,0 +1,40 @@
+diff --git a/modules/fdlibm/src/e_exp.cpp b/modules/fdlibm/src/e_exp.cpp
+--- a/modules/fdlibm/src/e_exp.cpp
++++ b/modules/fdlibm/src/e_exp.cpp
+@@ -91,16 +91,18 @@ ln2LO[2]   ={ 1.90821492927058770002e-10
+ 	     -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */
+ invln2 =  1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
+ P1   =  1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+ P2   = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+ P3   =  6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+ P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+ P5   =  4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
+ 
++static const double E = 2.7182818284590452354;	/* e */
++
+ static volatile double
+ huge	= 1.0e+300,
+ twom1000= 9.33263618503218878990e-302;     /* 2**-1000=0x01700000,0*/
+ 
+ double
+ __ieee754_exp(double x)	/* default IEEE double exp */
+ {
+ 	double y,hi=0.0,lo=0.0,c,t,twopk;
+@@ -122,16 +124,17 @@ double
+ 	    }
+ 	    if(x > o_threshold) return huge*huge; /* overflow */
+ 	    if(x < u_threshold) return twom1000*twom1000; /* underflow */
+ 	}
+ 
+     /* argument reduction */
+ 	if(hx > 0x3fd62e42) {		/* if  |x| > 0.5 ln2 */ 
+ 	    if(hx < 0x3FF0A2B2) {	/* and |x| < 1.5 ln2 */
++		if (x == 1.0) return E;
+ 		hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+ 	    } else {
+ 		k  = (int)(invln2*x+halF[xsb]);
+ 		t  = k;
+ 		hi = x - t*ln2HI[0];	/* t*ln2HI is exact here */
+ 		lo = t*ln2LO[0];
+ 	    }
+ 	    STRICT_ASSIGN(double, x, hi - lo);
--- a/modules/fdlibm/src/e_exp.cpp
+++ b/modules/fdlibm/src/e_exp.cpp
@@ -91,16 +91,18 @@ ln2LO[2]   ={ 1.90821492927058770002e-10
 	     -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */
 invln2 =  1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
 P1   =  1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
 P2   = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
 P3   =  6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
 P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
 P5   =  4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
 
+static const double E = 2.7182818284590452354;	/* e */
+
 static volatile double
 huge	= 1.0e+300,
 twom1000= 9.33263618503218878990e-302;     /* 2**-1000=0x01700000,0*/
 
 double
 __ieee754_exp(double x)	/* default IEEE double exp */
 {
 	double y,hi=0.0,lo=0.0,c,t,twopk;
@@ -122,16 +124,17 @@ double
 	    }
 	    if(x > o_threshold) return huge*huge; /* overflow */
 	    if(x < u_threshold) return twom1000*twom1000; /* underflow */
 	}
 
     /* argument reduction */
 	if(hx > 0x3fd62e42) {		/* if  |x| > 0.5 ln2 */ 
 	    if(hx < 0x3FF0A2B2) {	/* and |x| < 1.5 ln2 */
+		if (x == 1.0) return E;
 		hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
 	    } else {
 		k  = (int)(invln2*x+halF[xsb]);
 		t  = k;
 		hi = x - t*ln2HI[0];	/* t*ln2HI is exact here */
 		lo = t*ln2LO[0];
 	    }
 	    STRICT_ASSIGN(double, x, hi - lo);