xrpld
Loading...
Searching...
No Matches
IOUAmount_test.cpp
1#include <xrpl/basics/Number.h>
2#include <xrpl/beast/unit_test/suite.h>
3#include <xrpl/beast/utility/Zero.h>
4#include <xrpl/protocol/IOUAmount.h>
5
6#include <cstdint>
7#include <limits>
8#include <sstream>
9
10namespace xrpl {
11
13{
14public:
15 void
17 {
18 testcase("zero");
19
20 IOUAmount const z(0, 0);
21
22 BEAST_EXPECT(z.mantissa() == 0);
23 BEAST_EXPECT(z.exponent() == -100);
24 BEAST_EXPECT(!z);
25 BEAST_EXPECT(z.signum() == 0);
26 BEAST_EXPECT(z == beast::kZero);
27
28 BEAST_EXPECT((z + z) == z);
29 BEAST_EXPECT((z - z) == z);
30 BEAST_EXPECT(z == -z);
31
32 IOUAmount const zz(beast::kZero);
33 BEAST_EXPECT(z == zz);
34
35 // https://github.com/XRPLF/rippled/issues/5170
36 IOUAmount const zzz{};
37 BEAST_EXPECT(zzz == beast::kZero);
38 // BEAST_EXPECT(zzz == zz);
39 }
40
41 void
43 {
44 testcase("signum");
45
46 IOUAmount const neg(-1, 0);
47 BEAST_EXPECT(neg.signum() < 0);
48
49 IOUAmount const zer(0, 0);
50 BEAST_EXPECT(zer.signum() == 0);
51
52 IOUAmount const pos(1, 0);
53 BEAST_EXPECT(pos.signum() > 0);
54 }
55
56 void
58 {
59 testcase("beast::Zero Comparisons");
60
61 using beast::kZero;
62
63 {
64 IOUAmount const z(kZero);
65 BEAST_EXPECT(z == kZero);
66 BEAST_EXPECT(z >= kZero);
67 BEAST_EXPECT(z <= kZero);
68 unexpected(z != kZero);
69 unexpected(z > kZero);
70 unexpected(z < kZero);
71 }
72
73 {
74 IOUAmount const neg(-2, 0);
75 BEAST_EXPECT(neg < kZero);
76 BEAST_EXPECT(neg <= kZero);
77 BEAST_EXPECT(neg != kZero);
78 unexpected(neg == kZero);
79 }
80
81 {
82 IOUAmount const pos(2, 0);
83 BEAST_EXPECT(pos > kZero);
84 BEAST_EXPECT(pos >= kZero);
85 BEAST_EXPECT(pos != kZero);
86 unexpected(pos == kZero);
87 }
88 }
89
90 void
92 {
93 testcase("IOU Comparisons");
94
95 IOUAmount const n(-2, 0);
96 IOUAmount const z(0, 0);
97 IOUAmount const p(2, 0);
98
99 BEAST_EXPECT(z == z);
100 BEAST_EXPECT(z >= z);
101 BEAST_EXPECT(z <= z);
102 BEAST_EXPECT(z == -z);
103 // NOLINTBEGIN(misc-redundant-expression)
104 unexpected(z > z);
105 unexpected(z < z);
106 unexpected(z != z);
107 // NOLINTEND(misc-redundant-expression)
108 unexpected(z != -z);
109
110 BEAST_EXPECT(n < z);
111 BEAST_EXPECT(n <= z);
112 BEAST_EXPECT(n != z);
113 unexpected(n > z);
114 unexpected(n >= z);
115 unexpected(n == z);
116
117 BEAST_EXPECT(p > z);
118 BEAST_EXPECT(p >= z);
119 BEAST_EXPECT(p != z);
120 unexpected(p < z);
121 unexpected(p <= z);
122 unexpected(p == z);
123
124 BEAST_EXPECT(n < p);
125 BEAST_EXPECT(n <= p);
126 BEAST_EXPECT(n != p);
127 unexpected(n > p);
128 unexpected(n >= p);
129 unexpected(n == p);
130
131 BEAST_EXPECT(p > n);
132 BEAST_EXPECT(p >= n);
133 BEAST_EXPECT(p != n);
134 unexpected(p < n);
135 unexpected(p <= n);
136 unexpected(p == n);
137
138 BEAST_EXPECT(p > -p);
139 BEAST_EXPECT(p >= -p);
140 BEAST_EXPECT(p != -p);
141
142 BEAST_EXPECT(n < -n);
143 BEAST_EXPECT(n <= -n);
144 BEAST_EXPECT(n != -n);
145 }
146
147 void
149 {
150 testcase("IOU strings");
151
152 auto test = [this](IOUAmount const& n, std::string const& expected) {
153 auto const result = to_string(n);
155 ss << "to_string(" << result << "). Expected: " << expected;
156 BEAST_EXPECTS(result == expected, ss.str());
157 };
158
159 for (auto const mantissaSize : MantissaRange::getAllScales())
160 {
161 NumberMantissaScaleGuard const mg(mantissaSize);
162
163 test(IOUAmount(-2, 0), "-2");
164 test(IOUAmount(0, 0), "0");
165 test(IOUAmount(2, 0), "2");
166 test(IOUAmount(25, -3), "0.025");
167 test(IOUAmount(-25, -3), "-0.025");
168 test(IOUAmount(25, 1), "250");
169 test(IOUAmount(-25, 1), "-250");
170 test(IOUAmount(2, 20), "2e20");
171 test(IOUAmount(-2, -20), "-2e-20");
172 }
173 }
174
175 void
177 {
178 testcase("mulRatio");
179
180 /* The range for the mantissa when normalized */
181 static constexpr std::int64_t kMinMantissa = 1000000000000000ull;
182 static constexpr std::int64_t kMaxMantissa = 9999999999999999ull;
183 // log(2,maxMantissa) ~ 53.15
184 /* The range for the exponent when normalized */
185 static constexpr int kMinExponent = -96;
186 static constexpr int kMaxExponent = 80;
187 constexpr auto kMaxUInt = std::numeric_limits<std::uint32_t>::max();
188
189 {
190 // multiply by a number that would overflow the mantissa, then
191 // divide by the same number, and check we didn't lose any value
192 IOUAmount const bigMan(kMaxMantissa, 0);
193 BEAST_EXPECT(bigMan == mulRatio(bigMan, kMaxUInt, kMaxUInt, true));
194 // rounding mode shouldn't matter as the result is exact
195 BEAST_EXPECT(bigMan == mulRatio(bigMan, kMaxUInt, kMaxUInt, false));
196 }
197 {
198 // Similar test as above, but for negative values
199 IOUAmount const bigMan(-kMaxMantissa, 0);
200 BEAST_EXPECT(bigMan == mulRatio(bigMan, kMaxUInt, kMaxUInt, true));
201 // rounding mode shouldn't matter as the result is exact
202 BEAST_EXPECT(bigMan == mulRatio(bigMan, kMaxUInt, kMaxUInt, false));
203 }
204
205 {
206 // small amounts
208 // Round up should give the smallest allowable number
209 BEAST_EXPECT(tiny == mulRatio(tiny, 1, kMaxUInt, true));
210 BEAST_EXPECT(tiny == mulRatio(tiny, kMaxUInt - 1, kMaxUInt, true));
211 // rounding down should be zero
212 BEAST_EXPECT(beast::kZero == mulRatio(tiny, 1, kMaxUInt, false));
213 BEAST_EXPECT(beast::kZero == mulRatio(tiny, kMaxUInt - 1, kMaxUInt, false));
214
215 // tiny negative numbers
216 IOUAmount const tinyNeg(-kMinMantissa, kMinExponent);
217 // Round up should give zero
218 BEAST_EXPECT(beast::kZero == mulRatio(tinyNeg, 1, kMaxUInt, true));
219 BEAST_EXPECT(beast::kZero == mulRatio(tinyNeg, kMaxUInt - 1, kMaxUInt, true));
220 // rounding down should be tiny
221 BEAST_EXPECT(tinyNeg == mulRatio(tinyNeg, 1, kMaxUInt, false));
222 BEAST_EXPECT(tinyNeg == mulRatio(tinyNeg, kMaxUInt - 1, kMaxUInt, false));
223 }
224
225 { // rounding
226 {
227 IOUAmount const one(1, 0);
228 auto const rup = mulRatio(one, kMaxUInt - 1, kMaxUInt, true);
229 auto const rdown = mulRatio(one, kMaxUInt - 1, kMaxUInt, false);
230 BEAST_EXPECT(rup.mantissa() - rdown.mantissa() == 1);
231 }
232 {
234 auto const rup = mulRatio(big, kMaxUInt - 1, kMaxUInt, true);
235 auto const rdown = mulRatio(big, kMaxUInt - 1, kMaxUInt, false);
236 BEAST_EXPECT(rup.mantissa() - rdown.mantissa() == 1);
237 }
238
239 {
240 IOUAmount const negOne(-1, 0);
241 auto const rup = mulRatio(negOne, kMaxUInt - 1, kMaxUInt, true);
242 auto const rdown = mulRatio(negOne, kMaxUInt - 1, kMaxUInt, false);
243 BEAST_EXPECT(rup.mantissa() - rdown.mantissa() == 1);
244 }
245 }
246
247 {
248 // division by zero
249 IOUAmount one(1, 0);
250 except([&] { mulRatio(one, 1, 0, true); });
251 }
252
253 {
254 // overflow
256 except([&] { mulRatio(big, 2, 0, true); });
257 }
258 } // namespace xrpl
259
260 //--------------------------------------------------------------------------
261
262 void
263 run() override
264 {
265 testZero();
266 testSigNum();
269 testToString();
270 testMulRatio();
271 }
272};
273
275
276} // namespace xrpl
A testsuite class.
Definition suite.h:50
bool except(F &&f, String const &reason)
Definition suite.h:433
bool unexpected(Condition shouldBeFalse, String const &reason)
Definition suite.h:484
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
void run() override
Runs the suite.
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:24
mantissa_type mantissa() const noexcept
Definition IOUAmount.h:165
exponent_type exponent() const noexcept
Definition IOUAmount.h:159
int signum() const noexcept
Return the sign of the amount.
Definition IOUAmount.h:151
Sets the new scale and restores the old scale when it leaves scope.
Definition Number.h:920
T max(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
static constexpr int kMinExponent
Definition IOUAmount.cpp:25
static constexpr std::int64_t kMinMantissa
Definition IOUAmount.cpp:22
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
IOUAmount mulRatio(IOUAmount const &amt, std::uint32_t num, std::uint32_t den, bool roundUp)
Definition IOUAmount.cpp:93
static constexpr std::int64_t kMaxMantissa
Definition IOUAmount.cpp:23
static constexpr int kMaxExponent
Definition IOUAmount.cpp:26
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl)
T str(T... args)
static std::set< MantissaScale > const & getAllScales()
Definition Number.cpp:37