// Implements Math.fround (20.2.2.16) up to step 3 bool js::RoundFloat32(JSContext *cx, Handle<Value> v, float *out) { double d; bool success = ToNumber(cx, v, &d); *out = static_cast<float>(d); return success; }
bool js_math_pow(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double x; if (!ToNumber(cx, args.get(0), &x)) return false; double y; if (!ToNumber(cx, args.get(1), &y)) return false; double z = ecmaPow(x, y); args.rval().setNumber(z); return true; }
bool js::minmax_impl(JSContext *cx, bool max, HandleValue a, HandleValue b, MutableHandleValue res) { double x, y; if (!ToNumber(cx, a, &x)) return false; if (!ToNumber(cx, b, &y)) return false; if (max) res.setNumber(max_double(x, y)); else res.setNumber(min_double(x, y)); return true; }
bool js::math_atan2(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double y; if (!ToNumber(cx, args.get(0), &y)) return false; double x; if (!ToNumber(cx, args.get(1), &x)) return false; double z = ecmaAtan2(y, x); args.rval().setDouble(z); return true; }
bool js::math_atan2(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() <= 1) { args.rval().setDouble(js_NaN); return true; } double x, y; if (!ToNumber(cx, args[0], &x) || !ToNumber(cx, args[1], &y)) return false; double z = ecmaAtan2(x, y); args.rval().setDouble(z); return true; }
bool js::math_hypot_handle(JSContext* cx, HandleValueArray args, MutableHandleValue res) { // IonMonkey calls the system hypot function directly if two arguments are // given. Do that here as well to get the same results. if (args.length() == 2) { double x, y; if (!ToNumber(cx, args[0], &x)) return false; if (!ToNumber(cx, args[1], &y)) return false; double result = ecmaHypot(x, y); res.setNumber(result); return true; } bool isInfinite = false; bool isNaN = false; double scale = 0; double sumsq = 1; for (unsigned i = 0; i < args.length(); i++) { double x; if (!ToNumber(cx, args[i], &x)) return false; isInfinite |= mozilla::IsInfinite(x); isNaN |= mozilla::IsNaN(x); if (isInfinite || isNaN) continue; hypot_step(scale, sumsq, x); } double result = isInfinite ? PositiveInfinity<double>() : isNaN ? GenericNaN() : scale * sqrt(sumsq); res.setNumber(result); return true; }
bool js::math_round_handle(JSContext *cx, HandleValue arg, MutableHandleValue res) { double d; if (!ToNumber(cx, arg, &d)) return false; d = math_round_impl(d); res.setNumber(d); return true; }
bool js::math_ceil_handle(JSContext* cx, HandleValue v, MutableHandleValue res) { double d; if(!ToNumber(cx, v, &d)) return false; double result = math_ceil_impl(d); res.setNumber(result); return true; }
bool js::math_floor_handle(JSContext *cx, HandleValue v, MutableHandleValue r) { double d; if(!ToNumber(cx, v, &d)) return false; double z = math_floor_impl(d); r.setNumber(z); return true; }
bool js::math_abs_handle(JSContext *cx, js::HandleValue v, js::MutableHandleValue r) { double x; if (!ToNumber(cx, v, &x)) return false; double z = Abs(x); r.setNumber(z); return true; }
bool js_math_pow(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() <= 1) { args.rval().setDouble(js_NaN); return true; } double x, y; if (!ToNumber(cx, args[0], &x) || !ToNumber(cx, args[1], &y)) return false; /* * Special case for square roots. Note that pow(x, 0.5) != sqrt(x) * when x = -0.0, so we have to guard for this. */ if (IsFinite(x) && x != 0.0) { if (y == 0.5) { args.rval().setNumber(sqrt(x)); return true; } if (y == -0.5) { args.rval().setNumber(1.0/sqrt(x)); return true; } } /* pow(x, +-0) is always 1, even for x = NaN. */ if (y == 0) { args.rval().setInt32(1); return true; } double z = ecmaPow(x, y); args.rval().setNumber(z); return true; }
bool js::math_min(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double minval = PositiveInfinity<double>(); for (unsigned i = 0; i < args.length(); i++) { double x; if (!ToNumber(cx, args[i], &x)) return false; minval = min_double(x, minval); } args.rval().setNumber(minval); return true; }
bool js::math_sin_handle(JSContext* cx, HandleValue val, MutableHandleValue res) { double in; if (!ToNumber(cx, val, &in)) return false; MathCache* mathCache = cx->runtime()->getMathCache(cx); if (!mathCache) return false; double out = math_sin_impl(mathCache, in); res.setDouble(out); return true; }
bool js::math_sqrt_handle(JSContext *cx, HandleValue number, MutableHandleValue result) { double x; if (!ToNumber(cx, number, &x)) return false; MathCache *mathCache = cx->runtime()->getMathCache(cx); if (!mathCache) return false; double z = mathCache->lookup(sqrt, x, MathCache::Sqrt); result.setDouble(z); return true; }
bool js_math_min(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double minval = PositiveInfinity<double>(); for (unsigned i = 0; i < args.length(); i++) { double x; if (!ToNumber(cx, args[i], &x)) return false; // Math.min(num, NaN) => NaN, Math.min(-0, +0) => -0 if (x < minval || IsNaN(x) || (x == minval && IsNegativeZero(x))) minval = x; } args.rval().setNumber(minval); return true; }
bool js_math_max(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double maxval = NegativeInfinity(); for (unsigned i = 0; i < args.length(); i++) { double x; if (!ToNumber(cx, args[i], &x)) return false; // Math.max(num, NaN) => NaN, Math.max(-0, +0) => +0 if (x > maxval || IsNaN(x) || (x == maxval && IsNegative(maxval))) maxval = x; } args.rval().setNumber(maxval); return true; }
bool js::math_ceil(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { args.rval().setNaN(); return true; } double x; if (!ToNumber(cx, args[0], &x)) return false; double z = math_ceil_impl(x); args.rval().setNumber(z); return true; }
bool js_math_floor(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { args.rval().setDouble(js_NaN); return true; } double x; if (!ToNumber(cx, args[0], &x)) return false; double z = js_math_floor_impl(x); args.rval().setNumber(z); return true; }
bool js::math_fround(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { args.rval().setNaN(); return true; } double x; if (!ToNumber(cx, args[0], &x)) return false; float f = x; args.rval().setDouble(static_cast<double>(f)); return true; }
static bool math_function(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { args.rval().setNumber(GenericNaN()); return true; } double x; if (!ToNumber(cx, args[0], &x)) return false; MathCache *mathCache = cx->runtime()->getMathCache(cx); if (!mathCache) return false; double z = F(mathCache, x); args.rval().setNumber(z); return true; }
bool js::math_tan(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { args.rval().setNaN(); return true; } double x; if (!ToNumber(cx, args[0], &x)) return false; MathCache *mathCache = cx->runtime()->getMathCache(cx); if (!mathCache) return false; double z = math_tan_impl(mathCache, x); args.rval().setDouble(z); return true; }
bool js_math_sqrt(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { args.rval().setDouble(js_NaN); return true; } double x; if (!ToNumber(cx, args[0], &x)) return false; MathCache *mathCache = cx->runtime()->getMathCache(cx); if (!mathCache) return false; double z = mathCache->lookup(sqrt, x); args.rval().setDouble(z); return true; }