Incorporate newer, faster dtoa library
[WebKit-https.git] / Source / JavaScriptCore / runtime / NumberPrototype.cpp
1 /*
2  *  Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
18  *  USA
19  *
20  */
21
22 #include "config.h"
23 #include "NumberPrototype.h"
24
25 #include "BigInteger.h"
26 #include "Error.h"
27 #include "JSFunction.h"
28 #include "JSString.h"
29 #include "Operations.h"
30 #include "Uint16WithFraction.h"
31 #include "dtoa.h"
32 #include <wtf/Assertions.h>
33 #include <wtf/MathExtras.h>
34 #include <wtf/Vector.h>
35 #include <wtf/dtoa/double-conversion.h>
36
37 using namespace WTF::double_conversion;
38
39 namespace JSC {
40
41 static EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState*);
42 static EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState*);
43 static EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState*);
44 static EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState*);
45 static EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState*);
46 static EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*);
47
48 }
49
50 #include "NumberPrototype.lut.h"
51
52 namespace JSC {
53
54 const ClassInfo NumberPrototype::s_info = { "Number", &NumberObject::s_info, 0, ExecState::numberPrototypeTable };
55
56 /* Source for NumberPrototype.lut.h
57 @begin numberPrototypeTable
58   toString          numberProtoFuncToString         DontEnum|Function 1
59   toLocaleString    numberProtoFuncToLocaleString   DontEnum|Function 0
60   valueOf           numberProtoFuncValueOf          DontEnum|Function 0
61   toFixed           numberProtoFuncToFixed          DontEnum|Function 1
62   toExponential     numberProtoFuncToExponential    DontEnum|Function 1
63   toPrecision       numberProtoFuncToPrecision      DontEnum|Function 1
64 @end
65 */
66
67 ASSERT_CLASS_FITS_IN_CELL(NumberPrototype);
68
69 NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
70     : NumberObject(exec->globalData(), structure)
71 {
72     setInternalValue(exec->globalData(), jsNumber(0));
73
74     ASSERT(inherits(&s_info));
75     putAnonymousValue(globalObject->globalData(), 0, globalObject);
76 }
77
78 bool NumberPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
79 {
80     return getStaticFunctionSlot<NumberObject>(exec, ExecState::numberPrototypeTable(exec), this, propertyName, slot);
81 }
82
83 bool NumberPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
84 {
85     return getStaticFunctionDescriptor<NumberObject>(exec, ExecState::numberPrototypeTable(exec), this, propertyName, descriptor);
86 }
87
88 // ------------------------------ Functions ---------------------------
89
90 static ALWAYS_INLINE bool toThisNumber(JSValue thisValue, double &x)
91 {
92     JSValue v = thisValue.getJSNumber();
93     if (UNLIKELY(!v))
94         return false;
95     x = v.uncheckedGetNumber();
96     return true;
97 }
98
99 static ALWAYS_INLINE bool getIntegerArgumentInRange(ExecState* exec, int low, int high, int& result, bool& isUndefined)
100 {
101     result = 0;
102     isUndefined = false;
103
104     JSValue argument0 = exec->argument(0);
105     if (argument0.isUndefined()) {
106         isUndefined = true;
107         return true;
108     }
109
110     double asDouble = argument0.toInteger(exec);
111     if (asDouble < low || asDouble > high)
112         return false;
113
114     result = static_cast<int>(asDouble);
115     return true;
116 }
117
118 // The largest finite floating point number is 1.mantissa * 2^(0x7fe-0x3ff).
119 // Since 2^N in binary is a one bit followed by N zero bits. 1 * 2^3ff requires
120 // at most 1024 characters to the left of a decimal point, in base 2 (1025 if
121 // we include a minus sign). For the fraction, a value with an exponent of 0
122 // has up to 52 bits to the right of the decimal point. Each decrement of the
123 // exponent down to a minimum of -0x3fe adds an additional digit to the length
124 // of the fraction. As such the maximum fraction size is 1075 (1076 including
125 // a point). We pick a buffer size such that can simply place the point in the
126 // center of the buffer, and are guaranteed to have enough space in each direction
127 // fo any number of digits an IEEE number may require to represent.
128 typedef char RadixBuffer[2180];
129
130 // Mapping from integers 0..35 to digit identifying this value, for radix 2..36.
131 static const char* const radixDigits = "0123456789abcdefghijklmnopqrstuvwxyz";
132
133 static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radix)
134 {
135     ASSERT(isfinite(number));
136     ASSERT(radix >= 2 && radix <= 36);
137
138     // Position the decimal point at the center of the string, set
139     // the startOfResultString pointer to point at the decimal point.
140     char* decimalPoint = buffer + sizeof(buffer) / 2;
141     char* startOfResultString = decimalPoint;
142
143     // Extract the sign.
144     bool isNegative = number < 0;
145     if (signbit(number))
146         number = -number;
147     double integerPart = floor(number);
148
149     // We use this to test for odd values in odd radix bases.
150     // Where the base is even, (e.g. 10), to determine whether a value is even we need only
151     // consider the least significant digit. For example, 124 in base 10 is even, because '4'
152     // is even. if the radix is odd, then the radix raised to an integer power is also odd.
153     // E.g. in base 5, 124 represents (1 * 125 + 2 * 25 + 4 * 5). Since each digit in the value
154     // is multiplied by an odd number, the result is even if the sum of all digits is even.
155     //
156     // For the integer portion of the result, we only need test whether the integer value is
157     // even or odd. For each digit of the fraction added, we should invert our idea of whether
158     // the number is odd if the new digit is odd.
159     //
160     // Also initialize digit to this value; for even radix values we only need track whether
161     // the last individual digit was odd.
162     bool integerPartIsOdd = integerPart <= static_cast<double>(0x1FFFFFFFFFFFFFull) && static_cast<int64_t>(integerPart) & 1;
163     ASSERT(integerPartIsOdd == static_cast<bool>(fmod(integerPart, 2)));
164     bool isOddInOddRadix = integerPartIsOdd;
165     uint32_t digit = integerPartIsOdd;
166
167     // Check if the value has a fractional part to convert.
168     double fractionPart = number - integerPart;
169     if (fractionPart) {
170         // Write the decimal point now.
171         *decimalPoint = '.';
172
173         // Higher precision representation of the fractional part.
174         Uint16WithFraction fraction(fractionPart);
175
176         bool needsRoundingUp = false;
177         char* endOfResultString = decimalPoint + 1;
178
179         // Calculate the delta from the current number to the next & previous possible IEEE numbers.
180         double nextNumber = nextafter(number, std::numeric_limits<double>::infinity());
181         double lastNumber = nextafter(number, -std::numeric_limits<double>::infinity());
182         ASSERT(isfinite(nextNumber) && !signbit(nextNumber));
183         ASSERT(isfinite(lastNumber) && !signbit(lastNumber));
184         double deltaNextDouble = nextNumber - number;
185         double deltaLastDouble = number - lastNumber;
186         ASSERT(isfinite(deltaNextDouble) && !signbit(deltaNextDouble));
187         ASSERT(isfinite(deltaLastDouble) && !signbit(deltaLastDouble));
188
189         // We track the delta from the current value to the next, to track how many digits of the
190         // fraction we need to write. For example, if the value we are converting is precisely
191         // 1.2345, so far we have written the digits "1.23" to a string leaving a remainder of
192         // 0.45, and we want to determine whether we can round off, or whether we need to keep
193         // appending digits ('4'). We can stop adding digits provided that then next possible
194         // lower IEEE value is further from 1.23 than the remainder we'd be rounding off (0.45),
195         // which is to say, less than 1.2255. Put another way, the delta between the prior
196         // possible value and this number must be more than 2x the remainder we'd be rounding off
197         // (or more simply half the delta between numbers must be greater than the remainder).
198         //
199         // Similarly we need track the delta to the next possible value, to dertermine whether
200         // to round up. In almost all cases (other than at exponent boundaries) the deltas to
201         // prior and subsequent values are identical, so we don't need track then separately.
202         if (deltaNextDouble != deltaLastDouble) {
203             // Since the deltas are different track them separately. Pre-multiply by 0.5.
204             Uint16WithFraction halfDeltaNext(deltaNextDouble, 1);
205             Uint16WithFraction halfDeltaLast(deltaLastDouble, 1);
206
207             while (true) {
208                 // examine the remainder to determine whether we should be considering rounding
209                 // up or down. If remainder is precisely 0.5 rounding is to even.
210                 int dComparePoint5 = fraction.comparePoint5();
211                 if (dComparePoint5 > 0 || (!dComparePoint5 && (radix & 1 ? isOddInOddRadix : digit & 1))) {
212                     // Check for rounding up; are we closer to the value we'd round off to than
213                     // the next IEEE value would be?
214                     if (fraction.sumGreaterThanOne(halfDeltaNext)) {
215                         needsRoundingUp = true;
216                         break;
217                     }
218                 } else {
219                     // Check for rounding down; are we closer to the value we'd round off to than
220                     // the prior IEEE value would be?
221                     if (fraction < halfDeltaLast)
222                         break;
223                 }
224
225                 ASSERT(endOfResultString < (buffer + sizeof(buffer) - 1));
226                 // Write a digit to the string.
227                 fraction *= radix;
228                 digit = fraction.floorAndSubtract();
229                 *endOfResultString++ = radixDigits[digit];
230                 // Keep track whether the portion written is currently even, if the radix is odd.
231                 if (digit & 1)
232                     isOddInOddRadix = !isOddInOddRadix;
233
234                 // Shift the fractions by radix.
235                 halfDeltaNext *= radix;
236                 halfDeltaLast *= radix;
237             }
238         } else {
239             // This code is identical to that above, except since deltaNextDouble != deltaLastDouble
240             // we don't need to track these two values separately.
241             Uint16WithFraction halfDelta(deltaNextDouble, 1);
242
243             while (true) {
244                 int dComparePoint5 = fraction.comparePoint5();
245                 if (dComparePoint5 > 0 || (!dComparePoint5 && (radix & 1 ? isOddInOddRadix : digit & 1))) {
246                     if (fraction.sumGreaterThanOne(halfDelta)) {
247                         needsRoundingUp = true;
248                         break;
249                     }
250                 } else if (fraction < halfDelta)
251                     break;
252
253                 ASSERT(endOfResultString < (buffer + sizeof(buffer) - 1));
254                 fraction *= radix;
255                 digit = fraction.floorAndSubtract();
256                 if (digit & 1)
257                     isOddInOddRadix = !isOddInOddRadix;
258                 *endOfResultString++ = radixDigits[digit];
259
260                 halfDelta *= radix;
261             }
262         }
263
264         // Check if the fraction needs rounding off (flag set in the loop writing digits, above).
265         if (needsRoundingUp) {
266             // Whilst the last digit is the maximum in the current radix, remove it.
267             // e.g. rounding up the last digit in "12.3999" is the same as rounding up the
268             // last digit in "12.3" - both round up to "12.4".
269             while (endOfResultString[-1] == radixDigits[radix - 1])
270                 --endOfResultString;
271
272             // Radix digits are sequential in ascii/unicode, except for '9' and 'a'.
273             // E.g. the first 'if' case handles rounding 67.89 to 67.8a in base 16.
274             // The 'else if' case handles rounding of all other digits.
275             if (endOfResultString[-1] == '9')
276                 endOfResultString[-1] = 'a';
277             else if (endOfResultString[-1] != '.')
278                 ++endOfResultString[-1];
279             else {
280                 // One other possibility - there may be no digits to round up in the fraction
281                 // (or all may be been rounded off already), in which case we may need to
282                 // round into the integer portion of the number. Remove the decimal point.
283                 --endOfResultString;
284                 // In order to get here there must have been a non-zero fraction, in which case
285                 // there must be at least one bit of the value's mantissa not in use in the
286                 // integer part of the number. As such, adding to the integer part should not
287                 // be able to lose precision.
288                 ASSERT((integerPart + 1) - integerPart == 1);
289                 ++integerPart;
290             }
291         } else {
292             // We only need to check for trailing zeros if the value does not get rounded up.
293             while (endOfResultString[-1] == '0')
294                 --endOfResultString;
295         }
296
297         *endOfResultString = '\0';
298         ASSERT(endOfResultString < buffer + sizeof(buffer));
299     } else
300         *decimalPoint = '\0';
301
302     BigInteger units(integerPart);
303
304     // Always loop at least once, to emit at least '0'.
305     do {
306         ASSERT(buffer < startOfResultString);
307
308         // Read a single digit and write it to the front of the string.
309         // Divide by radix to remove one digit from the value.
310         digit = units.divide(radix);
311         *--startOfResultString = radixDigits[digit];
312     } while (!!units);
313
314     // If the number is negative, prepend '-'.
315     if (isNegative)
316         *--startOfResultString = '-';
317     ASSERT(buffer <= startOfResultString);
318
319     return startOfResultString;
320 }
321
322 // toExponential converts a number to a string, always formatting as an expoential.
323 // This method takes an optional argument specifying a number of *decimal places*
324 // to round the significand to (or, put another way, this method optionally rounds
325 // to argument-plus-one significant figures).
326 EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec)
327 {
328     // Get x (the double value of this, which should be a Number).
329     double x;
330     if (!toThisNumber(exec->hostThisValue(), x))
331         return throwVMTypeError(exec);
332
333     // Get the argument. 
334     int decimalPlacesInExponent;
335     bool isUndefined;
336     if (!getIntegerArgumentInRange(exec, 0, 20, decimalPlacesInExponent, isUndefined))
337         return throwVMError(exec, createRangeError(exec, "toExponential() argument must be between 0 and 20"));
338
339     // Handle NaN and Infinity.
340     if (!isfinite(x))
341         return JSValue::encode(jsString(exec, UString::number(x)));
342
343     // Round if the argument is not undefined, always format as exponential.
344     char buffer[WTF::NumberToStringBufferLength];
345     StringBuilder builder(buffer, WTF::NumberToStringBufferLength);
346     const DoubleToStringConverter& converter = DoubleToStringConverter::EcmaScriptConverter();
347     builder.Reset();
348     isUndefined
349         ? converter.ToExponential(x, -1, &builder)
350         : converter.ToExponential(x, decimalPlacesInExponent, &builder);
351     return JSValue::encode(jsString(exec, UString(builder.Finalize())));
352 }
353
354 // toFixed converts a number to a string, always formatting as an a decimal fraction.
355 // This method takes an argument specifying a number of decimal places to round the
356 // significand to. However when converting large values (1e+21 and above) this
357 // method will instead fallback to calling ToString. 
358 EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
359 {
360     // Get x (the double value of this, which should be a Number).
361     JSValue thisValue = exec->hostThisValue();
362     JSValue v = thisValue.getJSNumber();
363     if (!v)
364         return throwVMTypeError(exec);
365     double x = v.uncheckedGetNumber();
366
367     // Get the argument. 
368     int decimalPlaces;
369     bool isUndefined; // This is ignored; undefined treated as 0.
370     if (!getIntegerArgumentInRange(exec, 0, 20, decimalPlaces, isUndefined))
371         return throwVMError(exec, createRangeError(exec, "toFixed() argument must be between 0 and 20"));
372
373     // 15.7.4.5.7 states "If x >= 10^21, then let m = ToString(x)"
374     // This also covers Ininity, and structure the check so that NaN
375     // values are also handled by numberToString
376     if (!(fabs(x) < 1e+21))
377         return JSValue::encode(jsString(exec, UString::number(x)));
378
379     // The check above will return false for NaN or Infinity, these will be
380     // handled by numberToString.
381     ASSERT(isfinite(x));
382
383     char buffer[WTF::NumberToStringBufferLength];
384     StringBuilder builder(buffer, WTF::NumberToStringBufferLength);
385     const DoubleToStringConverter& converter = DoubleToStringConverter::EcmaScriptConverter();
386     builder.Reset();
387     converter.ToFixed(x, decimalPlaces, &builder);
388     return JSValue::encode(jsString(exec, UString(builder.Finalize())));
389 }
390
391 // toPrecision converts a number to a string, takeing an argument specifying a
392 // number of significant figures to round the significand to. For positive
393 // exponent, all values that can be represented using a decimal fraction will
394 // be, e.g. when rounding to 3 s.f. any value up to 999 will be formated as a
395 // decimal, whilst 1000 is converted to the exponential representation 1.00e+3.
396 // For negative exponents values >= 1e-6 are formated as decimal fractions,
397 // with smaller values converted to exponential representation.
398 EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec)
399 {
400     // Get x (the double value of this, which should be a Number).
401     JSValue thisValue = exec->hostThisValue();
402     JSValue v = thisValue.getJSNumber();
403     if (!v)
404         return throwVMTypeError(exec);
405     double x = v.uncheckedGetNumber();
406
407     // Get the argument. 
408     int significantFigures;
409     bool isUndefined;
410     if (!getIntegerArgumentInRange(exec, 1, 21, significantFigures, isUndefined))
411         return throwVMError(exec, createRangeError(exec, "toPrecision() argument must be between 1 and 21"));
412
413     // To precision called with no argument is treated as ToString.
414     if (isUndefined)
415         return JSValue::encode(jsString(exec, UString::number(x)));
416
417     // Handle NaN and Infinity.
418     if (!isfinite(x))
419         return JSValue::encode(jsString(exec, UString::number(x)));
420
421     char buffer[WTF::NumberToStringBufferLength];
422     StringBuilder builder(buffer, WTF::NumberToStringBufferLength);
423     const DoubleToStringConverter& converter = DoubleToStringConverter::EcmaScriptConverter();
424     builder.Reset();
425     converter.ToPrecision(x, significantFigures, &builder);
426     return JSValue::encode(jsString(exec, UString(builder.Finalize())));
427 }
428
429 EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
430 {
431     JSValue thisValue = exec->hostThisValue();
432     JSValue v = thisValue.getJSNumber();
433     if (!v)
434         return throwVMTypeError(exec);
435
436     JSValue radixValue = exec->argument(0);
437     int radix;
438     if (radixValue.isInt32())
439         radix = radixValue.asInt32();
440     else if (radixValue.isUndefined())
441         radix = 10;
442     else
443         radix = static_cast<int>(radixValue.toInteger(exec)); // nan -> 0
444
445     if (radix == 10)
446         return JSValue::encode(jsString(exec, v.toString(exec)));
447
448     // Fast path for number to character conversion.
449     if (radix == 36) {
450         if (v.isInt32()) {
451             int x = v.asInt32();
452             if (static_cast<unsigned>(x) < 36) { // Exclude negatives
453                 JSGlobalData* globalData = &exec->globalData();
454                 return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, radixDigits[x]));
455             }
456         }
457     }
458
459     if (radix < 2 || radix > 36)
460         return throwVMError(exec, createRangeError(exec, "toString() radix argument must be between 2 and 36"));
461
462     double x = v.uncheckedGetNumber();
463     if (!isfinite(x))
464         return JSValue::encode(jsString(exec, UString::number(x)));
465
466     RadixBuffer s;
467     return JSValue::encode(jsString(exec, toStringWithRadix(s, x, radix)));
468 }
469
470 EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec)
471 {
472     JSValue thisValue = exec->hostThisValue();
473     // FIXME: Not implemented yet.
474
475     JSValue v = thisValue.getJSNumber();
476     if (!v)
477         return throwVMTypeError(exec);
478
479     return JSValue::encode(jsString(exec, v.toString(exec)));
480 }
481
482 EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec)
483 {
484     JSValue thisValue = exec->hostThisValue();
485     JSValue v = thisValue.getJSNumber();
486     if (!v)
487         return throwVMTypeError(exec);
488
489     return JSValue::encode(v);
490 }
491
492 } // namespace JSC