xrpld
Loading...
Searching...
No Matches
Quality.h
1#pragma once
2
3#include <xrpl/beast/utility/Zero.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/protocol/AmountConversions.h>
6#include <xrpl/protocol/STAmount.h>
7
8#include <algorithm>
9#include <cmath>
10#include <concepts>
11#include <cstdint>
12#include <ostream>
13#include <utility>
14
15namespace xrpl {
16
27template <class In, class Out>
29{
30 TAmounts() = default;
31
33 {
34 }
35
36 TAmounts(In in, Out out) : in(std::move(in)), out(std::move(out))
37 {
38 }
39
43 [[nodiscard]] bool
44 empty() const noexcept
45 {
46 return in <= beast::kZero || out <= beast::kZero;
47 }
48
50 operator+=(TAmounts const& rhs)
51 {
52 in += rhs.in;
53 out += rhs.out;
54 return *this;
55 }
56
58 operator-=(TAmounts const& rhs)
59 {
60 in -= rhs.in;
61 out -= rhs.out;
62 return *this;
63 }
64
65 In in{};
67};
68
70
71template <class In, class Out>
72bool
73operator==(TAmounts<In, Out> const& lhs, TAmounts<In, Out> const& rhs) noexcept
74{
75 return lhs.in == rhs.in && lhs.out == rhs.out;
76}
77
78//------------------------------------------------------------------------------
79
80// XRPL specific constant used for parsing qualities and other things
81#define QUALITY_ONE 1'000'000'000
82
90{
91public:
92 // Type of the internal representation. Higher qualities
93 // have lower unsigned integer representations.
95
96 static int const kMinTickSize = 3;
97 static int const kMaxTickSize = 16;
98
99private:
100 // This has the same representation as STAmount, see the comment on the
101 // STAmount. However, this class does not always use the canonical
102 // representation. In particular, the increment and decrement operators may
103 // cause a non-canonical representation.
105
106public:
107 Quality() = default;
108
112 explicit Quality(std::uint64_t value);
113
117 explicit Quality(Amounts const& amount);
118
122 template <class In, class Out>
123 explicit Quality(TAmounts<In, Out> const& amount)
124 : Quality(Amounts(toSTAmount(amount.in), toSTAmount(amount.out)))
125 {
126 }
127
131 template <class In, class Out>
132 Quality(Out const& out, In const& in) : Quality(Amounts(toSTAmount(in), toSTAmount(out)))
133 {
134 }
135
140 Quality&
141 operator++();
142
143 Quality
144 operator++(int);
146
151 Quality&
152 operator--();
153
154 Quality
155 operator--(int);
157
161 [[nodiscard]] STAmount
162 rate() const
163 {
165 }
166
171 [[nodiscard]] Quality
172 round(int tickSize) const;
173
179 [[nodiscard]] Amounts
180 ceilIn(Amounts const& amount, STAmount const& limit) const;
181
182 template <class In, class Out>
183 [[nodiscard]] TAmounts<In, Out>
184 ceilIn(TAmounts<In, Out> const& amount, In const& limit) const;
185
186 // Some of the underlying rounding functions called by ceil_in() ignored
187 // low order bits that could influence rounding decisions. This "strict"
188 // method uses underlying functions that pay attention to all the bits.
189 [[nodiscard]] Amounts
190 ceilInStrict(Amounts const& amount, STAmount const& limit, bool roundUp) const;
191
192 template <class In, class Out>
193 [[nodiscard]] TAmounts<In, Out>
194 ceilInStrict(TAmounts<In, Out> const& amount, In const& limit, bool roundUp) const;
195
201 [[nodiscard]] Amounts
202 ceilOut(Amounts const& amount, STAmount const& limit) const;
203
204 template <class In, class Out>
205 [[nodiscard]] TAmounts<In, Out>
206 ceilOut(TAmounts<In, Out> const& amount, Out const& limit) const;
207
208 // Some of the underlying rounding functions called by ceil_out() ignored
209 // low order bits that could influence rounding decisions. This "strict"
210 // method uses underlying functions that pay attention to all the bits.
211 [[nodiscard]] Amounts
212 ceilOutStrict(Amounts const& amount, STAmount const& limit, bool roundUp) const;
213
214 template <class In, class Out>
215 [[nodiscard]] TAmounts<In, Out>
216 ceilOutStrict(TAmounts<In, Out> const& amount, Out const& limit, bool roundUp) const;
217
218private:
219 // The ceil_in and ceil_out methods that deal in TAmount all convert
220 // their arguments to STAmount and convert the result back to TAmount.
221 // This helper function takes care of all the conversion operations.
222 template <class In, class Out, class Lim, typename FnPtr, std::same_as<bool>... Round>
223 [[nodiscard]] TAmounts<In, Out>
225 TAmounts<In, Out> const& amount,
226 Lim const& limit,
227 Lim const& limitCmp,
228 FnPtr ceilFunction,
229 Round... round) const;
230
231public:
237 friend bool
238 operator<(Quality const& lhs, Quality const& rhs) noexcept
239 {
240 return lhs.value_ > rhs.value_;
241 }
242
243 friend bool
244 operator>(Quality const& lhs, Quality const& rhs) noexcept
245 {
246 return lhs.value_ < rhs.value_;
247 }
248
249 friend bool
250 operator<=(Quality const& lhs, Quality const& rhs) noexcept
251 {
252 return !(lhs > rhs);
253 }
254
255 friend bool
256 operator>=(Quality const& lhs, Quality const& rhs) noexcept
257 {
258 return !(lhs < rhs);
259 }
260
261 friend bool
262 operator==(Quality const& lhs, Quality const& rhs) noexcept
263 {
264 return lhs.value_ == rhs.value_;
265 }
266
268 operator<<(std::ostream& os, Quality const& quality)
269 {
270 os << quality.value_;
271 return os;
272 }
273
274 // return the relative distance (relative error) between two qualities. This
275 // is used for testing only. relative distance is abs(a-b)/min(a,b)
276 friend double
277 relativeDistance(Quality const& q1, Quality const& q2)
278 {
279 XRPL_ASSERT(
280 q1.value_ > 0 && q2.value_ > 0, "xrpl::Quality::relativeDistance : minimum inputs");
281
282 if (q1.value_ == q2.value_) // make expected common case fast
283 return 0;
284
285 auto const [minV, maxV] = std::minmax(q1.value_, q2.value_);
286
287 auto mantissa = [](std::uint64_t rate) { return rate & ~(255ull << (64 - 8)); };
288 auto exponent = [](std::uint64_t rate) { return static_cast<int>(rate >> (64 - 8)) - 100; };
289
290 auto const minVMantissa = mantissa(minV);
291 auto const maxVMantissa = mantissa(maxV);
292 auto const expDiff = exponent(maxV) - exponent(minV);
293
294 auto const minVD = static_cast<double>(minVMantissa);
295 double const maxVD =
296 (expDiff != 0) ? maxVMantissa * pow(10, expDiff) : static_cast<double>(maxVMantissa);
297
298 // maxVD and minVD are scaled so they have the same exponents. Dividing
299 // cancels out the exponents, so we only need to deal with the (scaled)
300 // mantissas
301 return (maxVD - minVD) / minVD;
302 }
303};
304
305template <class In, class Out, class Lim, typename FnPtr, std::same_as<bool>... Round>
306TAmounts<In, Out>
308 TAmounts<In, Out> const& amount,
309 Lim const& limit,
310 Lim const& limitCmp,
311 FnPtr ceilFunction,
312 Round... roundUp) const
313{
314 if (limitCmp <= limit)
315 return amount;
316
317 // Use the existing STAmount implementation for now, but consider
318 // replacing with code specific to IOUAMount and XRPAmount
319 Amounts const stAmt(toSTAmount(amount.in), toSTAmount(amount.out));
320 STAmount const stLim(toSTAmount(limit));
321 Amounts const stRes = ((*this).*ceilFunction)(stAmt, stLim, roundUp...);
322 return TAmounts<In, Out>(toAmount<In>(stRes.in), toAmount<Out>(stRes.out));
323}
324
325template <class In, class Out>
327Quality::ceilIn(TAmounts<In, Out> const& amount, In const& limit) const
328{
329 // Construct a function pointer to the function we want to call.
330 static constexpr Amounts (Quality::*kCeilInFnPtr)(Amounts const&, STAmount const&) const =
332
333 return ceilTAmountsHelper(amount, limit, amount.in, kCeilInFnPtr);
334}
335
336template <class In, class Out>
338Quality::ceilInStrict(TAmounts<In, Out> const& amount, In const& limit, bool roundUp) const
339{
340 // Construct a function pointer to the function we want to call.
341 static constexpr Amounts (Quality::*kCeilInFnPtr)(Amounts const&, STAmount const&, bool) const =
343
344 return ceilTAmountsHelper(amount, limit, amount.in, kCeilInFnPtr, roundUp);
345}
346
347template <class In, class Out>
349Quality::ceilOut(TAmounts<In, Out> const& amount, Out const& limit) const
350{
351 // Construct a function pointer to the function we want to call.
352 static constexpr Amounts (Quality::*kCeilOutFnPtr)(Amounts const&, STAmount const&) const =
354
355 return ceil_TAmounts_helper(amount, limit, amount.out, kCeilOutFnPtr);
356}
357
358template <class In, class Out>
360Quality::ceilOutStrict(TAmounts<In, Out> const& amount, Out const& limit, bool roundUp) const
361{
362 // Construct a function pointer to the function we want to call.
363 static constexpr Amounts (Quality::*kCeilOutFnPtr)(Amounts const&, STAmount const&, bool)
364 const = &Quality::ceilOutStrict;
365
366 return ceilTAmountsHelper(amount, limit, amount.out, kCeilOutFnPtr, roundUp);
367}
368
375composedQuality(Quality const& lhs, Quality const& rhs);
376
377} // namespace xrpl
Represents the logical ratio of output currency to input currency.
Definition Quality.h:90
Quality & operator++()
Advances to the next higher quality level.
Definition Quality.cpp:22
static int const kMaxTickSize
Definition Quality.h:97
TAmounts< In, Out > ceilTAmountsHelper(TAmounts< In, Out > const &amount, Lim const &limit, Lim const &limitCmp, FnPtr ceilFunction, Round... round) const
Definition Quality.h:307
STAmount rate() const
Returns the quality as STAmount.
Definition Quality.h:162
Quality round(int tickSize) const
Returns the quality rounded up to the specified number of decimal digits.
Definition Quality.cpp:134
friend std::ostream & operator<<(std::ostream &os, Quality const &quality)
Definition Quality.h:268
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
friend bool operator<=(Quality const &lhs, Quality const &rhs) noexcept
Definition Quality.h:250
friend bool operator<(Quality const &lhs, Quality const &rhs) noexcept
Returns true if lhs is lower quality than rhs.
Definition Quality.h:238
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(TAmounts< In, Out > const &amount)
Create a quality from the ratio of two amounts.
Definition Quality.h:123
static int const kMinTickSize
Definition Quality.h:96
friend bool operator>=(Quality const &lhs, Quality const &rhs) noexcept
Definition Quality.h:256
friend double relativeDistance(Quality const &q1, Quality const &q2)
Definition Quality.h:277
Quality & operator--()
Advances to the next lower quality level.
Definition Quality.cpp:38
std::uint64_t value_type
Definition Quality.h:94
Quality()=default
value_type value_
Definition Quality.h:104
Quality(Out const &out, In const &in)
Create a quality from the ratio of two amounts.
Definition Quality.h:132
friend bool operator>(Quality const &lhs, Quality const &rhs) noexcept
Definition Quality.h:244
friend bool operator==(Quality const &lhs, Quality const &rhs) noexcept
Definition Quality.h:262
T minmax(T... args)
constexpr Zero kZero
Definition Zero.h:30
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
constexpr bool operator==(BaseUInt< Bits, Tag > const &lhs, BaseUInt< Bits, Tag > const &rhs)
Definition base_uint.h:606
TAmounts< STAmount, STAmount > Amounts
Definition Quality.h:69
T toAmount(STAmount const &amt)=delete
STAmount amountFromQuality(std::uint64_t rate)
Definition STAmount.cpp:895
Quality composedQuality(Quality const &lhs, Quality const &rhs)
Calculate the quality of a two-hop path given the two hops.
Definition Quality.cpp:114
STAmount toSTAmount(IOUAmount const &iou, Asset const &asset)
Zero allows classes to offer efficient comparisons to zero.
Definition Zero.h:26
Represents a pair of input and output currencies.
Definition Quality.h:29
TAmounts(In in, Out out)
Definition Quality.h:36
bool empty() const noexcept
Returns true if either quantity is not positive.
Definition Quality.h:44
TAmounts(beast::Zero, beast::Zero)
Definition Quality.h:32
TAmounts & operator+=(TAmounts const &rhs)
Definition Quality.h:50
TAmounts()=default
TAmounts & operator-=(TAmounts const &rhs)
Definition Quality.h:58