From e12e0ee56198eedfb7770783d7153429b5fde3f4 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sun, 5 Jun 2022 15:09:40 +0200 Subject: [PATCH] Checking if in range --- big_int.cpp | 135 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 123 insertions(+), 12 deletions(-) diff --git a/big_int.cpp b/big_int.cpp index 79965b7..7a99e9e 100644 --- a/big_int.cpp +++ b/big_int.cpp @@ -30,12 +30,14 @@ We use two's complement 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 S128 +s128(U64 hi, U64 lo){ + S128 result = {hi,lo}; + return result; +} + function S64 is_negative(S128 v){ S64 result = v.hi >> 63; @@ -94,9 +96,17 @@ operator-(S128 a){ return a; } +/* +2022.05.06 - Mod and Div +@hack: only values less then U64MAX -U64MAX + +modulo can only overflow in this case (-)S64MIN % -1 || (-)S64MIN % -1 for ints +casuse the sign flips and MAX is smaller then MIN +so we do the arithmetic in UINT and convert back +*/ + function S128 s128_div_hack(S128 a, S128 b){ - // @hack: only values less then U64MAX -U64MAX S64 sign = 1; if(is_negative(a)){ sign *= -1; @@ -113,6 +123,24 @@ s128_div_hack(S128 a, S128 b){ return result; } +function S128 +s128_mod_hack(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); @@ -142,6 +170,70 @@ operator==(S128 a, S128 b){ return result; } +function B32 +operator!=(S128 a, S128 b){ + B32 result = !(a == b); + return result; +} + +function B32 +operator<(S128 a, S128 b){ + if(a.hi != b.hi){ + S64 a_hi = (S64)a.hi; + S64 b_hi = (S64)b.hi; + return a_hi < b_hi; + } + + return a.lo < b.lo; +} + +function B32 +operator>(S128 a, S128 b){ + if(a.hi != b.hi){ + S64 a_hi = (S64)a.hi; + S64 b_hi = (S64)b.hi; + return a_hi > b_hi; + } + return a.lo > b.lo; +} + +constexpr S128 const_s128_from_s64(S64 value){return {value < 0 ? ~0 : 0ull, (U64)value};} +constexpr S128 S128_max(){return {S64MAX, U64MAX};} +constexpr S128 S128_min(){return {(U64)S64MIN, 0};} +constexpr S128 S64_max() {return const_s128_from_s64(S64MAX);} +constexpr S128 S64_min() {return const_s128_from_s64(S64MIN);} +constexpr S128 S32_max() {return const_s128_from_s64(S32MAX);} +constexpr S128 S32_min() {return const_s128_from_s64(S32MIN);} +constexpr S128 S16_max() {return const_s128_from_s64(S16MAX);} +constexpr S128 S16_min() {return const_s128_from_s64(S16MIN);} +constexpr S128 S8_max() {return const_s128_from_s64(S8MAX);} +constexpr S128 S8_min() {return const_s128_from_s64(S8MIN);} +constexpr S128 U64_max() {return {0, U64MAX};} +constexpr S128 U64_min() {return {};} +constexpr S128 U32_max() {return {0, U32MAX};} +constexpr S128 U32_min() {return {};} +constexpr S128 U16_max() {return {0, U16MAX};} +constexpr S128 U16_min() {return {};} +constexpr S128 U8_max() {return {0, U8MAX};} +constexpr S128 U8_min() {return {};} + +function B32 +is_out_of_bounds(S128 value, Ast_Resolved_Type *type){ +#define BOUNDS_CASE(T) case TYPE_##T: return (value < T##_min()) || (value > T##_max()) + switch(type->kind){ + BOUNDS_CASE(S8); + BOUNDS_CASE(S16); + BOUNDS_CASE(S32); + BOUNDS_CASE(S64); + BOUNDS_CASE(U8); + BOUNDS_CASE(U16); + BOUNDS_CASE(U32); + BOUNDS_CASE(U64); + invalid_default_case; + } + return 0; +} + function void test_big_int(){ S128 v1 = s128_from_s64(-1); @@ -149,14 +241,14 @@ test_big_int(){ assert(is_negative(v1)); assert(sign(v1) == -1); - S128 v2 = s128_from_u64(U64MAX) + s128_from_u64(1); + S128 v2 = U64_max() + s128_from_u64(1); assert(v2.lo == 0 && v2.hi == 1); - S128 v3 = s128_from_u64(U64MAX) + s128_from_u64(100); + S128 v3 = U64_max() + s128_from_u64(100); assert(v3.lo == 99 && v3.hi == 1); // S64 s64_max = S64MAX; - S128 v4 = s128_from_s64(S64MIN) + s128_from_u64(100); + S128 v4 = S64_min() + s128_from_u64(100); assert((v4.lo - S64MAX) == 101); // 101 cause S64MIN is larher by 1 S128 v5 = {1, 0}; @@ -193,15 +285,34 @@ test_big_int(){ assert(!has_value_bigger_then_64bit(v7)); } - S128 v8 = s128_div_hack(-s128_from_u64(U64MAX), s128_from_s64(-1)); + S128 v8 = s128_div_hack(-U64_max(), s128_from_s64(-1)); assert(v8.lo == U64MAX && v8.hi == 0); - S128 v9 = s128_div_hack(s128_from_u64(S64MAX), s128_from_s64(S64MAX)); + S128 v9 = s128_div_hack(S64_max(), S64_max()); assert(v9 == s128_from_s64(1)); - S128 v10 = s128_div_hack(-s128_from_u64(S64MAX), s128_from_s64(S64MAX)); + S128 v10 = s128_div_hack(-S64_max(), S64_max()); assert(v10 == -s128_from_s64(1)); - S128 v11 = s128_div_hack(s128_from_s64(S64MIN), s128_from_s64(S64MAX)); + S128 v11 = s128_div_hack(S64_min(), S64_max()); assert(v11 == -s128_from_u64(1)); + + { + S128 v12 = s128_div_hack(s128_from_s64(-100), s128_from_s64(10)); + assert(v12 == -s128_from_u64(10)); + } + + { + assert(s128_from_s64(32) > s128_from_s64(16)); + assert(s128_from_s64(-32) < s128_from_s64(-16)); + assert(s128_from_s64(S64MIN) < (s128_from_s64(S64MIN)+s128_from_s64(10))); + assert(s128_from_s64(S64MIN) > (s128_from_s64(S64MIN)-s128_from_s64(10))); + assert(S64_min()*s128_from_u64(4) < S64_min()); + } + { + assert(!is_out_of_bounds(S64_max(), type_s64)); + assert(is_out_of_bounds(s128_from_s64(-19), type_u64)); + assert(!is_out_of_bounds(s128_from_s64(-19), type_s64)); + assert(is_out_of_bounds(U64_max(), type_s64)); + } } \ No newline at end of file