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