mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-04 11:15:56 +00:00
Add conversions between Number, XRPAmount and int64_t
* Conversions to Number are implicit * Conversions away from Number are explicit and potentially lossy * If lossy, round to nearest, and to even on tie
This commit is contained in:
committed by
Elliot Lee
parent
0ee63b7c7b
commit
476ee8a479
@@ -21,6 +21,7 @@
|
||||
#define RIPPLE_BASICS_NUMBER_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/IOUAmount.h>
|
||||
#include <ripple/basics/XRPAmount.h>
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
@@ -51,6 +52,7 @@ public:
|
||||
explicit constexpr Number(rep mantissa, int exponent, unchecked) noexcept;
|
||||
|
||||
Number(IOUAmount const& x);
|
||||
Number(XRPAmount const& x);
|
||||
|
||||
constexpr rep
|
||||
mantissa() const noexcept;
|
||||
@@ -81,6 +83,8 @@ public:
|
||||
operator/=(Number const& x);
|
||||
|
||||
explicit operator IOUAmount() const;
|
||||
explicit operator XRPAmount() const; // round to nearest, even on tie
|
||||
explicit operator rep() const; // round to nearest, even on tie
|
||||
|
||||
friend constexpr bool
|
||||
operator==(Number const& x, Number const& y) noexcept
|
||||
@@ -184,6 +188,10 @@ inline Number::Number(IOUAmount const& x) : Number{x.mantissa(), x.exponent()}
|
||||
{
|
||||
}
|
||||
|
||||
inline Number::Number(XRPAmount const& x) : Number{x.drops()}
|
||||
{
|
||||
}
|
||||
|
||||
inline constexpr Number::rep
|
||||
Number::mantissa() const noexcept
|
||||
{
|
||||
|
||||
@@ -374,6 +374,45 @@ Number::operator/=(Number const& y)
|
||||
return *this;
|
||||
}
|
||||
|
||||
Number::operator rep() const
|
||||
{
|
||||
std::int64_t drops = mantissa_;
|
||||
int offset = exponent_;
|
||||
guard g;
|
||||
if (drops != 0)
|
||||
{
|
||||
if (drops < 0)
|
||||
{
|
||||
g.set_negative();
|
||||
drops = -drops;
|
||||
}
|
||||
for (; offset < 0; ++offset)
|
||||
{
|
||||
g.push(drops % 10);
|
||||
drops /= 10;
|
||||
}
|
||||
for (; offset > 0; --offset)
|
||||
{
|
||||
if (drops > std::numeric_limits<decltype(drops)>::max() / 10)
|
||||
throw std::runtime_error("Number::operator rep() overflow");
|
||||
drops *= 10;
|
||||
}
|
||||
auto r = g.round();
|
||||
if (r == 1 || (r == 0 && (drops & 1) == 1))
|
||||
{
|
||||
++drops;
|
||||
}
|
||||
if (g.is_negative())
|
||||
drops = -drops;
|
||||
}
|
||||
return drops;
|
||||
}
|
||||
|
||||
Number::operator XRPAmount() const
|
||||
{
|
||||
return XRPAmount{static_cast<rep>(*this)};
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(Number const& amount)
|
||||
{
|
||||
|
||||
@@ -126,6 +126,75 @@ public:
|
||||
BEAST_EXPECT(x == z);
|
||||
}
|
||||
|
||||
void
|
||||
test_to_integer()
|
||||
{
|
||||
Number x[]{
|
||||
Number{0},
|
||||
Number{1},
|
||||
Number{2},
|
||||
Number{3},
|
||||
Number{-1},
|
||||
Number{-2},
|
||||
Number{-3},
|
||||
Number{10},
|
||||
Number{99},
|
||||
Number{1155},
|
||||
Number{9'999'999'999'999'999, 0},
|
||||
Number{9'999'999'999'999'999, 1},
|
||||
Number{9'999'999'999'999'999, 2},
|
||||
Number{-9'999'999'999'999'999, 2},
|
||||
Number{15, -1},
|
||||
Number{14, -1},
|
||||
Number{16, -1},
|
||||
Number{25, -1},
|
||||
Number{6, -1},
|
||||
Number{5, -1},
|
||||
Number{4, -1},
|
||||
Number{-15, -1},
|
||||
Number{-14, -1},
|
||||
Number{-16, -1},
|
||||
Number{-25, -1},
|
||||
Number{-6, -1},
|
||||
Number{-5, -1},
|
||||
Number{-4, -1}};
|
||||
std::int64_t y[]{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
-1,
|
||||
-2,
|
||||
-3,
|
||||
10,
|
||||
99,
|
||||
1155,
|
||||
9'999'999'999'999'999,
|
||||
99'999'999'999'999'990,
|
||||
999'999'999'999'999'900,
|
||||
-999'999'999'999'999'900,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
-2,
|
||||
-1,
|
||||
-2,
|
||||
-2,
|
||||
-1,
|
||||
0,
|
||||
0};
|
||||
static_assert(std::size(x) == std::size(y));
|
||||
for (unsigned u = 0; u < std::size(x); ++u)
|
||||
{
|
||||
auto j = static_cast<std::int64_t>(x[u]);
|
||||
BEAST_EXPECT(j == y[u]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
@@ -135,6 +204,7 @@ public:
|
||||
test_div();
|
||||
test_root();
|
||||
testConversions();
|
||||
test_to_integer();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user