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