Checking if in range
This commit is contained in:
135
big_int.cpp
135
big_int.cpp
@@ -30,12 +30,14 @@ We use two's complement
|
|||||||
|
|
||||||
struct S128{
|
struct S128{
|
||||||
U64 hi, lo;
|
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
|
function S64
|
||||||
is_negative(S128 v){
|
is_negative(S128 v){
|
||||||
S64 result = v.hi >> 63;
|
S64 result = v.hi >> 63;
|
||||||
@@ -94,9 +96,17 @@ operator-(S128 a){
|
|||||||
return 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
|
function S128
|
||||||
s128_div_hack(S128 a, S128 b){
|
s128_div_hack(S128 a, S128 b){
|
||||||
// @hack: only values less then U64MAX -U64MAX
|
|
||||||
S64 sign = 1;
|
S64 sign = 1;
|
||||||
if(is_negative(a)){
|
if(is_negative(a)){
|
||||||
sign *= -1;
|
sign *= -1;
|
||||||
@@ -113,6 +123,24 @@ s128_div_hack(S128 a, S128 b){
|
|||||||
return result;
|
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
|
function S128
|
||||||
u64_mul(U64 u, U64 v){
|
u64_mul(U64 u, U64 v){
|
||||||
U64 u_lo = lo32(u);
|
U64 u_lo = lo32(u);
|
||||||
@@ -142,6 +170,70 @@ operator==(S128 a, S128 b){
|
|||||||
return result;
|
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
|
function void
|
||||||
test_big_int(){
|
test_big_int(){
|
||||||
S128 v1 = s128_from_s64(-1);
|
S128 v1 = s128_from_s64(-1);
|
||||||
@@ -149,14 +241,14 @@ test_big_int(){
|
|||||||
assert(is_negative(v1));
|
assert(is_negative(v1));
|
||||||
assert(sign(v1) == -1);
|
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);
|
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);
|
assert(v3.lo == 99 && v3.hi == 1);
|
||||||
|
|
||||||
// S64 s64_max = S64MAX;
|
// 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
|
assert((v4.lo - S64MAX) == 101); // 101 cause S64MIN is larher by 1
|
||||||
|
|
||||||
S128 v5 = {1, 0};
|
S128 v5 = {1, 0};
|
||||||
@@ -193,15 +285,34 @@ test_big_int(){
|
|||||||
assert(!has_value_bigger_then_64bit(v7));
|
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);
|
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));
|
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));
|
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));
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user