general purpose min/max value for T procs
This commit is contained in:
parent
7063c63c2d
commit
b254ca34ae
3 changed files with 205 additions and 27 deletions
|
|
@ -3,6 +3,21 @@
|
|||
RUN_TESTS := false
|
||||
);
|
||||
|
||||
// @todo(judah): dumb we can't use meta.range_for here.
|
||||
|
||||
U8_Min, U8_Max :: #run meta.lo_for(u8), #run meta.hi_for(u8);
|
||||
U16_Min, U16_Max :: #run meta.lo_for(u16), #run meta.hi_for(u16);
|
||||
U32_Min, U32_Max :: #run meta.lo_for(u32), #run meta.hi_for(u32);
|
||||
U64_Min, U64_Max :: #run meta.lo_for(u64), #run meta.hi_for(u64);
|
||||
|
||||
S8_Min, S8_Max :: #run meta.lo_for(s8), #run meta.hi_for(s8);
|
||||
S16_Min, S16_Max :: #run meta.lo_for(s16), #run meta.hi_for(s16);
|
||||
S32_Min, S32_Max :: #run meta.lo_for(s32), #run meta.hi_for(s32);
|
||||
S64_Min, S64_Max :: #run meta.lo_for(s64), #run meta.hi_for(s64);
|
||||
|
||||
F32_Min, F32_Max :: #run meta.lo_for(float32), #run meta.hi_for(float32);
|
||||
F64_Min, F64_Max :: #run meta.lo_for(float64), #run meta.hi_for(float64);
|
||||
|
||||
#load "vec.jai";
|
||||
#load "mat.jai";
|
||||
#load "ease.jai";
|
||||
|
|
@ -19,9 +34,11 @@ bounds_check_index :: ($$idx: int, $count: int, loc := #caller_location) #expand
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
basic :: #import "Basic"; // @future
|
||||
|
||||
#if RUN_TESTS {
|
||||
test :: #import "jc/test";
|
||||
}
|
||||
|
||||
#scope_file;
|
||||
|
||||
meta :: #import "jc/meta";
|
||||
basic :: #import "Basic"; // @future
|
||||
|
|
|
|||
|
|
@ -354,3 +354,4 @@ quat :: (x: float = 0, y: float = 0, z: float = 0, w: float = 0) -> Quat #expand
|
|||
|
||||
meta :: #import "jc/meta";
|
||||
math :: #import "Math"; // @future
|
||||
basic :: #import "Basic"; // @future
|
||||
|
|
|
|||
|
|
@ -43,38 +43,198 @@ type_is_enum :: ($$T: Type) -> bool, *Type_Info_Enum {
|
|||
return ok, info.(*Type_Info_Enum);
|
||||
}
|
||||
|
||||
enum_min :: (T: Type) -> int #expand {
|
||||
return #run -> int {
|
||||
ok, info := type_is_enum(T);
|
||||
assert(ok, "type given to enum_min must be an enum");
|
||||
// Returns the lowest and highest values T can represent.
|
||||
// Note: T must be an integer, float, or enum type.
|
||||
range_for :: ($T: Type, loc := #caller_location) -> (T, T) #expand {
|
||||
// @note(judah): we need to runs here because jai is weird.
|
||||
return #run lo_for(T, loc = loc), #run hi_for(T, loc = loc);
|
||||
}
|
||||
|
||||
if info.values.count == 0 {
|
||||
// Returns the lowest value T can represent.
|
||||
// Note: T must be an integer, float, or enum type.
|
||||
lo_for :: ($T: Type, loc := #caller_location) -> T #expand {
|
||||
return #run -> T {
|
||||
info := T.(*Type_Info);
|
||||
if info.type == {
|
||||
case .INTEGER;
|
||||
i := info.(*Type_Info_Integer);
|
||||
if i.runtime_size == {
|
||||
case 1; return (ifx i.signed then -0x80 else 0).(T, no_check);
|
||||
case 2; return (ifx i.signed then -0x8000 else 0).(T, no_check);
|
||||
case 4; return (ifx i.signed then -0x8000_0000 else 0).(T, no_check);
|
||||
case 8; return (ifx i.signed then -0x8000_0000_0000_0000 else 0).(T, no_check);
|
||||
case;
|
||||
compiler.compiler_report("unhandled integer type", loc = loc);
|
||||
}
|
||||
|
||||
case .FLOAT;
|
||||
if info.runtime_size == {
|
||||
case 4; return (0h00800000).(T, no_check);
|
||||
case 8; return (0h00100000_00000000).(T, no_check);
|
||||
case;
|
||||
compiler.compiler_report("unhandled float type", loc = loc);
|
||||
}
|
||||
|
||||
case .ENUM;
|
||||
i := info.(*Type_Info_Enum);
|
||||
if i.values.count == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
min := 0xFFFFFF_FFFFFF;
|
||||
for info.values if it < min {
|
||||
min = it;
|
||||
min: T = i.values[0].(T, no_check);
|
||||
if i.internal_type.signed {
|
||||
for i.values if it.(T) < min {
|
||||
min = it.(T);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for i.values if it.(T) < min {
|
||||
min = it.(T);
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
|
||||
case;
|
||||
compiler.compiler_report("min requires an enum, integer, or float type", loc = loc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
enum_max :: (T: Type) -> int #expand {
|
||||
return #run -> int {
|
||||
ok, info := type_is_enum(T);
|
||||
assert(ok, "type given to enum_max must be an enum");
|
||||
// Returns the highest value T can represent.
|
||||
// Note: T must be an integer, float, or enum type.
|
||||
hi_for :: ($T: Type, loc := #caller_location) -> T #expand {
|
||||
return #run -> T {
|
||||
info := T.(*Type_Info);
|
||||
if info.type == {
|
||||
case .INTEGER;
|
||||
i := info.(*Type_Info_Integer);
|
||||
if i.runtime_size == {
|
||||
case 1; return (ifx i.signed then 0x7f else 0xff).(T, no_check);
|
||||
case 2; return (ifx i.signed then 0x7fff else 0xffff).(T, no_check);
|
||||
case 4; return (ifx i.signed then 0x7fff_ffff else 0xffff_ffff).(T, no_check);
|
||||
case 8; return (ifx i.signed then 0x7fff_ffff_ffff_ffff else 0xffff_ffff_ffff_ffff).(T, no_check);
|
||||
case;
|
||||
compiler.compiler_report("unhandled integer type", loc = loc);
|
||||
}
|
||||
|
||||
if info.values.count == 0 {
|
||||
case .FLOAT;
|
||||
if info.runtime_size == {
|
||||
case 4; return (0h7F7FFFFF).(T, no_check);
|
||||
case 8; return (0h7FEFFFFF_FFFFFFFF).(T, no_check);
|
||||
case;
|
||||
compiler.compiler_report("unhandled float type", loc = loc);
|
||||
}
|
||||
|
||||
case .ENUM;
|
||||
i := info.(*Type_Info_Enum);
|
||||
if i.values.count == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
max := 0;
|
||||
for info.values if it > max {
|
||||
max = it;
|
||||
max := i.values[0].(T, no_check);
|
||||
if i.internal_type.signed {
|
||||
for i.values if xx it > max {
|
||||
max = xx it;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for i.values if xx it > max {
|
||||
max = xx it;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
|
||||
case;
|
||||
compiler.compiler_report("max requires an enum, integer, or float type", loc = loc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#scope_file;
|
||||
|
||||
compiler :: #import "Compiler"; // @future
|
||||
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// TESTS
|
||||
// ----------------------------------------------------------
|
||||
|
||||
#if RUN_TESTS #run {
|
||||
test.run("lo_for:primitives", t => {
|
||||
test.expect(t, lo_for(u8) == 0);
|
||||
test.expect(t, lo_for(s8) == -128);
|
||||
test.expect(t, lo_for(u16) == 0);
|
||||
test.expect(t, lo_for(s16) == -32768);
|
||||
test.expect(t, lo_for(u32) == 0);
|
||||
test.expect(t, lo_for(s32) == -2147483648);
|
||||
test.expect(t, lo_for(u64) == 0);
|
||||
test.expect(t, lo_for(s64) == -9223372036854775808);
|
||||
|
||||
test.expect(t, lo_for(float32) == 0h00800000);
|
||||
test.expect(t, lo_for(float64) == 0h00100000_00000000);
|
||||
});
|
||||
|
||||
test.run("hi_for:primitives", t => {
|
||||
test.expect(t, hi_for(u8) == 255);
|
||||
test.expect(t, hi_for(s8) == 127);
|
||||
test.expect(t, hi_for(u16) == 65535);
|
||||
test.expect(t, hi_for(s16) == 32767);
|
||||
test.expect(t, hi_for(u32) == 4294967295);
|
||||
test.expect(t, hi_for(s32) == 2147483647);
|
||||
test.expect(t, hi_for(u64) == 18446744073709551615);
|
||||
test.expect(t, hi_for(s64) == 9223372036854775807);
|
||||
|
||||
test.expect(t, hi_for(float32) == 340282346638528859000000000000000000000.0);
|
||||
test.expect(t, hi_for(float64) == 179769313486231570900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0);
|
||||
});
|
||||
|
||||
test.run("lo_for/hi_for:enums", t => {
|
||||
U8_Enum :: enum u8 { lo :: -1; hi :: +1; }
|
||||
S8_Enum :: enum s8 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
test.expect(t, lo_for(U8_Enum) == U8_Enum.lo);
|
||||
test.expect(t, lo_for(S8_Enum) == S8_Enum.lo);
|
||||
test.expect(t, hi_for(U8_Enum) == U8_Enum.hi);
|
||||
test.expect(t, hi_for(S8_Enum) == S8_Enum.hi);
|
||||
}
|
||||
|
||||
U16_Enum :: enum u16 { lo :: -1; hi :: +1; }
|
||||
S16_Enum :: enum s16 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
test.expect(t, lo_for(U16_Enum) == U16_Enum.lo);
|
||||
test.expect(t, lo_for(S16_Enum) == S16_Enum.lo);
|
||||
test.expect(t, hi_for(U16_Enum) == U16_Enum.hi);
|
||||
test.expect(t, hi_for(S16_Enum) == S16_Enum.hi);
|
||||
}
|
||||
|
||||
U32_Enum :: enum u32 { lo :: -1; hi :: +1; }
|
||||
S32_Enum :: enum s32 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
test.expect(t, lo_for(U32_Enum) == U32_Enum.lo);
|
||||
test.expect(t, lo_for(S32_Enum) == S32_Enum.lo);
|
||||
test.expect(t, hi_for(U32_Enum) == U32_Enum.hi);
|
||||
test.expect(t, hi_for(S32_Enum) == S32_Enum.hi);
|
||||
}
|
||||
|
||||
U64_Enum :: enum u64 { lo :: -1; hi :: +1; }
|
||||
S64_Enum :: enum s64 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
test.expect(t, lo_for(U64_Enum) == U64_Enum.lo);
|
||||
test.expect(t, lo_for(S64_Enum) == S64_Enum.lo);
|
||||
test.expect(t, hi_for(U64_Enum) == U64_Enum.hi);
|
||||
test.expect(t, hi_for(S64_Enum) == S64_Enum.hi);
|
||||
}
|
||||
|
||||
// @note(judah): just making sure this compiles
|
||||
lo, hi := range_for(U64_Enum);
|
||||
test.expect(t, lo == U64_Enum.lo);
|
||||
test.expect(t, hi == U64_Enum.hi);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue