diff --git a/big_int.cpp b/big_int.cpp index 83f7ec4..83c38d9 100644 --- a/big_int.cpp +++ b/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); + } } \ No newline at end of file