New classes and types for handling asset amounts:

* Quality opaque type for order book quality
  * Amount replacement for STAmount
  * Amounts, in/out amount pair for offers
  * 'core' namespace with type aliases for Ripple primitives.
This commit is contained in:
Vinnie Falco
2014-04-08 17:45:01 -07:00
parent bd60a93cd6
commit 53bf5e7f36
8 changed files with 943 additions and 0 deletions

View File

@@ -820,6 +820,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\validators\ripple_validators.cpp" />
<ClCompile Include="..\..\src\ripple_app\book\tests\Quality.test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple_app\consensus\DisputedTx.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -2479,6 +2483,10 @@
<ClInclude Include="..\..\src\ripple\validators\impl\Validation.h" />
<ClInclude Include="..\..\src\ripple\validators\impl\Validator.h" />
<ClInclude Include="..\..\src\ripple\validators\ripple_validators.h" />
<ClInclude Include="..\..\src\ripple_app\book\Amount.h" />
<ClInclude Include="..\..\src\ripple_app\book\Amounts.h" />
<ClInclude Include="..\..\src\ripple_app\book\Quality.h" />
<ClInclude Include="..\..\src\ripple_app\book\Types.h" />
<ClInclude Include="..\..\src\ripple_app\consensus\DisputedTx.h" />
<ClInclude Include="..\..\src\ripple_app\consensus\LedgerConsensus.h" />
<ClInclude Include="..\..\src\ripple_app\contracts\Contract.h" />

View File

@@ -319,6 +319,15 @@
<Filter Include="[2] Old Ripple\ripple_app\transactors">
<UniqueIdentifier>{dcb7c75c-4f1d-486c-8079-52dc43644ae6}</UniqueIdentifier>
</Filter>
<Filter Include="[1] Ripple\common\tests">
<UniqueIdentifier>{1aa56407-a927-42be-862b-cd5324b4d63b}</UniqueIdentifier>
</Filter>
<Filter Include="[2] Old Ripple\ripple_app\book">
<UniqueIdentifier>{56248509-436d-4034-ab4e-64afbb532418}</UniqueIdentifier>
</Filter>
<Filter Include="[2] Old Ripple\ripple_app\book\tests">
<UniqueIdentifier>{28b72c9f-02e3-4b57-9386-957478e1f0b7}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\ripple_basics\containers\RangeSet.cpp">
@@ -1500,6 +1509,12 @@
<ClCompile Include="..\..\src\ripple_app\tx\LocalTxs.cpp">
<Filter>[2] Old Ripple\ripple_app\tx</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\common\tests\cross_offer.test.cpp">
<Filter>[1] Ripple\common\tests</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_app\book\tests\Quality.test.cpp">
<Filter>[2] Old Ripple\ripple_app\book\tests</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ripple_basics\containers\RangeSet.h">
@@ -3063,6 +3078,18 @@
<ClInclude Include="..\..\src\ripple_app\tx\LocalTxs.h">
<Filter>[2] Old Ripple\ripple_app\tx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_app\book\Amount.h">
<Filter>[2] Old Ripple\ripple_app\book</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_app\book\Amounts.h">
<Filter>[2] Old Ripple\ripple_app\book</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_app\book\Quality.h">
<Filter>[2] Old Ripple\ripple_app\book</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_app\book\Types.h">
<Filter>[2] Old Ripple\ripple_app\book</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\ripple_data\protocol\ripple.proto">

View File

