From 2123e81e8e19b32a6abea2224b126ac8dff65b75 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 13 Jan 2023 00:46:00 +0100 Subject: [PATCH] Make more of the builtins do promotion from int to double for convenience. --- lib/std/core/types.c3 | 12 +++++ lib/std/core/values.c3 | 13 ++++- lib/std/math.c3 | 86 +++++++++++++++++++----------- resources/examples/binarydigits.c3 | 2 +- src/compiler/sema_builtins.c | 3 +- 5 files changed, 83 insertions(+), 33 deletions(-) diff --git a/lib/std/core/types.c3 b/lib/std/core/types.c3 index 2c0cd78f2..438a52d03 100644 --- a/lib/std/core/types.c3 +++ b/lib/std/core/types.c3 @@ -182,6 +182,18 @@ macro bool @has_same(#a, #b, ...) return true; } +macro bool is_promotable_to_floatlike($Type) = types::is_floatlike($Type) || types::is_int($Type); + + +macro bool is_same_vector_type($Type1, $Type2) +{ + $if ($Type1.kindof != TypeKind.VECTOR): + return $Type2.kindof != TypeKind.VECTOR; + $else: + return $Type1.inner == $Type2.inner && $Type1.len == $Type2.len; + $endif; +} + macro bool is_equatable_value(value) { $if ($defined(value.less) || $defined(value.compare_to) || $defined(value.equals)): diff --git a/lib/std/core/values.c3 b/lib/std/core/values.c3 index 774b2e3e1..712d95de9 100644 --- a/lib/std/core/values.c3 +++ b/lib/std/core/values.c3 @@ -3,4 +3,15 @@ module std::core::values; macro bool @is_int(#value) = types::is_int($typeof(#value)); 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)); \ No newline at end of file +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_same_vector_type(#value1, #value2) = types::is_same_vector_type($typeof(#value1), $typeof(#value2)); +macro promote_int(x) +{ + $if (values::@is_int(x)): + return (double)x; + $else: + return x; + $endif; +} + diff --git a/lib/std/math.c3 b/lib/std/math.c3 index 0395ce0a4..37f72b72f 100644 --- a/lib/std/math.c3 +++ b/lib/std/math.c3 @@ -133,70 +133,87 @@ macro ceil(x) = $$ceil(x); macro clamp(x, lower, upper) = $$max(lower, $$min(x, upper)); /** - * @require values::@is_floatlike(mag) `The input must be a floating point value or float vector` - * @require types::is_same($typeof(mag), $typeof(sgn)) `The input types must be equal` + * @require values::@is_promotable_to_floatlike(mag) `The input must be a number value or float vector` + * @require values::@is_same_vector_type(mag, sgn) `The input types must match` **/ macro copysign(mag, sgn) = $$copysign(mag, sgn); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ macro cos(x) = $$cos(x); +/** + * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` + **/ macro cosec(x) = 1 / sin(x); +/** + * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` + **/ macro cosech(x) = 2 / (exp(x) - exp(-x)); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ macro cosh(x) = (exp(x) + exp(-x)) / 2.0; +/** + * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` + **/ macro cotan(x) = cos(x) / sin(x); +/** + * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` + **/ macro cotanh(x) = (exp(2.0 * x) + 1.0) / (exp(2.0 * x) - 1.0); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro exp(x) = $$exp(x); +macro exp(x) = $$exp(values::promote_int(x)); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro exp2(x) = $$exp2(x); +macro exp2(x) = $$exp2(values::promote_int(x)); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro floor(x) = $$floor(x); +macro floor(x) = $$floor(values::promote_int(x)); /** - * @require values::@is_floatlike(a) `The input must be a floating point value or float vector` - * @require types::@has_same(a, b, c) `The input types must be equal` + * @require values::@is_promotable_to_floatlike(a) `The input must be a number or float vector` + * @require values::@is_promotable_to_floatlike(b) `The input must be a number or float vector` + * @require values::@is_promotable_to_floatlike(c) `The input must be a number or float vector` + * @require types::@is_same_vector_type(a, b) `The input types must be equal` + * @require types::@is_same_vector_type(a, c) `The input types must match` **/ macro fma(a, b, c) = $$fma(a, b, c); + /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` - * @require values::@is_floatlike(y) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` + * @require values::@is_promotable_to_floatlike(y) `The input must be a number or a float vector` + * @require types::@is_same_vector_type(x, y) `The input types must match` **/ macro hypot(x, y) = sqrt(sqr(x) + sqr(y)); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro log(x) = $$log(x); +macro log(x) = $$log(values::promote_int(x)); /** - * @require values::is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro log2(x) = $$log2(x); +macro log2(x) = $$log2(values::promote_int(x)); /** - * @require values::is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro log10(x) = $$log10(x); +macro log10(x) = $$log10(values::promote_int(x)); /** * @require types::is_numerical($typeof(x)) `The input must be a floating point value or float vector` @@ -244,7 +261,7 @@ macro muladd(a, b, c) = $$fmuladd(a, b, c); macro nearbyint(x) = $$nearbyint(x); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` * @require values::@convertable_to(exp, x) || values::@is_int(exp) `The input must be an integer, castable to the type of x` **/ macro pow(x, exp) @@ -257,7 +274,7 @@ macro pow(x, exp) } /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_floatlike(x) `The input must be a number or a float vector` **/ macro rint(x) = $$rint(x); @@ -271,34 +288,43 @@ macro round(x) = $$round(x); **/ macro roundeven(x) = $$roundeven(x); +/** + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` + **/ macro sec(x) = 1 / cos(x); +/** + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` + **/ macro sech(x) = 2 / (exp(x) + exp(-x)); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro sin(x) = $$sin(x); +macro sin(x) = $$sin(values::promote_int(x)); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ macro sinh(x) = (exp(x) - exp(-x)) / 2.0; /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro sqr(x) = x * x; +macro sqr(x) = values::promote_int(x) * values::promote_int(x); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro sqrt(x) = $$sqrt(x); +macro sqrt(x) = $$sqrt(values::promote_int(x)); +/** + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` + **/ macro tan(x) = sin(x) / cos(x); /** - * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` + * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ macro tanh(x) = (exp(2.0 * x) - 1.0) / (exp(2.0 * x) + 1.0); diff --git a/resources/examples/binarydigits.c3 b/resources/examples/binarydigits.c3 index e5a77423f..c08da6723 100644 --- a/resources/examples/binarydigits.c3 +++ b/resources/examples/binarydigits.c3 @@ -13,7 +13,7 @@ fn void main() fn VarString bin(int x) { - int bits = 1 + (int)(x == 0 ? 0 : math::log10((double)(x)) / math::log10(2)); + int bits = x == 0 ? 1 : 1 + (int)math::log2(x); VarString str; str.append_repeat('0', bits); for (int i = 0; i < bits; i++) diff --git a/src/compiler/sema_builtins.c b/src/compiler/sema_builtins.c index de4073fa7..d53a4622f 100644 --- a/src/compiler/sema_builtins.c +++ b/src/compiler/sema_builtins.c @@ -98,7 +98,8 @@ static bool sema_check_builtin_args(Expr **args, BuiltinArg *arg_type, size_t ar case BA_FLOATLIKE: if (!type_flat_is_floatlike(type)) { - SEMA_ERROR(args[i], "Expected a floating point or floating point vector."); + SEMA_ERROR(args[i], "Expected a floating point or floating point vector, but was %s.", + type_quoted_error_string(type)); return false; } break;