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