Use common inline functions for splitting/combining uint128 to/from two uint64 values

This commit is contained in:
Peter Conrad 2019-06-11 08:40:46 +02:00
parent b16bf00a10
commit 1bda001b8c
4 changed files with 44 additions and 34 deletions

View file

@ -29,8 +29,8 @@ namespace fc {
inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth )
{
boost::endian::little_uint64_buf_at hilo[2];
hilo[0] = static_cast<uint64_t>(v >> 64);
hilo[1] = static_cast<uint64_t>(v & 0xffffffffffffffffULL);
hilo[0] = uint128_hi64( v );
hilo[1] = uint128_lo64( v );
s.write( hilo[0].data(), sizeof(hilo) );
}
template<typename Stream>
@ -38,9 +38,7 @@ namespace fc {
{
boost::endian::little_uint64_buf_at hilo[2];
s.read( (char*) hilo, sizeof(hilo) );
v = hilo[0].value();
v <<= 64;
v += hilo[1].value();
v = uint128( hilo[0].value(), hilo[1].value() );
}
template<typename Stream>

View file

@ -33,6 +33,13 @@ namespace fc {
using int128_t = __int128_t;
using uint128_t = __uint128_t;
inline uint64_t uint128_lo64(const uint128_t x) {
return static_cast<uint64_t>(x & 0xffffffffffffffffULL);
}
inline uint64_t uint128_hi64(const uint128_t x) {
return static_cast<uint64_t>( x >> 64 );
}
} // namespace fc
#else // __SIZEOF_INT128__
@ -44,6 +51,21 @@ namespace fc {
using boost::multiprecision::int128_t;
using boost::multiprecision::uint128_t;
inline uint64_t uint128_lo64(const uint128_t& x) {
return static_cast<uint64_t>(x & 0xffffffffffffffffULL);
}
inline uint64_t uint128_hi64(const uint128_t& x) {
return static_cast<uint64_t>( x >> 64 );
}
} // namespace fc
#endif // __SIZEOF_INT128__
namespace fc {
inline uint128_t uint128( const uint64_t hi, const uint64_t lo ) {
return ( uint128_t(hi) << 64 ) + lo;
}
} // namespace fc

View file

@ -54,8 +54,8 @@ void aes_encoder::init( const fc::sha256& key, const uint128_t& init_value )
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
boost::endian::little_uint64_buf_t iv[2];
iv[0] = static_cast<uint64_t>( init_value >> 64 );
iv[1] = static_cast<uint64_t>( init_value & 0xffffffffffffffffULL );
iv[0] = uint128_hi64( init_value );
iv[1] = uint128_lo64( init_value );
if(1 != EVP_EncryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data()))
{
FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init",
@ -122,8 +122,8 @@ void aes_decoder::init( const fc::sha256& key, const uint128_t& init_value )
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
boost::endian::little_uint64_buf_t iv[2];
iv[0] = static_cast<uint64_t>( init_value >> 64 );
iv[1] = static_cast<uint64_t>( init_value & 0xffffffffffffffffULL );
iv[0] = uint128_hi64( init_value );
iv[1] = uint128_lo64( init_value );
if(1 != EVP_DecryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data()))
{
FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init",

View file

@ -46,21 +46,14 @@ namespace fc {
using namespace std;
inline uint64_t Uint128Low64(const uint128_t& x) {
return static_cast<uint64_t>(x & 0xffffffffffffffffULL);
}
inline uint64_t Uint128High64(const uint128_t& x) {
return static_cast<uint64_t>( x >> 64 );
}
// Hash 128 input bits down to 64 bits of output.
// This is intended to be a reasonably good hash function.
inline uint64_t Hash128to64(const uint128_t& x) {
// Murmur-inspired hashing.
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
uint64_t a = (uint128_lo64(x) ^ uint128_hi64(x)) * kMul;
a ^= (a >> 47);
uint64_t b = (Uint128High64(x) ^ a) * kMul;
uint64_t b = (uint128_hi64(x) ^ a) * kMul;
b ^= (b >> 47);
b *= kMul;
return b;
@ -282,7 +275,7 @@ static uint64_t ShiftMix(uint64_t val) {
}
static uint64_t HashLen16(uint64_t u, uint64_t v) {
return Hash128to64( ( uint128_t(u) << 64 ) + v);
return Hash128to64( uint128( u, v) );
}
static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) {
@ -428,8 +421,8 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) {
// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
// of any length representable in signed long. Based on City and Murmur.
uint128_t CityMurmur(const char *s, size_t len, uint128_t seed) {
uint64_t a = Uint128Low64(seed);
uint64_t b = Uint128High64(seed);
uint64_t a = uint128_lo64(seed);
uint64_t b = uint128_hi64(seed);
uint64_t c = 0;
uint64_t d = 0;
signed long l = len - 16;
@ -454,7 +447,7 @@ uint128_t CityMurmur(const char *s, size_t len, uint128_t seed) {
}
a = HashLen16(a, c);
b = HashLen16(d, b);
return ( uint128_t(a ^ b) << 64 ) + HashLen16(b, a);
return uint128( a ^ b, HashLen16(b, a) );
}
uint128_t CityHash128WithSeed(const char *s, size_t len, uint128_t seed) {
@ -465,8 +458,8 @@ uint128_t CityHash128WithSeed(const char *s, size_t len, uint128_t seed) {
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
// v, w, x, y, and z.
pair<uint64_t, uint64_t> v, w;
uint64_t x = Uint128Low64(seed);
uint64_t y = Uint128High64(seed);
uint64_t x = uint128_lo64(seed);
uint64_t y = uint128_hi64(seed);
uint64_t z = len * k1;
v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
@ -516,15 +509,13 @@ uint128_t CityHash128WithSeed(const char *s, size_t len, uint128_t seed) {
// different 56-byte-to-8-byte hashes to get a 16-byte final result.
x = HashLen16(x, v.first);
y = HashLen16(y + z, w.first);
return ( uint128_t( HashLen16(x + v.second, w.second) + y ) << 64 )
+ HashLen16(x + w.second, y + v.second);
return uint128( HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second) );
}
uint128_t city_hash128(const char *s, size_t len) {
return len >= 16 ?
CityHash128WithSeed(s + 16, len - 16,
( uint128_t( Fetch64(s) ) << 64 ) + Fetch64(s + 8) + k0) :
CityHash128WithSeed(s, len, ( uint128_t(k0) << 64 ) + k1);
CityHash128WithSeed( s + 16, len - 16, uint128( Fetch64(s), Fetch64(s + 8) + k0 ) ) :
CityHash128WithSeed( s, len, uint128( k0, k1 ) );
}
//#ifdef __SSE4_2__
@ -648,10 +639,9 @@ uint128_t CityHashCrc128WithSeed(const char *s, size_t len, uint128_t seed) {
} else {
uint64_t result[4];
CityHashCrc256(s, len, result);
uint64_t u = Uint128High64(seed) + result[0];
uint64_t v = Uint128Low64(seed) + result[1];
return ( uint128_t( HashLen16(u, v + result[2]) ) << 64 )
+ HashLen16(Rotate(v, 32), u * k0 + result[3]);
uint64_t u = uint128_hi64(seed) + result[0];
uint64_t v = uint128_lo64(seed) + result[1];
return uint128( HashLen16(u, v + result[2]), HashLen16(Rotate(v, 32), u * k0 + result[3]) );
}
}
@ -661,7 +651,7 @@ uint128_t city_hash_crc_128(const char *s, size_t len) {
} else {
uint64_t result[4];
CityHashCrc256(s, len, result);
return ( uint128_t(result[2]) << 64 ) + result[3];
return uint128( result[2], result[3] );
}
}