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