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 <stdint.h> 35 #include "wtf/Assertions.h" 36 #include "wtf/text/WTFString.h" 37 38 namespace WebCore { 39 40 namespace DecimalPrivate { 41 class SpecialValueHandler; 42 } 43 44 // This class represents decimal base floating point number. 45 // 46 // FIXME: Once all C++ compiler support decimal type, we should replace this 47 // class to compiler supported one. See below URI for current status of decimal 48 // type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html 49 class Decimal { 50 WTF_MAKE_FAST_ALLOCATED; 51 public: 52 enum Sign { 53 Positive, 54 Negative, 55 }; 56 57 // You should not use EncodedData other than unit testing. 58 class EncodedData { 59 // For accessing FormatClass. 60 friend class Decimal; 61 friend class DecimalPrivate::SpecialValueHandler; 62 public: 63 EncodedData(Sign, int exponent, uint64_t coefficient); 64 65 bool operator==(const EncodedData&) const; 66 bool operator!=(const EncodedData& another) const { return !operator==(another); } 67 68 uint64_t coefficient() const { return m_coefficient; } 69 int countDigits() const; 70 int exponent() const { return m_exponent; } 71 bool isFinite() const { return !isSpecial(); } 72 bool isInfinity() const { return m_formatClass == ClassInfinity; } 73 bool isNaN() const { return m_formatClass == ClassNaN; } 74 bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; } 75 bool isZero() const { return m_formatClass == ClassZero; } 76 Sign sign() const { return m_sign; } 77 void setSign(Sign sign) { m_sign = sign; } 78 79 private: 80 enum FormatClass { 81 ClassInfinity, 82 ClassNormal, 83 ClassNaN, 84 ClassZero, 85 }; 86 87 EncodedData(Sign, FormatClass); 88 FormatClass formatClass() const { return m_formatClass; } 89 90 uint64_t m_coefficient; 91 int16_t m_exponent; 92 FormatClass m_formatClass; 93 Sign m_sign; 94 }; 95 96 Decimal(int32_t = 0); 97 Decimal(Sign, int exponent, uint64_t coefficient); 98 Decimal(const Decimal&); 99 100 Decimal& operator=(const Decimal&); 101 Decimal& operator+=(const Decimal&); 102 Decimal& operator-=(const Decimal&); 103 Decimal& operator*=(const Decimal&); 104 Decimal& operator/=(const Decimal&); 105 106 Decimal operator-() const; 107 108 bool operator==(const Decimal&) const; 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 115 Decimal operator+(const Decimal&) const; 116 Decimal operator-(const Decimal&) const; 117 Decimal operator*(const Decimal&) const; 118 Decimal operator/(const Decimal&) const; 119 120 int exponent() const 121 { 122 ASSERT(isFinite()); 123 return m_data.exponent(); 124 } 125 126 bool isFinite() const { return m_data.isFinite(); } 127 bool isInfinity() const { return m_data.isInfinity(); } 128 bool isNaN() const { return m_data.isNaN(); } 129 bool isNegative() const { return sign() == Negative; } 130 bool isPositive() const { return sign() == Positive; } 131 bool isSpecial() const { return m_data.isSpecial(); } 132 bool isZero() const { return m_data.isZero(); } 133 134 Decimal abs() const; 135 Decimal ceiling() const; 136 Decimal floor() const; 137 Decimal remainder(const Decimal&) const; 138 Decimal round() const; 139 140 double toDouble() const; 141 // Note: toString method supports infinity and nan but fromString not. 142 String toString() const; 143 144 static Decimal fromDouble(double); 145 // fromString supports following syntax EBNF: 146 // number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)? 147 // | sign? '.' digit+ (exponent-marker sign? digit+)? 148 // sign ::= '+' | '-' 149 // exponent-marker ::= 'e' | 'E' 150 // digit ::= '0' | '1' | ... | '9' 151 // Note: fromString doesn't support "infinity" and "nan". 152 static Decimal fromString(const String&); 153 static Decimal infinity(Sign); 154 static Decimal nan(); 155 static Decimal zero(Sign); 156 157 // You should not use below methods. We expose them for unit testing. 158 explicit Decimal(const EncodedData&); 159 const EncodedData& value() const { return m_data; } 160 161 private: 162 struct AlignedOperands { 163 uint64_t lhsCoefficient; 164 uint64_t rhsCoefficient; 165 int exponent; 166 }; 167 168 Decimal(double); 169 Decimal compareTo(const Decimal&) const; 170 171 static AlignedOperands alignOperands(const Decimal& lhs, const Decimal& rhs); 172 static inline Sign invertSign(Sign sign) { return sign == Negative ? Positive : Negative; } 173 174 Sign sign() const { return m_data.sign(); } 175 176 EncodedData m_data; 177 }; 178 179 } // namespace WebCore 180 181 #endif // Decimal_h 182