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