14#ifndef SST_CORE_DECIMAL_FIXEDPOINT_H 
   15#define SST_CORE_DECIMAL_FIXEDPOINT_H 
   17#include "sst/core/from_string.h" 
   39template <
int whole_words, 
int fraction_words>
 
   44    static constexpr uint32_t storage_radix      = 100000000;
 
   45    static constexpr uint64_t storage_radix_long = 100000000l;
 
   46    static constexpr int32_t  digits_per_word    = 8;
 
   60    template <
int A, 
int B>
 
   61    friend class sst_dec_fixed;
 
   72    uint32_t data[whole_words + fraction_words];
 
   86    void from_string(
const std::string& init_str)
 
   88        std::string init(init_str);
 
   90        for ( 
int i = 0; i < whole_words + fraction_words; ++i ) {
 
   95        if ( init[0] == 
'-' ) {
 
   97            init     = init.substr(1, init.npos);
 
  101        size_t  exponent_pos = init.find_last_of(
"eE");
 
  102        int32_t exponent     = 0;
 
  103        if ( exponent_pos != init.npos ) {
 
  104            exponent = 
static_cast<int32_t
>(SST::Core::from_string<double>(init.substr(exponent_pos + 1, init.npos)));
 
  105            init     = init.substr(0, exponent_pos);
 
  108        int dp = init.length();
 
  109        for ( 
size_t i = 0; i < init.length(); ++i ) {
 
  110            if ( init[i] == 
'.' ) { dp = i; }
 
  117        int start_of_digits = (fraction_words * digits_per_word) - (init.length() - dp) + exponent;
 
  121        int      start_pos_word = start_of_digits % digits_per_word;
 
  123        for ( 
int i = 0; i < start_pos_word; i++ ) {
 
  127        for ( 
int i = init.length() - 1; i >= 0; --i ) {
 
  128            int digit = start_of_digits + (init.length() - 1 - i);
 
  129            int word  = (digit / digits_per_word);
 
  131            data[word] += (SST::Core::from_string<uint32_t>(init.substr(i, 1)) * mult);
 
  133            if ( mult == storage_radix ) mult = 1;
 
  142    void from_uint64(uint64_t init)
 
  146        for ( 
int i = 0; i < whole_words + fraction_words; ++i ) {
 
  159        for ( 
int i = fraction_words; i < whole_words + fraction_words; ++i ) {
 
  160            data[i] = init % storage_radix_long;
 
  161            init /= storage_radix_long;
 
  170    void from_double(
double init)
 
  174        for ( 
int i = 0; i < whole_words + fraction_words; ++i ) {
 
  179        for ( 
int i = 0; i < whole_words - 1; ++i ) {
 
  180            factor *= storage_radix;
 
  183        for ( 
int i = whole_words + fraction_words - 1; i >= 0; --i ) {
 
  184            data[i] = 
static_cast<uint32_t
>(init / factor);
 
  185            init -= (data[i] * factor);
 
  186            factor /= storage_radix;
 
  199        for ( 
int i = 0; i < whole_words + fraction_words; ++i ) {
 
  231        T init, 
typename std::enable_if<std::is_signed<T>::value && std::is_integral<T>::value>::type* = 
nullptr)
 
  248    decimal_fixedpoint(
const T init, 
typename std::enable_if<std::is_floating_point<T>::value>::type* = 
nullptr)
 
  260        negative = init.negative;
 
  261        for ( 
int i = 0; i < whole_words + fraction_words; ++i ) {
 
  262            data[i] = init.data[i];
 
  271        negative = v.negative;
 
  272        for ( 
int i = 0; i < whole_words + fraction_words; ++i ) {
 
  323    void negate() { negative = negative ^ 0x1; }
 
  333        for ( 
int i = 0; i < fraction_words; ++i ) {
 
  334            factor /= storage_radix;
 
  337        for ( 
int i = 0; i < whole_words + fraction_words; ++i ) {
 
  338            ret += (
static_cast<double>(data[i]) * factor);
 
  339            factor *= storage_radix;
 
  353        for ( 
int i = 0; i < whole_words; ++i ) {
 
  354            ret += (
static_cast<int64_t
>(data[fraction_words + i]) * factor);
 
  355            factor *= storage_radix;
 
  360        if ( data[fraction_words - 1] > (storage_radix / 2) ) { round = 
true; }
 
  361        else if ( data[fraction_words - 1] == (storage_radix / 2) ) {
 
  362            for ( 
int i = fraction_words - 2; i >= 0; --i ) {
 
  363                if ( data[i] != 0 ) {
 
  372                if ( ret % 2 == 1 ) round = 
true;
 
  376        if ( negative ) ret = -ret;
 
  388        for ( 
int i = 0; i < whole_words; ++i ) {
 
  389            ret += (
static_cast<int64_t
>(data[i]) * factor);
 
  390            factor *= storage_radix;
 
  400        for ( 
int i = whole_words + fraction_words - 1; i >= 0; --i ) {
 
  401            if ( data[i] != 0 ) 
return false;
 
  409    template <
typename T>
 
  410    T 
convert_to(
typename std::enable_if<std::is_unsigned<T>::value>::type* = 0)
 const 
  418    template <
typename T>
 
  419    T 
convert_to(
typename std::enable_if<std::is_signed<T>::value && std::is_integral<T>::value>::type* = 0)
 const 
  421        return static_cast<T
>(
toLong());
 
  427    template <
typename T>
 
  428    T 
convert_to(
typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
 const 
  442        std::stringstream stream;
 
  443        if ( precision <= 0 || precision > ((whole_words + fraction_words) * digits_per_word) )
 
  444            precision = (whole_words + fraction_words) * digits_per_word;
 
  448        constexpr int num_digits = (whole_words + fraction_words) * digits_per_word;
 
  450        unsigned char digits[num_digits];
 
  451        for ( 
int i = 0; i < whole_words + fraction_words; ++i ) {
 
  452            uint32_t value = data[i];
 
  453            for ( 
int j = 0; j < digits_per_word; ++j ) {
 
  454                digits[i * digits_per_word + j] = value % 10;
 
  460        int first_non_zero = -1;
 
  461        for ( 
int i = num_digits - 1; i >= 0; --i ) {
 
  462            if ( digits[i] != 0 ) {
 
  469        if ( first_non_zero == -1 ) 
return "0";
 
  472        int  round_position = first_non_zero - precision;
 
  477        if ( round_position >= 0 ) {
 
  478            if ( digits[round_position] > 5 )
 
  480            else if ( digits[round_position] < 5 )
 
  484                for ( 
int i = round_position - 1; i >= 0; --i ) {
 
  485                    if ( digits[i] != 0 ) {
 
  493                    if ( digits[round_position + 1] % 2 == 1 ) round = 
true;
 
  499                unsigned char carry = 1;
 
  500                for ( 
int i = round_position + 1; i < num_digits; ++i ) {
 
  502                    carry     = digits[i] / 10;
 
  503                    digits[i] = digits[i] % 10;
 
  508            for ( 
int i = 0; i <= round_position; ++i ) {
 
  514        if ( negative ) stream << 
'-';
 
  518        for ( 
int i = num_digits - 1; i >= 0; --i ) {
 
  519            if ( digits[i] != 0 ) {
 
  526        if ( first_non_zero == -1 ) {
 
  529            stream << 
"1e+" << (whole_words * digits_per_word);
 
  536        if ( first_non_zero >= ((fraction_words * digits_per_word) + precision) ) {
 
  538            int exponent = first_non_zero - (fraction_words * digits_per_word);
 
  539            stream << static_cast<uint32_t>(digits[first_non_zero]) << 
".";
 
  541            for ( 
int i = first_non_zero - 1; i >= first_non_zero - precision; --i ) {
 
  545                if ( digits[i] == 0 )
 
  548                    for ( 
int j = 0; j < zeros; ++j ) {
 
  551                    stream << static_cast<uint32_t>(digits[i]);
 
  555            std::string ret = stream.str();
 
  556            if ( ret[ret.length() - 1] == 
'.' ) {
 
  557                ret = ret.substr(0, ret.length() - 1);
 
  558                stream.str(std::string(
""));
 
  561            stream << 
"e+" << std::setfill(
'0') << std::setw(2) << exponent;
 
  566        else if ( first_non_zero >= (fraction_words * digits_per_word) ) {
 
  568            for ( 
int i = first_non_zero; i >= (fraction_words * digits_per_word); --i ) {
 
  570                stream << static_cast<uint32_t>(digits[i]);
 
  575            for ( 
int i = (fraction_words * digits_per_word) - 1; i >= first_non_zero - precision && (i >= 0); --i ) {
 
  579                if ( digits[i] == 0 )
 
  582                    for ( 
int j = 0; j < zeros; ++j ) {
 
  585                    stream << static_cast<uint32_t>(digits[i]);
 
  589            std::string ret = stream.str();
 
  590            if ( ret[ret.length() - 1] == 
'.' ) {
 
  591                ret = ret.substr(0, ret.length() - 1);
 
  592                stream.str(std::string(
""));
 
  600        else if ( first_non_zero > (fraction_words * digits_per_word) - 5 ) {
 
  602            for ( 
int i = (fraction_words * digits_per_word) - 1; i > first_non_zero; --i ) {
 
  606            for ( 
int i = first_non_zero; (i >= first_non_zero - precision) && (i >= 0); --i ) {
 
  610                if ( digits[i] == 0 )
 
  613                    for ( 
int j = 0; j < zeros; ++j ) {
 
  616                    stream << static_cast<uint32_t>(digits[i]);
 
  624            int exponent = first_non_zero - (fraction_words * digits_per_word);
 
  625            exponent     = -exponent;
 
  626            stream << static_cast<uint32_t>(digits[first_non_zero]) << 
".";
 
  628            for ( 
int i = first_non_zero - 1; (i >= first_non_zero - precision) && (i >= 0); --i ) {
 
  632                if ( digits[i] == 0 )
 
  635                    for ( 
int j = 0; j < zeros; ++j ) {
 
  638                    stream << static_cast<uint32_t>(digits[i]);
 
  642            std::string ret = stream.str();
 
  643            if ( ret[ret.length() - 1] == 
'.' ) {
 
  644                ret = ret.substr(0, ret.length() - 1);
 
  645                stream.str(std::string(
""));
 
  648            stream << 
"e-" << std::setfill(
'0') << std::setw(2) << exponent;
 
  663        if ( (negative ^ v.negative) == 0 ) {
 
  666            uint64_t carry_over = 0;
 
  667            for ( 
int i = 0; i < whole_words + fraction_words; i++ ) {
 
  668                uint64_t value = 
static_cast<uint64_t
>(data[i]) + 
static_cast<uint64_t
>(v.data[i]) + carry_over;
 
  669                carry_over     = value / storage_radix;
 
  671                data[i]        = value % storage_radix;
 
  677        if ( 
operator>=(v) ) {
 
  680            uint64_t carry_over = 1;
 
  681            for ( 
int i = 0; i < whole_words + fraction_words; i++ ) {
 
  682                uint64_t 
negate = 
static_cast<uint64_t
>(storage_radix - 1) - 
static_cast<uint64_t
>(v.data[i]);
 
  684                uint64_t value = 
static_cast<uint64_t
>(data[i]) + 
negate + carry_over;
 
  685                carry_over     = value / storage_radix;
 
  686                data[i]        = 
static_cast<uint32_t
>(value % storage_radix);
 
  693            uint64_t carry_over = 1;
 
  694            for ( 
int i = 0; i < whole_words + fraction_words; i++ ) {
 
  695                uint64_t 
negate = 
static_cast<uint64_t
>(storage_radix - 1) - 
static_cast<uint64_t
>(data[i]);
 
  697                uint64_t value = 
static_cast<uint64_t
>(v.data[i]) + 
negate + carry_over;
 
  698                carry_over     = value / storage_radix;
 
  699                data[i]        = 
static_cast<uint32_t
>(value % storage_radix);
 
  702            negative = v.negative;
 
  734        uint64_t carry_over = 0;
 
  735        for ( 
int i = 0; i < fraction_words; ++i ) {
 
  736            uint64_t sum = carry_over;
 
  737            for ( 
int j = 0; j <= i; ++j ) {
 
  738                sum += 
static_cast<uint64_t
>(me.data[j]) * 
static_cast<uint64_t
>(v.data[i - j]);
 
  740            carry_over = sum / storage_radix_long;
 
  744        for ( 
int i = fraction_words; i < whole_words + fraction_words; ++i ) {
 
  745            uint64_t sum = carry_over;
 
  746            for ( 
int j = 0; j <= i; ++j ) {
 
  747                sum += 
static_cast<uint64_t
>(me.data[j]) * 
static_cast<uint64_t
>(v.data[i - j]);
 
  749            carry_over               = sum / storage_radix_long;
 
  750            data[i - fraction_words] = 
static_cast<uint32_t
>(sum % storage_radix_long);
 
  753        for ( 
int i = 0; i < fraction_words; ++i ) {
 
  754            uint64_t sum = carry_over;
 
  755            for ( 
int j = i + 1; j < whole_words + fraction_words; ++j ) {
 
  756                sum += 
static_cast<uint64_t
>(me.data[j]) *
 
  757                       static_cast<uint64_t
>(v.data[whole_words + fraction_words + i - j]);
 
  759            carry_over            = sum / storage_radix_long;
 
  760            data[i + whole_words] = 
static_cast<uint32_t
>(sum % storage_radix_long);
 
  763        negative = negative ^ v.negative;
 
  802        int digits_of_prec = std::numeric_limits<double>::digits10 / 2;
 
  805        for ( 
int i = digits_of_prec; i <= (whole_words + fraction_words) * digits_per_word; i *= 2 ) {
 
  824        for ( 
int i = whole_words + fraction_words - 1; i >= 0; --i ) {
 
  825            if ( data[i] != v.data[i] ) 
return false;
 
  837        for ( 
int i = whole_words + fraction_words - 1; i >= 0; --i ) {
 
  838            if ( data[i] != v.data[i] ) 
return true;
 
  850        for ( 
int i = whole_words + fraction_words - 1; i >= 0; --i ) {
 
  851            if ( data[i] > v.data[i] ) 
return true;
 
  852            if ( data[i] < v.data[i] ) 
return false;
 
  865        for ( 
int i = whole_words + fraction_words - 1; i >= 0; --i ) {
 
  866            if ( data[i] > v.data[i] ) 
return true;
 
  867            if ( data[i] < v.data[i] ) 
return false;
 
  879        for ( 
int i = whole_words + fraction_words - 1; i >= 0; --i ) {
 
  880            if ( data[i] < v.data[i] ) 
return true;
 
  881            if ( data[i] > v.data[i] ) 
return false;
 
  894        for ( 
int i = whole_words + fraction_words - 1; i >= 0; --i ) {
 
  895            if ( data[i] < v.data[i] ) 
return true;
 
  896            if ( data[i] > v.data[i] ) 
return false;
 
  902template <
int whole_words, 
int fraction_words>
 
  903decimal_fixedpoint<whole_words, fraction_words>
 
  904operator+(decimal_fixedpoint<whole_words, fraction_words> lhs, decimal_fixedpoint<whole_words, fraction_words> rhs)
 
  906    decimal_fixedpoint<whole_words, fraction_words> ret(lhs);
 
  910template <
int whole_words, 
int fraction_words>
 
  911decimal_fixedpoint<whole_words, fraction_words>
 
  912operator-(decimal_fixedpoint<whole_words, fraction_words> lhs, decimal_fixedpoint<whole_words, fraction_words> rhs)
 
  914    decimal_fixedpoint<whole_words, fraction_words> ret(lhs);
 
  918template <
int whole_words, 
int fraction_words>
 
  919decimal_fixedpoint<whole_words, fraction_words>
 
  920operator*(decimal_fixedpoint<whole_words, fraction_words> lhs, decimal_fixedpoint<whole_words, fraction_words> rhs)
 
  922    decimal_fixedpoint<whole_words, fraction_words> ret(lhs);
 
  926template <
int whole_words, 
int fraction_words>
 
  927decimal_fixedpoint<whole_words, fraction_words>
 
  928operator/(decimal_fixedpoint<whole_words, fraction_words> lhs, decimal_fixedpoint<whole_words, fraction_words> rhs)
 
  930    decimal_fixedpoint<whole_words, fraction_words> ret(lhs);
 
  934template <
int whole_words, 
int fraction_words, 
typename T>
 
  936operator==(
const T& lhs, 
const decimal_fixedpoint<whole_words, fraction_words>& rhs)
 
  938    return rhs == decimal_fixedpoint<whole_words, fraction_words>(lhs);
 
  941template <
int whole_words, 
int fraction_words, 
typename T>
 
  943operator!=(
const T& lhs, 
const decimal_fixedpoint<whole_words, fraction_words>& rhs)
 
  945    return rhs != decimal_fixedpoint<whole_words, fraction_words>(lhs);
 
  948template <
int whole_words, 
int fraction_words>
 
  950operator<<(std::ostream& os, 
const decimal_fixedpoint<whole_words, fraction_words>& rhs)
 
  952    os << rhs.toString(os.precision());
 
Class that implements a decimal fixed-point number.
Definition: decimal_fixedpoint.h:41
 
decimal_fixedpoint(const std::string &init)
Build a decimal_fixedpoint using a string initializer.
Definition: decimal_fixedpoint.h:211
 
T convert_to(typename std::enable_if< std::is_unsigned< T >::value >::type *=0) const
Templated conversion function for unsigned types.
Definition: decimal_fixedpoint.h:410
 
decimal_fixedpoint(T init, typename std::enable_if< std::is_unsigned< T >::value >::type *=nullptr)
Build a decimal_fixedpoint using a 64-bit unsigned number.
Definition: decimal_fixedpoint.h:219
 
std::string toString(int32_t precision=6) const
Create a string representation of this decimal_fixedpoint.
Definition: decimal_fixedpoint.h:439
 
decimal_fixedpoint & inverse()
Inverts the number (1 divided by this number)
Definition: decimal_fixedpoint.h:785
 
decimal_fixedpoint(const T init, typename std::enable_if< std::is_floating_point< T >::value >::type *=nullptr)
Build a decimal_fixedpoint using a double.
Definition: decimal_fixedpoint.h:248
 
bool operator>(const decimal_fixedpoint &v) const
Checks to see if this number is greater than another number.
Definition: decimal_fixedpoint.h:848
 
decimal_fixedpoint & operator=(const std::string &v)
Equal operator for string.
Definition: decimal_fixedpoint.h:314
 
decimal_fixedpoint & operator=(const decimal_fixedpoint &v)
Equal operator for other decimal_fixedpoint objects.
Definition: decimal_fixedpoint.h:269
 
decimal_fixedpoint(T init, typename std::enable_if< std::is_signed< T >::value &&std::is_integral< T >::value >::type *=nullptr)
Build a decimal_fixedpoint using a 64-bit signed number.
Definition: decimal_fixedpoint.h:230
 
decimal_fixedpoint(const decimal_fixedpoint &init)
Build a decimal_fixedpoint using another decimal_fixedpoint.
Definition: decimal_fixedpoint.h:258
 
T convert_to(typename std::enable_if< std::is_signed< T >::value &&std::is_integral< T >::value >::type *=0) const
Templated conversion function for signed integral types.
Definition: decimal_fixedpoint.h:419
 
bool operator!=(const decimal_fixedpoint &v) const
Checks to see if two numbers are not equal.
Definition: decimal_fixedpoint.h:835
 
constexpr int getWholeWords() const
Get the value of whole_words template parameter.
Definition: decimal_fixedpoint.h:51
 
int64_t toLong() const
Return a int64_t version of the decimal_fixedpoint.
Definition: decimal_fixedpoint.h:349
 
decimal_fixedpoint & operator=(int64_t v)
Equal operator for 64-bit signed int.
Definition: decimal_fixedpoint.h:290
 
double toDouble() const
Return a double precision version of the decimal_fixedpoint.
Definition: decimal_fixedpoint.h:329
 
decimal_fixedpoint & operator+=(const decimal_fixedpoint &v)
Adds another number to this one and sets it equal to the result.
Definition: decimal_fixedpoint.h:660
 
decimal_fixedpoint & operator=(double v)
Equal operator for double.
Definition: decimal_fixedpoint.h:305
 
bool isZero() const
Return true if value is zero, otherwise return false.
Definition: decimal_fixedpoint.h:398
 
decimal_fixedpoint()
Default constructor.
Definition: decimal_fixedpoint.h:196
 
uint64_t toUnsignedLong() const
Return a uint64_t version of the decimal_fixedpoint.
Definition: decimal_fixedpoint.h:384
 
decimal_fixedpoint & operator/=(const decimal_fixedpoint &v)
Divides another number from this one and sets it equal to the result.
Definition: decimal_fixedpoint.h:773
 
bool operator<(const decimal_fixedpoint &v) const
Checks to see if this number is less than another number.
Definition: decimal_fixedpoint.h:877
 
bool operator==(const decimal_fixedpoint &v) const
Checks to see if two numbers are equal.
Definition: decimal_fixedpoint.h:822
 
void negate()
Negate the value (change the sign bit).
Definition: decimal_fixedpoint.h:323
 
decimal_fixedpoint & operator=(uint64_t v)
Equal operator for 64-bit unsigned int.
Definition: decimal_fixedpoint.h:281
 
decimal_fixedpoint & operator-=(const decimal_fixedpoint &v)
Subtracts another number from this one and sets it equal to the result.
Definition: decimal_fixedpoint.h:713
 
T convert_to(typename std::enable_if< std::is_floating_point< T >::value >::type *=0) const
Templated conversion function for floating point types.
Definition: decimal_fixedpoint.h:428
 
bool operator<=(const decimal_fixedpoint &v) const
Checks to see if this number is less than or equal to another number.
Definition: decimal_fixedpoint.h:892
 
bool operator>=(const decimal_fixedpoint &v) const
Checks to see if this number is greater than or equal to another number.
Definition: decimal_fixedpoint.h:863
 
constexpr int getFractionWords() const
Get the value of fraction_words template parameter.
Definition: decimal_fixedpoint.h:56
 
decimal_fixedpoint & operator*=(const decimal_fixedpoint &v)
Multiplies another number to this one and sets it equal to the result.
Definition: decimal_fixedpoint.h:726