From ff7975aa8d1ff6f0904f0f5112d17ea819466983 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Wed, 6 Aug 2014 11:04:47 +0000 Subject: [PATCH] Revert "Implement trigonometric functions using a fdlibm port." This reverts r22918 and r22920. TBR=hpayer@chromium.org Review URL: https://codereview.chromium.org/448633002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22921 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- .gitignore | 2 +- BUILD.gn | 3 - DEPS | 1 - src/bootstrapper.cc | 46 +++-- src/math.js | 111 ++++++++++- src/runtime.cc | 16 -- src/runtime.h | 1 - src/trig-table.h | 38 ++++ test/mjsunit/debug-script.js | 2 +- test/mjsunit/mirror-script.js | 2 +- test/mjsunit/runtime-gen/rempio2.js | 5 - test/mjsunit/sin-cos.js | 97 +--------- test/test262/test262.status | 7 + third_party/fdlibm/LICENSE | 6 - third_party/fdlibm/README.v8 | 18 -- third_party/fdlibm/fdlibm.cc | 260 -------------------------- third_party/fdlibm/fdlibm.h | 31 ---- third_party/fdlibm/fdlibm.js | 356 ------------------------------------ tools/generate-runtime-tests.py | 6 +- tools/generate-trig-table.py | 83 +++++++++ tools/gyp/v8.gyp | 40 +++- tools/js2c.py | 22 --- 22 files changed, 313 insertions(+), 840 deletions(-) create mode 100644 src/trig-table.h delete mode 100644 test/mjsunit/runtime-gen/rempio2.js delete mode 100644 third_party/fdlibm/LICENSE delete mode 100644 third_party/fdlibm/README.v8 delete mode 100644 third_party/fdlibm/fdlibm.cc delete mode 100644 third_party/fdlibm/fdlibm.h delete mode 100644 third_party/fdlibm/fdlibm.js create mode 100644 tools/generate-trig-table.py diff --git a/.gitignore b/.gitignore index 707582c..158e493 100644 --- a/.gitignore +++ b/.gitignore @@ -63,7 +63,7 @@ shell_g /test/test262/tc39-test262-* /testing/gmock /testing/gtest -/third_party/icu +/third_party /tools/jsfunfuzz /tools/jsfunfuzz.zip /tools/oom_dump/oom_dump diff --git a/BUILD.gn b/BUILD.gn index b3813d2..07772ab 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -194,7 +194,6 @@ action("js2c") { "src/string.js", "src/symbol.js", "src/uri.js", - "third_party/fdlibm/fdlibm.js", "src/math.js", "src/messages.js", "src/apinatives.js", @@ -866,8 +865,6 @@ source_set("v8_base") { "src/zone-inl.h", "src/zone.cc", "src/zone.h", - "third_party/fdlibm/fdlibm.cc', - "third_party/fdlibm/fdlibm.h', ] if (v8_target_arch == "x86") { diff --git a/DEPS b/DEPS index d45080f..de9d013 100644 --- a/DEPS +++ b/DEPS @@ -41,7 +41,6 @@ include_rules = [ # Everybody can use some things. "+include", "+unicode", - "+third_party/fdlibm", ] # checkdeps.py shouldn't check for includes in these directories: diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index c297a37..a746c90 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -14,7 +14,7 @@ #include "src/isolate-inl.h" #include "src/natives.h" #include "src/snapshot.h" -#include "third_party/fdlibm/fdlibm.h" +#include "src/trig-table.h" namespace v8 { namespace internal { @@ -121,7 +121,7 @@ char* Bootstrapper::AllocateAutoDeletedArray(int bytes) { void Bootstrapper::TearDown() { if (delete_these_non_arrays_on_tear_down_ != NULL) { int len = delete_these_non_arrays_on_tear_down_->length(); - DCHECK(len < 25); // Don't use this mechanism for unbounded allocations. + DCHECK(len < 24); // Don't use this mechanism for unbounded allocations. for (int i = 0; i < len; i++) { delete delete_these_non_arrays_on_tear_down_->at(i); delete_these_non_arrays_on_tear_down_->at(i) = NULL; @@ -2651,19 +2651,43 @@ Genesis::Genesis(Isolate* isolate, NONE).Assert(); // Initialize trigonometric lookup tables and constants. - const int constants_size = ARRAY_SIZE(TrigonometricConstants::constants); - const int table_num_bytes = constants_size * kDoubleSize; - v8::Local trig_buffer = v8::ArrayBuffer::New( + const int table_num_bytes = TrigonometricLookupTable::table_num_bytes(); + v8::Local sin_buffer = v8::ArrayBuffer::New( reinterpret_cast(isolate), - const_cast(TrigonometricConstants::constants), - table_num_bytes); - v8::Local trig_table = - v8::Float64Array::New(trig_buffer, 0, constants_size); + TrigonometricLookupTable::sin_table(), table_num_bytes); + v8::Local cos_buffer = v8::ArrayBuffer::New( + reinterpret_cast(isolate), + TrigonometricLookupTable::cos_x_interval_table(), table_num_bytes); + v8::Local sin_table = v8::Float64Array::New( + sin_buffer, 0, TrigonometricLookupTable::table_size()); + v8::Local cos_table = v8::Float64Array::New( + cos_buffer, 0, TrigonometricLookupTable::table_size()); + Runtime::DefineObjectProperty(builtins, + factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("kSinTable")), + Utils::OpenHandle(*sin_table), + NONE).Assert(); + Runtime::DefineObjectProperty( + builtins, + factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("kCosXIntervalTable")), + Utils::OpenHandle(*cos_table), + NONE).Assert(); + Runtime::DefineObjectProperty( + builtins, + factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("kSamples")), + factory()->NewHeapNumber( + TrigonometricLookupTable::samples()), + NONE).Assert(); Runtime::DefineObjectProperty( builtins, - factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("kTrig")), - Utils::OpenHandle(*trig_table), NONE).Assert(); + factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("kIndexConvert")), + factory()->NewHeapNumber( + TrigonometricLookupTable::samples_over_pi_half()), + NONE).Assert(); } result_ = native_context(); diff --git a/src/math.js b/src/math.js index 436a41f..9dc4b37 100644 --- a/src/math.js +++ b/src/math.js @@ -56,6 +56,12 @@ function MathCeil(x) { return -MathFloor(-x); } +// ECMA 262 - 15.8.2.7 +function MathCos(x) { + x = MathAbs(x); // Convert to number and get rid of -0. + return TrigonometricInterpolation(x, 1); +} + // ECMA 262 - 15.8.2.8 function MathExp(x) { return %MathExpRT(TO_NUMBER_INLINE(x)); @@ -158,16 +164,97 @@ function MathRound(x) { return %RoundNumber(TO_NUMBER_INLINE(x)); } +// ECMA 262 - 15.8.2.16 +function MathSin(x) { + x = x * 1; // Convert to number and deal with -0. + if (%_IsMinusZero(x)) return x; + return TrigonometricInterpolation(x, 0); +} + // ECMA 262 - 15.8.2.17 function MathSqrt(x) { return %_MathSqrtRT(TO_NUMBER_INLINE(x)); } +// ECMA 262 - 15.8.2.18 +function MathTan(x) { + return MathSin(x) / MathCos(x); +} + // Non-standard extension. function MathImul(x, y) { return %NumberImul(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y)); } + +var kInversePiHalf = 0.636619772367581343; // 2 / pi +var kInversePiHalfS26 = 9.48637384723993156e-9; // 2 / pi / (2^26) +var kS26 = 1 << 26; +var kTwoStepThreshold = 1 << 27; +// pi / 2 rounded up +var kPiHalf = 1.570796326794896780; // 0x192d4454fb21f93f +// We use two parts for pi/2 to emulate a higher precision. +// pi_half_1 only has 26 significant bits for mantissa. +// Note that pi_half > pi_half_1 + pi_half_2 +var kPiHalf1 = 1.570796325802803040; // 0x00000054fb21f93f +var kPiHalf2 = 9.920935796805404252e-10; // 0x3326a611460b113e + +var kSamples; // Initialized to a number during genesis. +var kIndexConvert; // Initialized to kSamples / (pi/2) during genesis. +var kSinTable; // Initialized to a Float64Array during genesis. +var kCosXIntervalTable; // Initialized to a Float64Array during genesis. + +// This implements sine using the following algorithm. +// 1) Multiplication takes care of to-number conversion. +// 2) Reduce x to the first quadrant [0, pi/2]. +// Conveniently enough, in case of +/-Infinity, we get NaN. +// Note that we try to use only 26 instead of 52 significant bits for +// mantissa to avoid rounding errors when multiplying. For very large +// input we therefore have additional steps. +// 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant. +// 4) Do a table lookup for the closest samples to the left and right of x. +// 5) Find the derivatives at those sampling points by table lookup: +// dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2]. +// 6) Use cubic spline interpolation to approximate sin(x). +// 7) Negate the result if x was in the 3rd or 4th quadrant. +// 8) Get rid of -0 by adding 0. +function TrigonometricInterpolation(x, phase) { + if (x < 0 || x > kPiHalf) { + var multiple; + while (x < -kTwoStepThreshold || x > kTwoStepThreshold) { + // Let's assume this loop does not terminate. + // All numbers x in each loop forms a set S. + // (1) abs(x) > 2^27 for all x in S. + // (2) abs(multiple) != 0 since (2^27 * inverse_pi_half_s26) > 1 + // (3) multiple is rounded down in 2^26 steps, so the rounding error is + // at most max(ulp, 2^26). + // (4) so for x > 2^27, we subtract at most (1+pi/4)x and at least + // (1-pi/4)x + // (5) The subtraction results in x' so that abs(x') <= abs(x)*pi/4. + // Note that this difference cannot be simply rounded off. + // Set S cannot exist since (5) violates (1). Loop must terminate. + multiple = MathFloor(x * kInversePiHalfS26) * kS26; + x = x - multiple * kPiHalf1 - multiple * kPiHalf2; + } + multiple = MathFloor(x * kInversePiHalf); + x = x - multiple * kPiHalf1 - multiple * kPiHalf2; + phase += multiple; + } + var double_index = x * kIndexConvert; + if (phase & 1) double_index = kSamples - double_index; + var index = double_index | 0; + var t1 = double_index - index; + var t2 = 1 - t1; + var y1 = kSinTable[index]; + var y2 = kSinTable[index + 1]; + var dy = y2 - y1; + return (t2 * y1 + t1 * y2 + + t1 * t2 * ((kCosXIntervalTable[index] - dy) * t2 + + (dy - kCosXIntervalTable[index + 1]) * t1)) + * (1 - (phase & 2)) + 0; +} + + // ES6 draft 09-27-13, section 20.2.2.28. function MathSign(x) { x = TO_NUMBER_INLINE(x); @@ -177,6 +264,7 @@ function MathSign(x) { return NAN; } + // ES6 draft 09-27-13, section 20.2.2.34. function MathTrunc(x) { x = TO_NUMBER_INLINE(x); @@ -186,6 +274,7 @@ function MathTrunc(x) { return NAN; } + // ES6 draft 09-27-13, section 20.2.2.30. function MathSinh(x) { if (!IS_NUMBER(x)) x = NonNumberToNumber(x); @@ -194,6 +283,7 @@ function MathSinh(x) { return (MathExp(x) - MathExp(-x)) / 2; } + // ES6 draft 09-27-13, section 20.2.2.12. function MathCosh(x) { if (!IS_NUMBER(x)) x = NonNumberToNumber(x); @@ -201,6 +291,7 @@ function MathCosh(x) { return (MathExp(x) + MathExp(-x)) / 2; } + // ES6 draft 09-27-13, section 20.2.2.33. function MathTanh(x) { if (!IS_NUMBER(x)) x = NonNumberToNumber(x); @@ -213,6 +304,7 @@ function MathTanh(x) { return (exp1 - exp2) / (exp1 + exp2); } + // ES6 draft 09-27-13, section 20.2.2.5. function MathAsinh(x) { if (!IS_NUMBER(x)) x = NonNumberToNumber(x); @@ -223,6 +315,7 @@ function MathAsinh(x) { return -MathLog(-x + MathSqrt(x * x + 1)); } + // ES6 draft 09-27-13, section 20.2.2.3. function MathAcosh(x) { if (!IS_NUMBER(x)) x = NonNumberToNumber(x); @@ -232,6 +325,7 @@ function MathAcosh(x) { return MathLog(x + MathSqrt(x + 1) * MathSqrt(x - 1)); } + // ES6 draft 09-27-13, section 20.2.2.7. function MathAtanh(x) { if (!IS_NUMBER(x)) x = NonNumberToNumber(x); @@ -242,6 +336,7 @@ function MathAtanh(x) { return 0.5 * MathLog((1 + x) / (1 - x)); } + // ES6 draft 09-27-13, section 20.2.2.21. function MathLog10(x) { return MathLog(x) * 0.434294481903251828; // log10(x) = log(x)/log(10). @@ -253,6 +348,7 @@ function MathLog2(x) { return MathLog(x) * 1.442695040888963407; // log2(x) = log(x)/log(2). } + // ES6 draft 09-27-13, section 20.2.2.17. function MathHypot(x, y) { // Function length is 2. // We may want to introduce fast paths for two arguments and when @@ -285,12 +381,13 @@ function MathHypot(x, y) { // Function length is 2. return MathSqrt(sum) * max; } + // ES6 draft 09-27-13, section 20.2.2.16. function MathFroundJS(x) { return %MathFround(TO_NUMBER_INLINE(x)); } -// ES6 draft 07-18-14, section 20.2.2.11 + function MathClz32(x) { x = ToUint32(TO_NUMBER_INLINE(x)); if (x == 0) return 32; @@ -304,6 +401,7 @@ function MathClz32(x) { return result; } + // ES6 draft 09-27-13, section 20.2.2.9. // Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm // Using initial approximation adapted from Kahan's cbrt and 4 iterations @@ -327,6 +425,8 @@ function CubeRoot(x) { return NEWTON_ITERATION_CBRT(x, approx); } + + // ES6 draft 09-27-13, section 20.2.2.14. // Use Taylor series to approximate. // exp(x) - 1 at 0 == -1 + exp(0) + exp'(0)*x/1! + exp''(0)*x^2/2! + ... @@ -347,6 +447,7 @@ function MathExpm1(x) { } } + // ES6 draft 09-27-13, section 20.2.2.20. // Use Taylor series to approximate. With y = x + 1; // log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ... @@ -401,14 +502,14 @@ function SetUpMath() { "asin", MathAsinJS, "atan", MathAtanJS, "ceil", MathCeil, - "cos", MathCos, // implemented by third_party/fdlibm + "cos", MathCos, "exp", MathExp, "floor", MathFloor, "log", MathLog, "round", MathRound, - "sin", MathSin, // implemented by third_party/fdlibm + "sin", MathSin, "sqrt", MathSqrt, - "tan", MathTan, // implemented by third_party/fdlibm + "tan", MathTan, "atan2", MathAtan2JS, "pow", MathPow, "max", MathMax, @@ -436,6 +537,8 @@ function SetUpMath() { %SetInlineBuiltinFlag(MathRandom); %SetInlineBuiltinFlag(MathSin); %SetInlineBuiltinFlag(MathCos); + %SetInlineBuiltinFlag(MathTan); + %SetInlineBuiltinFlag(TrigonometricInterpolation); } SetUpMath(); diff --git a/src/runtime.cc b/src/runtime.cc index 347e4c8..5e18c97 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -45,7 +45,6 @@ #include "src/utils.h" #include "src/v8threads.h" #include "src/vm-state-inl.h" -#include "third_party/fdlibm/fdlibm.h" #ifdef V8_I18N_SUPPORT #include "src/i18n.h" @@ -7684,21 +7683,6 @@ RUNTIME_FUNCTION(Runtime_ConstructDouble) { } -RUNTIME_FUNCTION(Runtime_RemPiO2) { - HandleScope handle_scope(isolate); - DCHECK(args.length() == 1); - CONVERT_DOUBLE_ARG_CHECKED(x, 0); - Factory* factory = isolate->factory(); - double y[2]; - int n = rempio2(x, y); - Handle array = factory->NewFixedArray(3); - array->set(0, Smi::FromInt(n)); - array->set(1, *factory->NewHeapNumber(y[0])); - array->set(2, *factory->NewHeapNumber(y[1])); - return *factory->NewJSArrayWithElements(array); -} - - static const double kPiDividedBy4 = 0.78539816339744830962; diff --git a/src/runtime.h b/src/runtime.h index d0100c5..e8b7892 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -149,7 +149,6 @@ namespace internal { F(MathExpRT, 1, 1) \ F(RoundNumber, 1, 1) \ F(MathFround, 1, 1) \ - F(RemPiO2, 1, 1) \ \ /* Regular expressions */ \ F(RegExpCompile, 3, 1) \ diff --git a/src/trig-table.h b/src/trig-table.h new file mode 100644 index 0000000..7332152 --- /dev/null +++ b/src/trig-table.h @@ -0,0 +1,38 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_TRIG_TABLE_H_ +#define V8_TRIG_TABLE_H_ + + +namespace v8 { +namespace internal { + +class TrigonometricLookupTable : public AllStatic { + public: + // Casting away const-ness to use as argument for typed array constructor. + static void* sin_table() { + return const_cast(&kSinTable[0]); + } + + static void* cos_x_interval_table() { + return const_cast(&kCosXIntervalTable[0]); + } + + static double samples_over_pi_half() { return kSamplesOverPiHalf; } + static int samples() { return kSamples; } + static int table_num_bytes() { return kTableSize * sizeof(*kSinTable); } + static int table_size() { return kTableSize; } + + private: + static const double kSinTable[]; + static const double kCosXIntervalTable[]; + static const int kSamples; + static const int kTableSize; + static const double kSamplesOverPiHalf; +}; + +} } // namespace v8::internal + +#endif // V8_TRIG_TABLE_H_ diff --git a/test/mjsunit/debug-script.js b/test/mjsunit/debug-script.js index 54e80e0..3a4361a 100644 --- a/test/mjsunit/debug-script.js +++ b/test/mjsunit/debug-script.js @@ -59,7 +59,7 @@ for (i = 0; i < scripts.length; i++) { } // This has to be updated if the number of native scripts change. -assertTrue(named_native_count == 23 || named_native_count == 24); +assertTrue(named_native_count == 22 || named_native_count == 23); // Only the 'gc' extension is loaded. assertEquals(1, extension_count); // This script and mjsunit.js has been loaded. If using d8, d8 loads diff --git a/test/mjsunit/mirror-script.js b/test/mjsunit/mirror-script.js index e545a61..1d64ac2 100644 --- a/test/mjsunit/mirror-script.js +++ b/test/mjsunit/mirror-script.js @@ -84,7 +84,7 @@ function testScriptMirror(f, file_name, file_lines, type, compilation_type, // Test the script mirror for different functions. testScriptMirror(function(){}, 'mirror-script.js', 98, 2, 0); -testScriptMirror(Math.round, 'native math.js', -1, 0, 0); +testScriptMirror(Math.sin, 'native math.js', -1, 0, 0); testScriptMirror(eval('(function(){})'), null, 1, 2, 1, '(function(){})', 87); testScriptMirror(eval('(function(){\n })'), null, 2, 2, 1, '(function(){\n })', 88); diff --git a/test/mjsunit/runtime-gen/rempio2.js b/test/mjsunit/runtime-gen/rempio2.js deleted file mode 100644 index 03a84b3..0000000 --- a/test/mjsunit/runtime-gen/rempio2.js +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY -// Flags: --allow-natives-syntax --harmony -var _x = 1.5; -%RemPiO2(_x); diff --git a/test/mjsunit/sin-cos.js b/test/mjsunit/sin-cos.js index 71fae20..02ae57b 100644 --- a/test/mjsunit/sin-cos.js +++ b/test/mjsunit/sin-cos.js @@ -157,8 +157,8 @@ assertEquals(0, Math.sin("0x00000")); assertEquals(1, Math.cos("0x00000")); assertTrue(isNaN(Math.sin(Infinity))); assertTrue(isNaN(Math.cos("-Infinity"))); -assertTrue(Math.tan(Math.PI/2) > 1e16); -assertTrue(Math.tan(-Math.PI/2) < -1e16); +assertEquals("Infinity", String(Math.tan(Math.PI/2))); +assertEquals("-Infinity", String(Math.tan(-Math.PI/2))); assertEquals("-Infinity", String(1/Math.sin("-0"))); // Assert that the remainder after division by pi is reasonably precise. @@ -185,96 +185,3 @@ for (var i = -1024; i < 1024; i++) { assertFalse(isNaN(Math.cos(1.57079632679489700))); assertFalse(isNaN(Math.cos(-1e-100))); assertFalse(isNaN(Math.cos(-1e-323))); - -// Tests for specific values expected from the fdlibm implementation. - -var two_32 = Math.pow(2, -32); -var two_28 = Math.pow(2, -28); - -// Tests for Math.sin for |x| < pi/4 -assertEquals(Infinity, 1/Math.sin(+0.0)); -assertEquals(-Infinity, 1/Math.sin(-0.0)); -// sin(x) = x for x < 2^-27 -assertEquals(two_32, Math.sin(two_32)); -assertEquals(-two_32, Math.sin(-two_32)); -// sin(pi/8) = sqrt(sqrt(2)-1)/2^(3/4) -assertEquals(0.3826834323650898, Math.sin(Math.PI/8)); -assertEquals(-0.3826834323650898, -Math.sin(Math.PI/8)); - -// Tests for Math.cos for |x| < pi/4 -// cos(x) = 1 for |x| < 2^-27 -assertEquals(1, Math.cos(two_32)); -assertEquals(1, Math.cos(-two_32)); -// Test KERNELCOS for |x| < 0.3. -// cos(pi/20) = sqrt(sqrt(2)*sqrt(sqrt(5)+5)+4)/2^(3/2) -assertEquals(0.9876883405951378, Math.cos(Math.PI/20)); -// Test KERNELCOS for x ~= 0.78125 -assertEquals(0.7100335477927638, Math.cos(0.7812504768371582)); -assertEquals(0.7100338835660797, Math.cos(0.78125)); -// Test KERNELCOS for |x| > 0.3. -// cos(pi/8) = sqrt(sqrt(2)+1)/2^(3/4) -assertEquals(0.9238795325112867, Math.cos(Math.PI/8)); -// Test KERNELTAN for |x| < 0.67434. -assertEquals(0.9238795325112867, Math.cos(-Math.PI/8)); - -// Tests for Math.tan for |x| < pi/4 -assertEquals(Infinity, 1/Math.tan(0.0)); -assertEquals(-Infinity, 1/Math.tan(-0.0)); -// tan(x) = x for |x| < 2^-28 -assertEquals(two_32, Math.tan(two_32)); -assertEquals(-two_32, Math.tan(-two_32)); -// Test KERNELTAN for |x| > 0.67434. -assertEquals(0.8211418015898941, Math.tan(11/16)); -assertEquals(-0.8211418015898941, Math.tan(-11/16)); -assertEquals(0.41421356237309503, Math.tan(Math.PI / 8)); - -// Tests for Math.sin. -assertEquals(0.479425538604203, Math.sin(0.5)); -assertEquals(-0.479425538604203, Math.sin(-0.5)); -assertEquals(1, Math.sin(Math.PI/2)); -assertEquals(-1, Math.sin(-Math.PI/2)); -// Test that Math.sin(Math.PI) != 0 since Math.PI is not exact. -assertEquals(1.2246467991473532e-16, Math.sin(Math.PI)); -assertEquals(-7.047032979958965e-14, Math.sin(2200*Math.PI)); -// Test Math.sin for various phases. -assertEquals(-0.7071067811865477, Math.sin(7/4 * Math.PI)); -assertEquals(0.7071067811865474, Math.sin(9/4 * Math.PI)); -assertEquals(0.7071067811865483, Math.sin(11/4 * Math.PI)); -assertEquals(-0.7071067811865479, Math.sin(13/4 * Math.PI)); -assertEquals(-3.2103381051568376e-11, Math.sin(1048576/4 * Math.PI)); - -// Tests for Math.cos. -assertEquals(1, Math.cos(two_28)); -// Cover different code paths in KERNELCOS. -assertEquals(0.9689124217106447, Math.cos(0.25)); -assertEquals(0.8775825618903728, Math.cos(0.5)); -assertEquals(0.7073882691671998, Math.cos(0.785)); -// Test that Math.cos(Math.PI/2) != 0 since Math.PI is not exact. -assertEquals(6.123233995736766e-17, Math.cos(Math.PI/2)); -// Test Math.cos for various phases. -assertEquals(0.7071067811865474, Math.cos(7/4 * Math.PI)); -assertEquals(0.7071067811865477, Math.cos(9/4 * Math.PI)); -assertEquals(-0.7071067811865467, Math.cos(11/4 * Math.PI)); -assertEquals(-0.7071067811865471, Math.cos(13/4 * Math.PI)); -assertEquals(0.9367521275331447, Math.cos(1000000)); -assertEquals(-3.435757038074824e-12, Math.cos(1048575/2 * Math.PI)); - -// Tests for Math.tan. -assertEquals(two_28, Math.tan(two_28)); -// Test that Math.tan(Math.PI/2) != Infinity since Math.PI is not exact. -assertEquals(1.633123935319537e16, Math.tan(Math.PI/2)); -// Cover different code paths in KERNELTAN (tangent and cotangent) -assertEquals(0.5463024898437905, Math.tan(0.5)); -assertEquals(2.0000000000000027, Math.tan(1.107148717794091)); -assertEquals(-1.0000000000000004, Math.tan(7/4*Math.PI)); -assertEquals(0.9999999999999994, Math.tan(9/4*Math.PI)); -assertEquals(-6.420676210313675e-11, Math.tan(1048576/2*Math.PI)); -assertEquals(2.910566692924059e11, Math.tan(1048575/2*Math.PI)); - -// Test Hayne-Panek reduction. -assertEquals(0.377820109360752e0, Math.sin(Math.pow(2, 120))); -assertEquals(-0.9258790228548379e0, Math.cos(Math.pow(2, 120))); -assertEquals(-0.40806638884180424e0, Math.tan(Math.pow(2, 120))); -assertEquals(-0.377820109360752e0, Math.sin(-Math.pow(2, 120))); -assertEquals(-0.9258790228548379e0, Math.cos(-Math.pow(2, 120))); -assertEquals(0.40806638884180424e0, Math.tan(-Math.pow(2, 120))); diff --git a/test/test262/test262.status b/test/test262/test262.status index dd075d9..18d65c4 100644 --- a/test/test262/test262.status +++ b/test/test262/test262.status @@ -68,7 +68,14 @@ ##################### DELIBERATE INCOMPATIBILITIES ##################### + # This tests precision of Math functions. The implementation for those + # trigonometric functions are platform/compiler dependent. Furthermore, the + # expectation values by far deviates from the actual result given by an + # arbitrary-precision calculator, making those tests partly bogus. + 'S15.8.2.7_A7': [PASS, FAIL_OK], # Math.cos 'S15.8.2.8_A6': [PASS, FAIL_OK], # Math.exp (less precise with --fast-math) + 'S15.8.2.16_A7': [PASS, FAIL_OK], # Math.sin + 'S15.8.2.18_A7': [PASS, FAIL_OK], # Math.tan # Linux for ia32 (and therefore simulators) default to extended 80 bit # floating point formats, so these tests checking 64-bit FP precision fail. diff --git a/third_party/fdlibm/LICENSE b/third_party/fdlibm/LICENSE deleted file mode 100644 index b024795..0000000 --- a/third_party/fdlibm/LICENSE +++ /dev/null @@ -1,6 +0,0 @@ -Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - -Developed at SunSoft, a Sun Microsystems, Inc. business. -Permission to use, copy, modify, and distribute this -software is freely granted, provided that this notice -is preserved. diff --git a/third_party/fdlibm/README.v8 b/third_party/fdlibm/README.v8 deleted file mode 100644 index ea8fdb6..0000000 --- a/third_party/fdlibm/README.v8 +++ /dev/null @@ -1,18 +0,0 @@ -Name: Freely Distributable LIBM -Short Name: fdlibm -URL: http://www.netlib.org/fdlibm/ -Version: 5.3 -License: Freely Distributable. -License File: LICENSE. -Security Critical: yes. -License Android Compatible: yes. - -Description: -This is used to provide a accurate implementation for trigonometric functions -used in V8. - -Local Modifications: -For the use in V8, fdlibm has been reduced to include only sine, cosine and -tangent. To make inlining into generated code possible, a large portion of -that has been translated to Javascript. The rest remains in C, but has been -refactored and reformatted to interoperate with the rest of V8. diff --git a/third_party/fdlibm/fdlibm.cc b/third_party/fdlibm/fdlibm.cc deleted file mode 100644 index d027bf9..0000000 --- a/third_party/fdlibm/fdlibm.cc +++ /dev/null @@ -1,260 +0,0 @@ -// The following is adapted from fdlibm (http://www.netlib.org/fdlibm). -// -// ==================================================== -// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. -// -// Developed at SunSoft, a Sun Microsystems, Inc. business. -// Permission to use, copy, modify, and distribute this -// software is freely granted, provided that this notice -// is preserved. -// ==================================================== -// -// The original source code covered by the above license above has been -// modified significantly by Google Inc. -// Copyright 2014 the V8 project authors. All rights reserved. - -#include - -#include "src/v8.h" - -#include "src/double.h" -#include "third_party/fdlibm/fdlibm.h" - - -namespace v8 { -namespace internal { - -const double TrigonometricConstants::constants[] = { - 6.36619772367581382433e-01, // invpio2 0 - 1.57079632673412561417e+00, // pio2_1 1 - 6.07710050650619224932e-11, // pio2_1t 2 - 6.07710050630396597660e-11, // pio2_2 3 - 2.02226624879595063154e-21, // pio2_2t 4 - 2.02226624871116645580e-21, // pio2_3 5 - 8.47842766036889956997e-32, // pio2_3t 6 - -1.66666666666666324348e-01, // S1 7 - 8.33333333332248946124e-03, // 8 - -1.98412698298579493134e-04, // 9 - 2.75573137070700676789e-06, // 10 - -2.50507602534068634195e-08, // 11 - 1.58969099521155010221e-10, // S6 12 - 4.16666666666666019037e-02, // C1 13 - -1.38888888888741095749e-03, // 14 - 2.48015872894767294178e-05, // 15 - -2.75573143513906633035e-07, // 16 - 2.08757232129817482790e-09, // 17 - -1.13596475577881948265e-11, // C6 18 - 3.33333333333334091986e-01, // T0 19 - 1.33333333333201242699e-01, // 20 - 5.39682539762260521377e-02, // 21 - 2.18694882948595424599e-02, // 22 - 8.86323982359930005737e-03, // 23 - 3.59207910759131235356e-03, // 24 - 1.45620945432529025516e-03, // 25 - 5.88041240820264096874e-04, // 26 - 2.46463134818469906812e-04, // 27 - 7.81794442939557092300e-05, // 28 - 7.14072491382608190305e-05, // 29 - -1.85586374855275456654e-05, // 30 - 2.59073051863633712884e-05, // T12 31 - 7.85398163397448278999e-01, // pio4 32 - 3.06161699786838301793e-17, // pio4lo 33 -}; - - -// Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi -static const int two_over_pi[] = { - 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, - 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, - 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44, - 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, - 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, - 0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, - 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, - 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08, - 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, - 0x73A8C9, 0x60E27B, 0xC08C6B}; - -static const double zero = 0.0; -static const double two24 = 1.6777216e+07; -static const double one = 1.0; -static const double twon24 = 5.9604644775390625e-08; - -static const double PIo2[] = { - 1.57079625129699707031e+00, // 0x3FF921FB, 0x40000000 - 7.54978941586159635335e-08, // 0x3E74442D, 0x00000000 - 5.39030252995776476554e-15, // 0x3CF84698, 0x80000000 - 3.28200341580791294123e-22, // 0x3B78CC51, 0x60000000 - 1.27065575308067607349e-29, // 0x39F01B83, 0x80000000 - 1.22933308981111328932e-36, // 0x387A2520, 0x40000000 - 2.73370053816464559624e-44, // 0x36E38222, 0x80000000 - 2.16741683877804819444e-51 // 0x3569F31D, 0x00000000 -}; - - -int __kernel_rem_pio2(double* x, double* y, int e0, int nx) { - static const int32_t jk = 3; - double fw; - int32_t jx = nx - 1; - int32_t jv = (e0 - 3) / 24; - if (jv < 0) jv = 0; - int32_t q0 = e0 - 24 * (jv + 1); - int32_t m = jx + jk; - - double f[10]; - for (int i = 0, j = jv - jx; i <= m; i++, j++) { - f[i] = (j < 0) ? zero : static_cast(two_over_pi[j]); - } - - double q[10]; - for (int i = 0; i <= jk; i++) { - fw = 0.0; - for (int j = 0; j <= jx; j++) fw += x[j] * f[jx + i - j]; - q[i] = fw; - } - - int32_t jz = jk; - -recompute: - - int32_t iq[10]; - double z = q[jz]; - for (int i = 0, j = jz; j > 0; i++, j--) { - fw = static_cast(static_cast(twon24 * z)); - iq[i] = static_cast(z - two24 * fw); - z = q[j - 1] + fw; - } - - z = scalbn(z, q0); - z -= 8.0 * std::floor(z * 0.125); - int32_t n = static_cast(z); - z -= static_cast(n); - int32_t ih = 0; - if (q0 > 0) { - int32_t i = (iq[jz - 1] >> (24 - q0)); - n += i; - iq[jz - 1] -= i << (24 - q0); - ih = iq[jz - 1] >> (23 - q0); - } else if (q0 == 0) { - ih = iq[jz - 1] >> 23; - } else if (z >= 0.5) { - ih = 2; - } - - if (ih > 0) { - n += 1; - int32_t carry = 0; - for (int i = 0; i < jz; i++) { - int32_t j = iq[i]; - if (carry == 0) { - if (j != 0) { - carry = 1; - iq[i] = 0x1000000 - j; - } - } else { - iq[i] = 0xffffff - j; - } - } - if (q0 == 1) { - iq[jz - 1] &= 0x7fffff; - } else if (q0 == 2) { - iq[jz - 1] &= 0x3fffff; - } - if (ih == 2) { - z = one - z; - if (carry != 0) z -= scalbn(one, q0); - } - } - - if (z == zero) { - int32_t j = 0; - for (int i = jz - 1; i >= jk; i--) j |= iq[i]; - if (j == 0) { - int32_t k = 1; - while (iq[jk - k] == 0) k++; - for (int i = jz + 1; i <= jz + k; i++) { - f[jx + i] = static_cast(two_over_pi[jv + i]); - for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j]; - q[i] = fw; - } - jz += k; - goto recompute; - } - } - - if (z == 0.0) { - jz -= 1; - q0 -= 24; - while (iq[jz] == 0) { - jz--; - q0 -= 24; - } - } else { - z = scalbn(z, -q0); - if (z >= two24) { - fw = static_cast(static_cast(twon24 * z)); - iq[jz] = static_cast(z - two24 * fw); - jz += 1; - q0 += 24; - iq[jz] = static_cast(fw); - } else { - iq[jz] = static_cast(z); - } - } - - fw = scalbn(one, q0); - for (int i = jz; i >= 0; i--) { - q[i] = fw * static_cast(iq[i]); - fw *= twon24; - } - - double fq[10]; - for (int i = jz; i >= 0; i--) { - fw = 0.0; - for (int k = 0; k <= jk && k <= jz - i; k++) fw += PIo2[k] * q[i + k]; - fq[jz - i] = fw; - } - - fw = 0.0; - for (int i = jz; i >= 0; i--) fw += fq[i]; - y[0] = (ih == 0) ? fw : -fw; - fw = fq[0] - fw; - for (int i = 1; i <= jz; i++) fw += fq[i]; - y[1] = (ih == 0) ? fw : -fw; - return n & 7; -} - - -int rempio2(double x, double* y) { - int32_t hx = static_cast(double_to_uint64(x) >> 32); - int32_t ix = hx & 0x7fffffff; - - if (ix >= 0x7ff00000) { - *y = base::OS::nan_value(); - return 0; - } - - int32_t e0 = (ix >> 20) - 1046; - uint64_t zi = double_to_uint64(x) & 0xFFFFFFFFu; - zi |= static_cast(ix - (e0 << 20)) << 32; - double z = uint64_to_double(zi); - - double tx[3]; - for (int i = 0; i < 2; i++) { - tx[i] = static_cast(static_cast(z)); - z = (z - tx[i]) * two24; - } - tx[2] = z; - - int nx = 3; - while (tx[nx - 1] == zero) nx--; - int n = __kernel_rem_pio2(tx, y, e0, nx); - if (hx < 0) { - y[0] = -y[0]; - y[1] = -y[1]; - return -n; - } - return n; -} -} -} // namespace v8::internal diff --git a/third_party/fdlibm/fdlibm.h b/third_party/fdlibm/fdlibm.h deleted file mode 100644 index 4ce7794..0000000 --- a/third_party/fdlibm/fdlibm.h +++ /dev/null @@ -1,31 +0,0 @@ -// The following is adapted from fdlibm (http://www.netlib.org/fdlibm). -// -// ==================================================== -// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. -// -// Developed at SunSoft, a Sun Microsystems, Inc. business. -// Permission to use, copy, modify, and distribute this -// software is freely granted, provided that this notice -// is preserved. -// ==================================================== -// -// The original source code covered by the above license above has been -// modified significantly by Google Inc. -// Copyright 2014 the V8 project authors. All rights reserved. - -#ifndef V8_FDLIBM_H_ -#define V8_FDLIBM_H_ - -namespace v8 { -namespace internal { - -int rempio2(double x, double* y); - -// Constants to be exposed to builtins via Float64Array. -struct TrigonometricConstants { - static const double constants[34]; -}; -} -} // namespace v8::internal - -#endif // V8_FDLIBM_H_ diff --git a/third_party/fdlibm/fdlibm.js b/third_party/fdlibm/fdlibm.js deleted file mode 100644 index d5dbb72..0000000 --- a/third_party/fdlibm/fdlibm.js +++ /dev/null @@ -1,356 +0,0 @@ -// The following is adapted from fdlibm (http://www.netlib.org/fdlibm), -// -// ==================================================== -// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. -// -// Developed at SunSoft, a Sun Microsystems, Inc. business. -// Permission to use, copy, modify, and distribute this -// software is freely granted, provided that this notice -// is preserved. -// ==================================================== -// -// The original source code covered by the above license above has been -// modified significantly by Google Inc. -// Copyright 2014 the V8 project authors. All rights reserved. -// -// The following is a straightforward translation of fdlibm routines for -// sin, cos, and tan, by Raymond Toy (rtoy@google.com). - - -var kTrig; // Initialized to a Float64Array during genesis and is not writable. - -const INVPIO2 = kTrig[0]; -const PIO2_1 = kTrig[1]; -const PIO2_1T = kTrig[2]; -const PIO2_2 = kTrig[3]; -const PIO2_2T = kTrig[4]; -const PIO2_3 = kTrig[5]; -const PIO2_3T = kTrig[6]; -const PIO4 = kTrig[32]; -const PIO4LO = kTrig[33]; - -// Compute k and r such that x - k*pi/2 = r where |r| < pi/4. For -// precision, r is returned as two values y0 and y1 such that r = y0 + y1 -// to more than double precision. -macro REMPIO2(X) - var n, y0, y1; - var hx = %_DoubleHi(X); - var ix = hx & 0x7fffffff; - - if (ix < 0x4002d97c) { - // |X| ~< 3*pi/4, special case with n = +/- 1 - if (hx > 0) { - var z = X - PIO2_1; - if (ix != 0x3ff921fb) { - // 33+53 bit pi is good enough - y0 = z - PIO2_1T; - y1 = (z - y0) - PIO2_1T; - } else { - // near pi/2, use 33+33+53 bit pi - z -= PIO2_2; - y0 = z - PIO2_2T; - y1 = (z - y0) - PIO2_2T; - } - n = 1; - } else { - // Negative X - var z = X + PIO2_1; - if (ix != 0x3ff921fb) { - // 33+53 bit pi is good enough - y0 = z + PIO2_1T; - y1 = (z - y0) + PIO2_1T; - } else { - // near pi/2, use 33+33+53 bit pi - z += PIO2_2; - y0 = z + PIO2_2T; - y1 = (z - y0) + PIO2_2T; - } - n = -1; - } - } else if (ix <= 0x413921fb) { - // |X| ~<= 2^19*(pi/2), medium size - var t = MathAbs(X); - n = (t * INVPIO2 + 0.5) | 0; - var r = t - n * PIO2_1; - var w = n * PIO2_1T; - // First round good to 85 bit - y0 = r - w; - if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x1000000) { - // 2nd iteration needed, good to 118 - t = r; - w = n * PIO2_2; - r = t - w; - w = n * PIO2_2T - ((t - r) - w); - y0 = r - w; - if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x3100000) { - // 3rd iteration needed. 151 bits accuracy - t = r; - w = n * PIO2_3; - r = t - w; - w = n * PIO2_3T - ((t - r) - w); - y0 = r - w; - } - } - y1 = (r - y0) - w; - if (hx < 0) { - n = -n; - y0 = -y0; - y1 = -y1; - } - } else { - // Need to do full Payne-Hanek reduction here. - var r = %RemPiO2(X); - n = r[0]; - y0 = r[1]; - y1 = r[2]; - } -endmacro - - -// __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. -// Input Y is the tail of X so that x = X + Y. -// -// Algorithm -// 1. Since ieee_sin(-x) = -ieee_sin(x), we need only to consider positive x. -// 2. ieee_sin(x) is approximated by a polynomial of degree 13 on -// [0,pi/4] -// 3 13 -// sin(x) ~ x + S1*x + ... + S6*x -// where -// -// |ieee_sin(x) 2 4 6 8 10 12 | -58 -// |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 -// | x | -// -// 3. ieee_sin(X+Y) = ieee_sin(X) + sin'(X')*Y -// ~ ieee_sin(X) + (1-X*X/2)*Y -// For better accuracy, let -// 3 2 2 2 2 -// r = X *(S2+X *(S3+X *(S4+X *(S5+X *S6)))) -// then 3 2 -// sin(x) = X + (S1*X + (X *(r-Y/2)+Y)) -// -macro KSIN(x) -kTrig[7+x] -endmacro - -macro RETURN_KERNELSIN(X, Y, SIGN) - var z = X * X; - var v = z * X; - var r = KSIN(1) + z * (KSIN(2) + z * (KSIN(3) + - z * (KSIN(4) + z * KSIN(5)))); - return (X - ((z * (0.5 * Y - v * r) - Y) - v * KSIN(0))) SIGN; -endmacro - -// __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. -// Input Y is the tail of X so that x = X + Y. -// -// Algorithm -// 1. Since ieee_cos(-x) = ieee_cos(x), we need only to consider positive x. -// 2. ieee_cos(x) is approximated by a polynomial of degree 14 on -// [0,pi/4] -// 4 14 -// cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x -// where the remez error is -// -// | 2 4 6 8 10 12 14 | -58 -// |ieee_cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 -// | | -// -// 4 6 8 10 12 14 -// 3. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then -// ieee_cos(x) = 1 - x*x/2 + r -// since ieee_cos(X+Y) ~ ieee_cos(X) - ieee_sin(X)*Y -// ~ ieee_cos(X) - X*Y, -// a correction term is necessary in ieee_cos(x) and hence -// cos(X+Y) = 1 - (X*X/2 - (r - X*Y)) -// For better accuracy when x > 0.3, let qx = |x|/4 with -// the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. -// Then -// cos(X+Y) = (1-qx) - ((X*X/2-qx) - (r-X*Y)). -// Note that 1-qx and (X*X/2-qx) is EXACT here, and the -// magnitude of the latter is at least a quarter of X*X/2, -// thus, reducing the rounding error in the subtraction. -// -macro KCOS(x) -kTrig[13+x] -endmacro - -macro RETURN_KERNELCOS(X, Y, SIGN) - var ix = %_DoubleHi(X) & 0x7fffffff; - var z = X * X; - var r = z * (KCOS(0) + z * (KCOS(1) + z * (KCOS(2)+ - z * (KCOS(3) + z * (KCOS(4) + z * KCOS(5)))))); - if (ix < 0x3fd33333) { // |x| ~< 0.3 - return (1 - (0.5 * z - (z * r - X * Y))) SIGN; - } else { - var qx; - if (ix > 0x3fe90000) { // |x| > 0.78125 - qx = 0.28125; - } else { - qx = %_ConstructDouble(%_DoubleHi(0.25 * X), 0); - } - var hz = 0.5 * z - qx; - return (1 - qx - (hz - (z * r - X * Y))) SIGN; - } -endmacro - -// kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 -// Input x is assumed to be bounded by ~pi/4 in magnitude. -// Input y is the tail of x. -// Input k indicates whether ieee_tan (if k = 1) or -1/tan (if k = -1) -// is returned. -// -// Algorithm -// 1. Since ieee_tan(-x) = -ieee_tan(x), we need only to consider positive x. -// 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. -// 3. ieee_tan(x) is approximated by a odd polynomial of degree 27 on -// [0,0.67434] -// 3 27 -// tan(x) ~ x + T1*x + ... + T13*x -// where -// -// |ieee_tan(x) 2 4 26 | -59.2 -// |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 -// | x | -// -// Note: ieee_tan(x+y) = ieee_tan(x) + tan'(x)*y -// ~ ieee_tan(x) + (1+x*x)*y -// Therefore, for better accuracy in computing ieee_tan(x+y), let -// 3 2 2 2 2 -// r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) -// then -// 3 2 -// tan(x+y) = x + (T1*x + (x *(r+y)+y)) -// -// 4. For x in [0.67434,pi/4], let y = pi/4 - x, then -// tan(x) = ieee_tan(pi/4-y) = (1-ieee_tan(y))/(1+ieee_tan(y)) -// = 1 - 2*(ieee_tan(y) - (ieee_tan(y)^2)/(1+ieee_tan(y))) -// -// Set returnTan to 1 for tan; -1 for cot. Anything else is illegal -// and will cause incorrect results. -// -macro KTAN(x) -kTrig[19+x] -endmacro - -function KernelTan(x, y, returnTan) { - var z; - var w; - var hx = %_DoubleHi(x); - var ix = hx & 0x7fffffff; - - if (ix < 0x3e300000) { // |x| < 2^-28 - if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) { - // x == 0 && returnTan = -1 - return 1 / MathAbs(x); - } else { - if (returnTan == 1) { - return x; - } else { - // Compute -1/(x + y) carefully - var w = x + y; - var z = %_ConstructDouble(%_DoubleHi(w), 0); - var v = y - (z - x); - var a = -1 / w; - var t = %_ConstructDouble(%_DoubleHi(a), 0); - var s = 1 + t * z; - return t + a * (s + t * v); - } - } - } - if (ix >= 0x3fe59429) { // |x| > .6744 - if (x < 0) { - x = -x; - y = -y; - } - z = PIO4 - x; - w = PIO4LO - y; - x = z + w; - y = 0; - } - z = x * x; - w = z * z; - - // Break x^5 * (T1 + x^2*T2 + ...) into - // x^5 * (T1 + x^4*T3 + ... + x^20*T11) + - // x^5 * (x^2 * (T2 + x^4*T4 + ... + x^22*T12)) - var r = KTAN(1) + w * (KTAN(3) + w * (KTAN(5) + - w * (KTAN(7) + w * (KTAN(9) + w * KTAN(11))))); - var v = z * (KTAN(2) + w * (KTAN(4) + w * (KTAN(6) + - w * (KTAN(8) + w * (KTAN(10) + w * KTAN(12)))))); - var s = z * x; - r = y + z * (s * (r + v) + y); - r = r + KTAN(0) * s; - w = x + r; - if (ix >= 0x3fe59428) { - return (1 - ((hx >> 30) & 2)) * - (returnTan - 2.0 * (x - (w * w / (w + returnTan) - r))); - } - if (returnTan == 1) { - return w; - } else { - z = %_ConstructDouble(%_DoubleHi(w), 0); - v = r - (z - x); - var a = -1 / w; - var t = %_ConstructDouble(%_DoubleHi(a), 0); - s = 1 + t * z; - return t + a * (s + t * v); - } -} - -function MathSinSlow(x) { - REMPIO2(x); - var sign = 1 - (n & 2); - if (n & 1) { - RETURN_KERNELCOS(y0, y1, * sign); - } else { - RETURN_KERNELSIN(y0, y1, * sign); - } -} - -function MathCosSlow(x) { - REMPIO2(x); - if (n & 1) { - var sign = (n & 2) - 1; - RETURN_KERNELSIN(y0, y1, * sign); - } else { - var sign = 1 - (n & 2); - RETURN_KERNELCOS(y0, y1, * sign); - } -} - -// ECMA 262 - 15.8.2.16 -function MathSin(x) { - x = x * 1; // Convert to number. - if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { - // |x| < pi/4, approximately. No reduction needed. - RETURN_KERNELSIN(x, 0, /* empty */); - } - return MathSinSlow(x); -} - -// ECMA 262 - 15.8.2.7 -function MathCos(x) { - x = x * 1; // Convert to number. - if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { - // |x| < pi/4, approximately. No reduction needed. - RETURN_KERNELCOS(x, 0, /* empty */); - } - return MathCosSlow(x); -} - -// ECMA 262 - 15.8.2.18 -function MathTan(x) { - x = x * 1; // Convert to number. - if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { - // |x| < pi/4, approximately. No reduction needed. - return KernelTan(x, 0, 1); - } - REMPIO2(x); - return KernelTan(y0, y1, (n & 1) ? -1 : 1); -} diff --git a/tools/generate-runtime-tests.py b/tools/generate-runtime-tests.py index 7bf8736..c37ecca 100755 --- a/tools/generate-runtime-tests.py +++ b/tools/generate-runtime-tests.py @@ -47,11 +47,11 @@ EXPAND_MACROS = [ # that the parser doesn't bit-rot. Change the values as needed when you add, # remove or change runtime functions, but make sure we don't lose our ability # to parse them! -EXPECTED_FUNCTION_COUNT = 427 -EXPECTED_FUZZABLE_COUNT = 330 +EXPECTED_FUNCTION_COUNT = 426 +EXPECTED_FUZZABLE_COUNT = 329 EXPECTED_CCTEST_COUNT = 7 EXPECTED_UNKNOWN_COUNT = 16 -EXPECTED_BUILTINS_COUNT = 809 +EXPECTED_BUILTINS_COUNT = 813 # Don't call these at all. diff --git a/tools/generate-trig-table.py b/tools/generate-trig-table.py new file mode 100644 index 0000000..0a4fe28 --- /dev/null +++ b/tools/generate-trig-table.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# Copyright 2013 the V8 project authors. All rights reserved. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This is a utility for populating the lookup table for the +# approximation of trigonometric functions. + +import sys, math + +SAMPLES = 1800 + +TEMPLATE = """\ +// Copyright 2013 Google Inc. All Rights Reserved. + +// This file was generated from a python script. + +#include "src/v8.h" +#include "src/trig-table.h" + +namespace v8 { +namespace internal { + + const double TrigonometricLookupTable::kSinTable[] = + { %(sine_table)s }; + const double TrigonometricLookupTable::kCosXIntervalTable[] = + { %(cosine_table)s }; + const int TrigonometricLookupTable::kSamples = %(samples)i; + const int TrigonometricLookupTable::kTableSize = %(table_size)i; + const double TrigonometricLookupTable::kSamplesOverPiHalf = + %(samples_over_pi_half)s; + +} } // v8::internal +""" + +def main(): + pi_half = math.pi / 2 + interval = pi_half / SAMPLES + sin = [] + cos_times_interval = [] + table_size = SAMPLES + 2 + + for i in range(0, table_size): + sample = i * interval + sin.append(repr(math.sin(sample))) + cos_times_interval.append(repr(math.cos(sample) * interval)) + + output_file = sys.argv[1] + output = open(str(output_file), "w") + output.write(TEMPLATE % { + 'sine_table': ','.join(sin), + 'cosine_table': ','.join(cos_times_interval), + 'samples': SAMPLES, + 'table_size': table_size, + 'samples_over_pi_half': repr(SAMPLES / pi_half) + }) + +if __name__ == "__main__": + main() diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 967497b..097847e 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -121,12 +121,14 @@ 'dependencies': [ 'mksnapshot#host', 'js2c#host', + 'generate_trig_table#host', ], }, { 'toolsets': ['target'], 'dependencies': [ 'mksnapshot', 'js2c', + 'generate_trig_table', ], }], ['component=="shared_library"', { @@ -151,6 +153,7 @@ 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/libraries.cc', '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc', + '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc', '<(INTERMEDIATE_DIR)/snapshot.cc', '../../src/snapshot-common.cc', ], @@ -194,16 +197,17 @@ 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/libraries.cc', '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc', + '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc', '../../src/snapshot-common.cc', '../../src/snapshot-empty.cc', ], 'conditions': [ ['want_separate_host_toolset==1', { 'toolsets': ['host', 'target'], - 'dependencies': ['js2c#host'], + 'dependencies': ['js2c#host', 'generate_trig_table#host'], }, { 'toolsets': ['target'], - 'dependencies': ['js2c'], + 'dependencies': ['js2c', 'generate_trig_table'], }], ['component=="shared_library"', { 'defines': [ @@ -222,12 +226,14 @@ 'dependencies': [ 'mksnapshot#host', 'js2c#host', + 'generate_trig_table#host', 'natives_blob#host', ]}, { 'toolsets': ['target'], 'dependencies': [ 'mksnapshot', 'js2c', + 'generate_trig_table', 'natives_blob', ], }], @@ -251,6 +257,7 @@ '../..', ], 'sources': [ + '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc', '../../src/natives-external.cc', '../../src/snapshot-external.cc', ], @@ -284,6 +291,32 @@ }, ], }, + { 'target_name': 'generate_trig_table', + 'type': 'none', + 'conditions': [ + ['want_separate_host_toolset==1', { + 'toolsets': ['host'], + }, { + 'toolsets': ['target'], + }], + ], + 'actions': [ + { + 'action_name': 'generate', + 'inputs': [ + '../../tools/generate-trig-table.py', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc', + ], + 'action': [ + 'python', + '../../tools/generate-trig-table.py', + '<@(_outputs)', + ], + }, + ] + }, { 'target_name': 'v8_base', 'type': 'static_library', @@ -735,8 +768,6 @@ '../../src/zone-inl.h', '../../src/zone.cc', '../../src/zone.h', - '../../third_party/fdlibm/fdlibm.cc', - '../../third_party/fdlibm/fdlibm.h', ], 'conditions': [ ['want_separate_host_toolset==1', { @@ -1389,7 +1420,6 @@ '../../src/array.js', '../../src/string.js', '../../src/uri.js', - '../../third_party/fdlibm/fdlibm.js', '../../src/math.js', '../../src/messages.js', '../../src/apinatives.js', diff --git a/tools/js2c.py b/tools/js2c.py index 77485f6..60f088b 100755 --- a/tools/js2c.py +++ b/tools/js2c.py @@ -218,27 +218,6 @@ def ExpandInlineMacros(lines): lines = ExpandMacroDefinition(lines, pos, name_pattern, macro, non_expander) -INLINE_CONSTANT_PATTERN = re.compile(r'const\s+([a-zA-Z0-9_]+)\s*=\s*([^;\n]+)[;\n]') - -def ExpandInlineConstants(lines): - pos = 0 - while True: - const_match = INLINE_CONSTANT_PATTERN.search(lines, pos) - if const_match is None: - # no more constants - return lines - name = const_match.group(1) - replacement = const_match.group(2) - name_pattern = re.compile("\\b%s\\b" % name) - - # remove constant definition and replace - lines = (lines[:const_match.start()] + - re.sub(name_pattern, replacement, lines[const_match.end():])) - - # advance position to where the constant defintion was - pos = const_match.start() - - HEADER_TEMPLATE = """\ // Copyright 2011 Google Inc. All Rights Reserved. @@ -354,7 +333,6 @@ def BuildFilterChain(macro_filename): filter_chain.extend([ RemoveCommentsAndTrailingWhitespace, ExpandInlineMacros, - ExpandInlineConstants, Validate, jsmin.JavaScriptMinifier().JSMinify ]) -- 2.7.4