@@ -0,0 +1,330 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_CORE_AMOUNT_H_INCLUDED
#define RIPPLE_CORE_AMOUNT_H_INCLUDED
#include "../../ripple_data/protocol/SerializedObject.h"
#include "../../beast/beast/utility/noexcept.h"
#include "../../beast/beast/cxx14/type_traits.h" // <type_traits>
//------------------------------------------------------------------------------
struct Zero
{
Zero()
{
}
};
namespace {
static Zero const zero;
}
namespace detail {
namespace Zero_helpers {
template <class T>
int
get_signum (T const& t) noexcept
{
return signum(t);
}
}
}
/** Handle operators where T is on the left side using signum. */
template <class T>
bool operator==(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) == 0;
}
template <class T>
bool operator!=(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) != 0;
}
template <class T>
bool operator>(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) > 0;
}
template <class T>
bool operator>=(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) >= 0;
}
template <class T>
bool operator<(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) < 0;
}
template <class T>
bool operator<=(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) <= 0;
}
/** Handle operators where T is on the right side by reversing the operation,
so that T is on the left side.
*/
template <class T>
bool operator==(Zero, T const& t)
{
return t == zero;
}
template <class T>
bool operator!=(Zero, T const& t)
{
return t != zero;
}
template <class T>
bool operator>(Zero, T const& t)
{
return t < zero;
}
template <class T>
bool operator>=(Zero, T const& t)
{
return t <= zero;
}
template <class T>
bool operator<(Zero, T const& t)
{
return t > zero;
}
template <class T>
bool operator<=(Zero, T const& t)
{
return t >= zero;
}
/** Default implementation calls the method on the class.
Alternatively, signum may be overloaded in the same namespace and found
via argument dependent lookup.
*/
template <class T>
auto signum(T const& t) -> decltype(t.signum()) {
return t.signum();
}
//------------------------------------------------------------------------------
namespace ripple {
namespace core {
/** Custom floating point asset amount.
The "representation" may be integral or non-integral. For integral
representations, the exponent is always zero and the value held in the
mantissa is an exact quantity.
*/
class AmountType
{
private:
std::uint64_t m_mantissa;
int m_exponent;
bool m_negative;
bool m_integral;
AmountType (std::uint64_t mantissa,
int exponent, bool negative, bool integral)
: m_mantissa (mantissa)
, m_exponent (exponent)
, m_negative (negative)
, m_integral (integral)
{
}
public:
/** Default construction.
The value is uninitialized.
*/
AmountType() noexcept
{
}
/** Construct from an integer.
The representation is set to integral.
*/
/** @{ */
template <class Integer>
AmountType (Integer value,
std::enable_if_t <std::is_signed <Integer>::value>* = 0) noexcept
: m_mantissa (value)
, m_exponent (0)
, m_negative (value < 0)
, m_integral (true)
{
static_assert (std::is_integral<Integer>::value,
"Cannot construct from non-integral type.");
}
template <class Integer>
AmountType (Integer value,
std::enable_if_t <! std::is_signed <Integer>::value>* = 0) noexcept
: m_mantissa (value)
, m_exponent (0)
, m_negative (false)
{
static_assert (std::is_integral<Integer>::value,
"Cannot construct from non-integral type.");
}
/** @} */
/** Assign the value zero.
The representation is preserved.
*/
AmountType&
operator= (Zero) noexcept
{
m_mantissa = 0;
// VFALCO Why -100?
// "We have to use something in range."
// "This makes zero the smallest value."
m_exponent = m_integral ? 0 : -100;
m_exponent = 0;
m_negative = false;
return *this;
}
/** Returns the value in canonical format. */
AmountType
normal() const noexcept
{
if (m_integral)
{
AmountType result;
if (m_mantissa == 0)
{
result.m_exponent = 0;
result.m_negative = false;
}
return result;
}
return AmountType();
}
//
// Comparison
//
int
signum() const noexcept
{
if (m_mantissa == 0)
return 0;
return m_negative ? -1 : 1;
}
bool
operator== (AmountType const& other) const noexcept
{
return
m_negative == other.m_negative &&
m_mantissa == other.m_mantissa &&
m_exponent == other.m_exponent;
}
bool
operator!= (AmountType const& other) const noexcept
{
return ! (*this == other);
}
bool
operator< (AmountType const& other) const noexcept
{
return false;
}
bool
operator>= (AmountType const& other) const noexcept
{
return ! (*this < other);
}
bool
operator> (AmountType const& other) const noexcept
{
return other < *this;
}
bool
operator<= (AmountType const& other) const noexcept
{
return ! (other < *this);
}
//
// Arithmetic
//
AmountType
operator-() const noexcept
{
return AmountType (m_mantissa, m_exponent, ! m_negative, m_integral);
}
//
// Output
//
std::ostream&
operator<< (std::ostream& os)
{
int const sig (signum());
if (sig == 0)
return os << "0";
else if (sig < 0)
os << "-";
if (m_integral)
return os << m_mantissa;
if (m_exponent != 0 && (m_exponent < -25 || m_exponent > -5))
return os << m_mantissa << "e" << m_exponent;
//if (m_exponent > 0)
// return os <<
return os;
}
};
//------------------------------------------------------------------------------
typedef STAmount Amount;
}
}
#endif

