Division?

This commit is contained in:
Krzosa Karol
2022-06-05 13:08:41 +02:00
parent 968a6ac708
commit 73ca0c5405

View File

@@ -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);
}
} }