Skip to content

Commit

Permalink
Merge pull request steemit#2558 from steemit/2018-06-15-rc-support
Browse files Browse the repository at this point in the history
RC support code
  • Loading branch information
Michael Vandeberg authored Jun 15, 2018
2 parents db9edec + 1a035ff commit dd02462
Show file tree
Hide file tree
Showing 11 changed files with 287 additions and 11 deletions.
1 change: 0 additions & 1 deletion libraries/chain/include/steem/chain/account_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ namespace steem { namespace chain {
time_point_sec effective_on;
};

struct by_name;
struct by_proxy;
struct by_next_vesting_withdrawal;

Expand Down
1 change: 1 addition & 0 deletions libraries/chain/include/steem/chain/steem_object_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ inline std::string to_string( const shared_string& str ) { return std::string( s
inline void from_string( shared_string& out, const string& in ){ out.assign( in.begin(), in.end() ); }

struct by_id;
struct by_name;

enum object_type
{
Expand Down
1 change: 0 additions & 1 deletion libraries/chain/include/steem/chain/steem_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,6 @@ namespace steem { namespace chain {
allocator< decline_voting_rights_request_object >
> decline_voting_rights_request_index;

struct by_name;
typedef multi_index_container<
reward_fund_object,
indexed_by<
Expand Down
1 change: 0 additions & 1 deletion libraries/chain/include/steem/chain/witness_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ namespace steem { namespace chain {


struct by_vote_name;
struct by_name;
struct by_pow;
struct by_work;
struct by_schedule_time;
Expand Down
7 changes: 7 additions & 0 deletions libraries/chainbase/include/chainbase/chainbase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,13 @@ namespace chainbase {
return get_mutable_index<index_type>().emplace( std::forward<Constructor>(con) );
}

template< typename ObjectType >
size_t count()const
{
typedef typename get_index_type<ObjectType>::type index_type;
return get_index< index_type >().indices().size();
}

template< typename Lambda >
auto with_read_lock( Lambda&& callback, uint64_t wait_micro = 1000000 ) -> decltype( (*(Lambda*)nullptr)() )
{
Expand Down
79 changes: 79 additions & 0 deletions libraries/fc/include/fc/int_array.hpp
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
30 changes: 22 additions & 8 deletions libraries/fc/include/fc/io/raw.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <fc/fwd.hpp>
#include <fc/smart_ref_fwd.hpp>
#include <fc/array.hpp>
#include <fc/int_array.hpp>
#include <fc/time.hpp>
#include <fc/filesystem.hpp>
#include <fc/exception/exception.hpp>
Expand Down Expand Up @@ -120,22 +121,35 @@ namespace fc {
} FC_RETHROW_EXCEPTIONS( warn, "" ) }

template<typename Stream, typename T, size_t N>
inline void pack( Stream& s, const fc::array<T,N>& v) {
s.write((const char*)&v.data[0],N*sizeof(T));
}

template<typename Stream, typename T>
inline void pack( Stream& s, const std::shared_ptr<T>& v)
inline void pack( Stream& s, const fc::array<T,N>& v)
{
fc::raw::pack( s, *v );
s.write((const char*)&v.data[0],N*sizeof(T));
}

template<typename Stream, typename T, size_t N>
inline void unpack( Stream& s, fc::array<T,N>& v)
{ try {
s.read((char*)&v.data[0],N*sizeof(T));
s.read( (char*)&v.data[0], N*sizeof(T) );
} FC_RETHROW_EXCEPTIONS( warn, "fc::array<type,length>", ("type",fc::get_typename<T>::name())("length",N) ) }

template<typename Stream, typename T, size_t N>
inline void pack( Stream& s, const fc::int_array<T,N>& v)
{
s.write( (const char*)&v.data[0], N*sizeof(T) );
}

template<typename Stream, typename T, size_t N>
inline void unpack( Stream& s, fc::int_array<T,N>& v)
{ try {
s.read( (char*)&v.data[0], N*sizeof(T) );
} FC_RETHROW_EXCEPTIONS( warn, "fc::int_array<type,length>", ("type",fc::get_typename<T>::name())("length",N) ) }

template<typename Stream, typename T>
inline void pack( Stream& s, const std::shared_ptr<T>& v)
{
fc::raw::pack( s, *v );
}

template<typename Stream, typename T>
inline void unpack( Stream& s, std::shared_ptr<T>& v)
{ try {
Expand Down
4 changes: 4 additions & 0 deletions libraries/fc/include/fc/io/raw_fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace fc {
class variant_object;
class path;
template<typename... Types> class static_variant;
template<typename T, size_t N> class int_array;

template<typename IntType, typename EnumType> class enum_type;
namespace ip { class endpoint; }
Expand Down Expand Up @@ -116,6 +117,9 @@ namespace fc {
template<typename Stream, typename T, size_t N> inline void pack( Stream& s, const fc::array<T,N>& v);
template<typename Stream, typename T, size_t N> inline void unpack( Stream& s, fc::array<T,N>& v);

template<typename Stream, typename T, size_t N> inline void pack( Stream& s, const fc::int_array<T,N>& v);
template<typename Stream, typename T, size_t N> inline void unpack( Stream& s, fc::int_array<T,N>& v);

template<typename Stream> inline void pack( Stream& s, const bool& v );
template<typename Stream> inline void unpack( Stream& s, bool& v );

Expand Down
91 changes: 91 additions & 0 deletions libraries/fc/include/fc/saturation.hpp
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;
}

}
4 changes: 4 additions & 0 deletions libraries/fc/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ target_link_libraries( ecc_test fc )
add_executable( log_test crypto/log_test.cpp )
target_link_libraries( log_test fc )

add_executable( saturation_test saturation_test.cpp )
target_link_libraries( saturation_test fc )

#add_executable( test_aes aes_test.cpp )
#target_link_libraries( test_aes fc ${rt_library} ${pthread_library} )
#add_executable( test_sleep sleep.cpp )
Expand All @@ -63,6 +66,7 @@ add_executable( all_tests all_tests.cpp
thread/thread_tests.cpp
bloom_test.cpp
real128_test.cpp
saturation_test.cpp
utf8_test.cpp
)
target_link_libraries( all_tests fc )
79 changes: 79 additions & 0 deletions libraries/fc/tests/saturation_test.cpp
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;
}

0 comments on commit dd02462

Please sign in to comment.