2014-10-15 21:00:49 +00:00
|
|
|
#include <fc/real128.hpp>
|
|
|
|
|
#include <fc/crypto/bigint.hpp>
|
|
|
|
|
#include <fc/exception/exception.hpp>
|
|
|
|
|
#include <sstream>
|
2014-10-16 23:00:30 +00:00
|
|
|
#include <stdint.h>
|
2014-10-15 21:00:49 +00:00
|
|
|
|
2014-10-17 17:23:51 +00:00
|
|
|
#define PRECISION (uint64_t(1000000) * uint64_t(1000000) * uint64_t(1000000))
|
2014-10-16 00:46:24 +00:00
|
|
|
|
2014-10-15 21:00:49 +00:00
|
|
|
namespace fc
|
|
|
|
|
{
|
2014-10-16 00:46:24 +00:00
|
|
|
uint64_t real128::to_uint64()const
|
|
|
|
|
{
|
|
|
|
|
return (fixed/PRECISION).to_uint64();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
real128::real128( uint64_t integer )
|
|
|
|
|
{
|
|
|
|
|
fixed = uint128(integer) * PRECISION;
|
|
|
|
|
}
|
2014-10-15 21:00:49 +00:00
|
|
|
real128& real128::operator += ( const real128& o )
|
|
|
|
|
{
|
|
|
|
|
fixed += o.fixed;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
real128& real128::operator -= ( const real128& o )
|
|
|
|
|
{
|
|
|
|
|
fixed -= o.fixed;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
real128& real128::operator /= ( const real128& o )
|
|
|
|
|
{ try {
|
|
|
|
|
FC_ASSERT( o.fixed > uint128(0), "Divide by Zero" );
|
|
|
|
|
|
|
|
|
|
fc::bigint self(fixed);
|
|
|
|
|
fc::bigint other(o.fixed);
|
2014-10-16 00:46:24 +00:00
|
|
|
self *= PRECISION;
|
2014-10-15 21:00:49 +00:00
|
|
|
self /= other;
|
|
|
|
|
fixed = self;
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
} FC_CAPTURE_AND_RETHROW( (*this)(o) ) }
|
|
|
|
|
|
|
|
|
|
real128& real128::operator *= ( const real128& o )
|
|
|
|
|
{ try {
|
|
|
|
|
fc::bigint self(fixed);
|
|
|
|
|
fc::bigint other(o.fixed);
|
|
|
|
|
self *= other;
|
2014-10-16 00:46:24 +00:00
|
|
|
self /= PRECISION;
|
2014-10-15 21:00:49 +00:00
|
|
|
fixed = self;
|
|
|
|
|
return *this;
|
|
|
|
|
} FC_CAPTURE_AND_RETHROW( (*this)(o) ) }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
real128::real128( const std::string& ratio_str )
|
|
|
|
|
{
|
|
|
|
|
const char* c = ratio_str.c_str();
|
|
|
|
|
int digit = *c - '0';
|
|
|
|
|
if (digit >= 0 && digit <= 9)
|
|
|
|
|
{
|
|
|
|
|
uint64_t int_part = digit;
|
|
|
|
|
++c;
|
|
|
|
|
digit = *c - '0';
|
|
|
|
|
while (digit >= 0 && digit <= 9)
|
|
|
|
|
{
|
|
|
|
|
int_part = int_part * 10 + digit;
|
|
|
|
|
++c;
|
|
|
|
|
digit = *c - '0';
|
|
|
|
|
}
|
2014-10-16 00:46:24 +00:00
|
|
|
*this = real128(int_part);
|
2014-10-15 21:00:49 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// if the string doesn't look like "123.45" or ".45", this code isn't designed to parse it correctly
|
|
|
|
|
// in particular, we don't try to handle leading whitespace or '+'/'-' indicators at the beginning
|
|
|
|
|
assert(*c == '.');
|
|
|
|
|
fixed = fc::uint128();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (*c == '.')
|
|
|
|
|
{
|
|
|
|
|
c++;
|
|
|
|
|
digit = *c - '0';
|
|
|
|
|
if (digit >= 0 && digit <= 9)
|
|
|
|
|
{
|
|
|
|
|
int64_t frac_part = digit;
|
|
|
|
|
int64_t frac_magnitude = 10;
|
|
|
|
|
++c;
|
|
|
|
|
digit = *c - '0';
|
|
|
|
|
while (digit >= 0 && digit <= 9)
|
|
|
|
|
{
|
|
|
|
|
frac_part = frac_part * 10 + digit;
|
|
|
|
|
frac_magnitude *= 10;
|
|
|
|
|
++c;
|
|
|
|
|
digit = *c - '0';
|
|
|
|
|
}
|
|
|
|
|
*this += real128( frac_part ) / real128( frac_magnitude );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
real128::operator std::string()const
|
|
|
|
|
{
|
|
|
|
|
std::stringstream ss;
|
2014-10-16 00:46:24 +00:00
|
|
|
ss << std::string(fixed / PRECISION);
|
2014-10-15 21:00:49 +00:00
|
|
|
ss << '.';
|
2014-10-16 00:46:24 +00:00
|
|
|
auto frac = (fixed % PRECISION) + PRECISION;
|
|
|
|
|
ss << std::string( frac ).substr(1);
|
2014-10-15 21:00:49 +00:00
|
|
|
|
|
|
|
|
auto number = ss.str();
|
|
|
|
|
while( number.back() == '0' ) number.pop_back();
|
|
|
|
|
|
|
|
|
|
return number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void to_variant( const real128& var, variant& vo )
|
|
|
|
|
{
|
|
|
|
|
vo = std::string(var);
|
|
|
|
|
}
|
|
|
|
|
void from_variant( const variant& var, real128& vo )
|
|
|
|
|
{
|
|
|
|
|
vo = real128(var.as_string());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace fc
|