1#ifndef PROTOCOL_UNITS_H_INCLUDED
2#define PROTOCOL_UNITS_H_INCLUDED
4#include <xrpl/basics/safe_cast.h>
5#include <xrpl/beast/utility/Zero.h>
6#include <xrpl/beast/utility/instrumentation.h>
7#include <xrpl/json/json_value.h>
9#include <boost/multiprecision/cpp_int.hpp>
10#include <boost/operators.hpp>
57template <
class Other,
class VU>
68template <
class VU1,
class VU2>
72template <
class UnitTag,
class T>
73class ValueUnit :
private boost::totally_ordered<ValueUnit<UnitTag, T>>,
74 private boost::additive<ValueUnit<UnitTag, T>>,
75 private boost::equality_comparable<ValueUnit<UnitTag, T>, T>,
76 private boost::dividable<ValueUnit<UnitTag, T>, T>,
77 private boost::modable<ValueUnit<UnitTag, T>, T>,
78 private boost::unit_steppable<ValueUnit<UnitTag, T>>
118 template <Compatible<ValueUnit> Other>
213 template <Integral transparent = value_type>
235 template <Compatible<ValueUnit> Other>
248 template <Compatible<ValueUnit> Other>
263 operator bool() const noexcept
283 template <
class Other>
287 return static_cast<double>(
value_) / reference.
value();
312 return static_cast<jsontype
>(
value_);
339template <
class Char,
class Traits,
class UnitTag,
class T>
343 return os << q.value();
346template <
class UnitTag,
class T>
353template <
class Source>
362template <
class Source2,
class Source1>
366template <
class Dest,
class Source1,
class Source2>
370template <
class Dest,
class Source1,
class Source2>
375ValueUnit<unitlessTag, T>
381template <
class Source1,
class Source2, unit::muldivable<Source1, Source2> Dest>
386 if (value.value() < 0 || mul.value() < 0 || div.value() < 0)
391 value.value() >= 0,
"xrpl::unit::mulDivU : minimum value input");
393 mul.value() >= 0,
"xrpl::unit::mulDivU : minimum mul input");
394 XRPL_ASSERT(div.value() > 0,
"xrpl::unit::mulDivU : minimum div input");
398 using desttype =
typename Dest::value_type;
404 if (mul.value() == div.value())
406 if (value.value() > max)
408 return Dest{
static_cast<desttype
>(value.value())};
411 using namespace boost::multiprecision;
419 auto quotient = product / div.value();
424 return Dest{
static_cast<desttype
>(quotient)};
445template <
class Source1,
class Source2, unit::muldivable<Source1, Source2> Dest>
447mulDiv(Source1 value, Dest mul, Source2 div)
455 unit::muldivCommutable<Source1, Source2> Dest>
457mulDiv(Dest value, Source1 mul, Source2 div)
463template <unit::muldivDest Dest>
472template <unit::muldivDest Dest>
477 return mulDiv(mul, value, div);
480template <unit::muldivSource Source1, unit::muldivSources<Source1> Source2>
491 return unitresult->value();
494template <unit::muldivSource Source1, unit::muldivSources<Source1> Source2>
499 return mulDiv(mul, value, div);
502template <unit::IntegralValue Dest, unit::CastableValue<Dest> Src>
507 return Dest{safe_cast<typename Dest::value_type>(s.value())};
510template <unit::IntegralValue Dest, unit::Integral Src>
515 return Dest{safe_cast<typename Dest::value_type>(s)};
518template <unit::IntegralValue Dest, unit::CastableValue<Dest> Src>
523 return Dest{unsafe_cast<typename Dest::value_type>(s.value())};
526template <unit::IntegralValue Dest, unit::Integral Src>
531 return Dest{unsafe_cast<typename Dest::value_type>(s)};
constexpr ValueUnit(value_type value)
constexpr int signum() const noexcept
Return the sign of the amount.
friend constexpr ValueUnit operator*(value_type lhs, ValueUnit const &rhs)
constexpr value_type value() const
Returns the underlying value.
constexpr bool operator<(ValueUnit const &other) const
friend std::istream & operator>>(std::istream &s, ValueUnit &val)
ValueUnit & operator+=(ValueUnit const &other)
constexpr bool operator==(value_type other) const
constexpr bool operator==(ValueUnit const &other) const
constexpr bool operator==(ValueUnit< unit_type, Other > const &other) const
constexpr ValueUnit & operator=(value_type value)
constexpr ValueUnit(ValueUnit const &other)=default
constexpr ValueUnit & operator=(beast::Zero)
ValueUnit & operator/=(value_type const &rhs)
constexpr ValueUnit operator*(value_type const &rhs) const
constexpr ValueUnit operator-(value_type const &rhs) const
constexpr bool operator!=(ValueUnit< unit_type, Other > const &other) const
ValueUnit & operator%=(value_type const &rhs)
constexpr ValueUnit & operator=(ValueUnit const &other)=default
ValueUnit operator-() const
constexpr ValueUnit(ValueUnit< unit_type, Other > const &value)
Instances with the same unit, and a type that is "safe" to convert to this one can be converted impli...
constexpr ValueUnit(beast::Zero)
constexpr value_type fee() const
Returns the number of drops.
friend constexpr ValueUnit operator-(value_type lhs, ValueUnit const &rhs)
ValueUnit & operator*=(value_type const &rhs)
constexpr value_type operator/(ValueUnit const &rhs) const
Json::Value jsonClipped() const
ValueUnit & operator-=(ValueUnit const &other)
constexpr ValueUnit operator+(value_type const &rhs) const
friend constexpr ValueUnit operator+(value_type lhs, ValueUnit const &rhs)
constexpr double decimalFromReference(ValueUnit< unit_type, Other > reference) const
Usable is checked to ensure that only values with known valid type tags can be used (sometimes transp...
std::optional< Dest > mulDivU(Source1 value, Dest mul, Source2 div)
std::basic_ostream< Char, Traits > & operator<<(std::basic_ostream< Char, Traits > &os, ValueUnit< UnitTag, T > const &q)
std::string to_string(ValueUnit< UnitTag, T > const &amount)
ValueUnit< unitlessTag, T > scalar(T value)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > unsafe_cast(Src s) noexcept
std::optional< std::uint64_t > mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
Return value*mul/div accurately.
STAmount multiply(STAmount const &amount, Rate const &rate)
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safe_cast(Src s) noexcept
Zero allows classes to offer efficient comparisons to zero.