rippled
Number.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2022 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_BASICS_NUMBER_H_INCLUDED
21 #define RIPPLE_BASICS_NUMBER_H_INCLUDED
22 
23 #include <ripple/basics/XRPAmount.h>
24 #include <cstdint>
25 #include <limits>
26 #include <ostream>
27 #include <string>
28 
29 namespace ripple {
30 
31 class Number;
32 
34 to_string(Number const& amount);
35 
36 class Number
37 {
38  using rep = std::int64_t;
41 
42 public:
43  struct unchecked
44  {
45  explicit unchecked() = default;
46  };
47 
48  explicit constexpr Number() = default;
49 
51  explicit Number(rep mantissa, int exponent);
52  explicit constexpr Number(rep mantissa, int exponent, unchecked) noexcept;
53 
54  Number(XRPAmount const& x);
55 
56  constexpr rep
57  mantissa() const noexcept;
58  constexpr int
59  exponent() const noexcept;
60 
61  constexpr Number
62  operator+() const noexcept;
63  constexpr Number
64  operator-() const noexcept;
65  Number&
66  operator++();
67  Number
68  operator++(int);
69  Number&
70  operator--();
71  Number
72  operator--(int);
73 
74  Number&
75  operator+=(Number const& x);
76  Number&
77  operator-=(Number const& x);
78 
79  Number&
80  operator*=(Number const& x);
81  Number&
82  operator/=(Number const& x);
83 
84  static constexpr Number
85  min() noexcept;
86  static constexpr Number
87  max() noexcept;
88  static constexpr Number
89  lowest() noexcept;
90 
91  explicit operator XRPAmount() const; // round to nearest, even on tie
92  explicit operator rep() const; // round to nearest, even on tie
93 
94  friend constexpr bool
95  operator==(Number const& x, Number const& y) noexcept
96  {
97  return x.mantissa_ == y.mantissa_ && x.exponent_ == y.exponent_;
98  }
99 
100  friend constexpr bool
101  operator!=(Number const& x, Number const& y) noexcept
102  {
103  return !(x == y);
104  }
105 
106  friend constexpr bool
107  operator<(Number const& x, Number const& y) noexcept
108  {
109  // If the two amounts have different signs (zero is treated as positive)
110  // then the comparison is true iff the left is negative.
111  bool const lneg = x.mantissa_ < 0;
112  bool const rneg = y.mantissa_ < 0;
113 
114  if (lneg != rneg)
115  return lneg;
116 
117  // Both have same sign and the left is zero: the right must be
118  // greater than 0.
119  if (x.mantissa_ == 0)
120  return y.mantissa_ > 0;
121 
122  // Both have same sign, the right is zero and the left is non-zero.
123  if (y.mantissa_ == 0)
124  return false;
125 
126  // Both have the same sign, compare by exponents:
127  if (x.exponent_ > y.exponent_)
128  return lneg;
129  if (x.exponent_ < y.exponent_)
130  return !lneg;
131 
132  // If equal exponents, compare mantissas
133  return x.mantissa_ < y.mantissa_;
134  }
135 
136  friend constexpr bool
137  operator>(Number const& x, Number const& y) noexcept
138  {
139  return y < x;
140  }
141 
142  friend constexpr bool
143  operator<=(Number const& x, Number const& y) noexcept
144  {
145  return !(y < x);
146  }
147 
148  friend constexpr bool
149  operator>=(Number const& x, Number const& y) noexcept
150  {
151  return !(x < y);
152  }
153 
154  friend std::ostream&
156  {
157  return os << to_string(x);
158  }
159 
160  // Thread local rounding control. Default is to_nearest
162  static rounding_mode
163  getround();
164  // Returns previously set mode
165  static rounding_mode
166  setround(rounding_mode mode);
167 
168 private:
169  static thread_local rounding_mode mode_;
170 
171  void
172  normalize();
173  constexpr bool
174  isnormal() const noexcept;
175 
176  // The range for the mantissa when normalized
177  constexpr static std::int64_t minMantissa = 1'000'000'000'000'000LL;
178  constexpr static std::int64_t maxMantissa = 9'999'999'999'999'999LL;
179 
180  // The range for the exponent when normalized
181  constexpr static int minExponent = -32768;
182  constexpr static int maxExponent = 32768;
183 
184  class Guard;
185 };
186 
187 inline constexpr Number::Number(rep mantissa, int exponent, unchecked) noexcept
189 {
190 }
191 
193  : mantissa_{mantissa}, exponent_{exponent}
194 {
195  normalize();
196 }
197 
198 inline Number::Number(rep mantissa) : Number{mantissa, 0}
199 {
200 }
201 
202 inline Number::Number(XRPAmount const& x) : Number{x.drops()}
203 {
204 }
205 
206 inline constexpr Number::rep
207 Number::mantissa() const noexcept
208 {
209  return mantissa_;
210 }
211 
212 inline constexpr int
213 Number::exponent() const noexcept
214 {
215  return exponent_;
216 }
217 
218 inline constexpr Number
219 Number::operator+() const noexcept
220 {
221  return *this;
222 }
223 
224 inline constexpr Number
225 Number::operator-() const noexcept
226 {
227  auto x = *this;
228  x.mantissa_ = -x.mantissa_;
229  return x;
230 }
231 
232 inline Number&
234 {
235  *this += Number{1000000000000000, -15, unchecked{}};
236  return *this;
237 }
238 
239 inline Number
241 {
242  auto x = *this;
243  ++(*this);
244  return x;
245 }
246 
247 inline Number&
249 {
250  *this -= Number{1000000000000000, -15, unchecked{}};
251  return *this;
252 }
253 
254 inline Number
256 {
257  auto x = *this;
258  --(*this);
259  return x;
260 }
261 
262 inline Number&
264 {
265  return *this += -x;
266 }
267 
268 inline Number
269 operator+(Number const& x, Number const& y)
270 {
271  auto z = x;
272  z += y;
273  return z;
274 }
275 
276 inline Number
277 operator-(Number const& x, Number const& y)
278 {
279  auto z = x;
280  z -= y;
281  return z;
282 }
283 
284 inline Number
285 operator*(Number const& x, Number const& y)
286 {
287  auto z = x;
288  z *= y;
289  return z;
290 }
291 
292 inline Number
293 operator/(Number const& x, Number const& y)
294 {
295  auto z = x;
296  z /= y;
297  return z;
298 }
299 
300 inline constexpr Number
301 Number::min() noexcept
302 {
304 }
305 
306 inline constexpr Number
307 Number::max() noexcept
308 {
310 }
311 
312 inline constexpr Number
313 Number::lowest() noexcept
314 {
316 }
317 
318 inline constexpr bool
319 Number::isnormal() const noexcept
320 {
321  auto const abs_m = mantissa_ < 0 ? -mantissa_ : mantissa_;
322  return minMantissa <= abs_m && abs_m <= maxMantissa &&
324 }
325 
326 inline constexpr Number
327 abs(Number x) noexcept
328 {
329  if (x < Number{})
330  x = -x;
331  return x;
332 }
333 
334 // Returns f^n
335 // Uses a log_2(n) number of multiplications
336 
337 Number
338 power(Number const& f, unsigned n);
339 
340 // Returns f^(1/d)
341 // Uses Newton–Raphson iterations until the result stops changing
342 // to find the root of the polynomial g(x) = x^d - f
343 
344 Number
345 root(Number f, unsigned d);
346 
347 Number
348 root2(Number f);
349 
350 // Returns f^(n/d)
351 
352 Number
353 power(Number const& f, unsigned n, unsigned d);
354 
355 // Return 0 if abs(x) < limit, else returns x
356 
357 inline constexpr Number
358 squelch(Number const& x, Number const& limit) noexcept
359 {
360  if (abs(x) < limit)
361  return Number{};
362  return x;
363 }
364 
366 {
368 
369 public:
371  {
373  }
375  : mode_{mode}
376  {
377  }
378  saveNumberRoundMode(saveNumberRoundMode const&) = delete;
380  operator=(saveNumberRoundMode const&) = delete;
381 };
382 
383 } // namespace ripple
384 
385 #endif // RIPPLE_BASICS_NUMBER_H_INCLUDED
ripple::Number::lowest
static constexpr Number lowest() noexcept
Definition: Number.h:313
ripple::Number::operator<=
constexpr friend bool operator<=(Number const &x, Number const &y) noexcept
Definition: Number.h:143
ripple::Number::getround
static rounding_mode getround()
Definition: Number.cpp:41
ripple::root2
Number root2(Number f)
Definition: Number.cpp:689
ripple::Number::maxMantissa
constexpr static std::int64_t maxMantissa
Definition: Number.h:178
std::string
STL class.
ripple::Number::operator-=
Number & operator-=(Number const &x)
Definition: Number.h:263
ripple::XRPAmount::drops
constexpr value_type drops() const
Returns the number of drops.
Definition: XRPAmount.h:172
ripple::saveNumberRoundMode
Definition: Number.h:365
ripple::operator-
Number operator-(Number const &x, Number const &y)
Definition: Number.h:277
ripple::squelch
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition: Number.h:358
ripple::Number::exponent
constexpr int exponent() const noexcept
Definition: Number.h:213
ripple::Number::min
static constexpr Number min() noexcept
Definition: Number.h:301
ripple::Number::isnormal
constexpr bool isnormal() const noexcept
Definition: Number.h:319
ripple::Number::rounding_mode
rounding_mode
Definition: Number.h:161
ripple::Number::downward
@ downward
Definition: Number.h:161
ripple::Number::operator-
constexpr Number operator-() const noexcept
Definition: Number.h:225
std::numeric_limits::lowest
T lowest(T... args)
ripple::Number::operator!=
constexpr friend bool operator!=(Number const &x, Number const &y) noexcept
Definition: Number.h:101
ripple::Number::normalize
void normalize()
Definition: Number.cpp:172
ripple::Number::operator++
Number & operator++()
Definition: Number.h:233
ripple::Number::exponent_
int exponent_
Definition: Number.h:40
ripple::Number
Definition: Number.h:36
ripple::Number::mode_
static thread_local rounding_mode mode_
Definition: Number.h:169
ripple::operator+
constexpr base_uint< Bits, Tag > operator+(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:613
ripple::Number::setround
static rounding_mode setround(rounding_mode mode)
Definition: Number.cpp:47
std::ostream
STL class.
ripple::Number::towards_zero
@ towards_zero
Definition: Number.h:161
ripple::Number::maxExponent
constexpr static int maxExponent
Definition: Number.h:182
ripple::Number::operator+
constexpr Number operator+() const noexcept
Definition: Number.h:219
ripple::Number::operator--
Number & operator--()
Definition: Number.h:248
cstdint
ripple::Number::max
static constexpr Number max() noexcept
Definition: Number.h:307
std::int64_t
ripple::Number::operator>
constexpr friend bool operator>(Number const &x, Number const &y) noexcept
Definition: Number.h:137
ripple::Number::operator<
constexpr friend bool operator<(Number const &x, Number const &y) noexcept
Definition: Number.h:107
ripple::operator/
Number operator/(Number const &x, Number const &y)
Definition: Number.h:293
ripple::saveNumberRoundMode::mode_
Number::rounding_mode mode_
Definition: Number.h:367
ripple::power
Number power(Number const &f, unsigned n)
Definition: Number.cpp:601
ripple::Number::minExponent
constexpr static int minExponent
Definition: Number.h:181
ripple::Number::upward
@ upward
Definition: Number.h:161
ripple::Number::operator<<
friend std::ostream & operator<<(std::ostream &os, Number const &x)
Definition: Number.h:155
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Number::minMantissa
constexpr static std::int64_t minMantissa
Definition: Number.h:177
ripple::Number::operator>=
constexpr friend bool operator>=(Number const &x, Number const &y) noexcept
Definition: Number.h:149
ripple::saveNumberRoundMode::operator=
saveNumberRoundMode & operator=(saveNumberRoundMode const &)=delete
ripple::abs
constexpr Number abs(Number x) noexcept
Definition: Number.h:327
limits
ripple::Number::mantissa_
rep mantissa_
Definition: Number.h:39
std
STL namespace.
ripple::saveNumberRoundMode::saveNumberRoundMode
saveNumberRoundMode(Number::rounding_mode mode) noexcept
Definition: Number.h:374
ripple::saveNumberRoundMode::~saveNumberRoundMode
~saveNumberRoundMode()
Definition: Number.h:370
ripple::Number::Number
constexpr Number()=default
ripple::Number::rep
std::int64_t rep
Definition: Number.h:38
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::Number::Guard
Definition: Number.cpp:58
ostream
ripple::Number::unchecked
Definition: Number.h:43
ripple::Number::mantissa
constexpr rep mantissa() const noexcept
Definition: Number.h:207
ripple::Number::to_nearest
@ to_nearest
Definition: Number.h:161
ripple::operator*
Number operator*(Number const &x, Number const &y)
Definition: Number.h:285
ripple::Number::unchecked::unchecked
unchecked()=default
ripple::XRPAmount
Definition: XRPAmount.h:46
ripple::root
Number root(Number f, unsigned d)
Definition: Number.cpp:624
string