Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(952)

Side by Side Diff: src/math.js

Issue 148593004: A64: Synchronize with r18084. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mark-compact.cc ('k') | src/mips/assembler-mips.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 67
68 // ECMA 262 - 15.8.2.5 68 // ECMA 262 - 15.8.2.5
69 // The naming of y and x matches the spec, as does the order in which 69 // The naming of y and x matches the spec, as does the order in which
70 // ToNumber (valueOf) is called. 70 // ToNumber (valueOf) is called.
71 function MathAtan2(y, x) { 71 function MathAtan2(y, x) {
72 return %Math_atan2(TO_NUMBER_INLINE(y), TO_NUMBER_INLINE(x)); 72 return %Math_atan2(TO_NUMBER_INLINE(y), TO_NUMBER_INLINE(x));
73 } 73 }
74 74
75 // ECMA 262 - 15.8.2.6 75 // ECMA 262 - 15.8.2.6
76 function MathCeil(x) { 76 function MathCeil(x) {
77 return %Math_ceil(TO_NUMBER_INLINE(x)); 77 return -MathFloor(-x);
78 } 78 }
79 79
80 // ECMA 262 - 15.8.2.7 80 // ECMA 262 - 15.8.2.7
81 function MathCos(x) { 81 function MathCos(x) {
82 return MathCosImpl(x); 82 x = MathAbs(x); // Convert to number and get rid of -0.
83 return TrigonometricInterpolation(x, 1);
83 } 84 }
84 85
85 // ECMA 262 - 15.8.2.8 86 // ECMA 262 - 15.8.2.8
86 function MathExp(x) { 87 function MathExp(x) {
87 return %Math_exp(TO_NUMBER_INLINE(x)); 88 return %Math_exp(TO_NUMBER_INLINE(x));
88 } 89 }
89 90
90 // ECMA 262 - 15.8.2.9 91 // ECMA 262 - 15.8.2.9
91 function MathFloor(x) { 92 function MathFloor(x) {
92 x = TO_NUMBER_INLINE(x); 93 x = TO_NUMBER_INLINE(x);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 } 162 }
162 return r; 163 return r;
163 } 164 }
164 165
165 // ECMA 262 - 15.8.2.13 166 // ECMA 262 - 15.8.2.13
166 function MathPow(x, y) { 167 function MathPow(x, y) {
167 return %_MathPow(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y)); 168 return %_MathPow(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y));
168 } 169 }
169 170
170 // ECMA 262 - 15.8.2.14 171 // ECMA 262 - 15.8.2.14
172 var rngstate; // Initialized to a Uint32Array during genesis.
171 function MathRandom() { 173 function MathRandom() {
172 return %_RandomHeapNumber(); 174 var r0 = (MathImul(18273, rngstate[0] & 0xFFFF) + (rngstate[0] >>> 16)) | 0;
175 rngstate[0] = r0;
176 var r1 = (MathImul(36969, rngstate[1] & 0xFFFF) + (rngstate[1] >>> 16)) | 0;
177 rngstate[1] = r1;
178 var x = ((r0 << 16) + (r1 & 0xFFFF)) | 0;
179 // Division by 0x100000000 through multiplication by reciprocal.
180 return (x < 0 ? (x + 0x100000000) : x) * 2.3283064365386962890625e-10;
173 } 181 }
174 182
175 // ECMA 262 - 15.8.2.15 183 // ECMA 262 - 15.8.2.15
176 function MathRound(x) { 184 function MathRound(x) {
177 return %RoundNumber(TO_NUMBER_INLINE(x)); 185 return %RoundNumber(TO_NUMBER_INLINE(x));
178 } 186 }
179 187
180 // ECMA 262 - 15.8.2.16 188 // ECMA 262 - 15.8.2.16
181 function MathSin(x) { 189 function MathSin(x) {
182 return MathSinImpl(x); 190 x = x * 1; // Convert to number and deal with -0.
191 if (%_IsMinusZero(x)) return x;
192 return TrigonometricInterpolation(x, 0);
183 } 193 }
184 194
185 // ECMA 262 - 15.8.2.17 195 // ECMA 262 - 15.8.2.17
186 function MathSqrt(x) { 196 function MathSqrt(x) {
187 return %_MathSqrt(TO_NUMBER_INLINE(x)); 197 return %_MathSqrt(TO_NUMBER_INLINE(x));
188 } 198 }
189 199
190 // ECMA 262 - 15.8.2.18 200 // ECMA 262 - 15.8.2.18
191 function MathTan(x) { 201 function MathTan(x) {
192 return MathSinImpl(x) / MathCosImpl(x); 202 return MathSin(x) / MathCos(x);
193 } 203 }
194 204
195 // Non-standard extension. 205 // Non-standard extension.
196 function MathImul(x, y) { 206 function MathImul(x, y) {
197 return %NumberImul(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y)); 207 return %NumberImul(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y));
198 } 208 }
199 209
200 210
201 var MathSinImpl = function(x) { 211 var kInversePiHalf = 0.636619772367581343; // 2 / pi
202 InitTrigonometricFunctions(); 212 var kInversePiHalfS26 = 9.48637384723993156e-9; // 2 / pi / (2^26)
203 return MathSinImpl(x); 213 var kS26 = 1 << 26;
214 var kTwoStepThreshold = 1 << 27;
215 // pi / 2 rounded up
216 var kPiHalf = 1.570796326794896780; // 0x192d4454fb21f93f
217 // We use two parts for pi/2 to emulate a higher precision.
218 // pi_half_1 only has 26 significant bits for mantissa.
219 // Note that pi_half > pi_half_1 + pi_half_2
220 var kPiHalf1 = 1.570796325802803040; // 0x00000054fb21f93f
221 var kPiHalf2 = 9.920935796805404252e-10; // 0x3326a611460b113e
222
223 var kSamples; // Initialized to a number during genesis.
224 var kIndexConvert; // Initialized to kSamples / (pi/2) during genesis.
225 var kSinTable; // Initialized to a Float64Array during genesis.
226 var kCosXIntervalTable; // Initialized to a Float64Array during genesis.
227
228 // This implements sine using the following algorithm.
229 // 1) Multiplication takes care of to-number conversion.
230 // 2) Reduce x to the first quadrant [0, pi/2].
231 // Conveniently enough, in case of +/-Infinity, we get NaN.
232 // Note that we try to use only 26 instead of 52 significant bits for
233 // mantissa to avoid rounding errors when multiplying. For very large
234 // input we therefore have additional steps.
235 // 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant.
236 // 4) Do a table lookup for the closest samples to the left and right of x.
237 // 5) Find the derivatives at those sampling points by table lookup:
238 // dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2].
239 // 6) Use cubic spline interpolation to approximate sin(x).
240 // 7) Negate the result if x was in the 3rd or 4th quadrant.
241 // 8) Get rid of -0 by adding 0.
242 function TrigonometricInterpolation(x, phase) {
243 if (x < 0 || x > kPiHalf) {
244 var multiple;
245 while (x < -kTwoStepThreshold || x > kTwoStepThreshold) {
246 // Let's assume this loop does not terminate.
247 // All numbers x in each loop forms a set S.
248 // (1) abs(x) > 2^27 for all x in S.
249 // (2) abs(multiple) != 0 since (2^27 * inverse_pi_half_s26) > 1
250 // (3) multiple is rounded down in 2^26 steps, so the rounding error is
251 // at most max(ulp, 2^26).
252 // (4) so for x > 2^27, we subtract at most (1+pi/4)x and at least
253 // (1-pi/4)x
254 // (5) The subtraction results in x' so that abs(x') <= abs(x)*pi/4.
255 // Note that this difference cannot be simply rounded off.
256 // Set S cannot exist since (5) violates (1). Loop must terminate.
257 multiple = MathFloor(x * kInversePiHalfS26) * kS26;
258 x = x - multiple * kPiHalf1 - multiple * kPiHalf2;
259 }
260 multiple = MathFloor(x * kInversePiHalf);
261 x = x - multiple * kPiHalf1 - multiple * kPiHalf2;
262 phase += multiple;
263 }
264 var double_index = x * kIndexConvert;
265 if (phase & 1) double_index = kSamples - double_index;
266 var index = double_index | 0;
267 var t1 = double_index - index;
268 var t2 = 1 - t1;
269 var y1 = kSinTable[index];
270 var y2 = kSinTable[index + 1];
271 var dy = y2 - y1;
272 return (t2 * y1 + t1 * y2 +
273 t1 * t2 * ((kCosXIntervalTable[index] - dy) * t2 +
274 (dy - kCosXIntervalTable[index + 1]) * t1))
275 * (1 - (phase & 2)) + 0;
204 } 276 }
205 277
206
207 var MathCosImpl = function(x) {
208 InitTrigonometricFunctions();
209 return MathCosImpl(x);
210 }
211
212
213 var InitTrigonometricFunctions;
214
215
216 // Define constants and interpolation functions.
217 // Also define the initialization function that populates the lookup table
218 // and then wires up the function definitions.
219 function SetupTrigonometricFunctions() {
220 // TODO(yangguo): The following table size has been chosen to satisfy
221 // Sunspider's brittle result verification. Reconsider relevance.
222 var samples = 4489;
223 var pi = 3.1415926535897932;
224 var pi_half = pi / 2;
225 var inverse_pi_half = 2 / pi;
226 var two_pi = 2 * pi;
227 var four_pi = 4 * pi;
228 var interval = pi_half / samples;
229 var inverse_interval = samples / pi_half;
230 var table_sin;
231 var table_cos_interval;
232
233 // This implements sine using the following algorithm.
234 // 1) Multiplication takes care of to-number conversion.
235 // 2) Reduce x to the first quadrant [0, pi/2].
236 // Conveniently enough, in case of +/-Infinity, we get NaN.
237 // 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant.
238 // 4) Do a table lookup for the closest samples to the left and right of x.
239 // 5) Find the derivatives at those sampling points by table lookup:
240 // dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2].
241 // 6) Use cubic spline interpolation to approximate sin(x).
242 // 7) Negate the result if x was in the 3rd or 4th quadrant.
243 // 8) Get rid of -0 by adding 0.
244 var Interpolation = function(x) {
245 var double_index = x * inverse_interval;
246 var index = double_index | 0;
247 var t1 = double_index - index;
248 var t2 = 1 - t1;
249 var y1 = table_sin[index];
250 var y2 = table_sin[index + 1];
251 var dy = y2 - y1;
252 return (t2 * y1 + t1 * y2 +
253 t1 * t2 * ((table_cos_interval[index] - dy) * t2 +
254 (dy - table_cos_interval[index + 1]) * t1));
255 }
256
257 var MathSinInterpolation = function(x) {
258 // This is to make Sunspider's result verification happy.
259 if (x > four_pi) x -= four_pi;
260 var multiple = MathFloor(x * inverse_pi_half);
261 if (%_IsMinusZero(multiple)) return multiple;
262 x = (multiple & 1) * pi_half +
263 (1 - ((multiple & 1) << 1)) * (x - multiple * pi_half);
264 return Interpolation(x) * (1 - (multiple & 2)) + 0;
265 }
266
267 // Cosine is sine with a phase offset of pi/2.
268 var MathCosInterpolation = function(x) {
269 var multiple = MathFloor(x * inverse_pi_half);
270 var phase = multiple + 1;
271 x = (phase & 1) * pi_half +
272 (1 - ((phase & 1) << 1)) * (x - multiple * pi_half);
273 return Interpolation(x) * (1 - (phase & 2)) + 0;
274 };
275
276 %SetInlineBuiltinFlag(Interpolation);
277 %SetInlineBuiltinFlag(MathSinInterpolation);
278 %SetInlineBuiltinFlag(MathCosInterpolation);
279
280 InitTrigonometricFunctions = function() {
281 table_sin = new global.Float64Array(samples + 2);
282 table_cos_interval = new global.Float64Array(samples + 2);
283 %PopulateTrigonometricTable(table_sin, table_cos_interval, samples);
284 MathSinImpl = MathSinInterpolation;
285 MathCosImpl = MathCosInterpolation;
286 }
287 }
288
289 SetupTrigonometricFunctions();
290
291
292 // ------------------------------------------------------------------- 278 // -------------------------------------------------------------------
293 279
294 function SetUpMath() { 280 function SetUpMath() {
295 %CheckIsBootstrapping(); 281 %CheckIsBootstrapping();
296 282
297 %SetPrototype($Math, $Object.prototype); 283 %SetPrototype($Math, $Object.prototype);
298 %SetProperty(global, "Math", $Math, DONT_ENUM); 284 %SetProperty(global, "Math", $Math, DONT_ENUM);
299 %FunctionSetInstanceClassName(MathConstructor, 'Math'); 285 %FunctionSetInstanceClassName(MathConstructor, 'Math');
300 286
301 // Set up math constants. 287 // Set up math constants.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 "sin", MathSin, 341 "sin", MathSin,
356 "sqrt", MathSqrt, 342 "sqrt", MathSqrt,
357 "tan", MathTan, 343 "tan", MathTan,
358 "atan2", MathAtan2, 344 "atan2", MathAtan2,
359 "pow", MathPow, 345 "pow", MathPow,
360 "max", MathMax, 346 "max", MathMax,
361 "min", MathMin, 347 "min", MathMin,
362 "imul", MathImul 348 "imul", MathImul
363 )); 349 ));
364 350
351 %SetInlineBuiltinFlag(MathCeil);
352 %SetInlineBuiltinFlag(MathRandom);
365 %SetInlineBuiltinFlag(MathSin); 353 %SetInlineBuiltinFlag(MathSin);
366 %SetInlineBuiltinFlag(MathCos); 354 %SetInlineBuiltinFlag(MathCos);
367 %SetInlineBuiltinFlag(MathTan); 355 %SetInlineBuiltinFlag(MathTan);
356 %SetInlineBuiltinFlag(TrigonometricInterpolation);
368 } 357 }
369 358
370 SetUpMath(); 359 SetUpMath();
OLDNEW
« no previous file with comments | « src/mark-compact.cc ('k') | src/mips/assembler-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698