Bug 622348 - JavaScript Math.round incorrect for (2^53)-1. r=Waldo

--HG--
extra : rebase_source : 51a780cf5ce9cbcc84c56d8a8dbe2c5d9867b36b
This commit is contained in:
Tom Schuster 2011-12-25 15:16:12 +01:00
Родитель 7637869e5b
Коммит 4f4a9cacd2
4 изменённых файлов: 48 добавлений и 25 удалений

Просмотреть файл

@ -0,0 +1,10 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
assertEq(Math.round(9007199254740991), 9007199254740991);
assertEq(Math.round(-19007199254740990), -19007199254740990);
assertEq(Math.round("9007199254740991"), 9007199254740991);
assertEq(Math.round("-19007199254740990"), -19007199254740990);

Просмотреть файл

@ -577,26 +577,39 @@ js_copysign(double x, double y)
}
#endif
jsdouble
js_math_round_impl(jsdouble x)
{
return js_copysign(floor(x + 0.5), x);
}
JSBool
JSBool /* ES5 15.8.2.15. */
js_math_round(JSContext *cx, uintN argc, Value *vp)
{
jsdouble x, z;
CallArgs args = CallArgsFromVp(argc, vp);
if (argc == 0) {
vp->setDouble(js_NaN);
return JS_TRUE;
if (args.length() == 0) {
args.rval().setDouble(js_NaN);
return true;
}
if (!ToNumber(cx, vp[2], &x))
return JS_FALSE;
z = js_copysign(floor(x + 0.5), x);
vp->setNumber(z);
return JS_TRUE;
double x;
if (!ToNumber(cx, args[0], &x))
return false;
int32_t i;
if (JSDOUBLE_IS_INT32(x, &i)) {
args.rval().setInt32(i);
return true;
}
jsdpun u;
u.d = x;
/* Some numbers are so big that adding 0.5 would give the wrong number */
int exponent = ((u.s.hi & JSDOUBLE_HI32_EXPMASK) >> JSDOUBLE_HI32_EXPSHIFT) - JSDOUBLE_EXPBIAS;
if (exponent >= 52) {
args.rval().setNumber(x);
return true;
}
args.rval().setNumber(js_copysign(floor(x + 0.5), x));
return true;
}
static JSBool

Просмотреть файл

@ -121,7 +121,4 @@ js_math_ceil_impl(jsdouble x);
extern jsdouble
js_math_floor_impl(jsdouble x);
extern jsdouble
js_math_round_impl(jsdouble x);
#endif /* jsmath_h___ */

Просмотреть файл

@ -65,6 +65,16 @@
#endif
#endif
/* Low-level floating-point predicates. See bug 640494. */
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
#define JSDOUBLE_HI32_NAN 0x7ff80000
#define JSDOUBLE_LO32_NAN 0x00000000
#define JSDOUBLE_HI32_EXPSHIFT 20
#define JSDOUBLE_EXPBIAS 1023
typedef union jsdpun {
struct {
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
@ -77,13 +87,6 @@ typedef union jsdpun {
jsdouble d;
} jsdpun;
/* Low-level floating-point predicates. See bug 640494. */
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
#define JSDOUBLE_HI32_NAN 0x7ff80000
#define JSDOUBLE_LO32_NAN 0x00000000
static inline int
JSDOUBLE_IS_NaN(jsdouble d)
{