Division?
This commit is contained in:
87
big_int.cpp
87
big_int.cpp
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
We use two's complement
|
We use two's complement
|
||||||
|
|
||||||
Adding the value
|
- Adding the value, sub is similar
|
||||||
Adding a positive number to a negative number is actually subtracting 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.
|
Last bit is a biggest possible negative number for that bit range.
|
||||||
0111 1111 => 127
|
0111 1111 => 127
|
||||||
@@ -11,16 +11,30 @@ Last bit is a biggest possible negative number for that bit range.
|
|||||||
if we add 4 we get
|
if we add 4 we get
|
||||||
1000 0100 => -124
|
1000 0100 => -124
|
||||||
|
|
||||||
Negating the value
|
- Negating the value
|
||||||
1000 0001 => -127
|
1000 0001 => -127
|
||||||
flip bits
|
flip bits
|
||||||
0111 1110 => 126
|
0111 1110 => 126
|
||||||
we need to add 1
|
we need to add 1
|
||||||
0111 1111 -> 127
|
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
|
function S64
|
||||||
is_negative(S128 v){
|
is_negative(S128 v){
|
||||||
@@ -73,25 +87,6 @@ operator-(S128 a){
|
|||||||
return 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)
|
void mult64to128(U64 u, U64 v, U64& h, U64 &l)
|
||||||
{
|
{
|
||||||
U64 u1 = (u & 0xffffffff);
|
U64 u1 = (u & 0xffffffff);
|
||||||
@@ -113,6 +108,24 @@ void mult64to128(U64 u, U64 v, U64& h, U64 &l)
|
|||||||
l = (t << 32) + w3;
|
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
|
function S128
|
||||||
u64_mul(U64 u, U64 v){
|
u64_mul(U64 u, U64 v){
|
||||||
U64 u_lo = lo32(u);
|
U64 u_lo = lo32(u);
|
||||||
@@ -121,18 +134,11 @@ u64_mul(U64 u, U64 v){
|
|||||||
U64 v_hi = hi32(v);
|
U64 v_hi = hi32(v);
|
||||||
|
|
||||||
U64 t1 = u_lo * v_lo;
|
U64 t1 = u_lo * v_lo;
|
||||||
U64 t1_lo = lo32(t1);
|
U64 t2 = (u_hi * v_lo) + hi32(t1);
|
||||||
U64 t1_hi = hi32(t1);
|
U64 t3 = (u_lo * v_hi) + lo32(t2);
|
||||||
|
|
||||||
U64 t2 = (u_hi * v_lo) + t1_hi;
|
U64 lo = (t3 << 32) + lo32(t1);
|
||||||
U64 t2_lo = lo32(t2);
|
U64 hi = (u_hi * v_hi) + hi32(t2) + hi32(t3);
|
||||||
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;
|
|
||||||
return {hi,lo};
|
return {hi,lo};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +149,12 @@ operator*(S128 a, S128 b){
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function B32
|
||||||
|
operator==(S128 a, S128 b){
|
||||||
|
B32 result = (a.lo == b.lo) && (a.hi == b.hi);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
test_big_int(){
|
test_big_int(){
|
||||||
S128 v1 = s128(-1);
|
S128 v1 = s128(-1);
|
||||||
@@ -192,4 +204,13 @@ test_big_int(){
|
|||||||
assert(v7.hi == a && v7.lo == b);
|
assert(v7.hi == a && v7.lo == b);
|
||||||
assert(v7.lo == 52242*2);
|
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