hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit a73f5e017dfd686e9f352af0c63e20ba84ea6751
parent be7f7251890fabad7f5567361b9fb8bbf7f64307
Author: Sebastian <sebastian@sebsite.pw>
Date:   Sun,  1 Dec 2024 20:25:20 -0500

math: merge isclose with eqwithin

Now that we have optional parameters, we can get rid of eqwithin, and
instead use STANDARD_TOL as the default tol argument.

This is a breaking change.

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mmath/+test/floats_test.ha | 2+-
Mmath/+test/math_test.ha | 48++++++++++++++++++++++++------------------------
Mmath/+test/trig_test.ha | 30+++++++++++++++---------------
Mmath/math.ha | 38+++++++++-----------------------------
4 files changed, 49 insertions(+), 69 deletions(-)

diff --git a/math/+test/floats_test.ha b/math/+test/floats_test.ha @@ -174,7 +174,7 @@ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) { let res = modfracf64(TEST_INPUTS[idx]); assert(res.0 == TEST_MODFRAC[idx].0); - assert(isclose(res.1, TEST_MODFRAC[idx].1)); + assert(isclosef64(res.1, TEST_MODFRAC[idx].1)); }; let res = modfracf64(1.75f64); assert(res.0 == 1f64); diff --git a/math/+test/math_test.ha b/math/+test/math_test.ha @@ -1,18 +1,18 @@ // SPDX-License-Identifier: MPL-2.0 // (c) Hare authors <https://harelang.org> -@test fn eqwithin() void = { - assert(eqwithin(1f64, 2f64, 2f64)); - assert(eqwithin(1.0f32, 2.0f32, 2.0f32)); - assert(!eqwithin(1.0005f32, 1.0004f32, 0.00001f32)); - assert(isclose(1f64, 1.0000000000000000000000000001f64)); - assert(isclose(1.0f32, 1.0000000000000000000000000001f32)); - assert(!isclose(1.0005f32, 1.0004f32)); +@test fn isclose() void = { + assert(isclose(1f64, 2f64, 2f64)); + assert(isclose(1.0f32, 2.0f32, 2.0f32)); + assert(!isclose(1.0005f32, 1.0004f32, 0.00001f32)); + assert(isclosef64(1f64, 1.0000000000000000000000000001f64)); + assert(isclosef32(1.0f32, 1.0000000000000000000000000001f32)); + assert(!isclosef32(1.0005f32, 1.0004f32)); }; @test fn logf64() void = { for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) { - assert(isclose( + assert(isclosef64( logf64(absf64(TEST_INPUTS[idx])), TEST_LOG[idx])); }; @@ -26,7 +26,7 @@ @test fn log10f64() void = { for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) { - assert(isclose( + assert(isclosef64( log10f64(absf64(TEST_INPUTS[idx])), TEST_LOG10[idx])); }; @@ -34,7 +34,7 @@ @test fn log2f64() void = { for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) { - assert(isclose( + assert(isclosef64( log2f64(absf64(TEST_INPUTS[idx])), TEST_LOG2[idx])); }; @@ -42,7 +42,7 @@ @test fn log1p() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( log1pf64(TEST_INPUTS[idx] / 100f64), TEST_LOG1P[idx])); }; @@ -57,7 +57,7 @@ @test fn expf64() void = { for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) { - assert(isclose(expf64(TEST_INPUTS[idx]), TEST_EXP[idx])); + assert(isclosef64(expf64(TEST_INPUTS[idx]), TEST_EXP[idx])); }; assert(expf64(1f64) == E); assert(isnan(expf64(NAN))); @@ -70,7 +70,7 @@ @test fn exp2f64() void = { for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) { - assert(isclose(exp2f64(TEST_INPUTS[idx]), TEST_EXP2[idx])); + assert(isclosef64(exp2f64(TEST_INPUTS[idx]), TEST_EXP2[idx])); }; assert(exp2f64(0f64) == 1f64); assert(exp2f64(3f64) == 8f64); @@ -85,7 +85,7 @@ @test fn sqrt() void = { for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) { - assert(isclose( + assert(isclosef64( sqrtf64(absf64(TEST_INPUTS[idx])), TEST_SQRT[idx])); }; @@ -102,7 +102,7 @@ @test fn powf64() void = { for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) { - assert(eqwithin( + assert(isclosef64( powf64(10f64, TEST_INPUTS[idx]), TEST_POW[idx], 1e-8f64)); @@ -126,17 +126,17 @@ assert(powf64(2f64, -F64_MAX_NORMAL) == 0f64); assert(isinf(powf64(0.5f64, -F64_MAX_NORMAL))); // Positive fractional powers - assert(eqwithin(powf64(2f64, 1.5f64), + assert(isclosef64(powf64(2f64, 1.5f64), 2.8284271247461900976033774f64, 1e-10f64)); - assert(eqwithin(powf64(2f64, 5.5f64), + assert(isclosef64(powf64(2f64, 5.5f64), 45.254833995939041561654039f64, 1e-10f64)); // Negative fractional powers - assert(eqwithin(powf64(2f64, -1.5f64), + assert(isclosef64(powf64(2f64, -1.5f64), 0.3535533905932737622004221f64, 1e-10f64)); - assert(eqwithin(powf64(2f64, -5.5f64), + assert(isclosef64(powf64(2f64, -5.5f64), 0.0220970869120796101375263f64, 1e-10f64)); @@ -200,7 +200,7 @@ @test fn floor() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( floorf64(TEST_INPUTS[idx]), TEST_FLOOR[idx])); }; @@ -213,7 +213,7 @@ @test fn ceil() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( ceilf64(TEST_INPUTS[idx]), TEST_CEIL[idx])); }; @@ -228,7 +228,7 @@ @test fn trunc() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( truncf64(TEST_INPUTS[idx]), TEST_TRUNC[idx])); }; @@ -243,7 +243,7 @@ @test fn round() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( roundf64(TEST_INPUTS[idx]), TEST_ROUND[idx])); }; @@ -258,7 +258,7 @@ @test fn modf64() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( modf64(10f64, TEST_INPUTS[idx]), TEST_MODF[idx])); }; diff --git a/math/+test/trig_test.ha b/math/+test/trig_test.ha @@ -7,7 +7,7 @@ const j = reduced.0; const z = reduced.1; const xred = (j: i64: f64) * (PI / 4f64) + z; - assert(isclose( + assert(isclosef64( sinf64(TEST_INPUTS[idx]), sinf64(xred))); }; @@ -15,7 +15,7 @@ @test fn cos() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( cosf64(TEST_INPUTS[idx]), TEST_COS[idx])); }; assert(isnan(cosf64(-INF))); @@ -25,7 +25,7 @@ @test fn sin() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( sinf64(TEST_INPUTS[idx]), TEST_SIN[idx])); }; assert(isnan(sinf64(-INF))); @@ -37,7 +37,7 @@ @test fn tan() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( tanf64(TEST_INPUTS[idx]), TEST_TAN[idx])); }; assert(isnan(sinf64(-INF))); @@ -49,7 +49,7 @@ @test fn asin() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( asinf64(TEST_INPUTS[idx] / 10f64), TEST_ASIN[idx])); }; @@ -62,7 +62,7 @@ @test fn acos() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( acosf64(TEST_INPUTS[idx] / 10f64), TEST_ACOS[idx])); }; @@ -74,7 +74,7 @@ @test fn atan() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( atanf64(TEST_INPUTS[idx]), TEST_ATAN[idx])); }; @@ -87,7 +87,7 @@ @test fn sinh() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(eqwithin( + assert(isclosef64( sinhf64(TEST_INPUTS[idx]), TEST_SINH[idx], 1e-6f64)); @@ -101,7 +101,7 @@ @test fn cosh() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( coshf64(TEST_INPUTS[idx]), TEST_COSH[idx])); }; @@ -114,7 +114,7 @@ @test fn tanh() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( tanhf64(TEST_INPUTS[idx]), TEST_TANH[idx])); }; @@ -127,7 +127,7 @@ @test fn asinh() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( asinhf64(TEST_INPUTS[idx]), TEST_ASINH[idx])); }; @@ -140,7 +140,7 @@ @test fn acosh() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( acoshf64(1f64 + absf64(TEST_INPUTS[idx])), TEST_ACOSH[idx])); }; @@ -153,7 +153,7 @@ @test fn atanh() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( atanhf64(TEST_INPUTS[idx] / 10f64), TEST_ATANH[idx])); }; @@ -170,7 +170,7 @@ @test fn atan2() void = { for (let idx = 0z; idx < 10; idx += 1) { - assert(isclose( + assert(isclosef64( atan2f64(10f64, TEST_INPUTS[idx]), TEST_ATAN2[idx])); }; @@ -196,7 +196,7 @@ @test fn hypot() void = { for (let idx = 0z; idx < 10; idx += 1) { const a = absf64(1e200f64 * TEST_TANH[idx] * SQRT_2); - assert(isclose( + assert(isclosef64( hypotf64(1e200f64 * TEST_TANH[idx], 1e200f64 * TEST_TANH[idx]), a)); diff --git a/math/math.ha b/math/math.ha @@ -49,13 +49,13 @@ use types; -// The standard tolerance used by isclose(), which is just an arbitrary way to -// measure whether two floating-point numbers are "sufficiently" close to each -// other. -export def STANDARD_TOL: f64 = 1e-14; +// The standard tolerance used by [[isclosef32]] and [[isclosef64]], which is +// just an arbitrary way to measure whether two floating-point numbers are +// "sufficiently" close to each other. +export def STANDARD_TOL = 1e-14; // Returns whether x and y are within tol of each other. -export fn eqwithinf64(x: f64, y: f64, tol: f64) bool = { +export fn isclosef64(x: f64, y: f64, tol: f64 = STANDARD_TOL) bool = { if (isnan(x) || isnan(y) || isnan(tol)) { return false; }; @@ -63,7 +63,7 @@ export fn eqwithinf64(x: f64, y: f64, tol: f64) bool = { }; // Returns whether x and y are within tol of each other. -export fn eqwithinf32(x: f32, y: f32, tol: f32) bool = { +export fn isclosef32(x: f32, y: f32, tol: f32 = STANDARD_TOL) bool = { if (isnan(x) || isnan(y) || isnan(tol)) { return false; }; @@ -71,36 +71,16 @@ export fn eqwithinf32(x: f32, y: f32, tol: f32) bool = { }; // Returns whether x and y are within tol of each other. -export fn eqwithin( +export fn isclose( x: types::floating, y: types::floating, tol: types::floating, ) bool = { match (x) { case let n: f64 => - return eqwithinf64(n, y as f64, tol as f64); + return isclosef64(n, y as f64, tol as f64); case let n: f32 => - return eqwithinf32(n, y as f32, tol as f32); - }; -}; - -// Returns whether x and y are within [[STANDARD_TOL]] of each other. -export fn isclosef64(x: f64, y: f64) bool = { - return eqwithinf64(x, y, STANDARD_TOL); -}; - -// Returns whether x and y are within [[STANDARD_TOL]] of each other. -export fn isclosef32(x: f32, y: f32) bool = { - return eqwithinf32(x, y, STANDARD_TOL: f32); -}; - -// Returns whether x and y are within [[STANDARD_TOL]] of each other. -export fn isclose(x: types::floating, y: types::floating) bool = { - match (x) { - case let n: f64 => - return isclosef64(n, y as f64); - case let n: f32 => - return isclosef32(n, y as f32); + return isclosef32(n, y as f32, tol as f32); }; };