Implement full product for uint128 * uint128 -> 256-bit result

This commit is contained in:
theoretical 2015-01-06 18:54:44 -05:00
parent 40943808d0
commit 6ecb55ac2e
2 changed files with 63 additions and 0 deletions

View file

@ -1,4 +1,5 @@
#pragma once
#include <limits>
#include <stdint.h>
#include <string>
@ -78,6 +79,13 @@ namespace fc
uint64_t low_bits()const { return lo; }
uint64_t high_bits()const { return hi; }
static uint128 max_value() {
const uint64_t max64 = std::numeric_limits<uint64_t>::max();
return uint128( max64, max64 );
}
static void full_product( const uint128& a, const uint128& b, uint128& result_hi, uint128& result_lo );
private:
uint64_t hi;
uint64_t lo;

View file

@ -259,6 +259,61 @@ namespace fc
return *this;
}
void uint128::full_product( const uint128& a, const uint128& b, uint128& result_hi, uint128& result_lo )
{
// (ah * 2**64 + al) * (bh * 2**64 + bl)
// = (ah * bh * 2**128 + al * bh * 2**64 + ah * bl * 2**64 + al * bl
// = P * 2**128 + (Q + R) * 2**64 + S
// = Ph * 2**192 + Pl * 2**128
// + Qh * 2**128 + Ql * 2**64
// + Rh * 2**128 + Rl * 2**64
// + Sh * 2**64 + Sl
//
uint64_t ah = a.hi;
uint64_t al = a.lo;
uint64_t bh = b.hi;
uint64_t bl = b.lo;
uint128 s = al;
s *= bl;
uint128 r = ah;
r *= bl;
uint128 q = al;
q *= bh;
uint128 p = ah;
p *= bh;
uint64_t sl = s.lo;
uint64_t sh = s.hi;
uint64_t rl = r.lo;
uint64_t rh = r.hi;
uint64_t ql = q.lo;
uint64_t qh = q.hi;
uint64_t pl = p.lo;
uint64_t ph = p.hi;
uint64_t y[4]; // final result
y[0] = sl;
uint128_t acc = sh;
acc += ql;
acc += rl;
y[1] = acc.lo;
acc = acc.hi;
acc += qh;
acc += rh;
acc += pl;
y[2] = acc.lo;
y[3] = acc.hi + ph;
result_hi = uint128( y[3], y[2] );
result_lo = uint128( y[1], y[0] );
return;
}
void to_variant( const uint128& var, variant& vo ) { vo = std::string(var); }
void from_variant( const variant& var, uint128& vo ){ vo = uint128(var.as_string()); }