forked from steemit/steem
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request steemit#2558 from steemit/2018-06-15-rc-support
RC support code
- Loading branch information
Showing
11 changed files
with
287 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#pragma once | ||
|
||
#include <fc/variant.hpp> | ||
|
||
#include <limits> | ||
#include <vector> | ||
|
||
namespace fc { | ||
|
||
/** | ||
* Like fc::array, but does zero-initialization and has friendly JSON format | ||
*/ | ||
|
||
template<typename T, size_t N> | ||
class int_array | ||
{ | ||
public: | ||
int_array(){ memset( data, 0, sizeof(data) ); } | ||
|
||
T& at( size_t pos ) { FC_ASSERT( pos < N); return data[pos]; } | ||
const T& at( size_t pos )const { FC_ASSERT( pos < N); return data[pos]; } | ||
|
||
T& operator[]( size_t pos ) { FC_ASSERT( pos < N); return data[pos]; } | ||
const T& operator[]( size_t pos )const { FC_ASSERT( pos < N); return data[pos]; } | ||
|
||
const T* begin()const { return &data[0]; } | ||
const T* end()const { return &data[N]; } | ||
|
||
T* begin() { return &data[0]; } | ||
T* end() { return &data[N]; } | ||
|
||
size_t size()const { return N; } | ||
|
||
T data[N]; | ||
}; | ||
|
||
template<typename T,size_t N> struct get_typename< fc::int_array<T,N> > | ||
{ | ||
static const char* name() | ||
{ | ||
static std::string _name = std::string("fc::int_array<")+std::string(fc::get_typename<T>::name())+","+ fc::to_string(N) + ">"; | ||
return _name.c_str(); | ||
} | ||
}; | ||
|
||
template<typename T, size_t N> | ||
void from_variant( const variant& var, fc::int_array<T,N>& a ) | ||
{ | ||
memset( a.data, 0, sizeof(a.data) ); | ||
const variants& varray = var.get_array(); // throws if is not array | ||
FC_ASSERT( varray.size() == N ); | ||
|
||
for( size_t i=0; i<N; i++ ) | ||
{ | ||
if( std::numeric_limits<T>::is_signed ) | ||
{ | ||
int64_t temp = varray[i].as_int64(); | ||
FC_ASSERT( (temp >= std::numeric_limits<T>::min()) && (temp <= std::numeric_limits<T>::max()) ); | ||
a[i] = temp; | ||
} | ||
else | ||
{ | ||
uint64_t temp = varray[i].as_uint64(); | ||
FC_ASSERT( temp <= std::numeric_limits<T>::max() ); | ||
a[i] = temp; | ||
} | ||
} | ||
} | ||
|
||
template<typename T, size_t N> | ||
void to_variant( const fc::int_array<T,N>& a, variant& v ) | ||
{ | ||
std::vector<variant> vars(N); | ||
for( size_t i=0; i<N; i++ ) | ||
vars[i] = variant(a[i]); | ||
v = std::move(vars); | ||
} | ||
|
||
} // fc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
#include <limits> | ||
|
||
namespace fc { | ||
|
||
// Based loosely on http://locklessinc.com/articles/sat_arithmetic/ | ||
|
||
template< typename IntType > | ||
struct corresponding_unsigned; | ||
|
||
template<> | ||
struct corresponding_unsigned< int8_t > | ||
{ | ||
typedef uint8_t type; | ||
}; | ||
|
||
template<> | ||
struct corresponding_unsigned< int16_t > | ||
{ | ||
typedef uint16_t type; | ||
}; | ||
|
||
template<> | ||
struct corresponding_unsigned< int32_t > | ||
{ | ||
typedef uint32_t type; | ||
}; | ||
|
||
template<> | ||
struct corresponding_unsigned< int64_t > | ||
{ | ||
typedef uint64_t type; | ||
}; | ||
|
||
template< typename Signed > | ||
Signed signed_sat_add( Signed x, Signed y ) | ||
{ | ||
typedef typename corresponding_unsigned< Signed >::type u; | ||
u ux(x), uy(y); | ||
u res(ux+uy); | ||
|
||
// Compute saturated result sat, which is 0x7F... if x>=0, 0x80... otherwise | ||
u sat = (x >= 0) ? u( std::numeric_limits< Signed >::max() ) | ||
: u( std::numeric_limits< Signed >::min() ); | ||
|
||
// If overflow occurs, the correct result is sat | ||
// If no overflow occurs, the correct result is res | ||
// | ||
// Overflow occurred if and only if the following two conditions occur: | ||
// (a) ux,uy are the same sign s | ||
// (b) res has a different sign than s | ||
// | ||
// But we know: | ||
// (a) iff ~(ux^uy) has sign bit=1 | ||
// (b) iff (ux^res) has sign bit=1 | ||
// | ||
// Therefore the sign bit of ~(ux^uy) & (uy ^ res) is 1 iff overflow occurred | ||
// | ||
return (Signed(~(ux^uy) & (ux^res)) < 0) ? sat : res; | ||
} | ||
|
||
template< typename Signed > | ||
Signed signed_sat_sub( Signed x, Signed y ) | ||
{ | ||
typedef typename corresponding_unsigned< Signed >::type u; | ||
u ux(x), uy(y); | ||
u res(ux-uy); | ||
|
||
// Compute saturated result sat, which is 0x7F... if x>=0, 0x80... otherwise | ||
u sat = (x >= 0) ? u( std::numeric_limits< Signed >::max() ) | ||
: u( std::numeric_limits< Signed >::min() ); | ||
|
||
// If overflow occurs, the correct result is sat | ||
// If no overflow occurs, the correct result is res | ||
// | ||
// Overflow occurred if and only if the following two conditions occur: | ||
// (a) ux,uy are different signs | ||
// (b) res has a different sign than ux | ||
// | ||
// But we know: | ||
// (a) iff (ux^uy) has sign bit=1 | ||
// (b) iff (ux^res) has sign bit=1 | ||
// | ||
// Therefore the sign bit of ~(ux^uy) & (uy ^ res) is 1 iff overflow occurred | ||
// | ||
return (Signed((ux^uy) & (ux^res)) < 0) ? sat : res; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
|
||
#include <fc/saturation.hpp> | ||
|
||
#include <cstdint> | ||
#include <iostream> | ||
#include <limits> | ||
|
||
template< typename Signed, typename BiggerSigned > | ||
int test_all() | ||
{ | ||
const Signed a = std::numeric_limits< Signed >::min(); | ||
const Signed b = std::numeric_limits< Signed >::max(); | ||
|
||
Signed x = a; | ||
while( true ) | ||
{ | ||
Signed y = a; | ||
while( true ) | ||
{ | ||
BiggerSigned z0big = BiggerSigned(x) + BiggerSigned(y); | ||
if( z0big < a ) | ||
z0big = a; | ||
if( z0big > b ) | ||
z0big = b; | ||
Signed z0 = Signed(z0big); | ||
Signed z1 = fc::signed_sat_add( x, y ); | ||
|
||
if( z0 != z1 ) | ||
{ | ||
std::cout << "Addition does not work for " << x << ", " << y << std::endl; | ||
return 1; | ||
} | ||
|
||
z0big = BiggerSigned(x) - BiggerSigned(y); | ||
if( z0big < a ) | ||
z0big = a; | ||
if( z0big > b ) | ||
z0big = b; | ||
z0 = Signed(z0big); | ||
z1 = fc::signed_sat_sub( x, y ); | ||
|
||
if( z0 != z1 ) | ||
{ | ||
std::cout << "Subtraction does not work for " << x << ", " << y << std::endl; | ||
return 1; | ||
} | ||
|
||
if( y == b ) | ||
break; | ||
++y; | ||
} | ||
if( x == b ) | ||
break; | ||
++x; | ||
} | ||
return 0; | ||
} | ||
|
||
int64_t sat_add_i64( int64_t a, int64_t b ) | ||
{ | ||
return fc::signed_sat_add( a, b ); | ||
} | ||
|
||
int64_t sat_sub_i64( int64_t a, int64_t b ) | ||
{ | ||
return fc::signed_sat_sub( a, b ); | ||
} | ||
|
||
int main( int argc, char** argv, char** envp ) | ||
{ | ||
int result = test_all< int8_t, int16_t >(); | ||
if( result ) | ||
return 1; | ||
result = test_all< int16_t, int32_t >(); | ||
if( result ) | ||
return 1; | ||
|
||
return 0; | ||
} |