rippled
Loading...
Searching...
No Matches
Number.h
1#ifndef XRPL_BASICS_NUMBER_H_INCLUDED
2#define XRPL_BASICS_NUMBER_H_INCLUDED
3
4#include <cstdint>
5#include <limits>
6#include <ostream>
7#include <string>
8
9namespace xrpl {
10
11class Number;
12
14to_string(Number const& amount);
15
16template <typename T>
17constexpr bool
19{
20 while (value >= 10 && value % 10 == 0)
21 value /= 10;
22 return value == 1;
23}
24
25class Number
26{
30
31public:
32 // The range for the mantissa when normalized
33 constexpr static std::int64_t minMantissa = 1'000'000'000'000'000LL;
34 static_assert(isPowerOfTen(minMantissa));
35 constexpr static std::int64_t maxMantissa = minMantissa * 10 - 1;
36 static_assert(maxMantissa == 9'999'999'999'999'999LL);
37
38 // The range for the exponent when normalized
39 constexpr static int minExponent = -32768;
40 constexpr static int maxExponent = 32768;
41
42 struct unchecked
43 {
44 explicit unchecked() = default;
45 };
46
47 explicit constexpr Number() = default;
48
50 explicit Number(rep mantissa, int exponent);
51 explicit constexpr Number(rep mantissa, int exponent, unchecked) noexcept;
52
53 constexpr rep
54 mantissa() const noexcept;
55 constexpr int
56 exponent() const noexcept;
57
58 constexpr Number
59 operator+() const noexcept;
60 constexpr Number
61 operator-() const noexcept;
62 Number&
63 operator++();
64 Number
65 operator++(int);
66 Number&
67 operator--();
68 Number
69 operator--(int);
70
71 Number&
72 operator+=(Number const& x);
73 Number&
74 operator-=(Number const& x);
75
76 Number&
77 operator*=(Number const& x);
78 Number&
79 operator/=(Number const& x);
80
81 static constexpr Number
82 min() noexcept;
83 static constexpr Number
84 max() noexcept;
85 static constexpr Number
86 lowest() noexcept;
87
93 explicit
94 operator rep() const; // round to nearest, even on tie
95
96 friend constexpr bool
97 operator==(Number const& x, Number const& y) noexcept
98 {
99 return x.mantissa_ == y.mantissa_ && x.exponent_ == y.exponent_;
100 }
101
102 friend constexpr bool
103 operator!=(Number const& x, Number const& y) noexcept
104 {
105 return !(x == y);
106 }
107
108 friend constexpr bool
109 operator<(Number const& x, Number const& y) noexcept
110 {
111 // If the two amounts have different signs (zero is treated as positive)
112 // then the comparison is true iff the left is negative.
113 bool const lneg = x.mantissa_ < 0;
114 bool const rneg = y.mantissa_ < 0;
115
116 if (lneg != rneg)
117 return lneg;
118
119 // Both have same sign and the left is zero: the right must be
120 // greater than 0.
121 if (x.mantissa_ == 0)
122 return y.mantissa_ > 0;
123
124 // Both have same sign, the right is zero and the left is non-zero.
125 if (y.mantissa_ == 0)
126 return false;
127
128 // Both have the same sign, compare by exponents:
129 if (x.exponent_ > y.exponent_)
130 return lneg;
131 if (x.exponent_ < y.exponent_)
132 return !lneg;
133
134 // If equal exponents, compare mantissas
135 return x.mantissa_ < y.mantissa_;
136 }
137
139 constexpr int
140 signum() const noexcept
141 {
142 return (mantissa_ < 0) ? -1 : (mantissa_ ? 1 : 0);
143 }
144
145 Number
146 truncate() const noexcept;
147
148 friend constexpr bool
149 operator>(Number const& x, Number const& y) noexcept
150 {
151 return y < x;
152 }
153
154 friend constexpr bool
155 operator<=(Number const& x, Number const& y) noexcept
156 {
157 return !(y < x);
158 }
159
160 friend constexpr bool
161 operator>=(Number const& x, Number const& y) noexcept
162 {
163 return !(x < y);
164 }
165
167 operator<<(std::ostream& os, Number const& x)
168 {
169 return os << to_string(x);
170 }
171
172 // Thread local rounding control. Default is to_nearest
174 static rounding_mode
175 getround();
176 // Returns previously set mode
177 static rounding_mode
179
180private:
181 static thread_local rounding_mode mode_;
182
183 void
184 normalize();
185 constexpr bool
186 isnormal() const noexcept;
187
188 class Guard;
189};
190
191constexpr static Number numZero{};
192
193inline constexpr Number::Number(rep mantissa, int exponent, unchecked) noexcept
195{
196}
197
203
204inline Number::Number(rep mantissa) : Number{mantissa, 0}
205{
206}
207
208inline constexpr Number::rep
209Number::mantissa() const noexcept
210{
211 return mantissa_;
212}
213
214inline constexpr int
215Number::exponent() const noexcept
216{
217 return exponent_;
218}
219
220inline constexpr Number
221Number::operator+() const noexcept
222{
223 return *this;
224}
225
226inline constexpr Number
227Number::operator-() const noexcept
228{
229 auto x = *this;
230 x.mantissa_ = -x.mantissa_;
231 return x;
232}
233
234inline Number&
236{
237 *this += Number{1000000000000000, -15, unchecked{}};
238 return *this;
239}
240
241inline Number
243{
244 auto x = *this;
245 ++(*this);
246 return x;
247}
248
249inline Number&
251{
252 *this -= Number{1000000000000000, -15, unchecked{}};
253 return *this;
254}
255
256inline Number
258{
259 auto x = *this;
260 --(*this);
261 return x;
262}
263
264inline Number&
266{
267 return *this += -x;
268}
269
270inline Number
271operator+(Number const& x, Number const& y)
272{
273 auto z = x;
274 z += y;
275 return z;
276}
277
278inline Number
279operator-(Number const& x, Number const& y)
280{
281 auto z = x;
282 z -= y;
283 return z;
284}
285
286inline Number
287operator*(Number const& x, Number const& y)
288{
289 auto z = x;
290 z *= y;
291 return z;
292}
293
294inline Number
295operator/(Number const& x, Number const& y)
296{
297 auto z = x;
298 z /= y;
299 return z;
300}
301
302inline constexpr Number
303Number::min() noexcept
304{
306}
307
308inline constexpr Number
309Number::max() noexcept
310{
312}
313
314inline constexpr Number
316{
318}
319
320inline constexpr bool
321Number::isnormal() const noexcept
322{
323 auto const abs_m = mantissa_ < 0 ? -mantissa_ : mantissa_;
324 return minMantissa <= abs_m && abs_m <= maxMantissa &&
326}
327
328inline constexpr Number
329abs(Number x) noexcept
330{
331 if (x < Number{})
332 x = -x;
333 return x;
334}
335
336// Returns f^n
337// Uses a log_2(n) number of multiplications
338
339Number
340power(Number const& f, unsigned n);
341
342// Returns f^(1/d)
343// Uses Newton–Raphson iterations until the result stops changing
344// to find the root of the polynomial g(x) = x^d - f
345
346Number
347root(Number f, unsigned d);
348
349Number
350root2(Number f);
351
352// Returns f^(n/d)
353
354Number
355power(Number const& f, unsigned n, unsigned d);
356
357// Return 0 if abs(x) < limit, else returns x
358
359inline constexpr Number
360squelch(Number const& x, Number const& limit) noexcept
361{
362 if (abs(x) < limit)
363 return Number{};
364 return x;
365}
366
384
385// saveNumberRoundMode doesn't do quite enough for us. What we want is a
386// Number::RoundModeGuard that sets the new mode and restores the old mode
387// when it leaves scope. Since Number doesn't have that facility, we'll
388// build it here.
404
405} // namespace xrpl
406
407#endif // XRPL_BASICS_NUMBER_H_INCLUDED
NumberRoundModeGuard & operator=(NumberRoundModeGuard const &)=delete
NumberRoundModeGuard(NumberRoundModeGuard const &)=delete
NumberRoundModeGuard(Number::rounding_mode mode) noexcept
Definition Number.h:394
saveNumberRoundMode saved_
Definition Number.h:391
Number & operator++()
Definition Number.h:235
friend constexpr bool operator<(Number const &x, Number const &y) noexcept
Definition Number.h:109
static rounding_mode getround()
Definition Number.cpp:28
constexpr rep mantissa() const noexcept
Definition Number.h:209
static rounding_mode setround(rounding_mode mode)
Definition Number.cpp:34
static constexpr Number lowest() noexcept
Definition Number.h:315
constexpr bool isnormal() const noexcept
Definition Number.h:321
Number truncate() const noexcept
Definition Number.cpp:506
constexpr Number operator-() const noexcept
Definition Number.h:227
static thread_local rounding_mode mode_
Definition Number.h:181
static constexpr Number max() noexcept
Definition Number.h:309
static constexpr int minExponent
Definition Number.h:39
constexpr Number operator+() const noexcept
Definition Number.h:221
Number & operator--()
Definition Number.h:250
friend constexpr bool operator!=(Number const &x, Number const &y) noexcept
Definition Number.h:103
static constexpr std::int64_t maxMantissa
Definition Number.h:35
friend constexpr bool operator>=(Number const &x, Number const &y) noexcept
Definition Number.h:161
constexpr int exponent() const noexcept
Definition Number.h:215
static constexpr int maxExponent
Definition Number.h:40
rep mantissa_
Definition Number.h:28
friend std::ostream & operator<<(std::ostream &os, Number const &x)
Definition Number.h:167
constexpr int signum() const noexcept
Return the sign of the amount.
Definition Number.h:140
static constexpr Number min() noexcept
Definition Number.h:303
Number & operator-=(Number const &x)
Definition Number.h:265
int exponent_
Definition Number.h:29
static constexpr std::int64_t minMantissa
Definition Number.h:33
void normalize()
Definition Number.cpp:226
constexpr Number()=default
friend constexpr bool operator<=(Number const &x, Number const &y) noexcept
Definition Number.h:155
Number::rounding_mode mode_
Definition Number.h:369
saveNumberRoundMode(Number::rounding_mode mode) noexcept
Definition Number.h:376
saveNumberRoundMode(saveNumberRoundMode const &)=delete
saveNumberRoundMode & operator=(saveNumberRoundMode const &)=delete
T lowest(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
constexpr base_uint< Bits, Tag > operator+(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition base_uint.h:603
Number operator-(Number const &x, Number const &y)
Definition Number.h:279
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
static constexpr Number numZero
Definition Number.h:191
Number operator/(Number const &x, Number const &y)
Definition Number.h:295
Number root(Number f, unsigned d)
Definition Number.cpp:644
Number power(Number const &f, unsigned n)
Definition Number.cpp:621
Number operator*(Number const &x, Number const &y)
Definition Number.h:287
constexpr bool isPowerOfTen(T value)
Definition Number.h:18
Number root2(Number f)
Definition Number.cpp:709
constexpr Number abs(Number x) noexcept
Definition Number.h:329
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition Number.h:360