Division?
This commit is contained in:
115
big_int.cpp
115
big_int.cpp
@@ -1,26 +1,40 @@
|
||||
/*
|
||||
We use two's complement
|
||||
|
||||
Adding the value
|
||||
Adding a positive number to a negative number is actually subtracting the value.
|
||||
Last bit is a biggest possible negative number for that bit range.
|
||||
0111 1111 => 127
|
||||
1111 1111 => -128 - 127 = 1
|
||||
- Adding the value, sub is similar
|
||||
Adding a positive number to a negative number is actually subtracting the value.
|
||||
Last bit is a biggest possible negative number for that bit range.
|
||||
0111 1111 => 127
|
||||
1111 1111 => -128 - 127 = 1
|
||||
|
||||
1000 0000 => -128
|
||||
if we add 4 we get
|
||||
1000 0100 => -124
|
||||
1000 0000 => -128
|
||||
if we add 4 we get
|
||||
1000 0100 => -124
|
||||
|
||||
Negating the value
|
||||
1000 0001 => -127
|
||||
flip bits
|
||||
0111 1110 => 126
|
||||
we need to add 1
|
||||
0111 1111 -> 127
|
||||
- Negating the value
|
||||
1000 0001 => -127
|
||||
flip bits
|
||||
0111 1110 => 126
|
||||
we need to add 1
|
||||
0111 1111 -> 127
|
||||
|
||||
- Division
|
||||
We don't need full 128 bit divide
|
||||
we just need to make sure we always divide
|
||||
smaller then U64MAX and -U64MAX
|
||||
10 / -1 = -10
|
||||
10 / 1 = 10
|
||||
-10 / -1 = 10
|
||||
-10 / 1 = 10
|
||||
*/
|
||||
|
||||
struct S128{U64 hi, lo;};
|
||||
struct S128{
|
||||
U64 hi, lo;
|
||||
constexpr S128 max(){return {S64MAX, U64MAX};}
|
||||
constexpr S128 min(){return {(U64)S64MIN, 0};}
|
||||
#define S128MAX S128::max()
|
||||
#define S128MIN S128::min()
|
||||
};
|
||||
|
||||
function S64
|
||||
is_negative(S128 v){
|
||||
@@ -60,8 +74,8 @@ operator-(S128 a, S128 b){
|
||||
return {hi,lo};
|
||||
}
|
||||
|
||||
force_inline U64 lo32(U64 a){return a & 0xffffffff;}
|
||||
force_inline U64 hi32(U64 a){return a >> 32;}
|
||||
force_inline U64 lo32(U64 a){return a & 0xffffffff;}
|
||||
force_inline U64 hi32(U64 a){return a >> 32;}
|
||||
force_inline S128 operator~(S128 a){return {~a.hi, ~a.lo};}
|
||||
force_inline S128 operator^(S128 a, S128 b){return {a.hi ^ b.hi, a.lo ^ b.lo};}
|
||||
force_inline S128 operator&(S128 a, S128 b){return {a.hi & b.hi, a.lo & b.lo};}
|
||||
@@ -73,25 +87,6 @@ operator-(S128 a){
|
||||
return a;
|
||||
}
|
||||
|
||||
/*
|
||||
U64 u1 = lo32(u);
|
||||
U64 v1 = lo32(v);
|
||||
|
||||
U64 t = u1 * v1;
|
||||
U64 w3 = lo32(t);
|
||||
U64 k = hi32(t);
|
||||
|
||||
u >>= 32;
|
||||
t = u * v1 + k;
|
||||
k = lo32(t);
|
||||
U64 w1 = hi32(t);
|
||||
|
||||
v >>= 32;
|
||||
t = u1 * v + k;
|
||||
|
||||
return { (u * v) + w1 + hi32(t), (t << 32) + w3 };
|
||||
*/
|
||||
|
||||
void mult64to128(U64 u, U64 v, U64& h, U64 &l)
|
||||
{
|
||||
U64 u1 = (u & 0xffffffff);
|
||||
@@ -113,6 +108,24 @@ void mult64to128(U64 u, U64 v, U64& h, U64 &l)
|
||||
l = (t << 32) + w3;
|
||||
}
|
||||
|
||||
function S128
|
||||
operator/(S128 a, S128 b){
|
||||
S64 sign = 1;
|
||||
if(is_negative(a)){
|
||||
sign *= -1;
|
||||
a = -a;
|
||||
}
|
||||
if(is_negative(b)){
|
||||
sign *= -1;
|
||||
b = -b;
|
||||
}
|
||||
assert(a.hi == 0 && b.hi == 0);
|
||||
U64 division = a.lo / b.lo;
|
||||
S128 result = {0, division};
|
||||
if(sign == -1) result = -result;
|
||||
return result;
|
||||
}
|
||||
|
||||
function S128
|
||||
u64_mul(U64 u, U64 v){
|
||||
U64 u_lo = lo32(u);
|
||||
@@ -121,18 +134,11 @@ u64_mul(U64 u, U64 v){
|
||||
U64 v_hi = hi32(v);
|
||||
|
||||
U64 t1 = u_lo * v_lo;
|
||||
U64 t1_lo = lo32(t1);
|
||||
U64 t1_hi = hi32(t1);
|
||||
U64 t2 = (u_hi * v_lo) + hi32(t1);
|
||||
U64 t3 = (u_lo * v_hi) + lo32(t2);
|
||||
|
||||
U64 t2 = (u_hi * v_lo) + t1_hi;
|
||||
U64 t2_lo = lo32(t2);
|
||||
U64 t2_hi = hi32(t2);
|
||||
|
||||
U64 t3 = (u_lo * v_hi) + t2_lo;
|
||||
U64 t3_hi = hi32(t3);
|
||||
|
||||
U64 lo = (t3 << 32) + t1_lo;
|
||||
U64 hi = (u_hi * v_hi) + t2_hi + t3_hi;
|
||||
U64 lo = (t3 << 32) + lo32(t1);
|
||||
U64 hi = (u_hi * v_hi) + hi32(t2) + hi32(t3);
|
||||
return {hi,lo};
|
||||
}
|
||||
|
||||
@@ -143,6 +149,12 @@ operator*(S128 a, S128 b){
|
||||
return c;
|
||||
}
|
||||
|
||||
function B32
|
||||
operator==(S128 a, S128 b){
|
||||
B32 result = (a.lo == b.lo) && (a.hi == b.hi);
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
test_big_int(){
|
||||
S128 v1 = s128(-1);
|
||||
@@ -192,4 +204,13 @@ test_big_int(){
|
||||
assert(v7.hi == a && v7.lo == b);
|
||||
assert(v7.lo == 52242*2);
|
||||
}
|
||||
|
||||
{
|
||||
S128 v7 = u64_mul(0, 0);
|
||||
assert(v7 == s128(0));
|
||||
// U64 a,b;
|
||||
// mult64to128(52242, 2,a,b);
|
||||
// assert(v7.hi == a && v7.lo == b);
|
||||
// assert(v7.lo == 52242*2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user