View File

@@ -0,0 +1,66 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_CORE_AMOUNTS_H_INCLUDED
#define RIPPLE_CORE_AMOUNTS_H_INCLUDED
#include "Amount.h"
namespace ripple {
namespace core {
struct Amounts
{
Amounts() = default;
Amounts (Amount const& in_, Amount const& out_)
: in (in_)
, out (out_)
{
}
/** Returns `true` if either quantity is not positive. */
bool
empty() const noexcept
{
return ! in.isPositive() || ! out.isPositive();
}
Amount in;
Amount out;
};
inline
bool
operator== (Amounts const& lhs, Amounts const& rhs) noexcept
{
return lhs.in == rhs.in && lhs.out == rhs.out;
}
inline
bool
operator!= (Amounts const& lhs, Amounts const& rhs) noexcept
{
return ! (lhs == rhs);
}
}
}
#endif

View File

@@ -0,0 +1,198 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_CORE_QUALITY_H_INCLUDED
#define RIPPLE_CORE_QUALITY_H_INCLUDED
#include "Amount.h"
#include "Amounts.h"
#include <cassert>
#include <cstdint>
#include <limits>
#include <ostream>
namespace ripple {
namespace core {
/** Represents the logical ratio of output currency to input currency.
Internally this is stored using a custom floating point representation,
as the inverse of the ratio, so that quality will be descending in
a sequence of actual values that represent qualities.
*/
class Quality
{
public:
// Type of the internal representation. Higher qualities
// have lower unsigned integer representations.
typedef std::uint64_t value_type;
private:
value_type m_value;
public:
Quality() = default;
explicit
Quality (std::uint64_t value)
: m_value (value)
{
}
/** Create a quality from the ratio of two amounts. */
explicit
Quality (Amounts const& amount)
: m_value (Amount::getRate (amount.out, amount.in))
{
}
/** Advances to the next higher quality level. */
/** @{ */
Quality&
operator++()
{
assert (m_value > 0);
--m_value;
return *this;
}
Quality
operator++ (int)
{
Quality prev (*this);
--*this;
return prev;
}
/** @} */
/** Advances to the next lower quality level. */
/** @{ */
Quality&
operator--()
{
assert (m_value < std::numeric_limits<value_type>::max());
++m_value;
return *this;
}
Quality
operator-- (int)
{
Quality prev (*this);
++*this;
return prev;
}
/** @} */
/** Returns `true` if lhs is lower quality than `rhs`.
Lower quality means the taker receives a worse deal.
Higher quality is better for the taker.
*/
friend
bool
operator< (Quality const& lhs, Quality const& rhs) noexcept
{
return lhs.m_value > rhs.m_value;
}
friend
bool
operator== (Quality const& lhs, Quality const& rhs) noexcept
{
return lhs.m_value == rhs.m_value;
}
friend
std::ostream&
operator<< (std::ostream& os, Quality const& quality)
{
os << quality.m_value;
return os;
}
/** Returns the quality as Amount. */
Amount
rate() const
{
return Amount::setRate (m_value);
}
/** Returns the scaled amount with in capped.
Math is avoided if the result is exact. The output is clamped
to prevent money creation.
*/
Amounts
ceil_in (Amounts const& amount, Amount const& limit) const
{
if (amount.in > limit)
{
// VFALCO TODO make mulRound avoid math when v2==one
#if 0
Amounts result (limit, Amount::mulRound (
limit, rate(), amount.out, true));
#else
Amounts result (limit, Amount::divRound (
limit, rate(), amount.out, true));
#endif
// Clamp out
if (result.out > amount.out)
result.out = amount.out;
return result;
}
return amount;
}
/** Returns the scaled amount with out capped.
Math is avoided if the result is exact. The input is clamped
to prevent money creation.
*/
Amounts
ceil_out (Amounts const& amount, Amount const& limit) const
{
if (amount.out > limit)
{
// VFALCO TODO make divRound avoid math when v2==one
#if 0
Amounts result (Amount::divRound (
limit, rate(), amount.in, true), limit);
#else
Amounts result (Amount::mulRound (
limit, rate(), amount.in, true), limit);
#endif
// Clamp in
if (result.in > amount.in)
result.in = amount.in;
return result;
}
return amount;
}
};
inline
bool
operator!= (Quality const& lhs, Quality const& rhs) noexcept
{
return ! (lhs == rhs);
}
}
}
#endif

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_CORE_TYPES_H_INCLUDED
#define RIPPLE_CORE_TYPES_H_INCLUDED
#include "../ledger/LedgerEntrySet.h"
#include "../../ripple/types/api/RippleAssets.h"
#include "../../ripple/types/api/UInt160.h"
#include <chrono>
#include <cstdint>
namespace ripple {
namespace core {
/** A mutable view that overlays an immutable ledger to track changes. */
typedef LedgerEntrySet LedgerView;
/** Identifies an account. */
typedef uint160 Account;
/** Asset identifiers. */
typedef RippleCurrency Currency;
typedef RippleIssuer Issuer;
typedef RippleAsset Asset;
typedef RippleAssetRef AssetRef;
/** Uniquely identifies an order book. */
typedef RippleBook Book;
typedef RippleBookRef BookRef;
/** A clock representing network time.
This measures seconds since the Ripple epoch as seen
by the ledger close clock.
*/
class Clock // : public abstract_clock <std::chrono::seconds>
{
public:
typedef std::uint32_t time_point;
typedef std::chrono::seconds duration;
};
}
}
#endif

