rippled
Loading...
Searching...
No Matches
Quality.cpp
1#include <xrpl/beast/utility/Zero.h>
2#include <xrpl/beast/utility/instrumentation.h>
3#include <xrpl/protocol/Asset.h>
4#include <xrpl/protocol/Quality.h>
5#include <xrpl/protocol/STAmount.h>
6
7#include <cstdint>
8#include <limits>
9
10namespace xrpl {
11
12Quality::Quality(std::uint64_t value) : m_value(value)
13{
14}
15
16Quality::Quality(Amounts const& amount)
17 : m_value(getRate(amount.out, amount.in))
18{
19}
20
21Quality&
22Quality::operator++()
23{
24 XRPL_ASSERT(m_value > 0, "xrpl::Quality::operator++() : minimum value");
25 --m_value;
26 return *this;
27}
28
29Quality
30Quality::operator++(int)
31{
32 Quality prev(*this);
33 ++*this;
34 return prev;
35}
36
37Quality&
38Quality::operator--()
39{
40 XRPL_ASSERT(
42 "xrpl::Quality::operator--() : maximum value");
43 ++m_value;
44 return *this;
45}
46
47Quality
48Quality::operator--(int)
49{
50 Quality prev(*this);
51 --*this;
52 return prev;
53}
54
55template <STAmount (
56 *DivRoundFunc)(STAmount const&, STAmount const&, Asset const&, bool)>
57static Amounts
59 Amounts const& amount,
60 STAmount const& limit,
61 bool roundUp,
62 Quality const& quality)
63{
64 if (amount.in > limit)
65 {
66 Amounts result(
67 limit,
68 DivRoundFunc(limit, quality.rate(), amount.out.asset(), roundUp));
69 // Clamp out
70 if (result.out > amount.out)
71 result.out = amount.out;
72 XRPL_ASSERT(
73 result.in == limit, "xrpl::ceil_in_impl : result matches limit");
74 return result;
75 }
76 XRPL_ASSERT(amount.in <= limit, "xrpl::ceil_in_impl : result inside limit");
77 return amount;
78}
79
80Amounts
81Quality::ceil_in(Amounts const& amount, STAmount const& limit) const
82{
83 return ceil_in_impl<divRound>(amount, limit, /* roundUp */ true, *this);
84}
85
86Amounts
87Quality::ceil_in_strict(
88 Amounts const& amount,
89 STAmount const& limit,
90 bool roundUp) const
91{
92 return ceil_in_impl<divRoundStrict>(amount, limit, roundUp, *this);
93}
94
95template <STAmount (
96 *MulRoundFunc)(STAmount const&, STAmount const&, Asset const&, bool)>
97static Amounts
99 Amounts const& amount,
100 STAmount const& limit,
101 bool roundUp,
102 Quality const& quality)
103{
104 if (amount.out > limit)
105 {
106 Amounts result(
107 MulRoundFunc(limit, quality.rate(), amount.in.asset(), roundUp),
108 limit);
109 // Clamp in
110 if (result.in > amount.in)
111 result.in = amount.in;
112 XRPL_ASSERT(
113 result.out == limit, "xrpl::ceil_out_impl : result matches limit");
114 return result;
115 }
116 XRPL_ASSERT(
117 amount.out <= limit, "xrpl::ceil_out_impl : result inside limit");
118 return amount;
119}
120
121Amounts
122Quality::ceil_out(Amounts const& amount, STAmount const& limit) const
123{
124 return ceil_out_impl<mulRound>(amount, limit, /* roundUp */ true, *this);
125}
126
127Amounts
128Quality::ceil_out_strict(
129 Amounts const& amount,
130 STAmount const& limit,
131 bool roundUp) const
132{
133 return ceil_out_impl<mulRoundStrict>(amount, limit, roundUp, *this);
134}
135
136Quality
137composed_quality(Quality const& lhs, Quality const& rhs)
138{
139 STAmount const lhs_rate(lhs.rate());
140 XRPL_ASSERT(
141 lhs_rate != beast::zero, "xrpl::composed_quality : nonzero left input");
142
143 STAmount const rhs_rate(rhs.rate());
144 XRPL_ASSERT(
145 rhs_rate != beast::zero,
146 "xrpl::composed_quality : nonzero right input");
147
148 STAmount const rate(mulRound(lhs_rate, rhs_rate, lhs_rate.asset(), true));
149
150 std::uint64_t const stored_exponent(rate.exponent() + 100);
151 std::uint64_t const stored_mantissa(rate.mantissa());
152
153 XRPL_ASSERT(
154 (stored_exponent > 0) && (stored_exponent <= 255),
155 "xrpl::composed_quality : valid exponent");
156
157 return Quality((stored_exponent << (64 - 8)) | stored_mantissa);
158}
159
160Quality
161Quality::round(int digits) const
162{
163 // Modulus for mantissa
164 static std::uint64_t const mod[17] = {
165 /* 0 */ 10000000000000000,
166 /* 1 */ 1000000000000000,
167 /* 2 */ 100000000000000,
168 /* 3 */ 10000000000000,
169 /* 4 */ 1000000000000,
170 /* 5 */ 100000000000,
171 /* 6 */ 10000000000,
172 /* 7 */ 1000000000,
173 /* 8 */ 100000000,
174 /* 9 */ 10000000,
175 /* 10 */ 1000000,
176 /* 11 */ 100000,
177 /* 12 */ 10000,
178 /* 13 */ 1000,
179 /* 14 */ 100,
180 /* 15 */ 10,
181 /* 16 */ 1,
182 };
183
184 auto exponent = m_value >> (64 - 8);
185 auto mantissa = m_value & 0x00ffffffffffffffULL;
186 mantissa += mod[digits] - 1;
187 mantissa -= (mantissa % mod[digits]);
188
189 return Quality{(exponent << (64 - 8)) | mantissa};
190}
191
192} // namespace xrpl
Asset const & asset() const
Definition STAmount.h:475
auto const amount
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
Quality composed_quality(Quality const &lhs, Quality const &rhs)
Definition Quality.cpp:137
static Amounts ceil_in_impl(Amounts const &amount, STAmount const &limit, bool roundUp, Quality const &quality)
Definition Quality.cpp:58
static Amounts ceil_out_impl(Amounts const &amount, STAmount const &limit, bool roundUp, Quality const &quality)
Definition Quality.cpp:98
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
Definition STAmount.cpp:443
STAmount mulRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
T prev(T... args)