rippled
Quality.h
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 #ifndef RIPPLE_PROTOCOL_QUALITY_H_INCLUDED
21 #define RIPPLE_PROTOCOL_QUALITY_H_INCLUDED
22 
23 #include <ripple/basics/IOUAmount.h>
24 #include <ripple/basics/XRPAmount.h>
25 #include <ripple/protocol/AmountConversions.h>
26 #include <ripple/protocol/STAmount.h>
27 
28 #include <algorithm>
29 #include <cstdint>
30 #include <ostream>
31 
32 namespace ripple {
33 
43 template <class In, class Out>
44 struct TAmounts
45 {
46  TAmounts() = default;
47 
48  TAmounts(beast::Zero, beast::Zero) : in(beast::zero), out(beast::zero)
49  {
50  }
51 
52  TAmounts(In const& in_, Out const& out_) : in(in_), out(out_)
53  {
54  }
55 
57  bool
58  empty() const noexcept
59  {
60  return in <= beast::zero || out <= beast::zero;
61  }
62 
63  TAmounts&
64  operator+=(TAmounts const& rhs)
65  {
66  in += rhs.in;
67  out += rhs.out;
68  return *this;
69  }
70 
71  TAmounts&
72  operator-=(TAmounts const& rhs)
73  {
74  in -= rhs.in;
75  out -= rhs.out;
76  return *this;
77  }
78 
79  In in;
80  Out out;
81 };
82 
83 using Amounts = TAmounts<STAmount, STAmount>;
84 
85 template <class In, class Out>
86 bool
87 operator==(TAmounts<In, Out> const& lhs, TAmounts<In, Out> const& rhs) noexcept
88 {
89  return lhs.in == rhs.in && lhs.out == rhs.out;
90 }
91 
92 template <class In, class Out>
93 bool
94 operator!=(TAmounts<In, Out> const& lhs, TAmounts<In, Out> const& rhs) noexcept
95 {
96  return !(lhs == rhs);
97 }
98 
99 //------------------------------------------------------------------------------
100 
101 // Ripple specific constant used for parsing qualities and other things
102 #define QUALITY_ONE 1'000'000'000
103 
109 class Quality
110 {
111 public:
112  // Type of the internal representation. Higher qualities
113  // have lower unsigned integer representations.
114  using value_type = std::uint64_t;
115 
116  static const int minTickSize = 3;
117  static const int maxTickSize = 16;
118 
119 private:
120  // This has the same representation as STAmount, see the comment on the
121  // STAmount. However, this class does not always use the canonical
122  // representation. In particular, the increment and decrement operators may
123  // cause a non-canonical representation.
124  value_type m_value;
125 
126 public:
127  Quality() = default;
128 
130  explicit Quality(std::uint64_t value);
131 
133  explicit Quality(Amounts const& amount);
134 
136  template <class In, class Out>
137  explicit Quality(TAmounts<In, Out> const& amount)
138  : Quality(Amounts(toSTAmount(amount.in), toSTAmount(amount.out)))
139  {
140  }
141 
143  template <class In, class Out>
144  Quality(Out const& out, In const& in)
145  : Quality(Amounts(toSTAmount(in), toSTAmount(out)))
146  {
147  }
148 
151  Quality&
152  operator++();
153 
154  Quality
155  operator++(int);
160  Quality&
161  operator--();
162 
163  Quality
164  operator--(int);
168  STAmount
169  rate() const
170  {
171  return amountFromQuality(m_value);
172  }
173 
177  Quality
178  round(int tickSize) const;
179 
184  Amounts
185  ceil_in(Amounts const& amount, STAmount const& limit) const;
186 
187  template <class In, class Out>
188  TAmounts<In, Out>
189  ceil_in(TAmounts<In, Out> const& amount, In const& limit) const
190  {
191  if (amount.in <= limit)
192  return amount;
193 
194  // Use the existing STAmount implementation for now, but consider
195  // replacing with code specific to IOUAMount and XRPAmount
196  Amounts stAmt(toSTAmount(amount.in), toSTAmount(amount.out));
197  STAmount stLim(toSTAmount(limit));
198  auto const stRes = ceil_in(stAmt, stLim);
199  return TAmounts<In, Out>(
200  toAmount<In>(stRes.in), toAmount<Out>(stRes.out));
201  }
202 
207  Amounts
208  ceil_out(Amounts const& amount, STAmount const& limit) const;
209 
210  template <class In, class Out>
211  TAmounts<In, Out>
212  ceil_out(TAmounts<In, Out> const& amount, Out const& limit) const
213  {
214  if (amount.out <= limit)
215  return amount;
216 
217  // Use the existing STAmount implementation for now, but consider
218  // replacing with code specific to IOUAMount and XRPAmount
219  Amounts stAmt(toSTAmount(amount.in), toSTAmount(amount.out));
220  STAmount stLim(toSTAmount(limit));
221  auto const stRes = ceil_out(stAmt, stLim);
222  return TAmounts<In, Out>(
223  toAmount<In>(stRes.in), toAmount<Out>(stRes.out));
224  }
225 
226  Amounts
227  ceil_out_strict(Amounts const& amount, STAmount const& limit, bool roundUp)
228  const;
229 
230  template <class In, class Out>
231  TAmounts<In, Out>
232  ceil_out_strict(
233  TAmounts<In, Out> const& amount,
234  Out const& limit,
235  bool roundUp) const
236  {
237  if (amount.out <= limit)
238  return amount;
239 
240  // Use the existing STAmount implementation for now, but consider
241  // replacing with code specific to IOUAMount and XRPAmount
242  Amounts stAmt(toSTAmount(amount.in), toSTAmount(amount.out));
243  STAmount stLim(toSTAmount(limit));
244  auto const stRes = ceil_out_strict(stAmt, stLim, roundUp);
245  return TAmounts<In, Out>(
246  toAmount<In>(stRes.in), toAmount<Out>(stRes.out));
247  }
248 
253  friend bool
254  operator<(Quality const& lhs, Quality const& rhs) noexcept
255  {
256  return lhs.m_value > rhs.m_value;
257  }
258 
259  friend bool
260  operator>(Quality const& lhs, Quality const& rhs) noexcept
261  {
262  return lhs.m_value < rhs.m_value;
263  }
264 
265  friend bool
266  operator<=(Quality const& lhs, Quality const& rhs) noexcept
267  {
268  return !(lhs > rhs);
269  }
270 
271  friend bool
272  operator>=(Quality const& lhs, Quality const& rhs) noexcept
273  {
274  return !(lhs < rhs);
275  }
276 
277  friend bool
278  operator==(Quality const& lhs, Quality const& rhs) noexcept
279  {
280  return lhs.m_value == rhs.m_value;
281  }
282 
283  friend bool
284  operator!=(Quality const& lhs, Quality const& rhs) noexcept
285  {
286  return !(lhs == rhs);
287  }
288 
289  friend std::ostream&
290  operator<<(std::ostream& os, Quality const& quality)
291  {
292  os << quality.m_value;
293  return os;
294  }
295 
296  // return the relative distance (relative error) between two qualities. This
297  // is used for testing only. relative distance is abs(a-b)/min(a,b)
298  friend double
299  relativeDistance(Quality const& q1, Quality const& q2)
300  {
301  assert(q1.m_value > 0 && q2.m_value > 0);
302 
303  if (q1.m_value == q2.m_value) // make expected common case fast
304  return 0;
305 
306  auto const [minV, maxV] = std::minmax(q1.m_value, q2.m_value);
307 
308  auto mantissa = [](std::uint64_t rate) {
309  return rate & ~(255ull << (64 - 8));
310  };
311  auto exponent = [](std::uint64_t rate) {
312  return static_cast<int>(rate >> (64 - 8)) - 100;
313  };
314 
315  auto const minVMantissa = mantissa(minV);
316  auto const maxVMantissa = mantissa(maxV);
317  auto const expDiff = exponent(maxV) - exponent(minV);
318 
319  double const minVD = static_cast<double>(minVMantissa);
320  double const maxVD = expDiff ? maxVMantissa * pow(10, expDiff)
321  : static_cast<double>(maxVMantissa);
322 
323  // maxVD and minVD are scaled so they have the same exponents. Dividing
324  // cancels out the exponents, so we only need to deal with the (scaled)
325  // mantissas
326  return (maxVD - minVD) / minVD;
327  }
328 };
329 
334 Quality
335 composed_quality(Quality const& lhs, Quality const& rhs);
336 
337 } // namespace ripple
338 
339 #endif
ripple::composed_quality
Quality composed_quality(Quality const &lhs, Quality const &rhs)
Definition: Quality.cpp:124
ripple::QualityDirection::in
@ in
ripple::operator<<
std::ostream & operator<<(std::ostream &os, TOffer< TIn, TOut > const &offer)
Definition: Offer.h:303
algorithm
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:165
ripple::operator<=
bool operator<=(STAmount const &lhs, STAmount const &rhs)
Definition: STAmount.h:478
ripple::QualityDirection::out
@ out
ripple::operator>
bool operator>(STAmount const &lhs, STAmount const &rhs)
Definition: STAmount.h:472
ripple::operator<
bool operator<(CanonicalTXSet::Key const &lhs, CanonicalTXSet::Key const &rhs)
Definition: CanonicalTXSet.cpp:25
std::ostream
STL class.
std::minmax
T minmax(T... args)
ripple::toSTAmount
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
Definition: AmountConversions.h:30
ripple::operator!=
bool operator!=(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:175
ripple::operator>=
bool operator>=(STAmount const &lhs, STAmount const &rhs)
Definition: STAmount.h:484
beast::Zero
Zero allows classes to offer efficient comparisons to zero.
Definition: Zero.h:42
cstdint
std::uint64_t
ripple::amountFromQuality
STAmount amountFromQuality(std::uint64_t rate)
Definition: STAmount.cpp:850
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::round
T round(T... args)
std::empty
T empty(T... args)
ripple::keylet::quality
Keylet quality(Keylet const &k, std::uint64_t q) noexcept
The initial directory page for a specific quality.
Definition: Indexes.cpp:236
ostream
ripple::test::jtx::rate
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition: rate.cpp:30
std::pow
T pow(T... args)
beast
Definition: base_uint.h:641