1a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch/* 2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2010 Apple Inc. All rights reserved. 3a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 4a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Redistribution and use in source and binary forms, with or without 5a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * modification, are permitted provided that the following conditions 6a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * are met: 7a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 1. Redistributions of source code must retain the above copyright 8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * notice, this list of conditions and the following disclaimer. 9a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright 10a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * notice, this list of conditions and the following disclaimer in the 11a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * documentation and/or other materials provided with the distribution. 12a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch */ 25a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 26a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "config.h" 27a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "DecimalNumber.h" 28a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include <math.h> 29a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include <wtf/MathExtras.h> 30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include <wtf/text/WTFString.h> 31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 32a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochnamespace WTF { 33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochunsigned DecimalNumber::bufferLengthForStringDecimal() const 35a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 36a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned length = 0; 37a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // if the exponent is negative the number decimal representation is of the form: 38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // [<sign>]0.[<zeros>]<significand> 39a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_exponent < 0) { 40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_sign) 41a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; 42a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += 2; // for "0." 43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += -m_exponent - 1; 44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += m_precision; 45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return length; 46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned digitsBeforeDecimalPoint = m_exponent + 1; 49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // If the precision is <= than the number of digits to get up to the decimal 51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // point, then there is no fractional part, number is of the form: 52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // [<sign>]<significand>[<zeros>] 53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_precision <= digitsBeforeDecimalPoint) { 54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_sign) 55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; 56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += m_precision; 57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += digitsBeforeDecimalPoint - m_precision; 58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return length; 59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // If we get here, number starts before the decimal point, and ends after it, 62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // as such is of the form: 63a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // [<sign>]<significand-begin>.<significand-end> 64a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_sign) 65a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; 66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += digitsBeforeDecimalPoint; 67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; // for decimal point 68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += m_precision - digitsBeforeDecimalPoint; 69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return length; 71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochunsigned DecimalNumber::bufferLengthForStringExponential() const 74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 75a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned length = 0; 76a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_sign) 77a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; 78a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 79a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Add the significand 80a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; 81a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 82a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_precision > 1) { 83a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; // for decimal point 84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += m_precision - 1; 85a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 86a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Add "e+" or "e-" 88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += 2; 89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch int exponent = (m_exponent >= 0) ? m_exponent : -m_exponent; 91a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 92a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Add the exponent 93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (exponent >= 100) 94a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; 95a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (exponent >= 10) 96a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; 97a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ++length; 98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return length; 100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 101a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 102a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochunsigned DecimalNumber::toStringDecimal(UChar* buffer, unsigned bufferLength) const 103a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 104a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringDecimal()); 105a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 106a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Should always be at least one digit to add to the string! 107a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(m_precision); 108a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch UChar* next = buffer; 109a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 110a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // if the exponent is negative the number decimal representation is of the form: 111a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // [<sign>]0.[<zeros>]<significand> 112a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_exponent < 0) { 113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned zeros = -m_exponent - 1; 114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 115a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_sign) 116a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '-'; 117a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '0'; 118a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '.'; 119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = 0; i < zeros; ++i) 120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '0'; 121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = 0; i < m_precision; ++i) 122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = m_significand[i]; 123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return next - buffer; 125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 126a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 127a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned digitsBeforeDecimalPoint = m_exponent + 1; 128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // If the precision is <= than the number of digits to get up to the decimal 130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // point, then there is no fractional part, number is of the form: 131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // [<sign>]<significand>[<zeros>] 132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_precision <= digitsBeforeDecimalPoint) { 133a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_sign) 134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '-'; 135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = 0; i < m_precision; ++i) 136a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = m_significand[i]; 137a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = 0; i < (digitsBeforeDecimalPoint - m_precision); ++i) 138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '0'; 139a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return next - buffer; 141a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 142a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 143a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // If we get here, number starts before the decimal point, and ends after it, 144a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // as such is of the form: 145a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // [<sign>]<significand-begin>.<significand-end> 146a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 147a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_sign) 148a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '-'; 149a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = 0; i < digitsBeforeDecimalPoint; ++i) 150a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = m_significand[i]; 151a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '.'; 152a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = digitsBeforeDecimalPoint; i < m_precision; ++i) 153a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = m_significand[i]; 154a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 155a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return next - buffer; 156a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 157a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 158a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochunsigned DecimalNumber::toStringExponential(UChar* buffer, unsigned bufferLength) const 159a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 160a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringExponential()); 161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 162a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Should always be at least one digit to add to the string! 163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(m_precision); 164a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch UChar* next = buffer; 165a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Add the sign 167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_sign) 168a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '-'; 169a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Add the significand 171a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = m_significand[0]; 172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_precision > 1) { 173a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '.'; 174a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = 1; i < m_precision; ++i) 175a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = m_significand[i]; 176a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 177a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 178a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Add "e+" or "e-" 179a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = 'e'; 180a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch int exponent; 181a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_exponent >= 0) { 182a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '+'; 183a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch exponent = m_exponent; 184a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } else { 185a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '-'; 186a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch exponent = -m_exponent; 187a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 188a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 189a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Add the exponent 190a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (exponent >= 100) 191a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '0' + exponent / 100; 192a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (exponent >= 10) 193a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '0' + (exponent % 100) / 10; 194a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *next++ = '0' + exponent % 10; 195a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 196a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return next - buffer; 197a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 198a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 199a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} // namespace WTF 200