xrpld
Loading...
Searching...
No Matches
xrpl::Number::Guard Class Reference

Guard. More...

Collaboration diagram for xrpl::Number::Guard:

Public Member Functions

 Guard (InternalRep const &minMantissa, InternalRep const &maxMantissa, MantissaRange::CuspRoundingFix cuspRoundingFix)
 Guard (MantissaRange const &range)
void setPositive () noexcept
void setNegative () noexcept
void setDropped () noexcept
bool isNegative () const noexcept
template<class T>
void push (T d) noexcept
unsigned pop () noexcept
bool unrecoverable () const noexcept
bool empty () const noexcept
template<class T>
void doDropDigit (T &mantissa, int &exponent) noexcept
 Drop a digit from the mantissa, and increment the exponent, storing the dropped digit in this Guard.
template<class T>
void doDropDigitWithTarget (T &mantissa, int &exponent, int const targetExponent) noexcept
 Drop a digit from the mantissa, and increment the exponent, storing the dropped digit in this Guard.
template<UnsignedMantissa T>
void doRoundUp (bool &negative, T &mantissa, int &exponent, std::string location)
template<UnsignedMantissa T>
void doRoundDown (bool &negative, T &mantissa, int &exponent) const
void doRound (rep &drops, std::string location) const
template<>
void doDropDigit (UInt128T &mantissa, int &exponent) noexcept

Public Attributes

InternalRep const minMantissa
InternalRep const maxMantissa
MantissaRange::CuspRoundingFix const cuspRoundingFix

Private Types

enum class  Round { Exact = -2 , Down = -1 , Even = 0 , Up = 1 }

Private Member Functions

template<UnsignedMantissa T>
void pushOverflow (T mantissa)
Round round () const noexcept
void doPush (unsigned d) noexcept
template<UnsignedMantissa T>
void bringIntoRange (bool &negative, T &mantissa, int &exponent) const

Private Attributes

std::uint64_t digits_ {0}
std::uint8_t xbit_: 1 {0}
std::uint8_t sbit_: 1 {0}

Detailed Description

Guard.

The Guard class is used to temporarily add extra digits of precision to an operation. This enables the final result to be correctly rounded to the internal precision of Number.

At its core, the Guard really only needs three pieces of information to determine how to round:

  1. The rounding mode
  2. The last digit dropped from the mantissa (i.e. the first digit after the decimal point). (first byte of digits_)
  3. Whether any other non-zero digits were dropped from the mantissa. (remaining bytes of digits_ and xbit_)

Upward and Downward rounding modes round the unsigned mantissa toward or away from zero depending on whether the sign is negative (sbit_). For positive values, Upward is away, and Downward is toward. For negative values, that's reversed. For simplicity, I'm going to describe the logic using "TowardZero" and "AwayFromZero".

TowardZero is the easiest rounding mode. It always rounds down. digits_ and xbit_ are irrelevant. AwayFromZero is almost as simple. If both "digits_" and "xbit_" are zero (0), it rounds down. Else it rounds up. ToNearest is only a little more complicated. If the last dropped digit is < 5, then round down. If it is > 5, round up. If it is exactly 5, and there are any other digits (the remainder of "digits_" or "xbit_"), round up, else round to even.

The current implementation stores 16 digits in "digits_" so that digits can be "pop"ped back out if needed during subtraction (negative addition) operations.

Definition at line 219 of file libxrpl/basics/Number.cpp.

Member Enumeration Documentation

◆ Round

enum class xrpl::Number::Guard::Round
strongprivate
Enumerator
Exact 
Down 
Even 
Up 

Definition at line 315 of file libxrpl/basics/Number.cpp.

Constructor & Destructor Documentation

◆ Guard() [1/2]

xrpl::Number::Guard::Guard ( InternalRep const & minMantissa,
InternalRep const & maxMantissa,
MantissaRange::CuspRoundingFix cuspRoundingFix )
explicit

Definition at line 230 of file libxrpl/basics/Number.cpp.

◆ Guard() [2/2]

xrpl::Number::Guard::Guard ( MantissaRange const & range)
explicit

Definition at line 238 of file libxrpl/basics/Number.cpp.

Member Function Documentation

◆ setPositive()

void xrpl::Number::Guard::setPositive ( )
noexcept

Definition at line 346 of file libxrpl/basics/Number.cpp.

◆ setNegative()

void xrpl::Number::Guard::setNegative ( )
noexcept

Definition at line 352 of file libxrpl/basics/Number.cpp.

◆ setDropped()

void xrpl::Number::Guard::setDropped ( )
noexcept

