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