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