Adds flag for which sin/cos implementation to use

My plan is to add a finch flag to the chrome side. It'll be a kill
switch, but given the history with changing the implementation, I want
to make sure we have the ability to switch back.

Bug=v8:13477

Change-Id: I1559e10d134bd78699b1119be26934570c6e5241
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4108811
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84874}
This commit is contained in:
Scott Violet 2022-12-14 19:16:16 -08:00 committed by V8 LUCI CQ
parent 37e5a28add
commit ef680d1b01
10 changed files with 290 additions and 85 deletions

View File

@ -107,10 +107,8 @@ namespace {
int32_t __ieee754_rem_pio2(double x, double* y) V8_WARN_UNUSED_RESULT;
int __kernel_rem_pio2(double* x, double* y, int e0, int nx, int prec,
const int32_t* ipio2) V8_WARN_UNUSED_RESULT;
#if !defined(V8_USE_LIBM_TRIG_FUNCTIONS)
double __kernel_cos(double x, double y) V8_WARN_UNUSED_RESULT;
double __kernel_sin(double x, double y, int iy) V8_WARN_UNUSED_RESULT;
#endif
/* __ieee754_rem_pio2(x,y)
*
@ -271,7 +269,6 @@ int32_t __ieee754_rem_pio2(double x, double *y) {
return n;
}
#if !defined(V8_USE_LIBM_TRIG_FUNCTIONS)
/* __kernel_cos( x, y )
* kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
* Input x is assumed to be bounded by ~pi/4 in magnitude.
@ -337,7 +334,6 @@ V8_INLINE double __kernel_cos(double x, double y) {
return a - (iz - (z * r - x * y));
}
}
#endif
/* __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
* double x[],y[]; int e0,nx,prec; int ipio2[];
@ -647,7 +643,6 @@ recompute:
return n & 7;
}
#if !defined(V8_USE_LIBM_TRIG_FUNCTIONS)
/* __kernel_sin( x, y, iy)
* kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
* Input x is assumed to be bounded by ~pi/4 in magnitude.
@ -701,7 +696,6 @@ V8_INLINE double __kernel_sin(double x, double y, int iy) {
return x - ((z * (half * y - v * r) - y) - v * S1);
}
}
#endif
/* __kernel_tan( x, y, k )
* kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
@ -1324,7 +1318,6 @@ double atan2(double y, double x) {
}
}
#if !defined(V8_USE_LIBM_TRIG_FUNCTIONS)
/* cos(x)
* Return cosine function of x.
*
@ -1355,7 +1348,11 @@ double atan2(double y, double x) {
* Accuracy:
* TRIG(x) returns trig(x) nearly rounded
*/
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS)
double fdlibm_cos(double x) {
#else
double cos(double x) {
#endif
double y[2], z = 0.0;
int32_t n, ix;
@ -1384,7 +1381,6 @@ double cos(double x) {
}
}
}
#endif
/* exp(x)
* Returns the exponential of x.
@ -2418,7 +2414,6 @@ double cbrt(double x) {
return (t);
}
#if !defined(V8_USE_LIBM_TRIG_FUNCTIONS)
/* sin(x)
* Return sine function of x.
*
@ -2449,7 +2444,11 @@ double cbrt(double x) {
* Accuracy:
* TRIG(x) returns trig(x) nearly rounded
*/
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS)
double fdlibm_sin(double x) {
#else
double sin(double x) {
#endif
double y[2], z = 0.0;
int32_t n, ix;
@ -2478,7 +2477,6 @@ double sin(double x) {
}
}
}
#endif
/* tan(x)
* Return tangent function of x.
@ -3026,12 +3024,8 @@ double tanh(double x) {
#undef SET_LOW_WORD
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS) && defined(BUILDING_V8_BASE_SHARED)
double sin(double x) {
return glibc_sin(x);
}
double cos(double x) {
return glibc_cos(x);
}
double libm_sin(double x) { return glibc_sin(x); }
double libm_cos(double x) { return glibc_cos(x); }
#endif
} // namespace ieee754

View File

@ -37,15 +37,23 @@ V8_BASE_EXPORT double atan(double x);
// the two arguments to determine the quadrant of the result.
V8_BASE_EXPORT double atan2(double y, double x);
// Returns the cosine of |x|, where |x| is given in radians.
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS) && \
!defined(BUILDING_V8_BASE_SHARED) && \
!defined(USING_V8_BASE_SHARED)
inline double cos(double x) {
return glibc_cos(x);
}
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS)
// To ensure there aren't problems with libm's sin/cos, both implementations
// are shipped. The plan is to transition to libm once we ensure there are no
// compatibility or performance issues.
V8_BASE_EXPORT double fdlibm_sin(double x);
V8_BASE_EXPORT double fdlibm_cos(double x);
#if !defined(BUILDING_V8_BASE_SHARED) && !defined(USING_V8_BASE_SHARED)
inline double libm_sin(double x) { return glibc_sin(x); }
inline double libm_cos(double x) { return glibc_cos(x); }
#else
V8_BASE_EXPORT double libm_sin(double x);
V8_BASE_EXPORT double libm_cos(double x);
#endif
#else
V8_BASE_EXPORT double cos(double x);
V8_BASE_EXPORT double sin(double x);
#endif
// Returns the base-e exponential of |x|.
@ -80,17 +88,6 @@ V8_BASE_EXPORT double expm1(double x);
// behaviour is preserved for compatibility reasons.
V8_BASE_EXPORT double pow(double x, double y);
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS) && \
!defined(BUILDING_V8_BASE_SHARED) && \
!defined(USING_V8_BASE_SHARED)
inline double sin(double x) {
return glibc_sin(x);
}
#else
// Returns the sine of |x|, where |x| is given in radians.
V8_BASE_EXPORT double sin(double x);
#endif
// Returns the tangent of |x|, where |x| is given in radians.
V8_BASE_EXPORT double tan(double x);

View File

@ -359,4 +359,17 @@ Builtin ExampleBuiltinForTorqueFunctionPointerType(
} // namespace internal
} // namespace v8
// Helper while transitioning some functions to libm.
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS)
#define SIN_IMPL(X) \
v8_flags.use_libm_trig_functions ? base::ieee754::libm_sin(X) \
: base::ieee754::fdlibm_sin(X)
#define COS_IMPL(X) \
v8_flags.use_libm_trig_functions ? base::ieee754::libm_cos(X) \
: base::ieee754::fdlibm_cos(X)
#else
#define SIN_IMPL(X) base::ieee754::sin(X)
#define COS_IMPL(X) base::ieee754::cos(X)
#endif
#endif // V8_BUILTINS_BUILTINS_H_

View File

@ -880,8 +880,6 @@ FUNCTION_REFERENCE_WITH_TYPE(ieee754_atan2_function, base::ieee754::atan2,
BUILTIN_FP_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_cbrt_function, base::ieee754::cbrt,
BUILTIN_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_cos_function, base::ieee754::cos,
BUILTIN_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_cosh_function, base::ieee754::cosh,
BUILTIN_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_exp_function, base::ieee754::exp,
@ -896,8 +894,6 @@ FUNCTION_REFERENCE_WITH_TYPE(ieee754_log10_function, base::ieee754::log10,
BUILTIN_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_log2_function, base::ieee754::log2,
BUILTIN_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_sin_function, base::ieee754::sin,
BUILTIN_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_sinh_function, base::ieee754::sinh,
BUILTIN_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_tan_function, base::ieee754::tan,
@ -907,6 +903,32 @@ FUNCTION_REFERENCE_WITH_TYPE(ieee754_tanh_function, base::ieee754::tanh,
FUNCTION_REFERENCE_WITH_TYPE(ieee754_pow_function, base::ieee754::pow,
BUILTIN_FP_FP_CALL)
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS)
ExternalReference ExternalReference::ieee754_sin_function() {
static_assert(
IsValidExternalReferenceType<decltype(&base::ieee754::libm_sin)>::value);
static_assert(IsValidExternalReferenceType<
decltype(&base::ieee754::fdlibm_sin)>::value);
auto* f = v8_flags.use_libm_trig_functions ? base::ieee754::libm_sin
: base::ieee754::fdlibm_sin;
return ExternalReference(Redirect(FUNCTION_ADDR(f), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_cos_function() {
static_assert(
IsValidExternalReferenceType<decltype(&base::ieee754::libm_cos)>::value);
static_assert(IsValidExternalReferenceType<
decltype(&base::ieee754::fdlibm_cos)>::value);
auto* f = v8_flags.use_libm_trig_functions ? base::ieee754::libm_cos
: base::ieee754::fdlibm_cos;
return ExternalReference(Redirect(FUNCTION_ADDR(f), BUILTIN_FP_CALL));
}
#else
FUNCTION_REFERENCE_WITH_TYPE(ieee754_sin_function, base::ieee754::sin,
BUILTIN_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_cos_function, base::ieee754::cos,
BUILTIN_FP_CALL)
#endif
void* libc_memchr(void* string, int character, size_t search_length) {
return memchr(string, character, search_length);
}

View File

@ -12,6 +12,7 @@
#include "src/base/ieee754.h"
#include "src/base/logging.h"
#include "src/base/overflowing-math.h"
#include "src/builtins/builtins.h"
#include "src/compiler/diamond.h"
#include "src/compiler/graph.h"
#include "src/compiler/js-operator.h"
@ -771,7 +772,7 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
case IrOpcode::kFloat64Cos: {
Float64Matcher m(node->InputAt(0));
if (m.HasResolvedValue())
return ReplaceFloat64(base::ieee754::cos(m.ResolvedValue()));
return ReplaceFloat64(COS_IMPL(m.ResolvedValue()));
break;
}
case IrOpcode::kFloat64Cosh: {
@ -836,7 +837,7 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
case IrOpcode::kFloat64Sin: {
Float64Matcher m(node->InputAt(0));
if (m.HasResolvedValue())
return ReplaceFloat64(base::ieee754::sin(m.ResolvedValue()));
return ReplaceFloat64(SIN_IMPL(m.ResolvedValue()));
break;
}
case IrOpcode::kFloat64Sinh: {

View File

@ -20,6 +20,7 @@
#include "src/base/overflowing-math.h"
#include "src/base/template-utils.h"
#include "src/base/vector.h"
#include "src/builtins/builtins.h"
#include "src/codegen/machine-type.h"
#include "src/compiler/backend/instruction.h"
#include "src/compiler/machine-operator-reducer.h"
@ -250,9 +251,9 @@ class MachineOptimizationReducer : public Next {
case FloatUnaryOp::Kind::kExpm1:
return Asm().Float32Constant(base::ieee754::expm1(k));
case FloatUnaryOp::Kind::kSin:
return Asm().Float32Constant(base::ieee754::sin(k));
return Asm().Float32Constant(SIN_IMPL(k));
case FloatUnaryOp::Kind::kCos:
return Asm().Float32Constant(base::ieee754::cos(k));
return Asm().Float32Constant(COS_IMPL(k));
case FloatUnaryOp::Kind::kSinh:
return Asm().Float32Constant(base::ieee754::sinh(k));
case FloatUnaryOp::Kind::kCosh:
@ -314,9 +315,9 @@ class MachineOptimizationReducer : public Next {
case FloatUnaryOp::Kind::kExpm1:
return Asm().Float64Constant(base::ieee754::expm1(k));
case FloatUnaryOp::Kind::kSin:
return Asm().Float64Constant(base::ieee754::sin(k));
return Asm().Float64Constant(SIN_IMPL(k));
case FloatUnaryOp::Kind::kCos:
return Asm().Float64Constant(base::ieee754::cos(k));
return Asm().Float64Constant(COS_IMPL(k));
case FloatUnaryOp::Kind::kSinh:
return Asm().Float64Constant(base::ieee754::sinh(k));
case FloatUnaryOp::Kind::kCosh:

View File

@ -2394,6 +2394,10 @@ DEFINE_IMPLICATION(verify_predictable, predictable)
DEFINE_INT(dump_allocations_digest_at_alloc, -1,
"dump allocations digest each n-th allocation")
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS)
DEFINE_BOOL(use_libm_trig_functions, true, "use libm trig functions")
#endif
// Cleanup...
#undef FLAG_FULL
#undef FLAG_READONLY

View File

@ -11,6 +11,7 @@
#include "src/base/overflowing-math.h"
#include "src/base/safe_conversions.h"
#include "src/base/utils/random-number-generator.h"
#include "src/builtins/builtins.h"
#include "src/common/ptr-compr-inl.h"
#include "src/objects/objects-inl.h"
#include "src/utils/boxed-float.h"
@ -6318,7 +6319,7 @@ TEST(RunFloat64Cos) {
m.Return(m.Float64Cos(m.Parameter(0)));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(base::ieee754::cos(i), m.Call(i)); }
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(COS_IMPL(i), m.Call(i)); }
}
TEST(RunFloat64Cosh) {
@ -6428,7 +6429,7 @@ TEST(RunFloat64Sin) {
m.Return(m.Float64Sin(m.Parameter(0)));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(base::ieee754::sin(i), m.Call(i)); }
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(SIN_IMPL(i), m.Call(i)); }
}
TEST(RunFloat64Sinh) {

View File

@ -131,6 +131,175 @@ TEST(Ieee754, Atanh) {
EXPECT_DOUBLE_EQ(0.54930614433405478, atanh(0.5));
}
#if defined(V8_USE_LIBM_TRIG_FUNCTIONS)
TEST(Ieee754, LibmCos) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(libm_cos(kQNaN), IsNaN());
EXPECT_THAT(libm_cos(kSNaN), IsNaN());
EXPECT_THAT(libm_cos(kInfinity), IsNaN());
EXPECT_THAT(libm_cos(-kInfinity), IsNaN());
// Tests for cos for |x| < pi/4
EXPECT_EQ(1.0, 1 / libm_cos(-0.0));
EXPECT_EQ(1.0, 1 / libm_cos(0.0));
// cos(x) = 1 for |x| < 2^-27
EXPECT_EQ(1, libm_cos(2.3283064365386963e-10));
EXPECT_EQ(1, libm_cos(-2.3283064365386963e-10));
// Test KERNELCOS for |x| < 0.3.
// cos(pi/20) = sqrt(sqrt(2)*sqrt(sqrt(5)+5)+4)/2^(3/2)
EXPECT_EQ(0.9876883405951378, libm_cos(0.15707963267948966));
// Test KERNELCOS for x ~= 0.78125
EXPECT_EQ(0.7100335477927638, libm_cos(0.7812504768371582));
EXPECT_EQ(0.7100338835660797, libm_cos(0.78125));
// Test KERNELCOS for |x| > 0.3.
// cos(pi/8) = sqrt(sqrt(2)+1)/2^(3/4)
EXPECT_EQ(0.9238795325112867, libm_cos(0.39269908169872414));
// Test KERNELTAN for |x| < 0.67434.
EXPECT_EQ(0.9238795325112867, libm_cos(-0.39269908169872414));
// Tests for cos.
EXPECT_EQ(1, libm_cos(3.725290298461914e-9));
// Cover different code paths in KERNELCOS.
EXPECT_EQ(0.9689124217106447, libm_cos(0.25));
EXPECT_EQ(0.8775825618903728, libm_cos(0.5));
EXPECT_EQ(0.7073882691671998, libm_cos(0.785));
// Test that cos(Math.PI/2) != 0 since Math.PI is not exact.
EXPECT_EQ(6.123233995736766e-17, libm_cos(1.5707963267948966));
// Test cos for various phases.
EXPECT_EQ(0.7071067811865474, libm_cos(7.0 / 4 * kPI));
EXPECT_EQ(0.7071067811865477, libm_cos(9.0 / 4 * kPI));
EXPECT_EQ(-0.7071067811865467, libm_cos(11.0 / 4 * kPI));
EXPECT_EQ(-0.7071067811865471, libm_cos(13.0 / 4 * kPI));
EXPECT_EQ(0.9367521275331447, libm_cos(1000000.0));
EXPECT_EQ(-3.435757038074824e-12, libm_cos(1048575.0 / 2 * kPI));
// Test Hayne-Panek reduction.
EXPECT_EQ(-0.9258790228548379e0, libm_cos(kTwo120));
EXPECT_EQ(-0.9258790228548379e0, libm_cos(-kTwo120));
}
TEST(Ieee754, LibmSin) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(libm_sin(kQNaN), IsNaN());
EXPECT_THAT(libm_sin(kSNaN), IsNaN());
EXPECT_THAT(libm_sin(kInfinity), IsNaN());
EXPECT_THAT(libm_sin(-kInfinity), IsNaN());
// Tests for sin for |x| < pi/4
EXPECT_EQ(-kInfinity, Divide(1.0, libm_sin(-0.0)));
EXPECT_EQ(kInfinity, Divide(1.0, libm_sin(0.0)));
// sin(x) = x for x < 2^-27
EXPECT_EQ(2.3283064365386963e-10, libm_sin(2.3283064365386963e-10));
EXPECT_EQ(-2.3283064365386963e-10, libm_sin(-2.3283064365386963e-10));
// sin(pi/8) = sqrt(sqrt(2)-1)/2^(3/4)
EXPECT_EQ(0.3826834323650898, libm_sin(0.39269908169872414));
EXPECT_EQ(-0.3826834323650898, libm_sin(-0.39269908169872414));
// Tests for sin.
EXPECT_EQ(0.479425538604203, libm_sin(0.5));
EXPECT_EQ(-0.479425538604203, libm_sin(-0.5));
EXPECT_EQ(1, libm_sin(kPI / 2.0));
EXPECT_EQ(-1, libm_sin(-kPI / 2.0));
// Test that sin(Math.PI) != 0 since Math.PI is not exact.
EXPECT_EQ(1.2246467991473532e-16, libm_sin(kPI));
EXPECT_EQ(-7.047032979958965e-14, libm_sin(2200.0 * kPI));
// Test sin for various phases.
EXPECT_EQ(-0.7071067811865477, libm_sin(7.0 / 4.0 * kPI));
EXPECT_EQ(0.7071067811865474, libm_sin(9.0 / 4.0 * kPI));
EXPECT_EQ(0.7071067811865483, libm_sin(11.0 / 4.0 * kPI));
EXPECT_EQ(-0.7071067811865479, libm_sin(13.0 / 4.0 * kPI));
EXPECT_EQ(-3.2103381051568376e-11, libm_sin(1048576.0 / 4 * kPI));
// Test Hayne-Panek reduction.
EXPECT_EQ(0.377820109360752e0, libm_sin(kTwo120));
EXPECT_EQ(-0.377820109360752e0, libm_sin(-kTwo120));
}
TEST(Ieee754, FdlibmCos) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(fdlibm_cos(kQNaN), IsNaN());
EXPECT_THAT(fdlibm_cos(kSNaN), IsNaN());
EXPECT_THAT(fdlibm_cos(kInfinity), IsNaN());
EXPECT_THAT(fdlibm_cos(-kInfinity), IsNaN());
// Tests for cos for |x| < pi/4
EXPECT_EQ(1.0, 1 / fdlibm_cos(-0.0));
EXPECT_EQ(1.0, 1 / fdlibm_cos(0.0));
// cos(x) = 1 for |x| < 2^-27
EXPECT_EQ(1, fdlibm_cos(2.3283064365386963e-10));
EXPECT_EQ(1, fdlibm_cos(-2.3283064365386963e-10));
// Test KERNELCOS for |x| < 0.3.
// cos(pi/20) = sqrt(sqrt(2)*sqrt(sqrt(5)+5)+4)/2^(3/2)
EXPECT_EQ(0.9876883405951378, fdlibm_cos(0.15707963267948966));
// Test KERNELCOS for x ~= 0.78125
EXPECT_EQ(0.7100335477927638, fdlibm_cos(0.7812504768371582));
EXPECT_EQ(0.7100338835660797, fdlibm_cos(0.78125));
// Test KERNELCOS for |x| > 0.3.
// cos(pi/8) = sqrt(sqrt(2)+1)/2^(3/4)
EXPECT_EQ(0.9238795325112867, fdlibm_cos(0.39269908169872414));
// Test KERNELTAN for |x| < 0.67434.
EXPECT_EQ(0.9238795325112867, fdlibm_cos(-0.39269908169872414));
// Tests for cos.
EXPECT_EQ(1, fdlibm_cos(3.725290298461914e-9));
// Cover different code paths in KERNELCOS.
EXPECT_EQ(0.9689124217106447, fdlibm_cos(0.25));
EXPECT_EQ(0.8775825618903728, fdlibm_cos(0.5));
EXPECT_EQ(0.7073882691671998, fdlibm_cos(0.785));
// Test that cos(Math.PI/2) != 0 since Math.PI is not exact.
EXPECT_EQ(6.123233995736766e-17, fdlibm_cos(1.5707963267948966));
// Test cos for various phases.
EXPECT_EQ(0.7071067811865474, fdlibm_cos(7.0 / 4 * kPI));
EXPECT_EQ(0.7071067811865477, fdlibm_cos(9.0 / 4 * kPI));
EXPECT_EQ(-0.7071067811865467, fdlibm_cos(11.0 / 4 * kPI));
EXPECT_EQ(-0.7071067811865471, fdlibm_cos(13.0 / 4 * kPI));
EXPECT_EQ(0.9367521275331447, fdlibm_cos(1000000.0));
EXPECT_EQ(-3.435757038074824e-12, fdlibm_cos(1048575.0 / 2 * kPI));
// Test Hayne-Panek reduction.
EXPECT_EQ(-0.9258790228548379e0, fdlibm_cos(kTwo120));
EXPECT_EQ(-0.9258790228548379e0, fdlibm_cos(-kTwo120));
}
TEST(Ieee754, FdlibmSin) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(fdlibm_sin(kQNaN), IsNaN());
EXPECT_THAT(fdlibm_sin(kSNaN), IsNaN());
EXPECT_THAT(fdlibm_sin(kInfinity), IsNaN());
EXPECT_THAT(fdlibm_sin(-kInfinity), IsNaN());
// Tests for sin for |x| < pi/4
EXPECT_EQ(-kInfinity, Divide(1.0, fdlibm_sin(-0.0)));
EXPECT_EQ(kInfinity, Divide(1.0, fdlibm_sin(0.0)));
// sin(x) = x for x < 2^-27
EXPECT_EQ(2.3283064365386963e-10, fdlibm_sin(2.3283064365386963e-10));
EXPECT_EQ(-2.3283064365386963e-10, fdlibm_sin(-2.3283064365386963e-10));
// sin(pi/8) = sqrt(sqrt(2)-1)/2^(3/4)
EXPECT_EQ(0.3826834323650898, fdlibm_sin(0.39269908169872414));
EXPECT_EQ(-0.3826834323650898, fdlibm_sin(-0.39269908169872414));
// Tests for sin.
EXPECT_EQ(0.479425538604203, fdlibm_sin(0.5));
EXPECT_EQ(-0.479425538604203, fdlibm_sin(-0.5));
EXPECT_EQ(1, fdlibm_sin(kPI / 2.0));
EXPECT_EQ(-1, fdlibm_sin(-kPI / 2.0));
// Test that sin(Math.PI) != 0 since Math.PI is not exact.
EXPECT_EQ(1.2246467991473532e-16, fdlibm_sin(kPI));
EXPECT_EQ(-7.047032979958965e-14, fdlibm_sin(2200.0 * kPI));
// Test sin for various phases.
EXPECT_EQ(-0.7071067811865477, fdlibm_sin(7.0 / 4.0 * kPI));
EXPECT_EQ(0.7071067811865474, fdlibm_sin(9.0 / 4.0 * kPI));
EXPECT_EQ(0.7071067811865483, fdlibm_sin(11.0 / 4.0 * kPI));
EXPECT_EQ(-0.7071067811865479, fdlibm_sin(13.0 / 4.0 * kPI));
EXPECT_EQ(-3.2103381051568376e-11, fdlibm_sin(1048576.0 / 4 * kPI));
// Test Hayne-Panek reduction.
EXPECT_EQ(0.377820109360752e0, fdlibm_sin(kTwo120));
EXPECT_EQ(-0.377820109360752e0, fdlibm_sin(-kTwo120));
}
#else
TEST(Ieee754, Cos) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(cos(kQNaN), IsNaN());
@ -177,6 +346,45 @@ TEST(Ieee754, Cos) {
EXPECT_EQ(-0.9258790228548379e0, cos(-kTwo120));
}
TEST(Ieee754, Sin) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(sin(kQNaN), IsNaN());
EXPECT_THAT(sin(kSNaN), IsNaN());
EXPECT_THAT(sin(kInfinity), IsNaN());
EXPECT_THAT(sin(-kInfinity), IsNaN());
// Tests for sin for |x| < pi/4
EXPECT_EQ(-kInfinity, Divide(1.0, sin(-0.0)));
EXPECT_EQ(kInfinity, Divide(1.0, sin(0.0)));
// sin(x) = x for x < 2^-27
EXPECT_EQ(2.3283064365386963e-10, sin(2.3283064365386963e-10));
EXPECT_EQ(-2.3283064365386963e-10, sin(-2.3283064365386963e-10));
// sin(pi/8) = sqrt(sqrt(2)-1)/2^(3/4)
EXPECT_EQ(0.3826834323650898, sin(0.39269908169872414));
EXPECT_EQ(-0.3826834323650898, sin(-0.39269908169872414));
// Tests for sin.
EXPECT_EQ(0.479425538604203, sin(0.5));
EXPECT_EQ(-0.479425538604203, sin(-0.5));
EXPECT_EQ(1, sin(kPI / 2.0));
EXPECT_EQ(-1, sin(-kPI / 2.0));
// Test that sin(Math.PI) != 0 since Math.PI is not exact.
EXPECT_EQ(1.2246467991473532e-16, sin(kPI));
EXPECT_EQ(-7.047032979958965e-14, sin(2200.0 * kPI));
// Test sin for various phases.
EXPECT_EQ(-0.7071067811865477, sin(7.0 / 4.0 * kPI));
EXPECT_EQ(0.7071067811865474, sin(9.0 / 4.0 * kPI));
EXPECT_EQ(0.7071067811865483, sin(11.0 / 4.0 * kPI));
EXPECT_EQ(-0.7071067811865479, sin(13.0 / 4.0 * kPI));
EXPECT_EQ(-3.2103381051568376e-11, sin(1048576.0 / 4 * kPI));
// Test Hayne-Panek reduction.
EXPECT_EQ(0.377820109360752e0, sin(kTwo120));
EXPECT_EQ(-0.377820109360752e0, sin(-kTwo120));
}
#endif
TEST(Ieee754, Cosh) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(cosh(kQNaN), IsNaN());
@ -306,43 +514,6 @@ TEST(Ieee754, Cbrt) {
EXPECT_EQ(46.415888336127786, cbrt(100000));
}
TEST(Ieee754, Sin) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(sin(kQNaN), IsNaN());
EXPECT_THAT(sin(kSNaN), IsNaN());
EXPECT_THAT(sin(kInfinity), IsNaN());
EXPECT_THAT(sin(-kInfinity), IsNaN());
// Tests for sin for |x| < pi/4
EXPECT_EQ(-kInfinity, Divide(1.0, sin(-0.0)));
EXPECT_EQ(kInfinity, Divide(1.0, sin(0.0)));
// sin(x) = x for x < 2^-27
EXPECT_EQ(2.3283064365386963e-10, sin(2.3283064365386963e-10));
EXPECT_EQ(-2.3283064365386963e-10, sin(-2.3283064365386963e-10));
// sin(pi/8) = sqrt(sqrt(2)-1)/2^(3/4)
EXPECT_EQ(0.3826834323650898, sin(0.39269908169872414));
EXPECT_EQ(-0.3826834323650898, sin(-0.39269908169872414));
// Tests for sin.
EXPECT_EQ(0.479425538604203, sin(0.5));
EXPECT_EQ(-0.479425538604203, sin(-0.5));
EXPECT_EQ(1, sin(kPI / 2.0));
EXPECT_EQ(-1, sin(-kPI / 2.0));
// Test that sin(Math.PI) != 0 since Math.PI is not exact.
EXPECT_EQ(1.2246467991473532e-16, sin(kPI));
EXPECT_EQ(-7.047032979958965e-14, sin(2200.0 * kPI));
// Test sin for various phases.
EXPECT_EQ(-0.7071067811865477, sin(7.0 / 4.0 * kPI));
EXPECT_EQ(0.7071067811865474, sin(9.0 / 4.0 * kPI));
EXPECT_EQ(0.7071067811865483, sin(11.0 / 4.0 * kPI));
EXPECT_EQ(-0.7071067811865479, sin(13.0 / 4.0 * kPI));
EXPECT_EQ(-3.2103381051568376e-11, sin(1048576.0 / 4 * kPI));
// Test Hayne-Panek reduction.
EXPECT_EQ(0.377820109360752e0, sin(kTwo120));
EXPECT_EQ(-0.377820109360752e0, sin(-kTwo120));
}
TEST(Ieee754, Sinh) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(sinh(kQNaN), IsNaN());

View File

@ -10,6 +10,7 @@
#include "src/base/division-by-constant.h"
#include "src/base/ieee754.h"
#include "src/base/overflowing-math.h"
#include "src/builtins/builtins.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator.h"
#include "src/numbers/conversions-inl.h"
@ -2840,7 +2841,7 @@ TEST_F(MachineOperatorReducerTest, Float64CosWithConstant) {
Reduce(graph()->NewNode(machine()->Float64Cos(), Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::cos(x))));
IsFloat64Constant(NanSensitiveDoubleEq(COS_IMPL(x))));
}
}
@ -2939,7 +2940,7 @@ TEST_F(MachineOperatorReducerTest, Float64SinWithConstant) {
Reduce(graph()->NewNode(machine()->Float64Sin(), Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::sin(x))));
IsFloat64Constant(NanSensitiveDoubleEq(SIN_IMPL(x))));
}
}