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