DUK_LOCAL double duk__cbrt(double x) { /* cbrt() is C99. To avoid hassling embedders with the need to provide a * cube root function, we can get by with pow(). The result is not * identical, but that's OK: ES2015 says it's implementation-dependent. */ #if defined(DUK_CBRT) /* cbrt() matches ES2015 requirements. */ return DUK_CBRT(x); #else duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x); /* pow() does not, however. */ if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) { return x; } if (DUK_SIGNBIT(x)) { return -DUK_POW(-x, 1.0 / 3.0); } else { return DUK_POW(x, 1.0 / 3.0); } #endif }
static double duk__pow_fixed(double x, double y) { /* The ANSI C pow() semantics differ from Ecmascript. * * E.g. when x==1 and y is +/- infinite, the Ecmascript required * result is NaN, while at least Linux pow() returns 1. */ int cx, cy, sx; DUK_UNREF(cx); DUK_UNREF(sx); cy = DUK_FPCLASSIFY(y); if (cy == DUK_FP_NAN) { goto ret_nan; } if (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) { goto ret_nan; } #if defined(DUK_USE_POW_NETBSD_WORKAROUND) /* See test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least) does not * correctly handle some cases where x=+/-0. Specific fixes to these * here. */ cx = DUK_FPCLASSIFY(x); if (cx == DUK_FP_ZERO && y < 0.0) { sx = DUK_SIGNBIT(x); if (sx == 0) { /* Math.pow(+0,y) should be Infinity when y<0. NetBSD pow() * returns -Infinity instead when y is <0 and finite. The * if-clause also catches y == -Infinity (which works even * without the fix). */ return DUK_DOUBLE_INFINITY; } else { /* Math.pow(-0,y) where y<0 should be: * - -Infinity if y<0 and an odd integer * - Infinity otherwise * NetBSD pow() returns -Infinity for all finite y<0. The * if-clause also catches y == -Infinity (which works even * without the fix). */ /* fmod() return value has same sign as input (negative) so * the result here will be in the range ]-2,0], 1 indicates * odd. If x is -Infinity, NaN is returned and the odd check * always concludes "not odd" which results in desired outcome. */ double tmp = DUK_FMOD(y, 2); if (tmp == -1.0) { return -DUK_DOUBLE_INFINITY; } else { /* Not odd, or y == -Infinity */ return DUK_DOUBLE_INFINITY; } } } #endif return DUK_POW(x, y); ret_nan: return DUK_DOUBLE_NAN; }