View File

@@ -0,0 +1,249 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "../Quality.h"
#include "../../../beast/beast/unit_test/suite.h"
#include "../../../beast/beast/cxx14/type_traits.h"
namespace ripple {
namespace core {
class Quality_test : public beast::unit_test::suite
{
public:
// Create a raw, non-integral amount from mantissa and exponent
Amount
static raw (std::uint64_t mantissa, int exponent)
{
return Amount (uint160(3), uint160(3), mantissa, exponent);
}
template <class Integer>
static
Amount
amount (Integer integer,
std::enable_if_t <std::is_signed <Integer>::value>* = 0)
{
static_assert (std::is_integral <Integer>::value, "");
return Amount (integer, false);
}
template <class Integer>
static
Amount
amount (Integer integer,
std::enable_if_t <! std::is_signed <Integer>::value>* = 0)
{
static_assert (std::is_integral <Integer>::value, "");
if (integer < 0)
return Amount (-integer, true);
return Amount (integer, false);
}
template <class In, class Out>
static
Amounts
amounts (In in, Out out)
{
return Amounts (amount(in), amount(out));
}
template <class In1, class Out1, class Int, class In2, class Out2>
void
ceil_in (Quality const& q,
In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected)
{
auto expect_result (amounts (in_expected, out_expected));
auto actual_result (q.ceil_in (amounts(in, out), amount(limit)));
expect (actual_result == expect_result);
}
template <class In1, class Out1, class Int, class In2, class Out2>
void
ceil_out (Quality const& q,
In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected)
{
auto const expect_result (amounts (in_expected, out_expected));
auto const actual_result (q.ceil_out (amounts(in, out), amount(limit)));
expect (actual_result == expect_result);
}
void
test_ceil_in ()
{
testcase ("ceil_in");
{
// 1 in, 1 out:
Quality q (Amounts (amount(1), amount(1)));
ceil_in (q,
1, 1, // 1 in, 1 out
1, // limit: 1
1, 1); // 1 in, 1 out
ceil_in (q,
10, 10, // 10 in, 10 out
5, // limit: 5
5, 5); // 5 in, 5 out
ceil_in (q,
5, 5, // 5 in, 5 out
10, // limit: 10
5, 5); // 5 in, 5 out
}
{
// 1 in, 2 out:
Quality q (Amounts (amount(1), amount(2)));
ceil_in (q,
40, 80, // 40 in, 80 out
40, // limit: 40
40, 80); // 40 in, 20 out
ceil_in (q,
40, 80, // 40 in, 80 out
20, // limit: 20
20, 40); // 20 in, 40 out
ceil_in (q,
40, 80, // 40 in, 80 out
60, // limit: 60
40, 80); // 40 in, 80 out
}
{
// 2 in, 1 out:
Quality q (Amounts (amount(2), amount(1)));
ceil_in (q,
40, 20, // 40 in, 20 out
20, // limit: 20
20, 10); // 20 in, 10 out
ceil_in (q,
40, 20, // 40 in, 20 out
40, // limit: 40
40, 20); // 40 in, 20 out
ceil_in (q,
40, 20, // 40 in, 20 out
50, // limit: 40
40, 20); // 40 in, 20 out
}
}
void
test_ceil_out ()
{
testcase ("ceil_out");
{
// 1 in, 1 out:
Quality q (Amounts (amount(1),amount(1)));
ceil_out (q,
1, 1, // 1 in, 1 out
1, // limit 1
1, 1); // 1 in, 1 out
ceil_out (q,
10, 10, // 10 in, 10 out
5, // limit 5
5, 5); // 5 in, 5 out
ceil_out (q,
10, 10, // 10 in, 10 out
20, // limit 20
10, 10); // 10 in, 10 out
}
{
// 1 in, 2 out:
Quality q (Amounts (amount(1),amount(2)));
ceil_out (q,
40, 80, // 40 in, 80 out
40, // limit 40
20, 40); // 20 in, 40 out
ceil_out (q,
40, 80, // 40 in, 80 out
80, // limit 80
40, 80); // 40 in, 80 out
ceil_out (q,
40, 80, // 40 in, 80 out
100, // limit 100
40, 80); // 40 in, 80 out
}
{
// 2 in, 1 out:
Quality q (Amounts (amount(2),amount(1)));
ceil_out (q,
40, 20, // 40 in, 20 out
20, // limit 20
40, 20); // 40 in, 20 out
ceil_out (q,
40, 20, // 40 in, 20 out
40, // limit 40
40, 20); // 40 in, 20 out
ceil_out (q,
40, 20, // 40 in, 20 out
10, // limit 10
20, 10); // 20 in, 10 out
}
}
void
test_raw()
{
{
Quality q (0x5d048191fb9130daull); // 126836389.7680090
Amounts const value (
amount(349469768), // 349.469768 XRP
raw (2755280000000000ull, -15)); // 2.75528
Amount const limit (
raw (4131113916555555, -16)); // .4131113916555555
Amounts const result (q.ceil_out (value, limit));
expect (! result.in.isZero());
}
}
void
run()
{
test_ceil_in ();
test_ceil_out ();
test_raw();
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(Quality,core,ripple);
}
}

View File

@@ -37,3 +37,5 @@
#include "tx/Transaction.cpp"
#include "tx/TransactionEngine.cpp"
#include "tx/TransactionMeta.cpp"
#include "book/tests/Quality.test.cpp"