diff --git a/lib/std/core/types.c3 b/lib/std/core/types.c3 index cbdb67657..70780643c 100644 --- a/lib/std/core/types.c3 +++ b/lib/std/core/types.c3 @@ -208,7 +208,7 @@ macro bool may_load_atomic($Type) } macro bool is_promotable_to_floatlike($Type) => types::is_floatlike($Type) || types::is_int($Type); - +macro bool is_promotable_to_float($Type) => types::is_float($Type) || types::is_int($Type); macro bool is_same_vector_type($Type1, $Type2) { diff --git a/lib/std/core/values.c3 b/lib/std/core/values.c3 index 0daa86930..b6a054a46 100644 --- a/lib/std/core/values.c3 +++ b/lib/std/core/values.c3 @@ -8,6 +8,7 @@ macro bool @convertable_to(#a, #b) => $checks($typeof(#b) x = #a); macro bool @is_floatlike(#value) => types::is_floatlike($typeof(#value)); macro bool @is_float(#value) => types::is_float($typeof(#value)); macro bool @is_promotable_to_floatlike(#value) => types::is_promotable_to_floatlike($typeof(#value)); +macro bool @is_promotable_to_float(#value) => types::is_promotable_to_float($typeof(#value)); macro bool @is_same_vector_type(#value1, #value2) => types::is_same_vector_type($typeof(#value1), $typeof(#value2)); macro promote_int(x) { diff --git a/lib/std/math/math.c3 b/lib/std/math/math.c3 index 307fc512c..23a2945d3 100644 --- a/lib/std/math/math.c3 +++ b/lib/std/math/math.c3 @@ -329,15 +329,31 @@ macro pow(x, exp) } /** - * @require values::@is_float(a) : `The input must be floating type` + * @require values::@is_promotable_to_float(x) : `The input must be integer or floating type` **/ macro frexp(x, int* e) { - $if (@typeis(x, float)): - return _frexpf(x, e); - $else: - return _frexp(x, e); - $endif; + $switch($typeof(x)): + $case float: + $case float16: + return _frexpf((float)x, e); + $default: + return _frexp((double)x, e); + $endswitch; +} + +/** + * @require values::@is_promotable_to_float(x) : `The input must be integer or floating type` + **/ +macro int signbit(x) +{ + $switch($typeof(x)): + $case float: + $case float16: + return bitcast((float)x, uint) >> 31; + $default: + return (int)(bitcast((double)x, ulong) >> 63); + $endswitch; } /** @@ -716,4 +732,4 @@ extern fn double _tan(double x) @extern("tan"); extern fn float _tanf(float x) @extern("tanf"); extern fn double _scalbn(double x, int n) @extern("scalbn"); extern fn double _frexp(double x, int* e) @extern("frexp"); -extern fn float _frexpf(float x, int* e) @extern("frexp"); \ No newline at end of file +extern fn float _frexpf(float x, int* e) @extern("frexpf"); \ No newline at end of file diff --git a/test/unit/stdlib/math/frexp_signbit.c3 b/test/unit/stdlib/math/frexp_signbit.c3 new file mode 100644 index 000000000..7f6473e4b --- /dev/null +++ b/test/unit/stdlib/math/frexp_signbit.c3 @@ -0,0 +1,18 @@ +module std::math @test; + +fn void test_frexp() +{ + int a; + double z = math::frexp(231.23, &a); + assert((z - 0.903242187) < 0.0000001 && a == 8); + float z2 = math::frexp(231.23f, &a); + assert((z2 - 0.903242187) < 0.0000001 && a == 8); +} + +fn void test_signbit() +{ + assert(math::signbit(-231.3) == 1); + assert(math::signbit(231.3) == 0); + assert(math::signbit(float.inf) == 0); + assert(math::signbit(-float.inf) == 1); +}