From d6e9985a266c1298f1a2a3a5831945150c269d88 Mon Sep 17 00:00:00 2001 From: Dmitry Atamanov Date: Fri, 15 Sep 2023 11:44:09 +0500 Subject: [PATCH] Add `log(x, base)` function to `std::math` module. --- lib/std/math/math.c3 | 14 ++++++++--- releasenotes.md | 3 ++- test/unit/stdlib/math/math.c3 | 47 ++++++++++++++++++++++------------- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/lib/std/math/math.c3 b/lib/std/math/math.c3 index 4a032ac6b..752438ec3 100644 --- a/lib/std/math/math.c3 +++ b/lib/std/math/math.c3 @@ -310,8 +310,8 @@ macro floor(x) => $$floor(values::promote_int(x)); * @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` + * @require values::@is_same_vector_type(a, b) `The input types must be equal` + * @require values::@is_same_vector_type(a, c) `The input types must match` **/ macro fma(a, b, c) => $$fma(a, b, c); @@ -319,14 +319,20 @@ macro fma(a, b, c) => $$fma(a, b, c); /** * @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` + * @require values::@is_same_vector_type(x, y) `The input types must match` **/ macro hypot(x, y) => sqrt(sqr(x) + sqr(y)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro log(x) => $$log(values::promote_int(x)); +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)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` diff --git a/releasenotes.md b/releasenotes.md index 1e2ff2a33..02b602010 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -116,8 +116,9 @@ - Update addition and subtraction on enums. - `@ensure` checks only non-optional results. - `assert` may now take varargs for formatting. - + ### Stdlib changes +- Added `math::log(x , base)` and `math::ln(x)`. - Hashmap keys implicitly copied if copy/free are defined. - Socket handling. - `csv` package. diff --git a/test/unit/stdlib/math/math.c3 b/test/unit/stdlib/math/math.c3 index 2bcdc1d8c..a176ec7a4 100644 --- a/test/unit/stdlib/math/math.c3 +++ b/test/unit/stdlib/math/math.c3 @@ -16,23 +16,6 @@ fn void! test_abs() @test assert(math::abs(yy) == double[<3>] { 1, 0.5, 1000 }); } -fn void! test_sign() @test -{ - int x = -21; - assert(math::sign(x) == -1); - x = 238219382; - assert(math::sign(x) == 1); - x = 0; - assert(math::sign(x) == 0); - uint y = 23; - assert(math::sign(y) == 1); - y = 0; - assert(math::sign(y) == 0); - y = (uint)-21; - assert(math::sign(y) == 1); - assert(@typeis(math::sign(y), uint)); -} - fn void! test_atan() @test { int x = 231; @@ -109,6 +92,36 @@ fn void! test_floor() @test assert(math::floor(vec) == double[<5>] { -124, 123, 0, -1, 0 }); } +fn void! test_log() @test +{ + double x = math::E; + assert(math::log(x, x) == 1.0); + float y = math::E; + assert(math::log(y, y) == 1.0f); + $assert @typeis(math::log(y, y), float); + double[<3>] xx = { 2, 4, 8 }; + assert(math::log(xx, 2) == double[<3>] { 1.0, 2.0, 3.0 }); + float[<3>] yy = { 10, 100, 1000 }; + assert(math::log(yy, 10) == float[<3>] { 1.0, 2.0, 3.0 }); +} + +fn void! test_sign() @test +{ + int x = -21; + assert(math::sign(x) == -1); + x = 238219382; + assert(math::sign(x) == 1); + x = 0; + assert(math::sign(x) == 0); + uint y = 23; + assert(math::sign(y) == 1); + y = 0; + assert(math::sign(y) == 0); + y = (uint)-21; + assert(math::sign(y) == 1); + assert(@typeis(math::sign(y), uint)); +} + fn void! test_trunc() @test { double d = -123.9;