1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mfbt/decimal/Decimal.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1056 @@ 1.4 +/* 1.5 + * Copyright (C) 2012 Google Inc. All rights reserved. 1.6 + * 1.7 + * Redistribution and use in source and binary forms, with or without 1.8 + * modification, are permitted provided that the following conditions are 1.9 + * met: 1.10 + * 1.11 + * * Redistributions of source code must retain the above copyright 1.12 + * notice, this list of conditions and the following disclaimer. 1.13 + * * Redistributions in binary form must reproduce the above 1.14 + * copyright notice, this list of conditions and the following disclaimer 1.15 + * in the documentation and/or other materials provided with the 1.16 + * distribution. 1.17 + * * Neither the name of Google Inc. nor the names of its 1.18 + * contributors may be used to endorse or promote products derived from 1.19 + * this software without specific prior written permission. 1.20 + * 1.21 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + */ 1.33 + 1.34 +#include "Decimal.h" 1.35 +#include "moz-decimal-utils.h" 1.36 + 1.37 +#include <algorithm> 1.38 +#include <float.h> 1.39 + 1.40 +using namespace moz_decimal_utils; 1.41 + 1.42 +namespace WebCore { 1.43 + 1.44 +namespace DecimalPrivate { 1.45 + 1.46 +static int const ExponentMax = 1023; 1.47 +static int const ExponentMin = -1023; 1.48 +static int const Precision = 18; 1.49 + 1.50 +static const uint64_t MaxCoefficient = UINT64_C(0x16345785D89FFFF); // 999999999999999999 == 18 9's 1.51 + 1.52 +// This class handles Decimal special values. 1.53 +class SpecialValueHandler { 1.54 + WTF_MAKE_NONCOPYABLE(SpecialValueHandler); 1.55 +public: 1.56 + enum HandleResult { 1.57 + BothFinite, 1.58 + BothInfinity, 1.59 + EitherNaN, 1.60 + LHSIsInfinity, 1.61 + RHSIsInfinity, 1.62 + }; 1.63 + 1.64 + SpecialValueHandler(const Decimal& lhs, const Decimal& rhs); 1.65 + HandleResult handle(); 1.66 + Decimal value() const; 1.67 + 1.68 +private: 1.69 + enum Result { 1.70 + ResultIsLHS, 1.71 + ResultIsRHS, 1.72 + ResultIsUnknown, 1.73 + }; 1.74 + 1.75 + const Decimal& m_lhs; 1.76 + const Decimal& m_rhs; 1.77 + Result m_result; 1.78 +}; 1.79 + 1.80 +SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs) 1.81 + : m_lhs(lhs), m_rhs(rhs), m_result(ResultIsUnknown) 1.82 +{ 1.83 +} 1.84 + 1.85 +SpecialValueHandler::HandleResult SpecialValueHandler::handle() 1.86 +{ 1.87 + if (m_lhs.isFinite() && m_rhs.isFinite()) 1.88 + return BothFinite; 1.89 + 1.90 + const Decimal::EncodedData::FormatClass lhsClass = m_lhs.value().formatClass(); 1.91 + const Decimal::EncodedData::FormatClass rhsClass = m_rhs.value().formatClass(); 1.92 + if (lhsClass == Decimal::EncodedData::ClassNaN) { 1.93 + m_result = ResultIsLHS; 1.94 + return EitherNaN; 1.95 + } 1.96 + 1.97 + if (rhsClass == Decimal::EncodedData::ClassNaN) { 1.98 + m_result = ResultIsRHS; 1.99 + return EitherNaN; 1.100 + } 1.101 + 1.102 + if (lhsClass == Decimal::EncodedData::ClassInfinity) 1.103 + return rhsClass == Decimal::EncodedData::ClassInfinity ? BothInfinity : LHSIsInfinity; 1.104 + 1.105 + if (rhsClass == Decimal::EncodedData::ClassInfinity) 1.106 + return RHSIsInfinity; 1.107 + 1.108 + ASSERT_NOT_REACHED(); 1.109 + return BothFinite; 1.110 +} 1.111 + 1.112 +Decimal SpecialValueHandler::value() const 1.113 +{ 1.114 + switch (m_result) { 1.115 + case ResultIsLHS: 1.116 + return m_lhs; 1.117 + case ResultIsRHS: 1.118 + return m_rhs; 1.119 + case ResultIsUnknown: 1.120 + default: 1.121 + ASSERT_NOT_REACHED(); 1.122 + return m_lhs; 1.123 + } 1.124 +} 1.125 + 1.126 +// This class is used for 128 bit unsigned integer arithmetic. 1.127 +class UInt128 { 1.128 +public: 1.129 + UInt128(uint64_t low, uint64_t high) 1.130 + : m_high(high), m_low(low) 1.131 + { 1.132 + } 1.133 + 1.134 + UInt128& operator/=(uint32_t); 1.135 + 1.136 + uint64_t high() const { return m_high; } 1.137 + uint64_t low() const { return m_low; } 1.138 + 1.139 + static UInt128 multiply(uint64_t u, uint64_t v) { return UInt128(u * v, multiplyHigh(u, v)); } 1.140 + 1.141 +private: 1.142 + static uint32_t highUInt32(uint64_t x) { return static_cast<uint32_t>(x >> 32); } 1.143 + static uint32_t lowUInt32(uint64_t x) { return static_cast<uint32_t>(x & ((static_cast<uint64_t>(1) << 32) - 1)); } 1.144 + bool isZero() const { return !m_low && !m_high; } 1.145 + static uint64_t makeUInt64(uint32_t low, uint32_t high) { return low | (static_cast<uint64_t>(high) << 32); } 1.146 + 1.147 + static uint64_t multiplyHigh(uint64_t, uint64_t); 1.148 + 1.149 + uint64_t m_high; 1.150 + uint64_t m_low; 1.151 +}; 1.152 + 1.153 +UInt128& UInt128::operator/=(const uint32_t divisor) 1.154 +{ 1.155 + ASSERT(divisor); 1.156 + 1.157 + if (!m_high) { 1.158 + m_low /= divisor; 1.159 + return *this; 1.160 + } 1.161 + 1.162 + uint32_t dividend[4]; 1.163 + dividend[0] = lowUInt32(m_low); 1.164 + dividend[1] = highUInt32(m_low); 1.165 + dividend[2] = lowUInt32(m_high); 1.166 + dividend[3] = highUInt32(m_high); 1.167 + 1.168 + uint32_t quotient[4]; 1.169 + uint32_t remainder = 0; 1.170 + for (int i = 3; i >= 0; --i) { 1.171 + const uint64_t work = makeUInt64(dividend[i], remainder); 1.172 + remainder = static_cast<uint32_t>(work % divisor); 1.173 + quotient[i] = static_cast<uint32_t>(work / divisor); 1.174 + } 1.175 + m_low = makeUInt64(quotient[0], quotient[1]); 1.176 + m_high = makeUInt64(quotient[2], quotient[3]); 1.177 + return *this; 1.178 +} 1.179 + 1.180 +// Returns high 64bit of 128bit product. 1.181 +uint64_t UInt128::multiplyHigh(uint64_t u, uint64_t v) 1.182 +{ 1.183 + const uint64_t uLow = lowUInt32(u); 1.184 + const uint64_t uHigh = highUInt32(u); 1.185 + const uint64_t vLow = lowUInt32(v); 1.186 + const uint64_t vHigh = highUInt32(v); 1.187 + const uint64_t partialProduct = uHigh * vLow + highUInt32(uLow * vLow); 1.188 + return uHigh * vHigh + highUInt32(partialProduct) + highUInt32(uLow * vHigh + lowUInt32(partialProduct)); 1.189 +} 1.190 + 1.191 +static int countDigits(uint64_t x) 1.192 +{ 1.193 + int numberOfDigits = 0; 1.194 + for (uint64_t powerOfTen = 1; x >= powerOfTen; powerOfTen *= 10) { 1.195 + ++numberOfDigits; 1.196 + if (powerOfTen >= std::numeric_limits<uint64_t>::max() / 10) 1.197 + break; 1.198 + } 1.199 + return numberOfDigits; 1.200 +} 1.201 + 1.202 +static uint64_t scaleDown(uint64_t x, int n) 1.203 +{ 1.204 + ASSERT(n >= 0); 1.205 + while (n > 0 && x) { 1.206 + x /= 10; 1.207 + --n; 1.208 + } 1.209 + return x; 1.210 +} 1.211 + 1.212 +static uint64_t scaleUp(uint64_t x, int n) 1.213 +{ 1.214 + ASSERT(n >= 0); 1.215 + ASSERT(n < Precision); 1.216 + 1.217 + uint64_t y = 1; 1.218 + uint64_t z = 10; 1.219 + for (;;) { 1.220 + if (n & 1) 1.221 + y = y * z; 1.222 + 1.223 + n >>= 1; 1.224 + if (!n) 1.225 + return x * y; 1.226 + 1.227 + z = z * z; 1.228 + } 1.229 +} 1.230 + 1.231 +} // namespace DecimalPrivate 1.232 + 1.233 +using namespace DecimalPrivate; 1.234 + 1.235 +Decimal::EncodedData::EncodedData(Sign sign, FormatClass formatClass) 1.236 + : m_coefficient(0) 1.237 + , m_exponent(0) 1.238 + , m_formatClass(formatClass) 1.239 + , m_sign(sign) 1.240 +{ 1.241 +} 1.242 + 1.243 +Decimal::EncodedData::EncodedData(Sign sign, int exponent, uint64_t coefficient) 1.244 + : m_formatClass(coefficient ? ClassNormal : ClassZero) 1.245 + , m_sign(sign) 1.246 +{ 1.247 + if (exponent >= ExponentMin && exponent <= ExponentMax) { 1.248 + while (coefficient > MaxCoefficient) { 1.249 + coefficient /= 10; 1.250 + ++exponent; 1.251 + } 1.252 + } 1.253 + 1.254 + if (exponent > ExponentMax) { 1.255 + m_coefficient = 0; 1.256 + m_exponent = 0; 1.257 + m_formatClass = ClassInfinity; 1.258 + return; 1.259 + } 1.260 + 1.261 + if (exponent < ExponentMin) { 1.262 + m_coefficient = 0; 1.263 + m_exponent = 0; 1.264 + m_formatClass = ClassZero; 1.265 + return; 1.266 + } 1.267 + 1.268 + m_coefficient = coefficient; 1.269 + m_exponent = static_cast<int16_t>(exponent); 1.270 +} 1.271 + 1.272 +bool Decimal::EncodedData::operator==(const EncodedData& another) const 1.273 +{ 1.274 + return m_sign == another.m_sign 1.275 + && m_formatClass == another.m_formatClass 1.276 + && m_exponent == another.m_exponent 1.277 + && m_coefficient == another.m_coefficient; 1.278 +} 1.279 + 1.280 +Decimal::Decimal(int32_t i32) 1.281 + : m_data(i32 < 0 ? Negative : Positive, 0, i32 < 0 ? static_cast<uint64_t>(-static_cast<int64_t>(i32)) : static_cast<uint64_t>(i32)) 1.282 +{ 1.283 +} 1.284 + 1.285 +Decimal::Decimal(Sign sign, int exponent, uint64_t coefficient) 1.286 + : m_data(sign, coefficient ? exponent : 0, coefficient) 1.287 +{ 1.288 +} 1.289 + 1.290 +Decimal::Decimal(const EncodedData& data) 1.291 + : m_data(data) 1.292 +{ 1.293 +} 1.294 + 1.295 +Decimal::Decimal(const Decimal& other) 1.296 + : m_data(other.m_data) 1.297 +{ 1.298 +} 1.299 + 1.300 +Decimal& Decimal::operator=(const Decimal& other) 1.301 +{ 1.302 + m_data = other.m_data; 1.303 + return *this; 1.304 +} 1.305 + 1.306 +Decimal& Decimal::operator+=(const Decimal& other) 1.307 +{ 1.308 + m_data = (*this + other).m_data; 1.309 + return *this; 1.310 +} 1.311 + 1.312 +Decimal& Decimal::operator-=(const Decimal& other) 1.313 +{ 1.314 + m_data = (*this - other).m_data; 1.315 + return *this; 1.316 +} 1.317 + 1.318 +Decimal& Decimal::operator*=(const Decimal& other) 1.319 +{ 1.320 + m_data = (*this * other).m_data; 1.321 + return *this; 1.322 +} 1.323 + 1.324 +Decimal& Decimal::operator/=(const Decimal& other) 1.325 +{ 1.326 + m_data = (*this / other).m_data; 1.327 + return *this; 1.328 +} 1.329 + 1.330 +Decimal Decimal::operator-() const 1.331 +{ 1.332 + if (isNaN()) 1.333 + return *this; 1.334 + 1.335 + Decimal result(*this); 1.336 + result.m_data.setSign(invertSign(m_data.sign())); 1.337 + return result; 1.338 +} 1.339 + 1.340 +Decimal Decimal::operator+(const Decimal& rhs) const 1.341 +{ 1.342 + const Decimal& lhs = *this; 1.343 + const Sign lhsSign = lhs.sign(); 1.344 + const Sign rhsSign = rhs.sign(); 1.345 + 1.346 + SpecialValueHandler handler(lhs, rhs); 1.347 + switch (handler.handle()) { 1.348 + case SpecialValueHandler::BothFinite: 1.349 + break; 1.350 + 1.351 + case SpecialValueHandler::BothInfinity: 1.352 + return lhsSign == rhsSign ? lhs : nan(); 1.353 + 1.354 + case SpecialValueHandler::EitherNaN: 1.355 + return handler.value(); 1.356 + 1.357 + case SpecialValueHandler::LHSIsInfinity: 1.358 + return lhs; 1.359 + 1.360 + case SpecialValueHandler::RHSIsInfinity: 1.361 + return rhs; 1.362 + } 1.363 + 1.364 + const AlignedOperands alignedOperands = alignOperands(lhs, rhs); 1.365 + 1.366 + const uint64_t result = lhsSign == rhsSign 1.367 + ? alignedOperands.lhsCoefficient + alignedOperands.rhsCoefficient 1.368 + : alignedOperands.lhsCoefficient - alignedOperands.rhsCoefficient; 1.369 + 1.370 + if (lhsSign == Negative && rhsSign == Positive && !result) 1.371 + return Decimal(Positive, alignedOperands.exponent, 0); 1.372 + 1.373 + return static_cast<int64_t>(result) >= 0 1.374 + ? Decimal(lhsSign, alignedOperands.exponent, result) 1.375 + : Decimal(invertSign(lhsSign), alignedOperands.exponent, -static_cast<int64_t>(result)); 1.376 +} 1.377 + 1.378 +Decimal Decimal::operator-(const Decimal& rhs) const 1.379 +{ 1.380 + const Decimal& lhs = *this; 1.381 + const Sign lhsSign = lhs.sign(); 1.382 + const Sign rhsSign = rhs.sign(); 1.383 + 1.384 + SpecialValueHandler handler(lhs, rhs); 1.385 + switch (handler.handle()) { 1.386 + case SpecialValueHandler::BothFinite: 1.387 + break; 1.388 + 1.389 + case SpecialValueHandler::BothInfinity: 1.390 + return lhsSign == rhsSign ? nan() : lhs; 1.391 + 1.392 + case SpecialValueHandler::EitherNaN: 1.393 + return handler.value(); 1.394 + 1.395 + case SpecialValueHandler::LHSIsInfinity: 1.396 + return lhs; 1.397 + 1.398 + case SpecialValueHandler::RHSIsInfinity: 1.399 + return infinity(invertSign(rhsSign)); 1.400 + } 1.401 + 1.402 + const AlignedOperands alignedOperands = alignOperands(lhs, rhs); 1.403 + 1.404 + const uint64_t result = lhsSign == rhsSign 1.405 + ? alignedOperands.lhsCoefficient - alignedOperands.rhsCoefficient 1.406 + : alignedOperands.lhsCoefficient + alignedOperands.rhsCoefficient; 1.407 + 1.408 + if (lhsSign == Negative && rhsSign == Negative && !result) 1.409 + return Decimal(Positive, alignedOperands.exponent, 0); 1.410 + 1.411 + return static_cast<int64_t>(result) >= 0 1.412 + ? Decimal(lhsSign, alignedOperands.exponent, result) 1.413 + : Decimal(invertSign(lhsSign), alignedOperands.exponent, -static_cast<int64_t>(result)); 1.414 +} 1.415 + 1.416 +Decimal Decimal::operator*(const Decimal& rhs) const 1.417 +{ 1.418 + const Decimal& lhs = *this; 1.419 + const Sign lhsSign = lhs.sign(); 1.420 + const Sign rhsSign = rhs.sign(); 1.421 + const Sign resultSign = lhsSign == rhsSign ? Positive : Negative; 1.422 + 1.423 + SpecialValueHandler handler(lhs, rhs); 1.424 + switch (handler.handle()) { 1.425 + case SpecialValueHandler::BothFinite: { 1.426 + const uint64_t lhsCoefficient = lhs.m_data.coefficient(); 1.427 + const uint64_t rhsCoefficient = rhs.m_data.coefficient(); 1.428 + int resultExponent = lhs.exponent() + rhs.exponent(); 1.429 + UInt128 work(UInt128::multiply(lhsCoefficient, rhsCoefficient)); 1.430 + while (work.high()) { 1.431 + work /= 10; 1.432 + ++resultExponent; 1.433 + } 1.434 + return Decimal(resultSign, resultExponent, work.low()); 1.435 + } 1.436 + 1.437 + case SpecialValueHandler::BothInfinity: 1.438 + return infinity(resultSign); 1.439 + 1.440 + case SpecialValueHandler::EitherNaN: 1.441 + return handler.value(); 1.442 + 1.443 + case SpecialValueHandler::LHSIsInfinity: 1.444 + return rhs.isZero() ? nan() : infinity(resultSign); 1.445 + 1.446 + case SpecialValueHandler::RHSIsInfinity: 1.447 + return lhs.isZero() ? nan() : infinity(resultSign); 1.448 + } 1.449 + 1.450 + ASSERT_NOT_REACHED(); 1.451 + return nan(); 1.452 +} 1.453 + 1.454 +Decimal Decimal::operator/(const Decimal& rhs) const 1.455 +{ 1.456 + const Decimal& lhs = *this; 1.457 + const Sign lhsSign = lhs.sign(); 1.458 + const Sign rhsSign = rhs.sign(); 1.459 + const Sign resultSign = lhsSign == rhsSign ? Positive : Negative; 1.460 + 1.461 + SpecialValueHandler handler(lhs, rhs); 1.462 + switch (handler.handle()) { 1.463 + case SpecialValueHandler::BothFinite: 1.464 + break; 1.465 + 1.466 + case SpecialValueHandler::BothInfinity: 1.467 + return nan(); 1.468 + 1.469 + case SpecialValueHandler::EitherNaN: 1.470 + return handler.value(); 1.471 + 1.472 + case SpecialValueHandler::LHSIsInfinity: 1.473 + return infinity(resultSign); 1.474 + 1.475 + case SpecialValueHandler::RHSIsInfinity: 1.476 + return zero(resultSign); 1.477 + } 1.478 + 1.479 + ASSERT(lhs.isFinite()); 1.480 + ASSERT(rhs.isFinite()); 1.481 + 1.482 + if (rhs.isZero()) 1.483 + return lhs.isZero() ? nan() : infinity(resultSign); 1.484 + 1.485 + int resultExponent = lhs.exponent() - rhs.exponent(); 1.486 + 1.487 + if (lhs.isZero()) 1.488 + return Decimal(resultSign, resultExponent, 0); 1.489 + 1.490 + uint64_t remainder = lhs.m_data.coefficient(); 1.491 + const uint64_t divisor = rhs.m_data.coefficient(); 1.492 + uint64_t result = 0; 1.493 + while (result < MaxCoefficient / 100) { 1.494 + while (remainder < divisor) { 1.495 + remainder *= 10; 1.496 + result *= 10; 1.497 + --resultExponent; 1.498 + } 1.499 + result += remainder / divisor; 1.500 + remainder %= divisor; 1.501 + if (!remainder) 1.502 + break; 1.503 + } 1.504 + 1.505 + if (remainder > divisor / 2) 1.506 + ++result; 1.507 + 1.508 + return Decimal(resultSign, resultExponent, result); 1.509 +} 1.510 + 1.511 +bool Decimal::operator==(const Decimal& rhs) const 1.512 +{ 1.513 + if (isNaN() || rhs.isNaN()) 1.514 + return false; 1.515 + return m_data == rhs.m_data || compareTo(rhs).isZero(); 1.516 +} 1.517 + 1.518 +bool Decimal::operator!=(const Decimal& rhs) const 1.519 +{ 1.520 + if (isNaN() || rhs.isNaN()) 1.521 + return true; 1.522 + if (m_data == rhs.m_data) 1.523 + return false; 1.524 + const Decimal result = compareTo(rhs); 1.525 + if (result.isNaN()) 1.526 + return false; 1.527 + return !result.isZero(); 1.528 +} 1.529 + 1.530 +bool Decimal::operator<(const Decimal& rhs) const 1.531 +{ 1.532 + const Decimal result = compareTo(rhs); 1.533 + if (result.isNaN()) 1.534 + return false; 1.535 + return !result.isZero() && result.isNegative(); 1.536 +} 1.537 + 1.538 +bool Decimal::operator<=(const Decimal& rhs) const 1.539 +{ 1.540 + if (isNaN() || rhs.isNaN()) 1.541 + return false; 1.542 + if (m_data == rhs.m_data) 1.543 + return true; 1.544 + const Decimal result = compareTo(rhs); 1.545 + if (result.isNaN()) 1.546 + return false; 1.547 + return result.isZero() || result.isNegative(); 1.548 +} 1.549 + 1.550 +bool Decimal::operator>(const Decimal& rhs) const 1.551 +{ 1.552 + const Decimal result = compareTo(rhs); 1.553 + if (result.isNaN()) 1.554 + return false; 1.555 + return !result.isZero() && result.isPositive(); 1.556 +} 1.557 + 1.558 +bool Decimal::operator>=(const Decimal& rhs) const 1.559 +{ 1.560 + if (isNaN() || rhs.isNaN()) 1.561 + return false; 1.562 + if (m_data == rhs.m_data) 1.563 + return true; 1.564 + const Decimal result = compareTo(rhs); 1.565 + if (result.isNaN()) 1.566 + return false; 1.567 + return result.isZero() || !result.isNegative(); 1.568 +} 1.569 + 1.570 +Decimal Decimal::abs() const 1.571 +{ 1.572 + Decimal result(*this); 1.573 + result.m_data.setSign(Positive); 1.574 + return result; 1.575 +} 1.576 + 1.577 +Decimal::AlignedOperands Decimal::alignOperands(const Decimal& lhs, const Decimal& rhs) 1.578 +{ 1.579 + ASSERT(lhs.isFinite()); 1.580 + ASSERT(rhs.isFinite()); 1.581 + 1.582 + const int lhsExponent = lhs.exponent(); 1.583 + const int rhsExponent = rhs.exponent(); 1.584 + int exponent = std::min(lhsExponent, rhsExponent); 1.585 + uint64_t lhsCoefficient = lhs.m_data.coefficient(); 1.586 + uint64_t rhsCoefficient = rhs.m_data.coefficient(); 1.587 + 1.588 + if (lhsExponent > rhsExponent) { 1.589 + const int numberOfLHSDigits = countDigits(lhsCoefficient); 1.590 + if (numberOfLHSDigits) { 1.591 + const int lhsShiftAmount = lhsExponent - rhsExponent; 1.592 + const int overflow = numberOfLHSDigits + lhsShiftAmount - Precision; 1.593 + if (overflow <= 0) 1.594 + lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount); 1.595 + else { 1.596 + lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount - overflow); 1.597 + rhsCoefficient = scaleDown(rhsCoefficient, overflow); 1.598 + exponent += overflow; 1.599 + } 1.600 + } 1.601 + 1.602 + } else if (lhsExponent < rhsExponent) { 1.603 + const int numberOfRHSDigits = countDigits(rhsCoefficient); 1.604 + if (numberOfRHSDigits) { 1.605 + const int rhsShiftAmount = rhsExponent - lhsExponent; 1.606 + const int overflow = numberOfRHSDigits + rhsShiftAmount - Precision; 1.607 + if (overflow <= 0) 1.608 + rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount); 1.609 + else { 1.610 + rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount - overflow); 1.611 + lhsCoefficient = scaleDown(lhsCoefficient, overflow); 1.612 + exponent += overflow; 1.613 + } 1.614 + } 1.615 + } 1.616 + 1.617 + AlignedOperands alignedOperands; 1.618 + alignedOperands.exponent = exponent; 1.619 + alignedOperands.lhsCoefficient = lhsCoefficient; 1.620 + alignedOperands.rhsCoefficient = rhsCoefficient; 1.621 + return alignedOperands; 1.622 +} 1.623 + 1.624 +// Round toward positive infinity. 1.625 +// Note: Mac ports defines ceil(x) as wtf_ceil(x), so we can't use name "ceil" here. 1.626 +Decimal Decimal::ceiling() const 1.627 +{ 1.628 + if (isSpecial()) 1.629 + return *this; 1.630 + 1.631 + if (exponent() >= 0) 1.632 + return *this; 1.633 + 1.634 + uint64_t coefficient = m_data.coefficient(); 1.635 + const int numberOfDigits = countDigits(coefficient); 1.636 + const int numberOfDropDigits = -exponent(); 1.637 + if (numberOfDigits < numberOfDropDigits) 1.638 + return isPositive() ? Decimal(1) : zero(Positive); 1.639 + 1.640 + uint64_t result = scaleDown(coefficient, numberOfDropDigits); 1.641 + uint64_t droppedDigits = coefficient - scaleUp(result, numberOfDropDigits); 1.642 + if (droppedDigits && isPositive()) 1.643 + result += 1; 1.644 + return Decimal(sign(), 0, result); 1.645 +} 1.646 + 1.647 +Decimal Decimal::compareTo(const Decimal& rhs) const 1.648 +{ 1.649 + const Decimal result(*this - rhs); 1.650 + switch (result.m_data.formatClass()) { 1.651 + case EncodedData::ClassInfinity: 1.652 + return result.isNegative() ? Decimal(-1) : Decimal(1); 1.653 + 1.654 + case EncodedData::ClassNaN: 1.655 + case EncodedData::ClassNormal: 1.656 + return result; 1.657 + 1.658 + case EncodedData::ClassZero: 1.659 + return zero(Positive); 1.660 + 1.661 + default: 1.662 + ASSERT_NOT_REACHED(); 1.663 + return nan(); 1.664 + } 1.665 +} 1.666 + 1.667 +// Round toward negative infinity. 1.668 +Decimal Decimal::floor() const 1.669 +{ 1.670 + if (isSpecial()) 1.671 + return *this; 1.672 + 1.673 + if (exponent() >= 0) 1.674 + return *this; 1.675 + 1.676 + uint64_t coefficient = m_data.coefficient(); 1.677 + const int numberOfDigits = countDigits(coefficient); 1.678 + const int numberOfDropDigits = -exponent(); 1.679 + if (numberOfDigits < numberOfDropDigits) 1.680 + return isPositive() ? zero(Positive) : Decimal(-1); 1.681 + 1.682 + uint64_t result = scaleDown(coefficient, numberOfDropDigits); 1.683 + uint64_t droppedDigits = coefficient - scaleUp(result, numberOfDropDigits); 1.684 + if (droppedDigits && isNegative()) { 1.685 + result += 1; 1.686 + } 1.687 + return Decimal(sign(), 0, result); 1.688 +} 1.689 + 1.690 +Decimal Decimal::fromDouble(double doubleValue) 1.691 +{ 1.692 + if (std::isfinite(doubleValue)) 1.693 + return fromString(mozToString(doubleValue)); 1.694 + 1.695 + if (std::isinf(doubleValue)) 1.696 + return infinity(doubleValue < 0 ? Negative : Positive); 1.697 + 1.698 + return nan(); 1.699 +} 1.700 + 1.701 +Decimal Decimal::fromString(const String& str) 1.702 +{ 1.703 + int exponent = 0; 1.704 + Sign exponentSign = Positive; 1.705 + int numberOfDigits = 0; 1.706 + int numberOfDigitsAfterDot = 0; 1.707 + int numberOfExtraDigits = 0; 1.708 + Sign sign = Positive; 1.709 + 1.710 + enum { 1.711 + StateDigit, 1.712 + StateDot, 1.713 + StateDotDigit, 1.714 + StateE, 1.715 + StateEDigit, 1.716 + StateESign, 1.717 + StateSign, 1.718 + StateStart, 1.719 + StateZero, 1.720 + } state = StateStart; 1.721 + 1.722 +#define HandleCharAndBreak(expected, nextState) \ 1.723 + if (ch == expected) { \ 1.724 + state = nextState; \ 1.725 + break; \ 1.726 + } 1.727 + 1.728 +#define HandleTwoCharsAndBreak(expected1, expected2, nextState) \ 1.729 + if (ch == expected1 || ch == expected2) { \ 1.730 + state = nextState; \ 1.731 + break; \ 1.732 + } 1.733 + 1.734 + uint64_t accumulator = 0; 1.735 + for (unsigned index = 0; index < str.length(); ++index) { 1.736 + const int ch = str[index]; 1.737 + switch (state) { 1.738 + case StateDigit: 1.739 + if (ch >= '0' && ch <= '9') { 1.740 + if (numberOfDigits < Precision) { 1.741 + ++numberOfDigits; 1.742 + accumulator *= 10; 1.743 + accumulator += ch - '0'; 1.744 + } else 1.745 + ++numberOfExtraDigits; 1.746 + break; 1.747 + } 1.748 + 1.749 + HandleCharAndBreak('.', StateDot); 1.750 + HandleTwoCharsAndBreak('E', 'e', StateE); 1.751 + return nan(); 1.752 + 1.753 + case StateDot: 1.754 + if (ch >= '0' && ch <= '9') { 1.755 + if (numberOfDigits < Precision) { 1.756 + ++numberOfDigits; 1.757 + ++numberOfDigitsAfterDot; 1.758 + accumulator *= 10; 1.759 + accumulator += ch - '0'; 1.760 + } 1.761 + state = StateDotDigit; 1.762 + break; 1.763 + } 1.764 + 1.765 + case StateDotDigit: 1.766 + if (ch >= '0' && ch <= '9') { 1.767 + if (numberOfDigits < Precision) { 1.768 + ++numberOfDigits; 1.769 + ++numberOfDigitsAfterDot; 1.770 + accumulator *= 10; 1.771 + accumulator += ch - '0'; 1.772 + } 1.773 + break; 1.774 + } 1.775 + 1.776 + HandleTwoCharsAndBreak('E', 'e', StateE); 1.777 + return nan(); 1.778 + 1.779 + case StateE: 1.780 + if (ch == '+') { 1.781 + exponentSign = Positive; 1.782 + state = StateESign; 1.783 + break; 1.784 + } 1.785 + 1.786 + if (ch == '-') { 1.787 + exponentSign = Negative; 1.788 + state = StateESign; 1.789 + break; 1.790 + } 1.791 + 1.792 + if (ch >= '0' && ch <= '9') { 1.793 + exponent = ch - '0'; 1.794 + state = StateEDigit; 1.795 + break; 1.796 + } 1.797 + 1.798 + return nan(); 1.799 + 1.800 + case StateEDigit: 1.801 + if (ch >= '0' && ch <= '9') { 1.802 + exponent *= 10; 1.803 + exponent += ch - '0'; 1.804 + if (exponent > ExponentMax + Precision) { 1.805 + if (accumulator) 1.806 + return exponentSign == Negative ? zero(Positive) : infinity(sign); 1.807 + return zero(sign); 1.808 + } 1.809 + state = StateEDigit; 1.810 + break; 1.811 + } 1.812 + 1.813 + return nan(); 1.814 + 1.815 + case StateESign: 1.816 + if (ch >= '0' && ch <= '9') { 1.817 + exponent = ch - '0'; 1.818 + state = StateEDigit; 1.819 + break; 1.820 + } 1.821 + 1.822 + return nan(); 1.823 + 1.824 + case StateSign: 1.825 + if (ch >= '1' && ch <= '9') { 1.826 + accumulator = ch - '0'; 1.827 + numberOfDigits = 1; 1.828 + state = StateDigit; 1.829 + break; 1.830 + } 1.831 + 1.832 + HandleCharAndBreak('0', StateZero); 1.833 + return nan(); 1.834 + 1.835 + case StateStart: 1.836 + if (ch >= '1' && ch <= '9') { 1.837 + accumulator = ch - '0'; 1.838 + numberOfDigits = 1; 1.839 + state = StateDigit; 1.840 + break; 1.841 + } 1.842 + 1.843 + if (ch == '-') { 1.844 + sign = Negative; 1.845 + state = StateSign; 1.846 + break; 1.847 + } 1.848 + 1.849 + if (ch == '+') { 1.850 + sign = Positive; 1.851 + state = StateSign; 1.852 + break; 1.853 + } 1.854 + 1.855 + HandleCharAndBreak('0', StateZero); 1.856 + HandleCharAndBreak('.', StateDot); 1.857 + return nan(); 1.858 + 1.859 + case StateZero: 1.860 + if (ch == '0') 1.861 + break; 1.862 + 1.863 + if (ch >= '1' && ch <= '9') { 1.864 + accumulator = ch - '0'; 1.865 + numberOfDigits = 1; 1.866 + state = StateDigit; 1.867 + break; 1.868 + } 1.869 + 1.870 + HandleCharAndBreak('.', StateDot); 1.871 + HandleTwoCharsAndBreak('E', 'e', StateE); 1.872 + return nan(); 1.873 + 1.874 + default: 1.875 + ASSERT_NOT_REACHED(); 1.876 + return nan(); 1.877 + } 1.878 + } 1.879 + 1.880 + if (state == StateZero) 1.881 + return zero(sign); 1.882 + 1.883 + if (state == StateDigit || state == StateEDigit || state == StateDotDigit) { 1.884 + int resultExponent = exponent * (exponentSign == Negative ? -1 : 1) - numberOfDigitsAfterDot + numberOfExtraDigits; 1.885 + if (resultExponent < ExponentMin) 1.886 + return zero(Positive); 1.887 + 1.888 + const int overflow = resultExponent - ExponentMax + 1; 1.889 + if (overflow > 0) { 1.890 + if (overflow + numberOfDigits - numberOfDigitsAfterDot > Precision) 1.891 + return infinity(sign); 1.892 + accumulator = scaleUp(accumulator, overflow); 1.893 + resultExponent -= overflow; 1.894 + } 1.895 + 1.896 + return Decimal(sign, resultExponent, accumulator); 1.897 + } 1.898 + 1.899 + return nan(); 1.900 +} 1.901 + 1.902 +Decimal Decimal::infinity(const Sign sign) 1.903 +{ 1.904 + return Decimal(EncodedData(sign, EncodedData::ClassInfinity)); 1.905 +} 1.906 + 1.907 +Decimal Decimal::nan() 1.908 +{ 1.909 + return Decimal(EncodedData(Positive, EncodedData::ClassNaN)); 1.910 +} 1.911 + 1.912 +Decimal Decimal::remainder(const Decimal& rhs) const 1.913 +{ 1.914 + const Decimal quotient = *this / rhs; 1.915 + return quotient.isSpecial() ? quotient : *this - (quotient.isNegative() ? quotient.ceiling() : quotient.floor()) * rhs; 1.916 +} 1.917 + 1.918 +Decimal Decimal::round() const 1.919 +{ 1.920 + if (isSpecial()) 1.921 + return *this; 1.922 + 1.923 + if (exponent() >= 0) 1.924 + return *this; 1.925 + 1.926 + uint64_t result = m_data.coefficient(); 1.927 + const int numberOfDigits = countDigits(result); 1.928 + const int numberOfDropDigits = -exponent(); 1.929 + if (numberOfDigits < numberOfDropDigits) 1.930 + return zero(Positive); 1.931 + 1.932 + // We're implementing round-half-away-from-zero, so we only need the one 1.933 + // (the most significant) fractional digit: 1.934 + result = scaleDown(result, numberOfDropDigits - 1); 1.935 + if (result % 10 >= 5) 1.936 + result += 10; 1.937 + result /= 10; 1.938 + return Decimal(sign(), 0, result); 1.939 +} 1.940 + 1.941 +double Decimal::toDouble() const 1.942 +{ 1.943 + if (isFinite()) { 1.944 + bool valid; 1.945 + const double doubleValue = mozToDouble(toString(), &valid); 1.946 + return valid ? doubleValue : std::numeric_limits<double>::quiet_NaN(); 1.947 + } 1.948 + 1.949 + if (isInfinity()) 1.950 + return isNegative() ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity(); 1.951 + 1.952 + return std::numeric_limits<double>::quiet_NaN(); 1.953 +} 1.954 + 1.955 +String Decimal::toString() const 1.956 +{ 1.957 + switch (m_data.formatClass()) { 1.958 + case EncodedData::ClassInfinity: 1.959 + return sign() ? "-Infinity" : "Infinity"; 1.960 + 1.961 + case EncodedData::ClassNaN: 1.962 + return "NaN"; 1.963 + 1.964 + case EncodedData::ClassNormal: 1.965 + case EncodedData::ClassZero: 1.966 + break; 1.967 + 1.968 + default: 1.969 + ASSERT_NOT_REACHED(); 1.970 + return ""; 1.971 + } 1.972 + 1.973 + StringBuilder builder; 1.974 + if (sign()) 1.975 + builder.append('-'); 1.976 + 1.977 + int originalExponent = exponent(); 1.978 + uint64_t coefficient = m_data.coefficient(); 1.979 + 1.980 + if (originalExponent < 0) { 1.981 + const int maxDigits = DBL_DIG; 1.982 + uint64_t lastDigit = 0; 1.983 + while (countDigits(coefficient) > maxDigits) { 1.984 + lastDigit = coefficient % 10; 1.985 + coefficient /= 10; 1.986 + ++originalExponent; 1.987 + } 1.988 + 1.989 + if (lastDigit >= 5) 1.990 + ++coefficient; 1.991 + 1.992 + while (originalExponent < 0 && coefficient && !(coefficient % 10)) { 1.993 + coefficient /= 10; 1.994 + ++originalExponent; 1.995 + } 1.996 + } 1.997 + 1.998 + const String digits = mozToString(coefficient); 1.999 + int coefficientLength = static_cast<int>(digits.length()); 1.1000 + const int adjustedExponent = originalExponent + coefficientLength - 1; 1.1001 + if (originalExponent <= 0 && adjustedExponent >= -6) { 1.1002 + if (!originalExponent) { 1.1003 + builder.append(digits); 1.1004 + return builder.toString(); 1.1005 + } 1.1006 + 1.1007 + if (adjustedExponent >= 0) { 1.1008 + for (int i = 0; i < coefficientLength; ++i) { 1.1009 + builder.append(digits[i]); 1.1010 + if (i == adjustedExponent) 1.1011 + builder.append('.'); 1.1012 + } 1.1013 + return builder.toString(); 1.1014 + } 1.1015 + 1.1016 + builder.appendLiteral("0."); 1.1017 + for (int i = adjustedExponent + 1; i < 0; ++i) 1.1018 + builder.append('0'); 1.1019 + 1.1020 + builder.append(digits); 1.1021 + 1.1022 + } else { 1.1023 + builder.append(digits[0]); 1.1024 + while (coefficientLength >= 2 && digits[coefficientLength - 1] == '0') 1.1025 + --coefficientLength; 1.1026 + if (coefficientLength >= 2) { 1.1027 + builder.append('.'); 1.1028 + for (int i = 1; i < coefficientLength; ++i) 1.1029 + builder.append(digits[i]); 1.1030 + } 1.1031 + 1.1032 + if (adjustedExponent) { 1.1033 + builder.append(adjustedExponent < 0 ? "e" : "e+"); 1.1034 + builder.appendNumber(adjustedExponent); 1.1035 + } 1.1036 + } 1.1037 + return builder.toString(); 1.1038 +} 1.1039 + 1.1040 +bool Decimal::toString(char* strBuf, size_t bufLength) const 1.1041 +{ 1.1042 + ASSERT(bufLength > 0); 1.1043 + String str = toString(); 1.1044 + size_t length = str.copy(strBuf, bufLength); 1.1045 + if (length < bufLength) { 1.1046 + strBuf[length] = '\0'; 1.1047 + return true; 1.1048 + } 1.1049 + strBuf[bufLength - 1] = '\0'; 1.1050 + return false; 1.1051 +} 1.1052 + 1.1053 +Decimal Decimal::zero(Sign sign) 1.1054 +{ 1.1055 + return Decimal(EncodedData(sign, EncodedData::ClassZero)); 1.1056 +} 1.1057 + 1.1058 +} // namespace WebCore 1.1059 +