rippled
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 <ripple/protocol/Quality.h>
21 #include <cassert>
22 #include <limits>
23 
24 namespace ripple {
25 
26 Quality::Quality(std::uint64_t value) : m_value(value)
27 {
28 }
29 
30 Quality::Quality(Amounts const& amount)
31  : m_value(getRate(amount.out, amount.in))
32 {
33 }
34 
35 Quality&
36 Quality::operator++()
37 {
38  assert(m_value > 0);
39  --m_value;
40  return *this;
41 }
42 
43 Quality
44 Quality::operator++(int)
45 {
46  Quality prev(*this);
47  ++*this;
48  return prev;
49 }
50 
51 Quality&
52 Quality::operator--()
53 {
54  assert(m_value < std::numeric_limits<value_type>::max());
55  ++m_value;
56  return *this;
57 }
58 
59 Quality
60 Quality::operator--(int)
61 {
62  Quality prev(*this);
63  --*this;
64  return prev;
65 }
66 
67 Amounts
68 Quality::ceil_in(Amounts const& amount, STAmount const& limit) const
69 {
70  if (amount.in > limit)
71  {
72  Amounts result(
73  limit, divRound(limit, rate(), amount.out.issue(), true));
74  // Clamp out
75  if (result.out > amount.out)
76  result.out = amount.out;
77  assert(result.in == limit);
78  return result;
79  }
80  assert(amount.in <= limit);
81  return amount;
82 }
83 
84 Amounts
85 Quality::ceil_out(Amounts const& amount, STAmount const& limit) const
86 {
87  if (amount.out > limit)
88  {
89  Amounts result(mulRound(limit, rate(), amount.in.issue(), true), limit);
90  // Clamp in
91  if (result.in > amount.in)
92  result.in = amount.in;
93  assert(result.out == limit);
94  return result;
95  }
96  assert(amount.out <= limit);
97  return amount;
98 }
99 
100 Quality
101 composed_quality(Quality const& lhs, Quality const& rhs)
102 {
103  STAmount const lhs_rate(lhs.rate());
104  assert(lhs_rate != beast::zero);
105 
106  STAmount const rhs_rate(rhs.rate());
107  assert(rhs_rate != beast::zero);
108 
109  STAmount const rate(mulRound(lhs_rate, rhs_rate, lhs_rate.issue(), true));
110 
111  std::uint64_t const stored_exponent(rate.exponent() + 100);
112  std::uint64_t const stored_mantissa(rate.mantissa());
113 
114  assert((stored_exponent > 0) && (stored_exponent <= 255));
115 
116  return Quality((stored_exponent << (64 - 8)) | stored_mantissa);
117 }
118 
119 Quality
120 Quality::round(int digits) const
121 {
122  // Modulus for mantissa
123  static const std::uint64_t mod[17] = {
124  /* 0 */ 10000000000000000,
125  /* 1 */ 1000000000000000,
126  /* 2 */ 100000000000000,
127  /* 3 */ 10000000000000,
128  /* 4 */ 1000000000000,
129  /* 5 */ 100000000000,
130  /* 6 */ 10000000000,
131  /* 7 */ 1000000000,
132  /* 8 */ 100000000,
133  /* 9 */ 10000000,
134  /* 10 */ 1000000,
135  /* 11 */ 100000,
136  /* 12 */ 10000,
137  /* 13 */ 1000,
138  /* 14 */ 100,
139  /* 15 */ 10,
140  /* 16 */ 1,
141  };
142 
143  auto exponent = m_value >> (64 - 8);
144  auto mantissa = m_value & 0x00ffffffffffffffULL;
145  mantissa += mod[digits] - 1;
146  mantissa -= (mantissa % mod[digits]);
147 
148  return Quality{(exponent << (64 - 8)) | mantissa};
149 }
150 
151 } // namespace ripple
ripple::composed_quality
Quality composed_quality(Quality const &lhs, Quality const &rhs)
Definition: Quality.cpp:101
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:347
ripple::QualityDirection::in
@ in
ripple::mulRound
STAmount mulRound(STAmount const &v1, STAmount const &v2, Issue const &issue, bool roundUp)
Definition: STAmount.cpp:1305
ripple::getRate
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
Definition: STAmount.cpp:495
ripple::QualityDirection::out
@ out
ripple::divRound
STAmount divRound(STAmount const &num, STAmount const &den, Issue const &issue, bool roundUp)
Definition: STAmount.cpp:1391
ripple::STAmount
Definition: STAmount.h:45
std::uint64_t
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
limits
cassert
std::prev
T prev(T... args)
std::numeric_limits
ripple::test::jtx::rate
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition: rate.cpp:30