19#ifndef BASICS_FEES_H_INCLUDED
20#define BASICS_FEES_H_INCLUDED
22#include <xrpl/basics/safe_cast.h>
23#include <xrpl/beast/utility/Zero.h>
24#include <xrpl/beast/utility/instrumentation.h>
25#include <xrpl/json/json_value.h>
26#include <boost/multiprecision/cpp_int.hpp>
27#include <boost/operators.hpp>
59 std::is_class_v<T> && std::is_object_v<typename T::unit_type> &&
60 std::is_object_v<typename T::value_type>>;
69template <
class T,
class = enable_if_unit_t<T>>
71 std::is_same_v<typename T::unit_type, feeunitTag> ||
72 std::is_same_v<typename T::unit_type, feelevelTag> ||
73 std::is_same_v<typename T::unit_type, unitlessTag> ||
74 std::is_same_v<typename T::unit_type, dropTag>;
76template <
class UnitTag,
class T>
77class TaggedFee :
private boost::totally_ordered<TaggedFee<UnitTag, T>>,
78 private boost::additive<TaggedFee<UnitTag, T>>,
79 private boost::equality_comparable<TaggedFee<UnitTag, T>, T>,
80 private boost::dividable<TaggedFee<UnitTag, T>, T>,
81 private boost::modable<TaggedFee<UnitTag, T>, T>,
82 private boost::unit_steppable<TaggedFee<UnitTag, T>>
92 template <
class Other>
94 std::is_arithmetic_v<Other> && std::is_arithmetic_v<value_type> &&
95 std::is_convertible_v<Other, value_type>;
97 template <
class OtherFee,
class = enable_if_unit_t<OtherFee>>
99 is_compatible_v<typename OtherFee::value_type> &&
100 std::is_same_v<UnitTag, typename OtherFee::unit_type>;
102 template <
class Other>
106 template <
class OtherFee>
144 is_compatible_v<Other> &&
145 is_safetocasttovalue_v<value_type, Other>>>
212 template <
class transparent = value_type>
224 std::is_signed_v<T>,
"- operator illegal on unsigned fee types");
234 template <
class Other,
class = enable_if_compatible_t<Other>>
244 return fee_ == other;
247 template <
class Other,
class = enable_if_compatible_t<Other>>
262 operator bool() const noexcept
271 return (
fee_ < 0) ? -1 : (
fee_ ? 1 : 0);
281 template <
class Other>
285 return static_cast<double>(
fee_) / reference.
fee();
295 if constexpr (std::is_integral_v<value_type>)
298 std::is_signed_v<value_type>,
309 return static_cast<jsontype
>(
fee_);
336template <
class Char,
class Traits,
class UnitTag,
class T>
340 return os << q.value();
343template <
class UnitTag,
class T>
350template <
class Source,
class = enable_if_unit_t<Source>>
352 std::is_convertible_v<typename Source::value_type, std::uint64_t>;
354template <
class Dest,
class = enable_if_unit_t<Dest>>
356 can_muldiv_source_v<Dest> &&
357 std::is_convertible_v<std::uint64_t, typename Dest::value_type> &&
366 can_muldiv_source_v<Source1> && can_muldiv_source_v<Source2> &&
367 std::is_same_v<typename Source1::unit_type, typename Source2::unit_type>;
377 can_muldiv_sources_v<Source1, Source2> && can_muldiv_dest_v<Dest>;
388 !std::is_same_v<typename Source1::unit_type, typename Dest::unit_type>;
397template <
class Source1,
class Source2>
401template <
class Source1,
class Source2,
class Dest>
405template <
class Source1,
class Source2,
class Dest>
420 class = enable_muldiv_t<Source1, Source2, Dest>>
425 if (value.value() < 0 || mul.value() < 0 || div.value() < 0)
431 "ripple::feeunit::mulDivU : minimum value input");
433 mul.value() >= 0,
"ripple::feeunit::mulDivU : minimum mul input");
435 div.value() >= 0,
"ripple::feeunit::mulDivU : minimum div input");
439 using desttype =
typename Dest::value_type;
445 if (mul.value() == div.value())
447 if (value.value() > max)
449 return Dest{
static_cast<desttype
>(value.value())};
452 using namespace boost::multiprecision;
460 auto quotient = product / div.value();
465 return Dest{
static_cast<desttype
>(quotient)};
481mulDiv(Source1 value, Dest mul, Source2 div)
490 class = feeunit::enable_muldiv_commute_t<Source1, Source2, Dest>>
492mulDiv(Dest value, Source1 mul, Source2 div)
498template <
class Dest,
class = feeunit::enable_muldiv_dest_t<Dest>>
507template <
class Dest,
class = feeunit::enable_muldiv_dest_t<Dest>>
512 return mulDiv(mul, value, div);
518 class = feeunit::enable_muldiv_sources_t<Source1, Source2>>
529 return unitresult->value();
535 class = feeunit::enable_muldiv_sources_t<Source1, Source2>>
540 return mulDiv(mul, value, div);
543template <
class Dest,
class Src>
545 std::is_same_v<typename Dest::unit_type, typename Src::unit_type> &&
546 std::is_integral_v<typename Dest::value_type> &&
547 std::is_integral_v<typename Src::value_type>,
552 return Dest{safe_cast<typename Dest::value_type>(s.value())};
555template <
class Dest,
class Src>
557 std::is_same_v<typename Dest::unit_type, typename Src::unit_type> &&
558 std::is_integral_v<typename Dest::value_type> &&
559 std::is_integral_v<typename Src::value_type>,
564 return Dest{unsafe_cast<typename Dest::value_type>(s.value())};
constexpr TaggedFee(TaggedFee< unit_type, Other > const &fee)
Instances with the same unit, and a type that is "safe" to convert to this one can be converted impli...
std::enable_if_t< is_usable_unit_v< TaggedFee >, Json::Value > jsonClipped() const
constexpr TaggedFee & operator=(TaggedFee const &other)=default
TaggedFee & operator=(value_type fee)
bool operator==(value_type other) const
bool operator==(TaggedFee< unit_type, Other > const &other) const
constexpr value_type operator/(TaggedFee const &rhs) const
friend constexpr TaggedFee operator*(value_type lhs, TaggedFee const &rhs)
static constexpr bool is_compatiblefee_v
constexpr value_type value() const
Returns the underlying value.
friend std::istream & operator>>(std::istream &s, TaggedFee &val)
constexpr int signum() const noexcept
Return the sign of the amount.
std::enable_if_t< std::is_integral_v< transparent >, TaggedFee & > operator%=(value_type const &rhs)
typename std::enable_if_t< is_compatible_v< Other > > enable_if_compatible_t
constexpr TaggedFee & operator=(beast::Zero)
constexpr TaggedFee(value_type fee)
typename std::enable_if_t< is_compatiblefee_v< OtherFee > > enable_if_compatiblefee_t
constexpr TaggedFee(beast::Zero)
TaggedFee operator-() const
constexpr TaggedFee(TaggedFee const &other)=default
TaggedFee & operator-=(TaggedFee const &other)
TaggedFee & operator*=(value_type const &rhs)
constexpr double decimalFromReference(TaggedFee< unit_type, Other > reference) const
bool operator<(TaggedFee const &other) const
static constexpr bool is_compatible_v
constexpr value_type fee() const
Returns the number of drops.
TaggedFee & operator/=(value_type const &rhs)
constexpr TaggedFee operator*(value_type const &rhs) const
TaggedFee & operator+=(TaggedFee const &other)
bool operator!=(TaggedFee< unit_type, Other > const &other) const
bool operator==(TaggedFee const &other) const
typename std::enable_if_t< can_muldiv_sources_v< Source1, Source2 > > enable_muldiv_sources_t
constexpr bool is_usable_unit_v
is_usable_unit_v is checked to ensure that only values with known valid type tags can be used (someti...
std::string to_string(TaggedFee< UnitTag, T > const &amount)
constexpr bool can_muldiv_dest_v
std::optional< Dest > mulDivU(Source1 value, Dest mul, Source2 div)
constexpr bool can_muldiv_sources_v
typename std::enable_if_t< std::is_class_v< T > &&std::is_object_v< typename T::unit_type > &&std::is_object_v< typename T::value_type > > enable_if_unit_t
constexpr bool can_muldiv_commute_v
typename std::enable_if_t< can_muldiv_v< Source1, Source2, Dest > > enable_muldiv_t
std::basic_ostream< Char, Traits > & operator<<(std::basic_ostream< Char, Traits > &os, const TaggedFee< UnitTag, T > &q)
constexpr bool can_muldiv_v
typename std::enable_if_t< can_muldiv_source_v< T > > enable_muldiv_source_t
typename std::enable_if_t< can_muldiv_dest_v< T > > enable_muldiv_dest_t
typename std::enable_if_t< can_muldiv_commute_v< Source1, Source2, Dest > > enable_muldiv_commute_t
TaggedFee< unitlessTag, T > scalar(T value)
constexpr bool can_muldiv_source_v
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 > safe_cast(Src s) noexcept
STAmount multiply(STAmount const &amount, Rate const &rate)
std::optional< std::uint64_t > mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
Return value*mul/div accurately.
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > unsafe_cast(Src s) noexcept
Zero allows classes to offer efficient comparisons to zero.