Line data Source code
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 : /**
32 : * Imported from:
33 : * https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/platform/Decimal.h
34 : * Check UPSTREAM-GIT-SHA for the commit ID of the last update from Blink core.
35 : */
36 :
37 : #ifndef Decimal_h
38 : #define Decimal_h
39 :
40 : #include "mozilla/Assertions.h"
41 : #include <stdint.h>
42 : #include "mozilla/Types.h"
43 :
44 : #include <string>
45 :
46 : #ifndef ASSERT
47 : #define DEFINED_ASSERT_FOR_DECIMAL_H 1
48 : #define ASSERT MOZ_ASSERT
49 : #endif
50 :
51 : #define PLATFORM_EXPORT
52 :
53 : // To use USING_FAST_MALLOC we'd need:
54 : // https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/wtf/Allocator.h
55 : // Since we don't allocate Decimal objects, no need.
56 : #define USING_FAST_MALLOC(type) \
57 : void ignore_this_dummy_method() = delete
58 :
59 : #define DISALLOW_NEW() \
60 : private: \
61 : void* operator new(size_t) = delete; \
62 : void* operator new(size_t, void*) = delete; \
63 : public:
64 :
65 : namespace blink {
66 :
67 : namespace DecimalPrivate {
68 : class SpecialValueHandler;
69 : }
70 :
71 : // This class represents decimal base floating point number.
72 : //
73 : // FIXME: Once all C++ compiler support decimal type, we should replace this
74 : // class to compiler supported one. See below URI for current status of decimal
75 : // type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html
76 : class PLATFORM_EXPORT Decimal {
77 : USING_FAST_MALLOC(Decimal);
78 : public:
79 : enum Sign {
80 : Positive,
81 : Negative,
82 : };
83 :
84 : // You should not use EncodedData other than unit testing.
85 : class EncodedData {
86 : DISALLOW_NEW();
87 : // For accessing FormatClass.
88 : friend class Decimal;
89 : friend class DecimalPrivate::SpecialValueHandler;
90 : public:
91 : EncodedData(Sign, int exponent, uint64_t coefficient);
92 :
93 : bool operator==(const EncodedData&) const;
94 : bool operator!=(const EncodedData& another) const { return !operator==(another); }
95 :
96 0 : uint64_t coefficient() const { return m_coefficient; }
97 : int countDigits() const;
98 0 : int exponent() const { return m_exponent; }
99 0 : bool isFinite() const { return !isSpecial(); }
100 0 : bool isInfinity() const { return m_formatClass == ClassInfinity; }
101 0 : bool isNaN() const { return m_formatClass == ClassNaN; }
102 0 : bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; }
103 0 : bool isZero() const { return m_formatClass == ClassZero; }
104 0 : Sign sign() const { return m_sign; }
105 0 : void setSign(Sign sign) { m_sign = sign; }
106 :
107 : private:
108 : enum FormatClass {
109 : ClassInfinity,
110 : ClassNormal,
111 : ClassNaN,
112 : ClassZero,
113 : };
114 :
115 : EncodedData(Sign, FormatClass);
116 0 : FormatClass formatClass() const { return m_formatClass; }
117 :
118 : uint64_t m_coefficient;
119 : int16_t m_exponent;
120 : FormatClass m_formatClass;
121 : Sign m_sign;
122 : };
123 :
124 : MFBT_API explicit Decimal(int32_t = 0);
125 : MFBT_API Decimal(Sign, int exponent, uint64_t coefficient);
126 : MFBT_API Decimal(const Decimal&);
127 :
128 : MFBT_API Decimal& operator=(const Decimal&);
129 : MFBT_API Decimal& operator+=(const Decimal&);
130 : MFBT_API Decimal& operator-=(const Decimal&);
131 : MFBT_API Decimal& operator*=(const Decimal&);
132 : MFBT_API Decimal& operator/=(const Decimal&);
133 :
134 : MFBT_API Decimal operator-() const;
135 :
136 : MFBT_API bool operator==(const Decimal&) const;
137 : MFBT_API bool operator!=(const Decimal&) const;
138 : MFBT_API bool operator<(const Decimal&) const;
139 : MFBT_API bool operator<=(const Decimal&) const;
140 : MFBT_API bool operator>(const Decimal&) const;
141 : MFBT_API bool operator>=(const Decimal&) const;
142 :
143 : MFBT_API Decimal operator+(const Decimal&) const;
144 : MFBT_API Decimal operator-(const Decimal&) const;
145 : MFBT_API Decimal operator*(const Decimal&) const;
146 : MFBT_API Decimal operator/(const Decimal&) const;
147 :
148 0 : int exponent() const
149 : {
150 0 : ASSERT(isFinite());
151 0 : return m_data.exponent();
152 : }
153 :
154 0 : bool isFinite() const { return m_data.isFinite(); }
155 0 : bool isInfinity() const { return m_data.isInfinity(); }
156 0 : bool isNaN() const { return m_data.isNaN(); }
157 0 : bool isNegative() const { return sign() == Negative; }
158 0 : bool isPositive() const { return sign() == Positive; }
159 0 : bool isSpecial() const { return m_data.isSpecial(); }
160 0 : bool isZero() const { return m_data.isZero(); }
161 :
162 : MFBT_API Decimal abs() const;
163 : MFBT_API Decimal ceil() const;
164 : MFBT_API Decimal floor() const;
165 : MFBT_API Decimal remainder(const Decimal&) const;
166 : MFBT_API Decimal round() const;
167 :
168 : MFBT_API double toDouble() const;
169 : // Note: toString method supports infinity and nan but fromString not.
170 : MFBT_API std::string toString() const;
171 : MFBT_API bool toString(char* strBuf, size_t bufLength) const;
172 :
173 : static MFBT_API Decimal fromDouble(double);
174 : // fromString supports following syntax EBNF:
175 : // number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)?
176 : // | sign? '.' digit+ (exponent-marker sign? digit+)?
177 : // sign ::= '+' | '-'
178 : // exponent-marker ::= 'e' | 'E'
179 : // digit ::= '0' | '1' | ... | '9'
180 : // Note: fromString doesn't support "infinity" and "nan".
181 : static MFBT_API Decimal fromString(const std::string& aValue);
182 : static MFBT_API Decimal infinity(Sign);
183 : static MFBT_API Decimal nan();
184 : static MFBT_API Decimal zero(Sign);
185 :
186 : // You should not use below methods. We expose them for unit testing.
187 : MFBT_API explicit Decimal(const EncodedData&);
188 0 : const EncodedData& value() const { return m_data; }
189 :
190 : private:
191 : struct AlignedOperands {
192 : uint64_t lhsCoefficient;
193 : uint64_t rhsCoefficient;
194 : int exponent;
195 : };
196 :
197 : MFBT_API explicit Decimal(double);
198 : MFBT_API Decimal compareTo(const Decimal&) const;
199 :
200 : static MFBT_API AlignedOperands alignOperands(const Decimal& lhs, const Decimal& rhs);
201 0 : static inline Sign invertSign(Sign sign) { return sign == Negative ? Positive : Negative; }
202 :
203 0 : Sign sign() const { return m_data.sign(); }
204 :
205 : EncodedData m_data;
206 : };
207 :
208 : } // namespace blink
209 :
210 : namespace mozilla {
211 : typedef blink::Decimal Decimal;
212 : } // namespace mozilla
213 :
214 : #undef USING_FAST_MALLOC
215 :
216 : #ifdef DEFINED_ASSERT_FOR_DECIMAL_H
217 : #undef DEFINED_ASSERT_FOR_DECIMAL_H
218 : #undef ASSERT
219 : #endif
220 :
221 : #endif // Decimal_h
|