diff --git a/lib/std/core/values.c3 b/lib/std/core/values.c3 index 169cdc919..6ad9ed3a6 100644 --- a/lib/std/core/values.c3 +++ b/lib/std/core/values.c3 @@ -26,5 +26,21 @@ macro promote_int(x) $endif } +macro promote_int_same(x, y) +{ + $if @is_int(x): + $switch + $case $and(@is_vector(y), $typeof(y).inner == float.typeid): + return (float)x; + $case $typeof(y).typeid == float.typeid: + return (float)x; + $default: + return (double)x; + $endswitch + $else + return x; + $endif +} + macro TypeKind @inner_kind(#value) => types::inner_kind($typeof(#value)); diff --git a/lib/std/math/math.c3 b/lib/std/math/math.c3 index 0c205dd0d..7482130ab 100644 --- a/lib/std/math/math.c3 +++ b/lib/std/math/math.c3 @@ -266,7 +266,7 @@ macro clamp(x, lower, upper) => $$max(($typeof(x))lower, $$min(x, ($typeof(x))up * @require values::@is_promotable_to_floatlike(mag) `The input must be a number value or float vector` * @require values::@assign_to(sgn, values::promote_int(mag)) **/ -macro copysign(mag, sgn) => $$copysign(values::promote_int(mag), ($typeof(values::promote_int(mag)))sgn); +macro copysign(mag, sgn) => $$copysign(values::promote_int_same(mag, sgn), ($typeof(values::promote_int_same(mag, sgn)))sgn); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` @@ -339,7 +339,10 @@ macro ln(x) => $$log(values::promote_int(x)); * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` * @require values::@is_promotable_to_floatlike(base) `The base must be a number or a float vector` **/ -macro log(x, base) => $$log(values::promote_int(x)) / $$log(values::promote_int(base)); +macro log(x, base) +{ + return $$log(values::promote_int_same(x, base)) / $$log(values::promote_int_same(base, x)); +} /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` @@ -403,7 +406,7 @@ macro nearbyint(x) => $$nearbyint(x); macro pow(x, exp) { $if types::is_floatlike($typeof(exp)): - return $$pow(values::promote_int(x), ($typeof(values::promote_int(x)))exp); + return $$pow(values::promote_int_same(x, exp), ($typeof(values::promote_int_same(x, exp)))exp); $else return $$pow_int(values::promote_int(x), exp); $endif diff --git a/test/unit/regression/copysign.c3 b/test/unit/regression/copysign.c3 new file mode 100644 index 000000000..1c0fa5d82 --- /dev/null +++ b/test/unit/regression/copysign.c3 @@ -0,0 +1,15 @@ +module copysign @test; +import std::math; +fn void copysign_float() +{ + float a = 3; + float b = -4; + float c = math::copysign(a, b); + assert(c == -3); + float d = math::copysign(a, 3); + assert(d == 3); + assert(math::copysign(a, -3) == -3); + float e = math::copysign(3, a); + assert(e == 3); + assert(math::copysign(3, b) == -3); +} \ No newline at end of file