18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h> 29589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include <math.h> 306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include <limits.h> 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "conversions-inl.h" 3325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#include "dtoa.h" 34f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "strtod.h" 353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "utils.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochdouble StringToDouble(UnicodeCache* unicode_cache, 428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const char* str, int flags, double empty_string_val) { 436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const char* end = str + StrLength(str); 448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return InternalStringToDouble(unicode_cache, str, end, flags, 4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block empty_string_val); 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochdouble StringToDouble(UnicodeCache* unicode_cache, 508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Vector<const char> str, 5180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen int flags, 5280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen double empty_string_val) { 5380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen const char* end = str.start() + str.length(); 548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return InternalStringToDouble(unicode_cache, str.start(), end, flags, 5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block empty_string_val); 5680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 5780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 58257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochdouble StringToDouble(UnicodeCache* unicode_cache, 59257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Vector<const uc16> str, 60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int flags, 61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch double empty_string_val) { 62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const uc16* end = str.start() + str.length(); 63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return InternalStringToDouble(unicode_cache, str.start(), end, flags, 64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch empty_string_val); 65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* DoubleToCString(double v, Vector<char> buffer) { 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (fpclassify(v)) { 701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case FP_NAN: return "NaN"; 711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity"); 721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case FP_ZERO: return "0"; 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: { 743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SimpleStringBuilder builder(buffer.start(), buffer.length()); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int decimal_point; 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int sign; 7725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1; 788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang char decimal_rep[kV8DtoaBufferCapacity]; 796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int length; 8025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang DoubleToAscii(v, DTOA_SHORTEST, 0, 828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang &sign, &length, &decimal_point); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (sign) builder.AddCharacter('-'); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (length <= decimal_point && decimal_point <= 21) { 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ECMA-262 section 9.8.1 step 6. 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddString(decimal_rep); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddPadding('0', decimal_point - length); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (0 < decimal_point && decimal_point <= 21) { 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ECMA-262 section 9.8.1 step 7. 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddSubstring(decimal_rep, decimal_point); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter('.'); 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddString(decimal_rep + decimal_point); 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (decimal_point <= 0 && decimal_point > -6) { 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ECMA-262 section 9.8.1 step 8. 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddString("0."); 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddPadding('0', -decimal_point); 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddString(decimal_rep); 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ECMA-262 section 9.8.1 step 9 and 10 combined. 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter(decimal_rep[0]); 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (length != 1) { 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter('.'); 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddString(decimal_rep + 1); 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter('e'); 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter((decimal_point >= 0) ? '+' : '-'); 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int exponent = decimal_point - 1; 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (exponent < 0) exponent = -exponent; 1153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch builder.AddDecimalInteger(exponent); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return builder.Finalize(); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* IntToCString(int n, Vector<char> buffer) { 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool negative = false; 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (n < 0) { 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We must not negate the most negative int. 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (n == kMinInt) return DoubleToCString(n, buffer); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block negative = true; 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block n = -n; 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Build the string backwards from the least significant digit. 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int i = buffer.length(); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[--i] = '\0'; 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[--i] = '0' + (n % 10); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block n /= 10; 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } while (n); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (negative) buffer[--i] = '-'; 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return buffer.start() + i; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToFixedCString(double value, int f) { 1443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu const int kMaxDigitsBeforePoint = 21; 14525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen const double kFirstNonFixed = 1e21; 14625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen const int kMaxDigitsAfterPoint = 20; 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(f >= 0); 14825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ASSERT(f <= kMaxDigitsAfterPoint); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool negative = false; 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block double abs_value = value; 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value < 0) { 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abs_value = -value; 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block negative = true; 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // If abs_value has more than kMaxDigitsBeforePoint digits before the point 15825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // use the non-fixed conversion routine. 15925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (abs_value >= kFirstNonFixed) { 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char arr[100]; 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Vector<char> buffer(arr, ARRAY_SIZE(arr)); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return StrDup(DoubleToCString(value, buffer)); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find a sufficiently precise decimal representation of n. 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int decimal_point; 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int sign; 1683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Add space for the '\0' byte. 16925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen const int kDecimalRepCapacity = 1703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1; 17125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen char decimal_rep[kDecimalRepCapacity]; 17225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int decimal_rep_length; 1738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang DoubleToAscii(value, DTOA_FIXED, f, 1748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Vector<char>(decimal_rep, kDecimalRepCapacity), 1758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang &sign, &decimal_rep_length, &decimal_point); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create a representation that is padded with zeros if needed. 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int zero_prefix_length = 0; 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int zero_postfix_length = 0; 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (decimal_point <= 0) { 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block zero_prefix_length = -decimal_point + 1; 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decimal_point = 1; 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (zero_prefix_length + decimal_rep_length < decimal_point + f) { 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block zero_postfix_length = decimal_point + f - decimal_rep_length - 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block zero_prefix_length; 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned rep_length = 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block zero_prefix_length + decimal_rep_length + zero_postfix_length; 1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SimpleStringBuilder rep_builder(rep_length + 1); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rep_builder.AddPadding('0', zero_prefix_length); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rep_builder.AddString(decimal_rep); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rep_builder.AddPadding('0', zero_postfix_length); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* rep = rep_builder.Finalize(); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create the result string by appending a minus and putting in a 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // decimal point if needed. 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned result_size = decimal_point + f + 2; 2023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SimpleStringBuilder builder(result_size + 1); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (negative) builder.AddCharacter('-'); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddSubstring(rep, decimal_point); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f > 0) { 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter('.'); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddSubstring(rep + decimal_point, f); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DeleteArray(rep); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return builder.Finalize(); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic char* CreateExponentialRepresentation(char* decimal_rep, 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int exponent, 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool negative, 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int significant_digits) { 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool negative_exponent = false; 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (exponent < 0) { 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block negative_exponent = true; 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exponent = -exponent; 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave room in the result for appending a minus, for a period, the 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // letter 'e', a minus or a plus depending on the exponent, and a 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // three digit exponent. 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned result_size = significant_digits + 7; 2283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SimpleStringBuilder builder(result_size + 1); 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (negative) builder.AddCharacter('-'); 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter(decimal_rep[0]); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (significant_digits != 1) { 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter('.'); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddString(decimal_rep + 1); 235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int rep_length = StrLength(decimal_rep); 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block builder.AddPadding('0', significant_digits - rep_length); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter('e'); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter(negative_exponent ? '-' : '+'); 2413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch builder.AddDecimalInteger(exponent); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return builder.Finalize(); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToExponentialCString(double value, int f) { 2480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const int kMaxDigitsAfterPoint = 20; 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // f might be -1 to signal that f was undefined in JavaScript. 2500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool negative = false; 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value < 0) { 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = -value; 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block negative = true; 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find a sufficiently precise decimal representation of n. 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int decimal_point; 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int sign; 2610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // f corresponds to the digits after the point. There is always one digit 2620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // before the point. The number of requested_digits equals hence f + 1. 2630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // And we have to add one character for the null-terminator. 2640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1; 2650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Make sure that the buffer is big enough, even if we fall back to the 2660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // shortest representation (which happens when f equals -1). 2670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1); 2688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang char decimal_rep[kV8DtoaBufferCapacity]; 2690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int decimal_rep_length; 2700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f == -1) { 2728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang DoubleToAscii(value, DTOA_SHORTEST, 0, 2738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 2748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang &sign, &decimal_rep_length, &decimal_point); 2758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang f = decimal_rep_length - 1; 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang DoubleToAscii(value, DTOA_PRECISION, f + 1, 2788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 2798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang &sign, &decimal_rep_length, &decimal_point); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(decimal_rep_length > 0); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(decimal_rep_length <= f + 1); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int exponent = decimal_point - 1; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* result = 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToPrecisionCString(double value, int p) { 2930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const int kMinimalDigits = 1; 2940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const int kMaximalDigits = 21; 2950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(p >= kMinimalDigits && p <= kMaximalDigits); 2960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen USE(kMinimalDigits); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool negative = false; 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value < 0) { 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = -value; 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block negative = true; 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find a sufficiently precise decimal representation of n. 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int decimal_point; 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int sign; 3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Add one for the terminating null character. 3080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const int kV8DtoaBufferCapacity = kMaximalDigits + 1; 3098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang char decimal_rep[kV8DtoaBufferCapacity]; 3100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int decimal_rep_length; 3110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang DoubleToAscii(value, DTOA_PRECISION, p, 3138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 3148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang &sign, &decimal_rep_length, &decimal_point); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(decimal_rep_length <= p); 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int exponent = decimal_point - 1; 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* result = NULL; 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (exponent < -6 || exponent >= p) { 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CreateExponentialRepresentation(decimal_rep, exponent, negative, p); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use fixed notation. 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave room in the result for appending a minus, a period and in 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the case where decimal_point is not positive for a zero in 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // front of the period. 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned result_size = (decimal_point <= 0) 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ? -decimal_point + p + 3 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : p + 2; 3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SimpleStringBuilder builder(result_size + 1); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (negative) builder.AddCharacter('-'); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (decimal_point <= 0) { 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddString("0."); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddPadding('0', -decimal_point); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddString(decimal_rep); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddPadding('0', p - decimal_rep_length); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int m = Min(decimal_rep_length, decimal_point); 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddSubstring(decimal_rep, m); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddPadding('0', decimal_point - decimal_rep_length); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (decimal_point < p) { 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddCharacter('.'); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int extra = negative ? 2 : 1; 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (decimal_rep_length > decimal_point) { 348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const int len = StrLength(decimal_rep + decimal_point); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int n = Min(len, p - (builder.position() - extra)); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddSubstring(decimal_rep + decimal_point, n); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddPadding('0', extra + (p - builder.position())); 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = builder.Finalize(); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToRadixCString(double value, int radix) { 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(radix >= 2 && radix <= 36); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Character array used for conversion. 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Buffer for the integer part of the result. 1024 chars is enough 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for max integer value in radix 2. We need room for a sign too. 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kBufferSize = 1100; 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char integer_buffer[kBufferSize]; 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block integer_buffer[kBufferSize - 1] = '\0'; 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Buffer for the decimal part of the result. We only generate up 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to kBufferSize - 1 chars for the decimal part. 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char decimal_buffer[kBufferSize]; 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decimal_buffer[kBufferSize - 1] = '\0'; 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the value is positive. 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_negative = value < 0.0; 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_negative) value = -value; 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the integer part and the decimal part. 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block double integer_part = floor(value); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block double decimal_part = value - integer_part; 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the integer part starting from the back. Always generate 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // at least one digit. 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int integer_pos = kBufferSize - 2; 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block integer_buffer[integer_pos--] = 392589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch chars[static_cast<int>(fmod(integer_part, radix))]; 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block integer_part /= radix; 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } while (integer_part >= 1.0); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Sanity check. 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(integer_pos > 0); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Add sign if needed. 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_negative) integer_buffer[integer_pos--] = '-'; 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the decimal part. Repeatedly multiply by the radix to 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // generate the next char. Never generate more than kBufferSize - 1 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // chars. 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1093998): We will often generate a full decimal_buffer of 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // chars because hitting zero will often not happen. The right 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // solution would be to continue until the string representation can 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // be read back and yield the original value. To implement this 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // efficiently, we probably have to modify dtoa. 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int decimal_pos = 0; 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) { 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decimal_part *= radix; 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decimal_buffer[decimal_pos++] = 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block chars[static_cast<int>(floor(decimal_part))]; 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decimal_part -= floor(decimal_part); 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block decimal_buffer[decimal_pos] = '\0'; 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the result size. 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int integer_part_size = kBufferSize - 2 - integer_pos; 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make room for zero termination. 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned result_size = integer_part_size + decimal_pos; 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the number has a decimal part, leave room for the period. 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (decimal_pos > 0) result_size++; 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate result and fill in the parts. 4253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SimpleStringBuilder builder(result_size + 1); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (decimal_pos > 0) builder.AddCharacter('.'); 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builder.AddSubstring(decimal_buffer, decimal_pos); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return builder.Finalize(); 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 433