15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions in binary form must reproduce the above 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef Decimal_h 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define Decimal_h 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/PlatformExport.h" 357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/Assertions.h" 367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/text/WTFString.h" 371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include <stdint.h> 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 39c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace DecimalPrivate { 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SpecialValueHandler; 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This class represents decimal base floating point number. 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Once all C++ compiler support decimal type, we should replace this 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// class to compiler supported one. See below URI for current status of decimal 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html 501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class PLATFORM_EXPORT Decimal { 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WTF_MAKE_FAST_ALLOCATED; 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enum Sign { 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Positive, 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Negative, 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // You should not use EncodedData other than unit testing. 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) class EncodedData { 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For accessing FormatClass. 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) friend class Decimal; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) friend class DecimalPrivate::SpecialValueHandler; 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) public: 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EncodedData(Sign, int exponent, uint64_t coefficient); 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool operator==(const EncodedData&) const; 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool operator!=(const EncodedData& another) const { return !operator==(another); } 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) uint64_t coefficient() const { return m_coefficient; } 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int countDigits() const; 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int exponent() const { return m_exponent; } 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isFinite() const { return !isSpecial(); } 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isInfinity() const { return m_formatClass == ClassInfinity; } 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isNaN() const { return m_formatClass == ClassNaN; } 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; } 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isZero() const { return m_formatClass == ClassZero; } 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Sign sign() const { return m_sign; } 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void setSign(Sign sign) { m_sign = sign; } 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) private: 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enum FormatClass { 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ClassInfinity, 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ClassNormal, 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ClassNaN, 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ClassZero, 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EncodedData(Sign, FormatClass); 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FormatClass formatClass() const { return m_formatClass; } 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) uint64_t m_coefficient; 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int16_t m_exponent; 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FormatClass m_formatClass; 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Sign m_sign; 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal(int32_t = 0); 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal(Sign, int exponent, uint64_t coefficient); 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal(const Decimal&); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal& operator=(const Decimal&); 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal& operator+=(const Decimal&); 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal& operator-=(const Decimal&); 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal& operator*=(const Decimal&); 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal& operator/=(const Decimal&); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal operator-() const; 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool operator==(const Decimal&) const; 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool operator!=(const Decimal&) const; 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool operator<(const Decimal&) const; 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool operator<=(const Decimal&) const; 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool operator>(const Decimal&) const; 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool operator>=(const Decimal&) const; 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal operator+(const Decimal&) const; 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal operator-(const Decimal&) const; 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal operator*(const Decimal&) const; 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal operator/(const Decimal&) const; 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int exponent() const 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isFinite()); 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_data.exponent(); 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isFinite() const { return m_data.isFinite(); } 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isInfinity() const { return m_data.isInfinity(); } 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isNaN() const { return m_data.isNaN(); } 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isNegative() const { return sign() == Negative; } 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isPositive() const { return sign() == Positive; } 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isSpecial() const { return m_data.isSpecial(); } 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isZero() const { return m_data.isZero(); } 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal abs() const; 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal ceiling() const; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal floor() const; 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal remainder(const Decimal&) const; 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal round() const; 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double toDouble() const; 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Note: toString method supports infinity and nan but fromString not. 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String toString() const; 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static Decimal fromDouble(double); 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // fromString supports following syntax EBNF: 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)? 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // | sign? '.' digit+ (exponent-marker sign? digit+)? 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // sign ::= '+' | '-' 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // exponent-marker ::= 'e' | 'E' 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // digit ::= '0' | '1' | ... | '9' 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Note: fromString doesn't support "infinity" and "nan". 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static Decimal fromString(const String&); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static Decimal infinity(Sign); 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static Decimal nan(); 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static Decimal zero(Sign); 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // You should not use below methods. We expose them for unit testing. 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) explicit Decimal(const EncodedData&); 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const EncodedData& value() const { return m_data; } 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private: 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) struct AlignedOperands { 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) uint64_t lhsCoefficient; 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) uint64_t rhsCoefficient; 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int exponent; 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal(double); 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Decimal compareTo(const Decimal&) const; 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static AlignedOperands alignOperands(const Decimal& lhs, const Decimal& rhs); 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static inline Sign invertSign(Sign sign) { return sign == Negative ? Positive : Negative; } 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Sign sign() const { return m_data.sign(); } 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EncodedData m_data; 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 180c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // Decimal_h 183