xrpld
Loading...
Searching...
No Matches
Quality.cpp
1#include <xrpl/protocol/Quality.h>
2
3#include <xrpl/beast/utility/Zero.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/protocol/Asset.h>
6#include <xrpl/protocol/STAmount.h>
7
8#include <cstdint>
9#include <limits>
10
11namespace xrpl {
12
14{
15}
16
17Quality::Quality(Amounts const& amount) : value_(getRate(amount.out, amount.in))
18{
19}
20
23{
24 XRPL_ASSERT(value_ > 0, "xrpl::Quality::operator++() : minimum value");
25 --value_;
26 return *this;
27}
28
31{
32 Quality prev(*this);
33 ++*this;
34 return prev;
35}
36
39{
40 XRPL_ASSERT(
42 "xrpl::Quality::operator--() : maximum value");
43 ++value_;
44 return *this;
45}
46
49{
50 Quality prev(*this);
51 --*this;
52 return prev;
53}
54
55template <STAmount (*DivRoundFunc)(STAmount const&, STAmount const&, Asset const&, bool)>
56static Amounts
57ceilInImpl(Amounts const& amount, STAmount const& limit, bool roundUp, Quality const& quality)
58{
59 if (amount.in > limit)
60 {
61 Amounts result(limit, DivRoundFunc(limit, quality.rate(), amount.out.asset(), roundUp));
62 // Clamp out
63 if (result.out > amount.out)
64 result.out = amount.out;
65 XRPL_ASSERT(result.in == limit, "xrpl::ceilInImpl : result matches limit");
66 return result;
67 }
68 XRPL_ASSERT(amount.in <= limit, "xrpl::ceilInImpl : result inside limit");
69 return amount;
70}
71
73Quality::ceilIn(Amounts const& amount, STAmount const& limit) const
74{
75 return ceilInImpl<divRound>(amount, limit, /* roundUp */ true, *this);
76}
77
79Quality::ceilInStrict(Amounts const& amount, STAmount const& limit, bool roundUp) const
80{
81 return ceilInImpl<divRoundStrict>(amount, limit, roundUp, *this);
82}
83
84template <STAmount (*MulRoundFunc)(STAmount const&, STAmount const&, Asset const&, bool)>
85static Amounts
86ceilOutImpl(Amounts const& amount, STAmount const& limit, bool roundUp, Quality const& quality)
87{
88 if (amount.out > limit)
89 {
90 Amounts result(MulRoundFunc(limit, quality.rate(), amount.in.asset(), roundUp), limit);
91 // Clamp in
92 if (result.in > amount.in)
93 result.in = amount.in;
94 XRPL_ASSERT(result.out == limit, "xrpl::ceilOutImpl : result matches limit");
95 return result;
96 }
97 XRPL_ASSERT(amount.out <= limit, "xrpl::ceilOutImpl : result inside limit");
98 return amount;
99}
100
102Quality::ceilOut(Amounts const& amount, STAmount const& limit) const
103{
104 return ceilOutImpl<mulRound>(amount, limit, /* roundUp */ true, *this);
105}
106
108Quality::ceilOutStrict(Amounts const& amount, STAmount const& limit, bool roundUp) const
109{
110 return ceilOutImpl<mulRoundStrict>(amount, limit, roundUp, *this);
111}
112
114composedQuality(Quality const& lhs, Quality const& rhs)
115{
116 STAmount const lhsRate(lhs.rate());
117 XRPL_ASSERT(lhsRate != beast::kZero, "xrpl::composedQuality : nonzero left input");
118
119 STAmount const rhsRate(rhs.rate());
120 XRPL_ASSERT(rhsRate != beast::kZero, "xrpl::composedQuality : nonzero right input");
121
122 STAmount const rate(mulRound(lhsRate, rhsRate, lhsRate.asset(), true));
123
124 std::uint64_t const storedExponent(rate.exponent() + 100);
125 std::uint64_t const storedMantissa(rate.mantissa());
126
127 XRPL_ASSERT(
128 (storedExponent > 0) && (storedExponent <= 255), "xrpl::composedQuality : valid exponent");
129
130 return Quality((storedExponent << (64 - 8)) | storedMantissa);
131}
132
133Quality
134Quality::round(int digits) const
135{
136 // Modulus for mantissa
137 static std::uint64_t const kMod[17] = {
138 /* 0 */ 10000000000000000,
139 /* 1 */ 1000000000000000,
140 /* 2 */ 100000000000000,
141 /* 3 */ 10000000000000,
142 /* 4 */ 1000000000000,
143 /* 5 */ 100000000000,
144 /* 6 */ 10000000000,
145 /* 7 */ 1000000000,
146 /* 8 */ 100000000,
147 /* 9 */ 10000000,
148 /* 10 */ 1000000,
149 /* 11 */ 100000,
150 /* 12 */ 10000,
151 /* 13 */ 1000,
152 /* 14 */ 100,
153 /* 15 */ 10,
154 /* 16 */ 1,
155 };
156
157 auto exponent = value_ >> (64 - 8);
158 auto mantissa = value_ & 0x00ffffffffffffffULL;
159 mantissa += kMod[digits] - 1;
160 mantissa -= (mantissa % kMod[digits]);
161
162 return Quality{(exponent << (64 - 8)) | mantissa};
163}
164
165} // namespace xrpl
Represents the logical ratio of output currency to input currency.
Definition Quality.h:91
Quality & operator++()
Advances to the next higher quality level.
Definition Quality.cpp:22
STAmount rate() const
Returns the quality as STAmount.
Definition Quality.h:149
Quality round(int tickSize) const
Returns the quality rounded up to the specified number of decimal digits.
Definition Quality.cpp:134
Amounts ceilOut(Amounts const &amount, STAmount const &limit) const
Returns the scaled amount with out capped.
Definition Quality.cpp:102
Amounts ceilIn(Amounts const &amount, STAmount const &limit) const
Returns the scaled amount with in capped.
Definition Quality.cpp:73
Amounts ceilOutStrict(Amounts const &amount, STAmount const &limit, bool roundUp) const
Definition Quality.cpp:108
Amounts ceilInStrict(Amounts const &amount, STAmount const &limit, bool roundUp) const
Definition Quality.cpp:79
Quality & operator--()
Advances to the next lower quality level.
Definition Quality.cpp:38
Quality()=default
value_type value_
Definition Quality.h:105
Asset const & asset() const
Definition STAmount.h:478
T max(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
TAmounts< STAmount, STAmount > Amounts
Definition Quality.h:64
static Amounts ceilOutImpl(Amounts const &amount, STAmount const &limit, bool roundUp, Quality const &quality)
Definition Quality.cpp:86
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
Definition STAmount.cpp:422
STAmount mulRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
static Amounts ceilInImpl(Amounts const &amount, STAmount const &limit, bool roundUp, Quality const &quality)
Definition Quality.cpp:57
Quality composedQuality(Quality const &lhs, Quality const &rhs)
Calculate the quality of a two-hop path given the two hops.
Definition Quality.cpp:114