More work on 128bit arithmetic
This commit is contained in:
81
big_int.cpp
81
big_int.cpp
@@ -48,8 +48,15 @@ sign(S128 val){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function B32
|
||||||
|
has_value_bigger_then_64bit(S128 v){
|
||||||
|
U64 hi = v.hi << 1; // clear sign bit
|
||||||
|
B32 result = hi != 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function S128
|
function S128
|
||||||
s128(S64 value){
|
s128_from_s64(S64 value){
|
||||||
S128 result = {value < 0 ? ~0 : 0ull, (U64)value};
|
S128 result = {value < 0 ? ~0 : 0ull, (U64)value};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -83,33 +90,13 @@ force_inline S128 operator|(S128 a, S128 b){return {a.hi | b.hi, a.lo | b.lo};}
|
|||||||
|
|
||||||
function S128
|
function S128
|
||||||
operator-(S128 a){
|
operator-(S128 a){
|
||||||
a = (~a) + s128(1);
|
a = (~a) + s128_from_u64(1);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mult64to128(U64 u, U64 v, U64& h, U64 &l)
|
|
||||||
{
|
|
||||||
U64 u1 = (u & 0xffffffff);
|
|
||||||
U64 v1 = (v & 0xffffffff);
|
|
||||||
U64 t = (u1 * v1);
|
|
||||||
U64 w3 = (t & 0xffffffff); // w3 = t1_lo
|
|
||||||
U64 k = (t >> 32); // k = t1_hi
|
|
||||||
|
|
||||||
u >>= 32; // u_hi
|
|
||||||
t = (u * v1) + k; // t2 = (u_hi * v_lo) + t1_hi
|
|
||||||
k = (t & 0xffffffff); // t2_lo
|
|
||||||
U64 w1 = (t >> 32); // t2_hi
|
|
||||||
|
|
||||||
v >>= 32;
|
|
||||||
t = (u1 * v) + k; // t3 = (u_lo * v_hi) + t2_lo
|
|
||||||
k = (t >> 32); // t3_hi
|
|
||||||
|
|
||||||
h = (u * v) + w1 + k;
|
|
||||||
l = (t << 32) + w3;
|
|
||||||
}
|
|
||||||
|
|
||||||
function S128
|
function S128
|
||||||
operator/(S128 a, S128 b){
|
s128_div_hack(S128 a, S128 b){
|
||||||
|
// @hack: only values less then U64MAX -U64MAX
|
||||||
S64 sign = 1;
|
S64 sign = 1;
|
||||||
if(is_negative(a)){
|
if(is_negative(a)){
|
||||||
sign *= -1;
|
sign *= -1;
|
||||||
@@ -157,7 +144,7 @@ operator==(S128 a, S128 b){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
test_big_int(){
|
test_big_int(){
|
||||||
S128 v1 = s128(-1);
|
S128 v1 = s128_from_s64(-1);
|
||||||
assert(v1.hi == U64MAX && v1.lo == U64MAX);
|
assert(v1.hi == U64MAX && v1.lo == U64MAX);
|
||||||
assert(is_negative(v1));
|
assert(is_negative(v1));
|
||||||
assert(sign(v1) == -1);
|
assert(sign(v1) == -1);
|
||||||
@@ -169,48 +156,52 @@ test_big_int(){
|
|||||||
assert(v3.lo == 99 && v3.hi == 1);
|
assert(v3.lo == 99 && v3.hi == 1);
|
||||||
|
|
||||||
// S64 s64_max = S64MAX;
|
// S64 s64_max = S64MAX;
|
||||||
S128 v4 = s128(S64MIN) + s128_from_u64(100);
|
S128 v4 = s128_from_s64(S64MIN) + s128_from_u64(100);
|
||||||
assert((v4.lo - S64MAX) == 101); // 101 cause S64MIN is larher by 1
|
assert((v4.lo - S64MAX) == 101); // 101 cause S64MIN is larher by 1
|
||||||
|
|
||||||
S128 v5 = {1, 0};
|
S128 v5 = {1, 0};
|
||||||
S128 v6 = v5 - s128(1);
|
assert(has_value_bigger_then_64bit(v5));
|
||||||
|
S128 v6 = v5 - s128_from_u64(1);
|
||||||
assert(v6.lo == U64MAX && v6.hi == 0);
|
assert(v6.lo == U64MAX && v6.hi == 0);
|
||||||
|
|
||||||
{
|
{
|
||||||
S128 v7 = u64_mul(S64MAX, S64MAX);
|
S128 v7 = u64_mul(S64MAX, S64MAX);
|
||||||
U64 a,b;
|
assert(v7.hi == 0x3fffffffffffffff && v7.lo == 0x0000000000000001);
|
||||||
mult64to128(S64MAX,S64MAX,a,b);
|
|
||||||
assert(v7.hi == a && v7.lo == b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
S128 v7 = u64_mul(S64MIN, S64MIN);
|
S128 v7 = u64_mul(S64MIN, S64MIN);
|
||||||
U64 a,b;
|
assert(v7.hi == 0x4000000000000000 && v7.lo == 0);
|
||||||
mult64to128(S64MIN,S64MIN,a,b);
|
assert(has_value_bigger_then_64bit(v7));
|
||||||
assert(v7.hi == a && v7.lo == b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
S128 v7 = u64_mul(15125125, -1424124);
|
S128 v7 = u64_mul(U64MAX, U64MAX);
|
||||||
U64 a,b;
|
assert(v7.hi == 0xfffffffffffffffe && v7.lo == 0x0000000000000001);
|
||||||
mult64to128(15125125,-1424124,a,b);
|
assert(has_value_bigger_then_64bit(v7));
|
||||||
assert(v7.hi == a && v7.lo == b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
S128 v7 = u64_mul(52242, 2);
|
S128 v7 = u64_mul(52242, 2);
|
||||||
U64 a,b;
|
|
||||||
mult64to128(52242, 2,a,b);
|
|
||||||
assert(v7.hi == a && v7.lo == b);
|
|
||||||
assert(v7.lo == 52242*2);
|
assert(v7.lo == 52242*2);
|
||||||
|
assert(!has_value_bigger_then_64bit(v7));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
S128 v7 = u64_mul(0, 0);
|
S128 v7 = u64_mul(0, 0);
|
||||||
assert(v7 == s128(0));
|
assert(v7 == s128_from_u64(0));
|
||||||
// U64 a,b;
|
assert(!has_value_bigger_then_64bit(v7));
|
||||||
// mult64to128(52242, 2,a,b);
|
|
||||||
// assert(v7.hi == a && v7.lo == b);
|
|
||||||
// assert(v7.lo == 52242*2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
S128 v8 = s128_div_hack(-s128_from_u64(U64MAX), s128_from_s64(-1));
|
||||||
|
assert(v8.lo == U64MAX && v8.hi == 0);
|
||||||
|
|
||||||
|
S128 v9 = s128_div_hack(s128_from_u64(S64MAX), s128_from_s64(S64MAX));
|
||||||
|
assert(v9 == s128_from_s64(1));
|
||||||
|
|
||||||
|
S128 v10 = s128_div_hack(-s128_from_u64(S64MAX), s128_from_s64(S64MAX));
|
||||||
|
assert(v10 == -s128_from_s64(1));
|
||||||
|
|
||||||
|
S128 v11 = s128_div_hack(s128_from_s64(S64MIN), s128_from_s64(S64MAX));
|
||||||
|
assert(v11 == -s128_from_u64(1));
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user