FC Updates from BitShares and myself #21
5 changed files with 0 additions and 251 deletions
|
|
@ -195,7 +195,6 @@ option( UNITY_BUILD OFF )
|
|||
|
||||
set( fc_sources
|
||||
src/uint128.cpp
|
||||
src/real128.cpp
|
||||
src/variant.cpp
|
||||
src/exception.cpp
|
||||
src/variant_object.cpp
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
#pragma once
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
#define FC_REAL128_PRECISION (uint64_t(1000000) * uint64_t(1000000) * uint64_t(1000000))
|
||||
|
||||
namespace fc {
|
||||
class variant;
|
||||
|
||||
/**
|
||||
* Provides fixed point math operations based on decimal fractions
|
||||
* with 18 places.
|
||||
* Delegates to fc::bigint for multiplication and division.
|
||||
*/
|
||||
class real128
|
||||
{
|
||||
public:
|
||||
real128( uint64_t integer = 0);
|
||||
explicit real128( const std::string& str );
|
||||
operator std::string()const;
|
||||
|
||||
friend real128 operator * ( real128 a, const real128& b ) { a *= b; return a; }
|
||||
friend real128 operator / ( real128 a, const real128& b ) { a /= b; return a; }
|
||||
friend real128 operator + ( real128 a, const real128& b ) { a += b; return a; }
|
||||
friend real128 operator - ( real128 a, const real128& b ) { a -= b; return a; }
|
||||
|
||||
real128& operator += ( const real128& o );
|
||||
real128& operator -= ( const real128& o );
|
||||
real128& operator /= ( const real128& o );
|
||||
real128& operator *= ( const real128& o );
|
||||
|
||||
static real128 from_fixed( const uint128& fixed );
|
||||
|
||||
uint64_t to_uint64()const;
|
||||
|
||||
template<typename Stream>
|
||||
inline void pack( Stream& s, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) {
|
||||
pack( s, fixed, _max_depth );
|
||||
}
|
||||
private:
|
||||
uint128 fixed;
|
||||
};
|
||||
|
||||
void to_variant( const real128& var, variant& vo, uint32_t max_depth = 1 );
|
||||
void from_variant( const variant& var, real128& vo, uint32_t max_depth = 1 );
|
||||
|
||||
namespace raw
|
||||
{
|
||||
template<typename Stream>
|
||||
inline void pack( Stream& s, const real128& value_to_pack, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
|
||||
{ value_to_pack.pack( s, _max_depth ); }
|
||||
|
||||
template<typename Stream>
|
||||
inline void unpack( Stream& s, real128& value_to_unpack, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
|
||||
{
|
||||
uint128_t delegate;
|
||||
unpack( s, delegate, _max_depth );
|
||||
value_to_unpack = fc::real128::from_fixed( delegate );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fc
|
||||
130
src/real128.cpp
130
src/real128.cpp
|
|
@ -1,130 +0,0 @@
|
|||
#include <fc/real128.hpp>
|
||||
#include <fc/crypto/bigint.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <sstream>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace fc
|
||||
{
|
||||
uint64_t real128::to_uint64()const
|
||||
{
|
||||
return (fixed/ FC_REAL128_PRECISION).to_uint64();
|
||||
}
|
||||
|
||||
real128::real128( uint64_t integer )
|
||||
{
|
||||
fixed = uint128(integer) * FC_REAL128_PRECISION;
|
||||
}
|
||||
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);
|
||||
self *= FC_REAL128_PRECISION;
|
||||
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;
|
||||
self /= FC_REAL128_PRECISION;
|
||||
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';
|
||||
}
|
||||
*this = real128(int_part);
|
||||
}
|
||||
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;
|
||||
ss << std::string(fixed / FC_REAL128_PRECISION);
|
||||
ss << '.';
|
||||
auto frac = (fixed % FC_REAL128_PRECISION) + FC_REAL128_PRECISION;
|
||||
ss << std::string( frac ).substr(1);
|
||||
|
||||
auto number = ss.str();
|
||||
while( number.back() == '0' ) number.pop_back();
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
real128 real128::from_fixed( const uint128& fixed )
|
||||
{
|
||||
real128 result;
|
||||
result.fixed = fixed;
|
||||
return result;
|
||||
}
|
||||
|
||||
void to_variant( const real128& var, variant& vo, uint32_t max_depth )
|
||||
{
|
||||
vo = std::string(var);
|
||||
}
|
||||
void from_variant( const variant& var, real128& vo, uint32_t max_depth )
|
||||
{
|
||||
vo = real128(var.as_string());
|
||||
}
|
||||
|
||||
} // namespace fc
|
||||
|
|
@ -10,9 +10,6 @@ target_link_libraries( task_cancel_test fc )
|
|||
add_executable( bloom_test all_tests.cpp bloom_test.cpp )
|
||||
target_link_libraries( bloom_test fc )
|
||||
|
||||
add_executable( real128_test all_tests.cpp real128_test.cpp )
|
||||
target_link_libraries( real128_test fc )
|
||||
|
||||
add_executable( hmac_test hmac_test.cpp )
|
||||
target_link_libraries( hmac_test fc )
|
||||
|
||||
|
|
@ -44,7 +41,6 @@ add_executable( all_tests all_tests.cpp
|
|||
thread/thread_tests.cpp
|
||||
thread/parallel_tests.cpp
|
||||
bloom_test.cpp
|
||||
real128_test.cpp
|
||||
serialization_test.cpp
|
||||
stacktrace_test.cpp
|
||||
time_test.cpp
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
#include <fc/real128.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <fc/log/logger.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(fc)
|
||||
|
||||
using fc::real128;
|
||||
using std::string;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(real128_test)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(string(real128()), string("0."));
|
||||
BOOST_CHECK_EQUAL(string(real128(0)), string("0."));
|
||||
BOOST_CHECK_EQUAL(real128(8).to_uint64(), 8u);
|
||||
BOOST_CHECK_EQUAL(real128(6789).to_uint64(), 6789u);
|
||||
BOOST_CHECK_EQUAL(real128(10000).to_uint64(), 10000u);
|
||||
BOOST_CHECK_EQUAL(string(real128(1)), string("1."));
|
||||
BOOST_CHECK_EQUAL(string(real128(5)), string("5."));
|
||||
BOOST_CHECK_EQUAL(string(real128(12345)), string("12345."));
|
||||
BOOST_CHECK_EQUAL(string(real128(0)), string(real128("0")));
|
||||
|
||||
real128 ten(10);
|
||||
real128 two(2);
|
||||
real128 twenty(20);
|
||||
real128 pi(31415926535);
|
||||
pi /= 10000000000;
|
||||
|
||||
BOOST_CHECK_EQUAL( string(ten), "10." );
|
||||
BOOST_CHECK_EQUAL( string(two), "2." );
|
||||
BOOST_CHECK_EQUAL( string(ten+two), "12." );
|
||||
BOOST_CHECK_EQUAL( string(ten-two), "8." );
|
||||
BOOST_CHECK_EQUAL( string(ten*two), "20." );
|
||||
BOOST_CHECK_EQUAL( string(ten/two), "5." );
|
||||
BOOST_CHECK_EQUAL( string(ten/two/two/two*two*two*two), "10." );
|
||||
BOOST_CHECK_EQUAL( string(ten/two/two/two*two*two*two), string(ten) );
|
||||
BOOST_CHECK_EQUAL( string(twenty/ten), string(two) );
|
||||
BOOST_CHECK_EQUAL( string(pi), "3.1415926535" );
|
||||
BOOST_CHECK_EQUAL( string(pi*10), "31.415926535" );
|
||||
BOOST_CHECK_EQUAL( string(pi*20), "62.83185307" );
|
||||
BOOST_CHECK_EQUAL( string(real128("62.83185307")/twenty), string(pi) );
|
||||
BOOST_CHECK_EQUAL( string(pi*1), "3.1415926535" );
|
||||
BOOST_CHECK_EQUAL( string(pi*0), "0." );
|
||||
|
||||
BOOST_CHECK_EQUAL(real128("12345.6789").to_uint64(), 12345u);
|
||||
BOOST_CHECK_EQUAL((real128("12345.6789")*10000).to_uint64(), 123456789u);
|
||||
BOOST_CHECK_EQUAL(string(real128("12345.6789")), string("12345.6789"));
|
||||
|
||||
BOOST_CHECK_EQUAL( real128(uint64_t(-1)).to_uint64(), uint64_t(-1) );
|
||||
|
||||
wdump( (ten)(two)(twenty) );
|
||||
wdump((real128("12345.6789")) );
|
||||
wdump( (ten/3*3) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Loading…
Reference in a new issue