Definition at line 358 of file libxrpl/basics/Number.cpp.

◆ isNegative()

bool xrpl::Number::Guard::isNegative ( ) const
nodiscardnoexcept

Definition at line 364 of file libxrpl/basics/Number.cpp.

◆ push()

template<class T>
void xrpl::Number::Guard::push ( T d)
noexcept

Definition at line 380 of file libxrpl/basics/Number.cpp.

◆ pop()

unsigned xrpl::Number::Guard::pop ( )
noexcept

Definition at line 386 of file libxrpl/basics/Number.cpp.

◆ unrecoverable()

bool xrpl::Number::Guard::unrecoverable ( ) const
nodiscardnoexcept

Definition at line 394 of file libxrpl/basics/Number.cpp.

◆ empty()

bool xrpl::Number::Guard::empty ( ) const
nodiscardnoexcept

Definition at line 400 of file libxrpl/basics/Number.cpp.

◆ doDropDigit() [1/2]

template<class T>
void xrpl::Number::Guard::doDropDigit ( T & mantissa,
int & exponent )
noexcept

Drop a digit from the mantissa, and increment the exponent, storing the dropped digit in this Guard.

Substitute for: push(mantissa % 10); mantissa /= 10; ++exponent;

Definition at line 407 of file libxrpl/basics/Number.cpp.

◆ doDropDigitWithTarget()

template<class T>
void xrpl::Number::Guard::doDropDigitWithTarget ( T & mantissa,
int & exponent,
int const targetExponent )
noexcept

Drop a digit from the mantissa, and increment the exponent, storing the dropped digit in this Guard.

If a drop will not do anything meaningful (there are no recoverable digits in the guard, and the mantissa is 0), and if targetExponent > exponent, simply set exponent to targetExponent.

Definition at line 428 of file libxrpl/basics/Number.cpp.

◆ doRoundUp()

template<UnsignedMantissa T>
void xrpl::Number::Guard::doRoundUp ( bool & negative,
T & mantissa,
int & exponent,
std::string location )

Definition at line 580 of file libxrpl/basics/Number.cpp.

◆ doRoundDown()

template<UnsignedMantissa T>
void xrpl::Number::Guard::doRoundDown ( bool & negative,
T & mantissa,
int & exponent ) const

Definition at line 656 of file libxrpl/basics/Number.cpp.

◆ doRound()

void xrpl::Number::Guard::doRound ( rep & drops,
std::string location ) const

Definition at line 692 of file libxrpl/basics/Number.cpp.

◆ pushOverflow()

template<UnsignedMantissa T>
void xrpl::Number::Guard::pushOverflow ( T mantissa)
private

Definition at line 447 of file libxrpl/basics/Number.cpp.

◆ round()

Number::Guard::Round xrpl::Number::Guard::round ( ) const
nodiscardprivatenoexcept

Definition at line 509 of file libxrpl/basics/Number.cpp.

◆ doPush()

void xrpl::Number::Guard::doPush ( unsigned d)
privatenoexcept

Definition at line 370 of file libxrpl/basics/Number.cpp.

◆ bringIntoRange()

template<UnsignedMantissa T>
void xrpl::Number::Guard::bringIntoRange ( bool & negative,
T & mantissa,
int & exponent ) const
private

Definition at line 553 of file libxrpl/basics/Number.cpp.

◆ doDropDigit() [2/2]

template<>
void xrpl::Number::Guard::doDropDigit ( UInt128T & mantissa,
int & exponent )
noexcept

Definition at line 416 of file libxrpl/basics/Number.cpp.

Member Data Documentation

◆ digits_

std::uint64_t xrpl::Number::Guard::digits_ {0}
private

Definition at line 221 of file libxrpl/basics/Number.cpp.

◆ xbit_

std::uint8_t xrpl::Number::Guard::xbit_
private

Definition at line 222 of file libxrpl/basics/Number.cpp.

◆ sbit_

std::uint8_t xrpl::Number::Guard::sbit_
private

Definition at line 223 of file libxrpl/basics/Number.cpp.

◆ minMantissa

InternalRep const xrpl::Number::Guard::minMantissa

Definition at line 226 of file libxrpl/basics/Number.cpp.

◆ maxMantissa

InternalRep const xrpl::Number::Guard::maxMantissa

Definition at line 227 of file libxrpl/basics/Number.cpp.

◆ cuspRoundingFix

MantissaRange::CuspRoundingFix const xrpl::Number::Guard::cuspRoundingFix

Definition at line 228 of file libxrpl/basics/Number.cpp.