1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef Decimal_h 32 #define Decimal_h 33 34 #include "platform/PlatformExport.h" 35 #include "wtf/Assertions.h" 36 #include "wtf/text/WTFString.h" 37 #include <stdint.h> 38 39 namespace WebCore { 40 41 namespace DecimalPrivate { 42 class SpecialValueHandler; 43 } 44 45 // This class represents decimal base floating point number. 46 // 47 // FIXME: Once all C++ compiler support decimal type, we should replace this 48 // class to compiler supported one. See below URI for current status of decimal 49 // type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html 50 class PLATFORM_EXPORT Decimal { 51 WTF_MAKE_FAST_ALLOCATED; 52 public: 53 enum Sign { 54 Positive, 55 Negative, 56 }; 57 58 // You should not use EncodedData other than unit testing. 59 class EncodedData { 60 // For accessing FormatClass. 61 friend class Decimal; 62 friend class DecimalPrivate::SpecialValueHandler; 63 public: 64 EncodedData(Sign, int exponent, uint64_t coefficient); 65 66 bool operator==(const EncodedData&) const; 67 bool operator!=(const EncodedData& another) const { return !operator==(another); } 68 coefficient()69 uint64_t coefficient() const { return m_coefficient; } 70 int countDigits() const; exponent()71 int exponent() const { return m_exponent; } isFinite()72 bool isFinite() const { return !isSpecial(); } isInfinity()73 bool isInfinity() const { return m_formatClass == ClassInfinity; } isNaN()74 bool isNaN() const { return m_formatClass == ClassNaN; } isSpecial()75 bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; } isZero()76 bool isZero() const { return m_formatClass == ClassZero; } sign()77 Sign sign() const { return m_sign; } setSign(Sign sign)78 void setSign(Sign sign) { m_sign = sign; } 79 80 private: 81 enum FormatClass { 82 ClassInfinity, 83 ClassNormal, 84 ClassNaN, 85 ClassZero, 86 }; 87 88 EncodedData(Sign, FormatClass); formatClass()89 FormatClass formatClass() const { return m_formatClass; } 90 91 uint64_t m_coefficient; 92 int16_t m_exponent; 93 FormatClass m_formatClass; 94 Sign m_sign; 95 }; 96 97 Decimal(int32_t = 0); 98 Decimal(Sign, int exponent, uint64_t coefficient); 99 Decimal(const Decimal&); 100 101 Decimal& operator=(const Decimal&); 102 Decimal& operator+=(const Decimal&); 103 Decimal& operator-=(const Decimal&); 104 Decimal& operator*=(const Decimal&); 105 Decimal& operator/=(const Decimal&); 106 107 Decimal operator-() const; 108 109 bool operator==(const Decimal&) const; 110 bool operator!=(const Decimal&) const; 111 bool operator<(const Decimal&) const; 112 bool operator<=(const Decimal&) const; 113 bool operator>(const Decimal&) const; 114 bool operator>=(const Decimal&) const; 115 116 Decimal operator+(const Decimal&) const; 117 Decimal operator-(const Decimal&) const; 118 Decimal operator*(const Decimal&) const; 119 Decimal operator/(const Decimal&) const; 120 exponent()121 int exponent() const 122 { 123 ASSERT(isFinite()); 124 return m_data.exponent(); 125 } 126 isFinite()127 bool isFinite() const { return m_data.isFinite(); } isInfinity()128 bool isInfinity() const { return m_data.isInfinity(); } isNaN()129 bool isNaN() const { return m_data.isNaN(); } isNegative()130 bool isNegative() const { return sign() == Negative; } isPositive()131 bool isPositive() const { return sign() == Positive; } isSpecial()132 bool isSpecial() const { return m_data.isSpecial(); } isZero()133 bool isZero() const { return m_data.isZero(); } 134 135 Decimal abs() const; 136 Decimal ceiling() const; 137 Decimal floor() const; 138 Decimal remainder(const Decimal&) const; 139 Decimal round() const; 140 141 double toDouble() const; 142 // Note: toString method supports infinity and nan but fromString not. 143 String toString() const; 144 145 static Decimal fromDouble(double); 146 // fromString supports following syntax EBNF: 147 // number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)? 148 // | sign? '.' digit+ (exponent-marker sign? digit+)? 149 // sign ::= '+' | '-' 150 // exponent-marker ::= 'e' | 'E' 151 // digit ::= '0' | '1' | ... | '9' 152 // Note: fromString doesn't support "infinity" and "nan". 153 static Decimal fromString(const String&); 154 static Decimal infinity(Sign); 155 static Decimal nan(); 156 static Decimal zero(Sign); 157 158 // You should not use below methods. We expose them for unit testing. 159 explicit Decimal(const EncodedData&); value()160 const EncodedData& value() const { return m_data; } 161 162 private: 163 struct AlignedOperands { 164 uint64_t lhsCoefficient; 165 uint64_t rhsCoefficient; 166 int exponent; 167 }; 168 169 Decimal(double); 170 Decimal compareTo(const Decimal&) const; 171 172 static AlignedOperands alignOperands(const Decimal& lhs, const Decimal& rhs); invertSign(Sign sign)173 static inline Sign invertSign(Sign sign) { return sign == Negative ? Positive : Negative; } 174 sign()175 Sign sign() const { return m_data.sign(); } 176 177 EncodedData m_data; 178 }; 179 180 } // namespace WebCore 181 182 #endif // Decimal_h 183