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