commit 0e4d23b852c210e65ed9f2b85312bad6208d021b
parent 696e57b2dbf9376d4be889cef45731fec9745012
Author: Bor Grošelj Simić <bgs@turminal.net>
Date: Sun, 19 Feb 2023 05:29:01 +0100
move tests depending on +test into +test
This used to work because harec didn't typecheck @test functions when
called without -T
Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>
Diffstat:
13 files changed, 956 insertions(+), 950 deletions(-)
diff --git a/crypto/bigint/+test/utils.ha b/crypto/bigint/+test/utils.ha
@@ -39,3 +39,28 @@ export fn equalshex(x: []word, h: str) bool = {
defer free(result);
return result == h;
};
+
+@test fn iszero() void = {
+ let x = fromhex("210032a0");
+ let y = fromhex("00000000");
+
+ assert(iszero(x) == 0);
+ assert(iszero(y) == 1);
+
+ free(x);
+ free(y);
+};
+
+@test fn zero() void = {
+ let w: [4]word = [0xffffffff...];
+
+ // set effective word len to 2 words.
+ const elen = countbits(w[1..3]);
+ w[0] = elen;
+
+ zero(w[..3], elen);
+
+ // check if zero does not overwrite more or less than elen
+ assert(w[0] == elen);
+ assert(w[3] == 0xffffffff);
+};
diff --git a/crypto/bigint/util.ha b/crypto/bigint/util.ha
@@ -28,20 +28,6 @@ export fn zero(x: []word, ebitlen: word) void = {
bytes::zero((x: *[*]u8)[size(word)..(1 + ewordlen) * size(word)]);
};
-@test fn zero() void = {
- let w: [4]word = [0xffffffff...];
-
- // set effective word len to 2 words.
- const elen = countbits(w[1..3]);
- w[0] = elen;
-
- zero(w[..3], elen);
-
- // check if zero does not overwrite more or less than elen
- assert(w[0] == elen);
- assert(w[3] == 0xffffffff);
-};
-
// Checks whether the effective words of 'x' are zero. Returns 1 if so, or 0
// otherwise.
fn iszero(x: []word) u32 = {
@@ -53,17 +39,6 @@ fn iszero(x: []word) u32 = {
return ~(z | -(z: i32): u32) >> 31;
};
-@test fn iszero() void = {
- let x = fromhex("210032a0");
- let y = fromhex("00000000");
-
- assert(iszero(x) == 0);
- assert(iszero(y) == 1);
-
- free(x);
- free(y);
-};
-
fn isodd(x: []word) bool = {
return x[1] & 1 == 1;
};
diff --git a/hare/unit/+test.ha b/hare/unit/+test.ha
@@ -25,3 +25,122 @@ fn freetestctx(ctx: *context) void = {
// TODO: Some of this should be in -test
types::store_free(ctx.store);
};
+
+@test fn access() void = {
+ // TODO: Test error cases, more access types
+ const ctx = mktestctx();
+ defer freetestctx(&ctx);
+ const object = scope_insert(&ctx, object {
+ kind = object_kind::BIND,
+ ident = ["hello"],
+ name = ["hello"],
+ _type = &types::builtin_u32,
+ ...
+ });
+ const aexpr = parse_expr("hello");
+ defer ast::expr_finish(aexpr);
+ const expr = process_access(&ctx, aexpr)!;
+ const access = expr.expr as access;
+ const ao = access as access_object;
+ assert(ao == object);
+ assert(expr.result == &types::builtin_u32);
+};
+
+@test fn compound() void = {
+ const ctx = mktestctx();
+ defer freetestctx(&ctx);
+ const aexpr = parse_expr("{ void; void; void; }");
+ defer ast::expr_finish(aexpr);
+ const expr = process_compound(&ctx, aexpr)!;
+ assert(expr.result.repr as types::builtin == types::builtin::VOID);
+ const compound = expr.expr as compound;
+ assert(len(compound) == 3);
+
+ const aexpr = parse_expr("{ return; }");
+ defer ast::expr_finish(aexpr);
+ const expr = process_compound(&ctx, aexpr)!;
+ assert(expr.terminates);
+
+ // TODO: test yields
+};
+
+@test fn constant() void = {
+ const ctx = mktestctx();
+ defer freetestctx(&ctx);
+ const aexpr = parse_expr("void");
+ defer ast::expr_finish(aexpr);
+ const expr = process_constant(&ctx, aexpr)!;
+ assert(expr.result.repr as types::builtin == types::builtin::VOID);
+ const constexpr = expr.expr as constant;
+ assert(constexpr is void);
+
+ const aexpr = parse_expr("true");
+ defer ast::expr_finish(aexpr);
+ const expr = process_constant(&ctx, aexpr)!;
+ assert(expr.result.repr as types::builtin == types::builtin::BOOL);
+ const constexpr = expr.expr as constant;
+ assert(constexpr as bool == true);
+
+ const aexpr = parse_expr("false");
+ defer ast::expr_finish(aexpr);
+ const expr = process_constant(&ctx, aexpr)!;
+ assert(expr.result.repr as types::builtin == types::builtin::BOOL);
+ const constexpr = expr.expr as constant;
+ assert(constexpr as bool == false);
+
+ const aexpr = parse_expr("null");
+ defer ast::expr_finish(aexpr);
+ const expr = process_constant(&ctx, aexpr)!;
+ assert(expr.result.repr as types::builtin == types::builtin::NULL);
+ assert(expr.expr is constant);
+
+ const cases: [_](str, types::builtin, constant) = [
+ ("1234", types::builtin::INT, 1234),
+ ("1234u", types::builtin::UINT, 1234u),
+ ("\"hello world\"", types::builtin::STR, "hello world"),
+ ("'!'", types::builtin::RUNE, '!'),
+ ("13.37", types::builtin::F64, 13.37f64),
+ ];
+ for (let i = 0z; i < len(cases); i += 1) {
+ const _case = cases[i];
+ const aexpr = parse_expr(_case.0);
+ defer ast::expr_finish(aexpr);
+ const expr = process_constant(&ctx, aexpr)!;
+ assert(expr.result.repr as types::builtin == _case.1);
+ const constexpr = expr.expr as constant;
+ match (_case.2) {
+ case let s: str =>
+ assert(constexpr as str == s);
+ case let r: rune =>
+ assert(constexpr as rune == r);
+ case let i: i64 =>
+ assert(constexpr as i64 == i);
+ case let u: u64 =>
+ assert(constexpr as u64 == u);
+ case let f: f64 =>
+ assert(constexpr as f64 == f);
+ case void =>
+ abort();
+ };
+ };
+};
+
+@test fn _return() void = {
+ const ctx = mktestctx();
+ defer freetestctx(&ctx);
+ const aexpr = parse_expr("return;");
+ defer ast::expr_finish(aexpr);
+ const ret_expr = process_return(&ctx, aexpr)!;
+ assert(ret_expr.terminates);
+ assert(ret_expr.result.repr as types::builtin == types::builtin::VOID);
+ const rval = ret_expr.expr as _return;
+ assert(rval == null);
+
+ const aexpr = parse_expr("return 10;");
+ defer ast::expr_finish(aexpr);
+ const ret_expr = process_return(&ctx, aexpr)!;
+ assert(ret_expr.terminates);
+ assert(ret_expr.result.repr as types::builtin == types::builtin::VOID);
+ const rval = ret_expr.expr as _return;
+ assert((rval as *expr).expr is constant);
+};
diff --git a/hare/unit/process.ha b/hare/unit/process.ha
@@ -173,26 +173,6 @@ fn process_access(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
});
};
-@test fn access() void = {
- // TODO: Test error cases, more access types
- const ctx = mktestctx();
- defer freetestctx(&ctx);
- const object = scope_insert(&ctx, object {
- kind = object_kind::BIND,
- ident = ["hello"],
- name = ["hello"],
- _type = &types::builtin_u32,
- ...
- });
- const aexpr = parse_expr("hello");
- defer ast::expr_finish(aexpr);
- const expr = process_access(&ctx, aexpr)!;
- const access = expr.expr as access;
- const ao = access as access_object;
- assert(ao == object);
- assert(expr.result == &types::builtin_u32);
-};
-
fn process_binding(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
const bind = aexpr.expr as ast::binding_expr;
assert(!bind.is_static && !bind.is_const); // TODO
@@ -250,24 +230,6 @@ fn process_compound(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
});
};
-@test fn compound() void = {
- const ctx = mktestctx();
- defer freetestctx(&ctx);
- const aexpr = parse_expr("{ void; void; void; }");
- defer ast::expr_finish(aexpr);
- const expr = process_compound(&ctx, aexpr)!;
- assert(expr.result.repr as types::builtin == types::builtin::VOID);
- const compound = expr.expr as compound;
- assert(len(compound) == 3);
-
- const aexpr = parse_expr("{ return; }");
- defer ast::expr_finish(aexpr);
- const expr = process_compound(&ctx, aexpr)!;
- assert(expr.terminates);
-
- // TODO: test yields
-};
-
fn process_constant(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
const constexpr = aexpr.expr as ast::constant_expr;
const (result, ex) = match (constexpr) {
@@ -336,67 +298,6 @@ fn process_constant(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
});
};
-@test fn constant() void = {
- const ctx = mktestctx();
- defer freetestctx(&ctx);
- const aexpr = parse_expr("void");
- defer ast::expr_finish(aexpr);
- const expr = process_constant(&ctx, aexpr)!;
- assert(expr.result.repr as types::builtin == types::builtin::VOID);
- const constexpr = expr.expr as constant;
- assert(constexpr is void);
-
- const aexpr = parse_expr("true");
- defer ast::expr_finish(aexpr);
- const expr = process_constant(&ctx, aexpr)!;
- assert(expr.result.repr as types::builtin == types::builtin::BOOL);
- const constexpr = expr.expr as constant;
- assert(constexpr as bool == true);
-
- const aexpr = parse_expr("false");
- defer ast::expr_finish(aexpr);
- const expr = process_constant(&ctx, aexpr)!;
- assert(expr.result.repr as types::builtin == types::builtin::BOOL);
- const constexpr = expr.expr as constant;
- assert(constexpr as bool == false);
-
- const aexpr = parse_expr("null");
- defer ast::expr_finish(aexpr);
- const expr = process_constant(&ctx, aexpr)!;
- assert(expr.result.repr as types::builtin == types::builtin::NULL);
- assert(expr.expr is constant);
-
- const cases: [_](str, types::builtin, constant) = [
- ("1234", types::builtin::INT, 1234),
- ("1234u", types::builtin::UINT, 1234u),
- ("\"hello world\"", types::builtin::STR, "hello world"),
- ("'!'", types::builtin::RUNE, '!'),
- ("13.37", types::builtin::F64, 13.37f64),
- ];
- for (let i = 0z; i < len(cases); i += 1) {
- const _case = cases[i];
- const aexpr = parse_expr(_case.0);
- defer ast::expr_finish(aexpr);
- const expr = process_constant(&ctx, aexpr)!;
- assert(expr.result.repr as types::builtin == _case.1);
- const constexpr = expr.expr as constant;
- match (_case.2) {
- case let s: str =>
- assert(constexpr as str == s);
- case let r: rune =>
- assert(constexpr as rune == r);
- case let i: i64 =>
- assert(constexpr as i64 == i);
- case let u: u64 =>
- assert(constexpr as u64 == u);
- case let f: f64 =>
- assert(constexpr as f64 == f);
- case void =>
- abort();
- };
- };
-};
-
fn process_return(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
const ret = aexpr.expr as ast::return_expr;
const rval = match (ret) {
@@ -414,23 +315,3 @@ fn process_return(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
expr = rval: _return,
});
};
-
-@test fn _return() void = {
- const ctx = mktestctx();
- defer freetestctx(&ctx);
- const aexpr = parse_expr("return;");
- defer ast::expr_finish(aexpr);
- const ret_expr = process_return(&ctx, aexpr)!;
- assert(ret_expr.terminates);
- assert(ret_expr.result.repr as types::builtin == types::builtin::VOID);
- const rval = ret_expr.expr as _return;
- assert(rval == null);
-
- const aexpr = parse_expr("return 10;");
- defer ast::expr_finish(aexpr);
- const ret_expr = process_return(&ctx, aexpr)!;
- assert(ret_expr.terminates);
- assert(ret_expr.result.repr as types::builtin == types::builtin::VOID);
- const rval = ret_expr.expr as _return;
- assert((rval as *expr).expr is constant);
-};
diff --git a/math/data+test.ha b/math/+test/data.ha
diff --git a/math/+test/floats.ha b/math/+test/floats.ha
@@ -0,0 +1,296 @@
+@test fn floatbits() void = {
+ const a: [_]f64 = [INF, -INF, 0.0, 1.0, -1.0, 123456789.0,
+ F64_MIN, F64_MIN_NORMAL, F64_MAX_NORMAL];
+ for (let i = 0z; i < len(a); i += 1) {
+ assert(f64frombits(f64bits(a[i])) == a[i]);
+ };
+ const a: [_]f32 = [INF, -INF, 0.0, 1.0, -1.0, -123456.0,
+ F32_MIN, F32_MIN_NORMAL, F32_MAX_NORMAL];
+ for (let i = 0z; i < len(a); i += 1) {
+ assert(f32frombits(f32bits(a[i])) == a[i]);
+ };
+};
+
+@test fn isnan() void = {
+ assert(isnan(NAN));
+ assert(isnan(-NAN));
+ assert(isnan(f64frombits(0xfffabcdef1234567)));
+ assert(!isnan(INF));
+ assert(!isnan(1.23f32));
+};
+
+@test fn float_normality() void = {
+ assert(isnormal(0.0));
+ assert(isnormal(1.0));
+ assert(!isnormal(NAN));
+ assert(!isnormal(INF));
+ assert(!isnormal(1.0e-310));
+ assert(!isnormal(1.0e-40f32));
+
+ assert(isnormalf32(1.0));
+ assert(isnormalf32(0.0));
+ assert(!isnormalf32(NAN));
+ assert(!isnormalf32(INF));
+ assert(!isnormalf32(-1.0e-40));
+ assert(isnormalf32(-1.0e-50));
+
+ assert(isnormalf64(1.0));
+ assert(isnormalf64(0.0));
+ assert(!isnormalf64(NAN));
+ assert(!isnormalf64(INF));
+ assert(!isnormalf64(-1.0e-320));
+ assert(isnormalf64(-1.0e-330));
+
+ assert(issubnormal(1.0e-320));
+ assert(issubnormal(1.0e-42f32));
+ assert(!issubnormal(NAN));
+ assert(!issubnormal(INF));
+ assert(!issubnormal(1.0));
+ assert(!issubnormal(0.0));
+
+ assert(issubnormalf32(1.0e-45));
+ assert(issubnormalf32(-1.0e-39));
+ assert(!issubnormalf32(-NAN));
+ assert(!issubnormalf32(-INF));
+ assert(!issubnormalf32(0.0));
+ assert(!issubnormalf32(-1.0e-49));
+
+ assert(issubnormalf64(5.0e-324));
+ assert(issubnormalf64(-2.0e-310));
+ assert(!issubnormalf64(-NAN));
+ assert(!issubnormalf64(-INF));
+ assert(!issubnormalf64(-1.0e-400));
+ assert(!issubnormalf64(0.0));
+};
+
+@test fn absf() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ assert(absf(TEST_INPUTS[idx]) == TEST_ABSF[idx]);
+ };
+ assert(absf64(2f64) == 2f64);
+ assert(absf32(2.0f32) == 2.0f32);
+ assert(absf(2f64) == 2f64);
+ assert(absf(2.0f32) == 2f64);
+ assert(absf(-2f64) == 2f64);
+ assert(absf(-2.0f32) == 2.0f32);
+ assert(absf(0f32) == 0f32);
+ assert(absf(0f64) == 0f64);
+};
+
+@test fn copysign() void = {
+ assert(copysign(100f64, 1f64) == 100f64);
+ assert(copysign(100f64, -1f64) == -100f64);
+ assert(copysign(100.0f32, 1.0f32) == 100.0f32);
+ assert(copysign(100.0f32, -1.0f32) == -100.0f32);
+ assert(copysign(100f64, 0f64) == 100f64);
+ assert(copysign(100f64, -0f64) == -100f64);
+ assert(copysign(0f64, 100f64) == 0f64);
+ assert(signf(copysign(0f64, 100f64)) > 0);
+ assert(copysign(0f64, -100f64) == 0f64);
+ assert(signf(copysign(0f64, -100f64)) < 0);
+};
+
+@test fn signf() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ assert(signf(TEST_INPUTS[idx]) == TEST_SIGNF[idx]);
+ };
+ assert(signf(0f64) == 1i64);
+ assert(signf(-0f64) == -1i64);
+ assert(signf(0.0f32) == 1i64);
+ assert(signf(-0.0f32) == -1i64);
+ assert(signf(1.5f64) == 1i64);
+ assert(signf(-1.5f64) == -1i64);
+ assert(ispositive(1f64));
+ assert(!ispositive(-1f64));
+ assert(isnegative(-1f64));
+ assert(!isnegative(1f64));
+};
+
+@test fn normalize() void = {
+ let res = normalizef64(5.0e-320);
+ assert(res.0 > F64_MIN_NORMAL);
+ assert(res.1 < 0i64);
+ res = normalizef64(5.0e-300);
+ assert(res.0 == 5.0e-300);
+ assert(res.1 == 0i64);
+};
+
+@test fn frexp() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ let res = frexp(TEST_INPUTS[idx]);
+ let expected = TEST_FREXP[idx];
+ assert(res.0 == expected.0);
+ assert(res.1 == expected.1);
+ };
+ let res = frexp(3f64);
+ assert(res.0 == 0.75f64);
+ assert(res.1 == 2i64);
+ res = frexp(2.42f64);
+ assert(res.0 == 0.605f64);
+ assert(res.1 == 2i64);
+ res = frexp(NAN);
+ assert(res.1 == 0);
+ res = frexp(INF);
+ assert(res.1 == 0);
+};
+
+@test fn frexp_ldexp() void = {
+ const tests64: [_]f64 = [INF, -INF,
+ 0.0, 1.0, -1.0, 2.42, 123456789.0,
+ F64_MIN_NORMAL, F64_MAX_NORMAL,
+ 3.0e-310f64];
+ for (let i = 0z; i < len(tests64); i += 1) {
+ const parts = frexpf64(tests64[i]);
+ const res64 = ldexpf64(parts.0, parts.1);
+ assert(res64 == tests64[i]);
+ };
+ assert(ldexpf64(1f64, -1076i64) == 0f64);
+ assert(ldexpf64(-1f64, -1076i64) == -0f64);
+ assert(signf(ldexpf64(-1f64, -1076i64)) < 0);
+ assert(ldexpf64(2f64, 1024i64) == INF);
+ assert(ldexpf64(-2f64, 1024i64) == -INF);
+
+ const tests32: [_]f32 = [INF, -INF,
+ 0.0, 1.0, -1.0, 2.42, 123456789.0,
+ F32_MIN_NORMAL, F32_MAX_NORMAL,
+ 3.0e-39f32];
+ for (let i = 0z; i < len(tests32); i += 1) {
+ const parts = frexpf32(tests32[i]);
+ const res = ldexpf32(parts.0, parts.1);
+ assert(res == tests32[i]);
+ };
+ assert(ldexpf32(1.0f32, -1076i32) == 0.0f32);
+ assert(ldexpf32(-1.0f32, -1076i32) == -0.0f32);
+ assert(signf(ldexpf32(-1.0f32, -1076i32)) < 0);
+ assert(ldexpf32(2.0f32, 1024i32) == INF);
+ assert(ldexpf32(-2.0f32, 1024i32) == -INF);
+};
+
+@test fn modfrac() void = {
+ // 64
+ 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));
+ };
+ let res = modfracf64(1.75f64);
+ assert(res.0 == 1i64);
+ assert(res.1 == 0.75f64);
+ res = modfracf64(0.75f64);
+ assert(res.0 == 0i64);
+ assert(res.1 == 0.75f64);
+ res = modfracf64(-0.75f64);
+ assert(res.0 == -0i64);
+ assert(res.1 == -0.75f64);
+ res = modfracf64(0f64);
+ assert(res.0 == 0i64);
+ assert(res.1 == 0f64);
+ assert(signf(res.1) > 0);
+ res = modfracf64(-0f64);
+ assert(res.0 == -0i64);
+ assert(res.1 == -0f64);
+ assert(signf(res.1) < 0);
+ res = modfracf64(23.50f64);
+ assert(res.0 == 23i64);
+ assert(res.1 == 0.50f64);
+
+ // 32
+ let res = modfracf32(1.75f32);
+ assert(res.0 == 1i32);
+ assert(res.1 == 0.75f32);
+ res = modfracf32(0.75f32);
+ assert(res.0 == 0i32);
+ assert(res.1 == 0.75f32);
+ res = modfracf32(-0.75f32);
+ assert(res.0 == -0i32);
+ assert(res.1 == -0.75f32);
+ res = modfracf32(0.0f32);
+ assert(res.0 == 0i32);
+ assert(res.1 == 0.0f32);
+ assert(signf(res.1) > 0);
+ res = modfracf32(-0.0f32);
+ assert(res.0 == -0i32);
+ assert(res.1 == -0.0f32);
+ assert(signf(res.1) < 0);
+ res = modfracf32(23.50f32);
+ assert(res.0 == 23i32);
+ assert(res.1 == 0.50f32);
+};
+
+@test fn nextafter() void = {
+ let f = &f64frombits;
+ // from musl's testsuite
+ assert(nextafterf64(f(0xc0202239f3c6a8f1), f(0x40122484b9ef31f0)) == f(0xc0202239f3c6a8f0));
+ assert(nextafterf64(f(0x401161868e18bc67), f(0xc021c6a6cdce75e8)) == f(0x401161868e18bc66));
+ assert(nextafterf64(f(0xc020c34b3e01e6e7), f(0xc0061bde29e83f6d)) == f(0xc020c34b3e01e6e6));
+ assert(nextafterf64(f(0xc01a206f0a19dcc4), f(0x40124527f7b576ac)) == f(0xc01a206f0a19dcc3));
+ assert(nextafterf64(f(0x402288bbb0d6a1e6), f(0x40133edd910a3c01)) == f(0x402288bbb0d6a1e5));
+ assert(nextafterf64(f(0xc019ccd8be03f495), f(0x3fe52fb12ef638a1)) == f(0xc019ccd8be03f494));
+ assert(nextafterf64(f(0x401f6f80ed2eab44), f(0x3faab3ff8575b21d)) == f(0x401f6f80ed2eab43));
+ assert(nextafterf64(f(0xbfe95882b433fad3), f(0x401eb4a2e7ce0693)) == f(0xbfe95882b433fad2));
+ assert(nextafterf64(f(0x3fe3b3d617ae3c4a), f(0x40001860611d75e1)) == f(0x3fe3b3d617ae3c4b));
+ assert(nextafterf64(f(0xbfe1e159e36313ee), f(0x3fa081bd34224213)) == f(0xbfe1e159e36313ed));
+
+ assert(nextafterf64(f(0xbfe1e159e36313ee), f(0xbfe1e159e36313ee)) == f(0xbfe1e159e36313ee));
+ assert(nextafterf64(0.0f64, 1.0f64) == f(0x1));
+ assert(nextafterf64(0.0f64, -1.0f64) == f(0x8000000000000001));
+ assert(nextafterf64(-0.0f64, 1.0f64) == f(0x1));
+ assert(nextafterf64(-0.0f64, -1.0f64) == f(0x8000000000000001));
+ assert(nextafterf64(0.0f64, 0.0f64) == 0.0f64);
+ assert(nextafterf64(-0.0f64, 0.0f64) == 0.0f64);
+ assert(nextafterf64(0.0f64, -0.0f64) == -0.0f64);
+ assert(isnan(nextafterf64(1.0f64, NAN)));
+ assert(isnan(nextafterf64(NAN, -2f64)));
+ assert(isnan(nextafterf64(NAN, NAN)));
+
+ let f = &f32frombits;
+ assert(nextafterf32(f(0xc10111d0), f(0x40912426)) == f(0xc10111cf));
+ assert(nextafterf32(f(0x408b0c34), f(0xc10e3536)) == f(0x408b0c33));
+ assert(nextafterf32(f(0xc1061a5a), f(0xc030def1)) == f(0xc1061a59));
+ assert(nextafterf32(f(0xc0d10378), f(0x40922940)) == f(0xc0d10377));
+ assert(nextafterf32(f(0x411445de), f(0x4099f6ed)) == f(0x411445dd));
+ assert(nextafterf32(f(0xc0ce66c6), f(0x3f297d89)) == f(0xc0ce66c5));
+ assert(nextafterf32(f(0x40fb7c07), f(0x3d559ffc)) == f(0x40fb7c06));
+ assert(nextafterf32(f(0xbf4ac416), f(0x40f5a517)) == f(0xbf4ac415));
+ assert(nextafterf32(f(0x3f1d9eb1), f(0x4000c303)) == f(0x3f1d9eb2));
+ assert(nextafterf32(f(0xbf0f0acf), f(0x3d040dea)) == f(0xbf0f0ace));
+
+ assert(nextafterf32(f(0xbf0f0acf), f(0xbf0f0acf)) == f(0xbf0f0acf));
+ assert(nextafterf32(0.0f32, 1.0f32) == f(0x1));
+ assert(nextafterf32(0.0f32, -1.0f32) == f(0x80000001));
+ assert(nextafterf32(-0.0f32, 1.0f32) == f(0x1));
+ assert(nextafterf32(-0.0f32, -1.0f32) == f(0x80000001));
+ assert(nextafterf32(0.0f32, 0.0f32) == 0.0f32);
+ assert(nextafterf32(-0.0f32, 0.0f32) == 0.0f32);
+ assert(nextafterf32(0.0f32, -0.0f32) == -0.0f32);
+ assert(isnan(nextafterf32(1.0f32, NAN)));
+ assert(isnan(nextafterf32(NAN, -2f32)));
+ assert(isnan(nextafterf32(NAN, NAN)));
+};
+
+@test fn nearbyint() void = {
+ // from musl's testsuite
+ let f = &f64frombits;
+ assert(nearbyintf64(f(0xc0202239f3c6a8f1)) == f(0xc020000000000000));
+ assert(nearbyintf64(f(0x401161868e18bc67)) == f(0x4010000000000000));
+ assert(nearbyintf64(f(0xc020c34b3e01e6e7)) == f(0xc020000000000000));
+ assert(nearbyintf64(f(0xc01a206f0a19dcc4)) == f(0xc01c000000000000));
+ assert(nearbyintf64(f(0x402288bbb0d6a1e6)) == f(0x4022000000000000));
+ assert(nearbyintf64(f(0x3fe52efd0cd80497)) == f(0x3ff0000000000000));
+ assert(nearbyintf64(f(0xbfda05cc754481d1)) == f(0x8000000000000000));
+ assert(nearbyintf64(f(0x3fe1f9ef934745cb)) == f(0x3ff0000000000000));
+ assert(nearbyintf64(f(0x3fe8c5db097f7442)) == f(0x3ff0000000000000));
+ assert(nearbyintf64(f(0xbfe5b86ea8118a0e)) == f(0xbff0000000000000));
+
+ let f = &f32frombits;
+ assert(nearbyintf32(f(0xc10111d0)) == f(0xc1000000));
+ assert(nearbyintf32(f(0x408b0c34)) == f(0x40800000));
+ assert(nearbyintf32(f(0xc1061a5a)) == f(0xc1000000));
+ assert(nearbyintf32(f(0xc0d10378)) == f(0xc0e00000));
+ assert(nearbyintf32(f(0x411445de)) == f(0x41100000));
+ assert(nearbyintf32(f(0x3f2977e8)) == f(0x3f800000));
+ assert(nearbyintf32(f(0xbed02e64)) == f(0x80000000));
+ assert(nearbyintf32(f(0x3f0fcf7d)) == f(0x3f800000));
+ assert(nearbyintf32(f(0x3f462ed8)) == f(0x3f800000));
+ assert(nearbyintf32(f(0xbf2dc375)) == f(0xbf800000));
+};
diff --git a/math/+test/math.ha b/math/+test/math.ha
@@ -0,0 +1,287 @@
+@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 logf64() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ assert(isclose(
+ logf64(absf64(TEST_INPUTS[idx])),
+ TEST_LOG[idx]));
+ };
+ assert(logf64(E) == 1f64);
+ assert(logf64(54.598150033144239078110261202860878402790f64) == 4f64);
+ assert(isnan(logf64(-1f64)));
+ assert(logf64(INF) == INF);
+ assert(logf64(0f64) == -INF);
+ assert(isnan(logf64(NAN)));
+};
+
+@test fn log10f64() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ assert(isclose(
+ log10f64(absf64(TEST_INPUTS[idx])),
+ TEST_LOG10[idx]));
+ };
+};
+
+@test fn log2f64() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ assert(isclose(
+ log2f64(absf64(TEST_INPUTS[idx])),
+ TEST_LOG2[idx]));
+ };
+};
+
+@test fn log1p() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ log1pf64(TEST_INPUTS[idx] / 100f64),
+ TEST_LOG1P[idx]));
+ };
+ assert(isnan(log1pf64(-INF)));
+ assert(isnan(log1pf64(-PI)));
+ assert(log1pf64(-1f64) == -INF);
+ assert(log1pf64(-0f64) == -0f64);
+ assert(log1pf64(0f64) == 0f64);
+ assert(log1pf64(INF) == INF);
+ assert(isnan(log1pf64(NAN)));
+};
+
+@test fn expf64() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ assert(isclose(expf64(TEST_INPUTS[idx]), TEST_EXP[idx]));
+ };
+ assert(expf64(1f64) == E);
+ assert(isnan(expf64(NAN)));
+ assert(isinf(expf64(INF)));
+ assert(expf64(-INF) == 0f64);
+ assert(isinf(expf64(99999f64)));
+ assert(expf64(-99999f64) == 0f64);
+ assert(expf64(0.5e-20) == 1f64);
+};
+
+@test fn exp2f64() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ assert(isclose(exp2f64(TEST_INPUTS[idx]), TEST_EXP2[idx]));
+ };
+ assert(exp2f64(0f64) == 1f64);
+ assert(exp2f64(3f64) == 8f64);
+ assert(exp2f64(-2f64) == 0.25f64);
+ assert(!isinf(exp2f64(256f64)));
+ assert(isinf(exp2f64(99999f64)));
+ assert(exp2f64(-99999f64) == 0f64);
+ assert(isnan(exp2f64(NAN)));
+ assert(isinf(exp2f64(INF)));
+ assert(exp2f64(-INF) == 0f64);
+};
+
+@test fn sqrt() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ assert(isclose(
+ sqrtf64(absf64(TEST_INPUTS[idx])),
+ TEST_SQRT[idx]));
+ };
+ assert(sqrtf64(2f64) == SQRT_2);
+ assert(sqrtf64(4f64) == 2f64);
+ assert(sqrtf64(16f64) == 4f64);
+ assert(sqrtf64(65536f64) == 256f64);
+ assert(sqrtf64(powf64(123f64, 2f64)) == 123f64);
+ assert(sqrtf64(0f64) == 0f64);
+ assert(isnan(sqrtf64(NAN)));
+ assert(sqrtf64(INF) == INF);
+ assert(isnan(sqrtf64(-2f64)));
+};
+
+@test fn powf64() void = {
+ for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
+ assert(eqwithin(
+ powf64(10f64, TEST_INPUTS[idx]),
+ TEST_POW[idx],
+ 1e-8f64));
+ };
+ // Positive integer
+ assert(powf64(2f64, 2f64) == 4f64);
+ assert(powf64(3f64, 3f64) == 27f64);
+ // Very large positive integer
+ assert(!isinf(powf64(2f64, 1020f64)));
+ assert(isinf(powf64(2f64, 1050f64)));
+ // Negative integer
+ assert(powf64(2f64, -1f64) == 0.5f64);
+ assert(powf64(2f64, -2f64) == 0.25f64);
+ // Very small negative integer
+ assert(powf64(2f64, -1020f64) > 0f64);
+ assert(powf64(2f64, -1080f64) == 0f64);
+ // Positive fractional powers
+ assert(eqwithin(powf64(2f64, 1.5f64),
+ 2.8284271247461900976033774f64,
+ 1e-10f64));
+ assert(eqwithin(powf64(2f64, 5.5f64),
+ 45.254833995939041561654039f64,
+ 1e-10f64));
+ // Negative fractional powers
+ assert(eqwithin(powf64(2f64, -1.5f64),
+ 0.3535533905932737622004221f64,
+ 1e-10f64));
+ assert(eqwithin(powf64(2f64, -5.5f64),
+ 0.0220970869120796101375263f64,
+ 1e-10f64));
+
+ // Special cases
+ // pow(x, ±0) = 1 for any x
+ assert(powf64(123f64, 0f64) == 1f64);
+ // pow(1, y) = 1 for any y
+ assert(powf64(1f64, 123f64) == 1f64);
+ // pow(x, 1) = x for any x
+ assert(powf64(123f64, 1f64) == 123f64);
+ // pow(NaN, y) = NaN
+ assert(isnan(powf64(NAN, 123f64)));
+ // pow(x, NaN) = NaN
+ assert(isnan(powf64(123f64, NAN)));
+ // pow(±0, y) = ±Inf for y an odd integer < 0
+ assert(powf64(0f64, -3f64) == INF);
+ assert(powf64(-0f64, -3f64) == -INF);
+ // pow(±0, -Inf) = +Inf
+ assert(powf64(0f64, -INF) == INF);
+ assert(powf64(-0f64, -INF) == INF);
+ // pow(±0, +Inf) = +0
+ assert(powf64(0f64, INF) == 0f64);
+ assert(powf64(-0f64, INF) == 0f64);
+ // pow(±0, y) = +Inf for finite y < 0 and not an odd integer
+ assert(powf64(0f64, -2f64) == INF);
+ assert(powf64(0f64, -2f64) == INF);
+ //pow(±0, y) = ±0 for y an odd integer > 0
+ assert(powf64(0f64, 123f64) == 0f64);
+ const neg_zero = powf64(-0f64, 123f64);
+ assert(neg_zero == 0f64);
+ assert(isnegative(neg_zero));
+ // pow(±0, y) = +0 for finite y > 0 and not an odd integer
+ assert(powf64(0f64, 8f64) == 0f64);
+ // pow(-1, ±Inf) = 1
+ assert(powf64(-1f64, INF) == 1f64);
+ assert(powf64(-1f64, -INF) == 1f64);
+ // pow(x, +Inf) = +Inf for |x| > 1
+ assert(powf64(123f64, INF) == INF);
+ // pow(x, -Inf) = +0 for |x| > 1
+ assert(powf64(123f64, -INF) == 0f64);
+ // pow(x, +Inf) = +0 for |x| < 1
+ assert(powf64(0.5f64, INF) == 0f64);
+ assert(powf64(-0.5f64, INF) == 0f64);
+ // pow(x, -Inf) = +Inf for |x| < 1
+ assert(powf64(0.5f64, -INF) == INF);
+ assert(powf64(-0.5f64, -INF) == INF);
+ // pow(+Inf, y) = +Inf for y > 0
+ assert(powf64(INF, 123f64) == INF);
+ // pow(+Inf, y) = +0 for y < 0
+ assert(powf64(INF, -1f64) == 0f64);
+ // pow(-Inf, y) = pow(-0, -y)
+ assert(powf64(-INF, 123f64) == powf64(-0f64, -123f64));
+ // pow(x, y) = NaN for finite x < 0 and finite non-integer y
+ assert(isnan(powf64(-2f64, 1.23f64)));
+ // sqrt
+ assert(powf64(4f64, 0.5f64) == sqrtf64(4f64));
+ assert(powf64(4f64, 0.5f64) == 2f64);
+ assert(powf64(4f64, -0.5f64) == (1f64 / sqrtf64(4f64)));
+ assert(powf64(4f64, -0.5f64) == (1f64 / 2f64));
+};
+
+@test fn floor() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ floorf64(TEST_INPUTS[idx]),
+ TEST_FLOOR[idx]));
+ };
+ assert(floorf64(-INF) == -INF);
+ assert(floorf64(-0f64) == -0f64);
+ assert(floorf64(0f64) == 0f64);
+ assert(floorf64(INF) == INF);
+ assert(isnan(floorf64(NAN)));
+};
+
+@test fn ceil() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ ceilf64(TEST_INPUTS[idx]),
+ TEST_CEIL[idx]));
+ };
+ assert(ceilf64(-INF) == -INF);
+ assert(ceilf64(-0f64) == -0f64);
+ assert(ceilf64(0f64) == 0f64);
+ assert(ceilf64(INF) == INF);
+ assert(isnan(ceilf64(NAN)));
+};
+
+@test fn trunc() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ truncf64(TEST_INPUTS[idx]),
+ TEST_TRUNC[idx]));
+ };
+ assert(truncf64(-INF) == -INF);
+ assert(truncf64(-0f64) == -0f64);
+ assert(truncf64(0f64) == 0f64);
+ assert(truncf64(INF) == INF);
+ assert(isnan(truncf64(NAN)));
+};
+
+@test fn round() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ roundf64(TEST_INPUTS[idx]),
+ TEST_ROUND[idx]));
+ };
+ assert(roundf64(-INF) == -INF);
+ assert(roundf64(-0f64) == -0f64);
+ assert(roundf64(0f64) == 0f64);
+ assert(roundf64(INF) == INF);
+ assert(isnan(roundf64(NAN)));
+};
+
+@test fn modf64() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ modf64(10f64, TEST_INPUTS[idx]),
+ TEST_MODF[idx]));
+ };
+
+ assert(isnan(modf64(-INF, -INF)));
+ assert(isnan(modf64(-INF, -PI)));
+ assert(isnan(modf64(-INF, 0f64)));
+ assert(isnan(modf64(-INF, PI)));
+ assert(isnan(modf64(-INF, INF)));
+ assert(isnan(modf64(-INF, NAN)));
+ assert(modf64(-PI, -INF) == -PI);
+ assert(isnan(modf64(-PI, 0f64)));
+ assert(modf64(-PI, INF) == -PI);
+ assert(isnan(modf64(-PI, NAN)));
+ assert(modf64(-0f64, -INF) == -0f64);
+ assert(isnan(modf64(-0f64, 0f64)));
+ assert(modf64(-0f64, INF) == -0f64);
+ assert(isnan(modf64(-0f64, NAN)));
+ assert(modf64(0f64, -INF) == 0f64);
+ assert(isnan(modf64(0f64, 0f64)));
+ assert(modf64(0f64, INF) == 0f64);
+ assert(isnan(modf64(0f64, NAN)));
+ assert(modf64(PI, -INF) == PI);
+ assert(isnan(modf64(PI, 0f64)));
+ assert(modf64(PI, INF) == PI);
+ assert(isnan(modf64(PI, NAN)));
+ assert(isnan(modf64(INF, -INF)));
+ assert(isnan(modf64(INF, -PI)));
+ assert(isnan(modf64(INF, 0f64)));
+ assert(isnan(modf64(INF, PI)));
+ assert(isnan(modf64(INF, INF)));
+ assert(isnan(modf64(INF, NAN)));
+ assert(isnan(modf64(NAN, -INF)));
+ assert(isnan(modf64(NAN, -PI)));
+ assert(isnan(modf64(NAN, 0f64)));
+ assert(isnan(modf64(NAN, PI)));
+ assert(isnan(modf64(NAN, INF)));
+ assert(isnan(modf64(NAN, NAN)));
+ assert(modf64(5.9790119248836734e+200, 1.1258465975523544) ==
+ 0.6447968302508578);
+};
diff --git a/math/+test/trig.ha b/math/+test/trig.ha
@@ -0,0 +1,220 @@
+@test fn trig_reduce() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ const reduced = trig_reduce(TEST_INPUTS[idx]);
+ const j = reduced.0;
+ const z = reduced.1;
+ const xred = (j: i64: f64) * (PI / 4f64) + z;
+ assert(isclose(
+ sinf64(TEST_INPUTS[idx]),
+ sinf64(xred)));
+ };
+};
+
+@test fn cos() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ cosf64(TEST_INPUTS[idx]), TEST_COS[idx]));
+ };
+ assert(isnan(cosf64(-INF)));
+ assert(isnan(cosf64(INF)));
+ assert(isnan(cosf64(NAN)));
+};
+
+@test fn sin() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ sinf64(TEST_INPUTS[idx]), TEST_SIN[idx]));
+ };
+ assert(isnan(sinf64(-INF)));
+ assert(sinf64(-0f64) == -0f64);
+ assert(sinf64(0f64) == 0f64);
+ assert(isnan(sinf64(INF)));
+ assert(isnan(sinf64(NAN)));
+};
+
+@test fn tan() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ tanf64(TEST_INPUTS[idx]), TEST_TAN[idx]));
+ };
+ assert(isnan(sinf64(-INF)));
+ assert(sinf64(-0f64) == -0f64);
+ assert(sinf64(0f64) == 0f64);
+ assert(isnan(sinf64(INF)));
+ assert(isnan(sinf64(NAN)));
+};
+
+@test fn asin() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ asinf64(TEST_INPUTS[idx] / 10f64),
+ TEST_ASIN[idx]));
+ };
+ assert(isnan(asinf64(-PI)));
+ assert(asinf64(-0f64) == -0f64);
+ assert(asinf64(0f64) == 0f64);
+ assert(isnan(asinf64(PI)));
+ assert(isnan(asinf64(NAN)));
+};
+
+@test fn acos() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ acosf64(TEST_INPUTS[idx] / 10f64),
+ TEST_ACOS[idx]));
+ };
+ assert(isnan(acosf64(-PI)));
+ assert(acosf64(1f64) == 0f64);
+ assert(isnan(acosf64(PI)));
+ assert(isnan(acosf64(NAN)));
+};
+
+@test fn atan() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ atanf64(TEST_INPUTS[idx]),
+ TEST_ATAN[idx]));
+ };
+ assert(atanf64(-INF) == -PI / 2f64);
+ assert(atanf64(-0f64) == -0f64);
+ assert(atanf64(0f64) == 0f64);
+ assert(atanf64(INF) == PI / 2f64);
+ assert(isnan(atanf64(NAN)));
+};
+
+@test fn sinh() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(eqwithin(
+ sinhf64(TEST_INPUTS[idx]),
+ TEST_SINH[idx],
+ 1e-6f64));
+ };
+ assert(sinhf64(-INF) == -INF);
+ assert(sinhf64(-0f64) == -0f64);
+ assert(sinhf64(0f64) == 0f64);
+ assert(sinhf64(INF) == INF);
+ assert(isnan(sinhf64(NAN)));
+};
+
+@test fn cosh() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ coshf64(TEST_INPUTS[idx]),
+ TEST_COSH[idx]));
+ };
+ assert(coshf64(-INF) == INF);
+ assert(coshf64(-0f64) == 1f64);
+ assert(coshf64(0f64) == 1f64);
+ assert(coshf64(INF) == INF);
+ assert(isnan(coshf64(NAN)));
+};
+
+@test fn tanh() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ tanhf64(TEST_INPUTS[idx]),
+ TEST_TANH[idx]));
+ };
+ assert(tanhf64(-INF) == -1f64);
+ assert(tanhf64(-0f64) == -0f64);
+ assert(tanhf64(0f64) == 0f64);
+ assert(tanhf64(INF) == 1f64);
+ assert(isnan(tanhf64(NAN)));
+};
+
+@test fn asinh() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ asinhf64(TEST_INPUTS[idx]),
+ TEST_ASINH[idx]));
+ };
+ assert(asinhf64(-INF) == -INF);
+ assert(asinhf64(-0f64) == -0f64);
+ assert(asinhf64(0f64) == 0f64);
+ assert(asinhf64(INF) == INF);
+ assert(isnan(asinhf64(NAN)));
+};
+
+@test fn acosh() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ acoshf64(1f64 + absf64(TEST_INPUTS[idx])),
+ TEST_ACOSH[idx]));
+ };
+ assert(isnan(acoshf64(-INF)));
+ assert(isnan(acoshf64(0.5f64)));
+ assert(acoshf64(1f64) == 0f64);
+ assert(acoshf64(INF) == INF);
+ assert(isnan(acoshf64(NAN)));
+};
+
+@test fn atanh() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ atanhf64(TEST_INPUTS[idx] / 10f64),
+ TEST_ATANH[idx]));
+ };
+ assert(isnan(atanhf64(-INF)));
+ assert(isnan(atanhf64(-PI)));
+ assert(atanhf64(-1f64) == -INF);
+ assert(atanhf64(-0f64) == -0f64);
+ assert(atanhf64(0f64) == 0f64);
+ assert(atanhf64(1f64) == INF);
+ assert(isnan(atanhf64(PI)));
+ assert(isnan(atanhf64(INF)));
+ assert(isnan(atanhf64(NAN)));
+};
+
+@test fn atan2() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ atan2f64(10f64, TEST_INPUTS[idx]),
+ TEST_ATAN2[idx]));
+ };
+ assert(isnan(atan2f64(-INF, NAN)));
+ assert(atan2f64(-PI, INF) == -0f64);
+ assert(isnan(atan2f64(-PI, NAN)));
+ assert(atan2f64(-0f64, 0f64) == -0f64);
+ assert(atan2f64(-0f64, PI) == -0f64);
+ assert(atan2f64(-0f64, INF) == -0f64);
+ assert(isnan(atan2f64(-0f64, NAN)));
+ assert(atan2f64(0f64, 0f64) == 0f64);
+ assert(atan2f64(0f64, PI) == 0f64);
+ assert(atan2f64(0f64, INF) == 0f64);
+ assert(isnan(atan2f64(0f64, NAN)));
+ assert(atan2f64(PI, INF) == 0f64);
+ assert(atan2f64(1f64, INF) == 0f64);
+ assert(atan2f64(-1f64, INF) == -0f64);
+ assert(isnan(atan2f64(PI, NAN)));
+ assert(isnan(atan2f64(INF, NAN)));
+ assert(isnan(atan2f64(NAN, NAN)));
+};
+
+@test fn hypot() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ const a = absf64(1e200f64 * TEST_TANH[idx] * SQRT_2);
+ assert(isclose(
+ hypotf64(1e200f64 * TEST_TANH[idx],
+ 1e200f64 * TEST_TANH[idx]),
+ a));
+ };
+ assert(hypotf64(-INF, -INF) == INF);
+ assert(hypotf64(-INF, 0f64) == INF);
+ assert(hypotf64(-INF, INF) == INF);
+ assert(hypotf64(-INF, NAN) == INF);
+ assert(hypotf64(-0f64, -0f64) == 0f64);
+ assert(hypotf64(-0f64, 0f64) == 0f64);
+ assert(hypotf64(0f64, -0f64) == 0f64);
+ assert(hypotf64(0f64, 0f64) == 0f64);
+ assert(hypotf64(0f64, -INF) == INF);
+ assert(hypotf64(0f64, INF) == INF);
+ assert(isnan(hypotf64(0f64, NAN)));
+ assert(hypotf64(INF, -INF) == INF);
+ assert(hypotf64(INF, 0f64) == INF);
+ assert(hypotf64(INF, INF) == INF);
+ assert(hypotf64(INF, NAN) == INF);
+ assert(hypotf64(NAN, -INF) == INF);
+ assert(isnan(hypotf64(NAN, 0f64)));
+ assert(hypotf64(NAN, INF) == INF);
+ assert(isnan(hypotf64(NAN, NAN)));
+};
diff --git a/math/floats.ha b/math/floats.ha
@@ -18,19 +18,6 @@ export fn f64frombits(n: u64) f64 = *(&n: *f64);
// Returns f32 with the given binary representation.
export fn f32frombits(n: u32) f32 = *(&n: *f32);
-@test fn floatbits() void = {
- const a: [_]f64 = [INF, -INF, 0.0, 1.0, -1.0, 123456789.0,
- F64_MIN, F64_MIN_NORMAL, F64_MAX_NORMAL];
- for (let i = 0z; i < len(a); i += 1) {
- assert(f64frombits(f64bits(a[i])) == a[i]);
- };
- const a: [_]f32 = [INF, -INF, 0.0, 1.0, -1.0, -123456.0,
- F32_MIN, F32_MIN_NORMAL, F32_MAX_NORMAL];
- for (let i = 0z; i < len(a); i += 1) {
- assert(f32frombits(f32bits(a[i])) == a[i]);
- };
-};
-
// The number of bits in the significand of the binary representation of f64.
export def F64_MANTISSA_BITS: u64 = 52;
@@ -161,14 +148,6 @@ export def INF: f32 = 1.0 / 0.0;
// Returns true if the given floating-point number is NaN.
export fn isnan(n: f64) bool = n != n;
-@test fn isnan() void = {
- assert(isnan(NAN));
- assert(isnan(-NAN));
- assert(isnan(f64frombits(0xfffabcdef1234567)));
- assert(!isnan(INF));
- assert(!isnan(1.23f32));
-};
-
// Returns true if the given floating-point number is infinite.
export fn isinf(n: f64) bool = {
const bits = f64bits(n);
@@ -237,50 +216,6 @@ export fn issubnormalf32(n: f32) bool = {
return exp == 0 && mant != 0;
};
-@test fn float_normality() void = {
- assert(isnormal(0.0));
- assert(isnormal(1.0));
- assert(!isnormal(NAN));
- assert(!isnormal(INF));
- assert(!isnormal(1.0e-310));
- assert(!isnormal(1.0e-40f32));
-
- assert(isnormalf32(1.0));
- assert(isnormalf32(0.0));
- assert(!isnormalf32(NAN));
- assert(!isnormalf32(INF));
- assert(!isnormalf32(-1.0e-40));
- assert(isnormalf32(-1.0e-50));
-
- assert(isnormalf64(1.0));
- assert(isnormalf64(0.0));
- assert(!isnormalf64(NAN));
- assert(!isnormalf64(INF));
- assert(!isnormalf64(-1.0e-320));
- assert(isnormalf64(-1.0e-330));
-
- assert(issubnormal(1.0e-320));
- assert(issubnormal(1.0e-42f32));
- assert(!issubnormal(NAN));
- assert(!issubnormal(INF));
- assert(!issubnormal(1.0));
- assert(!issubnormal(0.0));
-
- assert(issubnormalf32(1.0e-45));
- assert(issubnormalf32(-1.0e-39));
- assert(!issubnormalf32(-NAN));
- assert(!issubnormalf32(-INF));
- assert(!issubnormalf32(0.0));
- assert(!issubnormalf32(-1.0e-49));
-
- assert(issubnormalf64(5.0e-324));
- assert(issubnormalf64(-2.0e-310));
- assert(!issubnormalf64(-NAN));
- assert(!issubnormalf64(-INF));
- assert(!issubnormalf64(-1.0e-400));
- assert(!issubnormalf64(0.0));
-};
-
// Returns the absolute value of f64 n.
export fn absf64(n: f64) f64 = {
if (isnan(n)) {
@@ -307,20 +242,6 @@ export fn absf(n: types::floating) f64 = {
};
};
-@test fn absf() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- assert(absf(TEST_INPUTS[idx]) == TEST_ABSF[idx]);
- };
- assert(absf64(2f64) == 2f64);
- assert(absf32(2.0f32) == 2.0f32);
- assert(absf(2f64) == 2f64);
- assert(absf(2.0f32) == 2f64);
- assert(absf(-2f64) == 2f64);
- assert(absf(-2.0f32) == 2.0f32);
- assert(absf(0f32) == 0f32);
- assert(absf(0f64) == 0f64);
-};
-
// Returns 1 if x is positive and -1 if x is negative. Note that zero is also
// signed.
export fn signf64(x: f64) i64 = {
@@ -352,22 +273,6 @@ export fn signf(x: types::floating) i64 = {
};
};
-@test fn signf() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- assert(signf(TEST_INPUTS[idx]) == TEST_SIGNF[idx]);
- };
- assert(signf(0f64) == 1i64);
- assert(signf(-0f64) == -1i64);
- assert(signf(0.0f32) == 1i64);
- assert(signf(-0.0f32) == -1i64);
- assert(signf(1.5f64) == 1i64);
- assert(signf(-1.5f64) == -1i64);
- assert(ispositive(1f64));
- assert(!ispositive(-1f64));
- assert(isnegative(-1f64));
- assert(!isnegative(1f64));
-};
-
// Returns whether or not x is positive.
export fn ispositivef64(x: f64) bool = signf64(x) == 1i64;
@@ -422,19 +327,6 @@ export fn copysign(x: types::floating, y: types::floating) f64 = {
};
};
-@test fn copysign() void = {
- assert(copysign(100f64, 1f64) == 100f64);
- assert(copysign(100f64, -1f64) == -100f64);
- assert(copysign(100.0f32, 1.0f32) == 100.0f32);
- assert(copysign(100.0f32, -1.0f32) == -100.0f32);
- assert(copysign(100f64, 0f64) == 100f64);
- assert(copysign(100f64, -0f64) == -100f64);
- assert(copysign(0f64, 100f64) == 0f64);
- assert(signf(copysign(0f64, 100f64)) > 0);
- assert(copysign(0f64, -100f64) == 0f64);
- assert(signf(copysign(0f64, -100f64)) < 0);
-};
-
// Takes a potentially subnormal f64 n and returns a normal f64 normal_float
// and an exponent exp such that n == normal_float * 2^{exp}.
export fn normalizef64(n: f64) (f64, i64) = {
@@ -457,15 +349,6 @@ export fn normalizef32(n: f32) (f64, i64) = {
return (n, 0);
};
-@test fn normalize() void = {
- let res = normalizef64(5.0e-320);
- assert(res.0 > F64_MIN_NORMAL);
- assert(res.1 < 0i64);
- res = normalizef64(5.0e-300);
- assert(res.0 == 5.0e-300);
- assert(res.1 == 0i64);
-};
-
// Breaks a f64 down into its mantissa and exponent. The mantissa will be
// between 0.5 and 1.
export fn frexpf64(n: f64) (f64, i64) = {
@@ -514,25 +397,6 @@ export fn frexp(n: types::floating) (f64, i64) = {
};
};
-@test fn frexp() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- let res = frexp(TEST_INPUTS[idx]);
- let expected = TEST_FREXP[idx];
- assert(res.0 == expected.0);
- assert(res.1 == expected.1);
- };
- let res = frexp(3f64);
- assert(res.0 == 0.75f64);
- assert(res.1 == 2i64);
- res = frexp(2.42f64);
- assert(res.0 == 0.605f64);
- assert(res.1 == 2i64);
- res = frexp(NAN);
- assert(res.1 == 0);
- res = frexp(INF);
- assert(res.1 == 0);
-};
-
// Creates an f64 from a mantissa and an exponent.
export fn ldexpf64(mantissa: f64, exp: i64) f64 = {
if (isnan(mantissa) || isinf(mantissa) || mantissa == 0f64) {
@@ -613,38 +477,6 @@ export fn ldexpf32(mantissa: f32, exp: i64) f32 = {
return subnormal_factor * f32frombits(res);
};
-@test fn frexp_ldexp() void = {
- const tests64: [_]f64 = [INF, -INF,
- 0.0, 1.0, -1.0, 2.42, 123456789.0,
- F64_MIN_NORMAL, F64_MAX_NORMAL,
- 3.0e-310f64];
- for (let i = 0z; i < len(tests64); i += 1) {
- const parts = frexpf64(tests64[i]);
- const res64 = ldexpf64(parts.0, parts.1);
- assert(res64 == tests64[i]);
- };
- assert(ldexpf64(1f64, -1076i64) == 0f64);
- assert(ldexpf64(-1f64, -1076i64) == -0f64);
- assert(signf(ldexpf64(-1f64, -1076i64)) < 0);
- assert(ldexpf64(2f64, 1024i64) == INF);
- assert(ldexpf64(-2f64, 1024i64) == -INF);
-
- const tests32: [_]f32 = [INF, -INF,
- 0.0, 1.0, -1.0, 2.42, 123456789.0,
- F32_MIN_NORMAL, F32_MAX_NORMAL,
- 3.0e-39f32];
- for (let i = 0z; i < len(tests32); i += 1) {
- const parts = frexpf32(tests32[i]);
- const res = ldexpf32(parts.0, parts.1);
- assert(res == tests32[i]);
- };
- assert(ldexpf32(1.0f32, -1076i32) == 0.0f32);
- assert(ldexpf32(-1.0f32, -1076i32) == -0.0f32);
- assert(signf(ldexpf32(-1.0f32, -1076i32)) < 0);
- assert(ldexpf32(2.0f32, 1024i32) == INF);
- assert(ldexpf32(-2.0f32, 1024i32) == -INF);
-};
-
// Returns the integer and fractional parts of an f64.
export fn modfracf64(n: f64) (i64, f64) = {
if (n < 1f64) {
@@ -699,56 +531,6 @@ export fn modfracf32(n: f32) (i32, f32) = {
return ((int_part: i32), frac_part);
};
-@test fn modfrac() void = {
- // 64
- 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));
- };
- let res = modfracf64(1.75f64);
- assert(res.0 == 1i64);
- assert(res.1 == 0.75f64);
- res = modfracf64(0.75f64);
- assert(res.0 == 0i64);
- assert(res.1 == 0.75f64);
- res = modfracf64(-0.75f64);
- assert(res.0 == -0i64);
- assert(res.1 == -0.75f64);
- res = modfracf64(0f64);
- assert(res.0 == 0i64);
- assert(res.1 == 0f64);
- assert(signf(res.1) > 0);
- res = modfracf64(-0f64);
- assert(res.0 == -0i64);
- assert(res.1 == -0f64);
- assert(signf(res.1) < 0);
- res = modfracf64(23.50f64);
- assert(res.0 == 23i64);
- assert(res.1 == 0.50f64);
-
- // 32
- let res = modfracf32(1.75f32);
- assert(res.0 == 1i32);
- assert(res.1 == 0.75f32);
- res = modfracf32(0.75f32);
- assert(res.0 == 0i32);
- assert(res.1 == 0.75f32);
- res = modfracf32(-0.75f32);
- assert(res.0 == -0i32);
- assert(res.1 == -0.75f32);
- res = modfracf32(0.0f32);
- assert(res.0 == 0i32);
- assert(res.1 == 0.0f32);
- assert(signf(res.1) > 0);
- res = modfracf32(-0.0f32);
- assert(res.0 == -0i32);
- assert(res.1 == -0.0f32);
- assert(signf(res.1) < 0);
- res = modfracf32(23.50f32);
- assert(res.0 == 23i32);
- assert(res.1 == 0.50f32);
-};
// Returns the f32 that is closest to 'x' in direction of 'y'. Returns NaN
// if either parameter is NaN. Returns 'x' if both parameters are same.
@@ -804,57 +586,6 @@ export fn nextafterf64(x: f64, y: f64) f64 = {
return f64frombits(ux);
};
-@test fn nextafter() void = {
- let f = &f64frombits;
- // from musl's testsuite
- assert(nextafterf64(f(0xc0202239f3c6a8f1), f(0x40122484b9ef31f0)) == f(0xc0202239f3c6a8f0));
- assert(nextafterf64(f(0x401161868e18bc67), f(0xc021c6a6cdce75e8)) == f(0x401161868e18bc66));
- assert(nextafterf64(f(0xc020c34b3e01e6e7), f(0xc0061bde29e83f6d)) == f(0xc020c34b3e01e6e6));
- assert(nextafterf64(f(0xc01a206f0a19dcc4), f(0x40124527f7b576ac)) == f(0xc01a206f0a19dcc3));
- assert(nextafterf64(f(0x402288bbb0d6a1e6), f(0x40133edd910a3c01)) == f(0x402288bbb0d6a1e5));
- assert(nextafterf64(f(0xc019ccd8be03f495), f(0x3fe52fb12ef638a1)) == f(0xc019ccd8be03f494));
- assert(nextafterf64(f(0x401f6f80ed2eab44), f(0x3faab3ff8575b21d)) == f(0x401f6f80ed2eab43));
- assert(nextafterf64(f(0xbfe95882b433fad3), f(0x401eb4a2e7ce0693)) == f(0xbfe95882b433fad2));
- assert(nextafterf64(f(0x3fe3b3d617ae3c4a), f(0x40001860611d75e1)) == f(0x3fe3b3d617ae3c4b));
- assert(nextafterf64(f(0xbfe1e159e36313ee), f(0x3fa081bd34224213)) == f(0xbfe1e159e36313ed));
-
- assert(nextafterf64(f(0xbfe1e159e36313ee), f(0xbfe1e159e36313ee)) == f(0xbfe1e159e36313ee));
- assert(nextafterf64(0.0f64, 1.0f64) == f(0x1));
- assert(nextafterf64(0.0f64, -1.0f64) == f(0x8000000000000001));
- assert(nextafterf64(-0.0f64, 1.0f64) == f(0x1));
- assert(nextafterf64(-0.0f64, -1.0f64) == f(0x8000000000000001));
- assert(nextafterf64(0.0f64, 0.0f64) == 0.0f64);
- assert(nextafterf64(-0.0f64, 0.0f64) == 0.0f64);
- assert(nextafterf64(0.0f64, -0.0f64) == -0.0f64);
- assert(isnan(nextafterf64(1.0f64, NAN)));
- assert(isnan(nextafterf64(NAN, -2f64)));
- assert(isnan(nextafterf64(NAN, NAN)));
-
- let f = &f32frombits;
- assert(nextafterf32(f(0xc10111d0), f(0x40912426)) == f(0xc10111cf));
- assert(nextafterf32(f(0x408b0c34), f(0xc10e3536)) == f(0x408b0c33));
- assert(nextafterf32(f(0xc1061a5a), f(0xc030def1)) == f(0xc1061a59));
- assert(nextafterf32(f(0xc0d10378), f(0x40922940)) == f(0xc0d10377));
- assert(nextafterf32(f(0x411445de), f(0x4099f6ed)) == f(0x411445dd));
- assert(nextafterf32(f(0xc0ce66c6), f(0x3f297d89)) == f(0xc0ce66c5));
- assert(nextafterf32(f(0x40fb7c07), f(0x3d559ffc)) == f(0x40fb7c06));
- assert(nextafterf32(f(0xbf4ac416), f(0x40f5a517)) == f(0xbf4ac415));
- assert(nextafterf32(f(0x3f1d9eb1), f(0x4000c303)) == f(0x3f1d9eb2));
- assert(nextafterf32(f(0xbf0f0acf), f(0x3d040dea)) == f(0xbf0f0ace));
-
- assert(nextafterf32(f(0xbf0f0acf), f(0xbf0f0acf)) == f(0xbf0f0acf));
- assert(nextafterf32(0.0f32, 1.0f32) == f(0x1));
- assert(nextafterf32(0.0f32, -1.0f32) == f(0x80000001));
- assert(nextafterf32(-0.0f32, 1.0f32) == f(0x1));
- assert(nextafterf32(-0.0f32, -1.0f32) == f(0x80000001));
- assert(nextafterf32(0.0f32, 0.0f32) == 0.0f32);
- assert(nextafterf32(-0.0f32, 0.0f32) == 0.0f32);
- assert(nextafterf32(0.0f32, -0.0f32) == -0.0f32);
- assert(isnan(nextafterf32(1.0f32, NAN)));
- assert(isnan(nextafterf32(NAN, -2f32)));
- assert(isnan(nextafterf32(NAN, NAN)));
-};
-
// Round a f32 to nearest integer value in floating point format
fn nearbyintf32(x: f32) f32 = {
let n = f32bits(x);
@@ -892,30 +623,3 @@ fn nearbyintf64(x: f64) f64 = {
else
return y;
};
-
-@test fn nearbyint() void = {
- // from musl's testsuite
- let f = &f64frombits;
- assert(nearbyintf64(f(0xc0202239f3c6a8f1)) == f(0xc020000000000000));
- assert(nearbyintf64(f(0x401161868e18bc67)) == f(0x4010000000000000));
- assert(nearbyintf64(f(0xc020c34b3e01e6e7)) == f(0xc020000000000000));
- assert(nearbyintf64(f(0xc01a206f0a19dcc4)) == f(0xc01c000000000000));
- assert(nearbyintf64(f(0x402288bbb0d6a1e6)) == f(0x4022000000000000));
- assert(nearbyintf64(f(0x3fe52efd0cd80497)) == f(0x3ff0000000000000));
- assert(nearbyintf64(f(0xbfda05cc754481d1)) == f(0x8000000000000000));
- assert(nearbyintf64(f(0x3fe1f9ef934745cb)) == f(0x3ff0000000000000));
- assert(nearbyintf64(f(0x3fe8c5db097f7442)) == f(0x3ff0000000000000));
- assert(nearbyintf64(f(0xbfe5b86ea8118a0e)) == f(0xbff0000000000000));
-
- let f = &f32frombits;
- assert(nearbyintf32(f(0xc10111d0)) == f(0xc1000000));
- assert(nearbyintf32(f(0x408b0c34)) == f(0x40800000));
- assert(nearbyintf32(f(0xc1061a5a)) == f(0xc1000000));
- assert(nearbyintf32(f(0xc0d10378)) == f(0xc0e00000));
- assert(nearbyintf32(f(0x411445de)) == f(0x41100000));
- assert(nearbyintf32(f(0x3f2977e8)) == f(0x3f800000));
- assert(nearbyintf32(f(0xbed02e64)) == f(0x80000000));
- assert(nearbyintf32(f(0x3f0fcf7d)) == f(0x3f800000));
- assert(nearbyintf32(f(0x3f462ed8)) == f(0x3f800000));
- assert(nearbyintf32(f(0xbf2dc375)) == f(0xbf800000));
-};
diff --git a/math/math.ha b/math/math.ha
@@ -106,15 +106,6 @@ export fn isclose(x: types::floating, y: types::floating) bool = {
};
};
-@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));
-};
-
// e - https://oeis.org/A001113
export def E: f64 = 2.71828182845904523536028747135266249775724709369995957496696763;
// pi - https://oeis.org/A000796
@@ -231,33 +222,11 @@ export fn logf64(x: f64) f64 = {
return k * LN2_HI - ((hfsq - (s * (hfsq + R) + k * LN2_LO)) - f);
};
-@test fn logf64() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- assert(isclose(
- logf64(absf64(TEST_INPUTS[idx])),
- TEST_LOG[idx]));
- };
- assert(logf64(E) == 1f64);
- assert(logf64(54.598150033144239078110261202860878402790f64) == 4f64);
- assert(isnan(logf64(-1f64)));
- assert(logf64(INF) == INF);
- assert(logf64(0f64) == -INF);
- assert(isnan(logf64(NAN)));
-};
-
// Returns the decimal logarithm of x.
export fn log10f64(x: f64) f64 = {
return logf64(x) * (1f64 / LN_10);
};
-@test fn log10f64() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- assert(isclose(
- log10f64(absf64(TEST_INPUTS[idx])),
- TEST_LOG10[idx]));
- };
-};
-
// Returns the binary logarithm of x.
export fn log2f64(x: f64) f64 = {
const frexp_res = frexpf64(x);
@@ -271,14 +240,6 @@ export fn log2f64(x: f64) f64 = {
return logf64(frac) * (1f64 / LN_2) + (exp: f64);
};
-@test fn log2f64() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- assert(isclose(
- log2f64(absf64(TEST_INPUTS[idx])),
- TEST_LOG2[idx]));
- };
-};
-
// double log1p(double x)
//
// Method :
@@ -456,21 +417,6 @@ export fn log1pf64(x: f64) f64 = {
((hfsq - (s * (hfsq + R) + ((k: f64) * LN2LO + c))) - f);
};
-@test fn log1p() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- log1pf64(TEST_INPUTS[idx] / 100f64),
- TEST_LOG1P[idx]));
- };
- assert(isnan(log1pf64(-INF)));
- assert(isnan(log1pf64(-PI)));
- assert(log1pf64(-1f64) == -INF);
- assert(log1pf64(-0f64) == -0f64);
- assert(log1pf64(0f64) == 0f64);
- assert(log1pf64(INF) == INF);
- assert(isnan(log1pf64(NAN)));
-};
-
// exp(x)
// Returns the exponential of x.
//
@@ -611,34 +557,6 @@ export fn exp2f64(x: f64) f64 = {
return expmultif64(hi, lo, k);
};
-@test fn expf64() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- assert(isclose(expf64(TEST_INPUTS[idx]), TEST_EXP[idx]));
- };
- assert(expf64(1f64) == E);
- assert(isnan(expf64(NAN)));
- assert(isinf(expf64(INF)));
- assert(expf64(-INF) == 0f64);
- assert(isinf(expf64(99999f64)));
- assert(expf64(-99999f64) == 0f64);
- assert(expf64(0.5e-20) == 1f64);
-};
-
-@test fn exp2f64() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- assert(isclose(exp2f64(TEST_INPUTS[idx]), TEST_EXP2[idx]));
- };
- assert(exp2f64(0f64) == 1f64);
- assert(exp2f64(3f64) == 8f64);
- assert(exp2f64(-2f64) == 0.25f64);
- assert(!isinf(exp2f64(256f64)));
- assert(isinf(exp2f64(99999f64)));
- assert(exp2f64(-99999f64) == 0f64);
- assert(isnan(exp2f64(NAN)));
- assert(isinf(exp2f64(INF)));
- assert(exp2f64(-INF) == 0f64);
-};
-
// __ieee754_sqrt(x)
// Return correctly rounded sqrt.
// -----------------------------------------
@@ -761,23 +679,6 @@ export fn sqrtf64(x: f64) f64 = {
return f64frombits(bits);
};
-@test fn sqrt() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- assert(isclose(
- sqrtf64(absf64(TEST_INPUTS[idx])),
- TEST_SQRT[idx]));
- };
- assert(sqrtf64(2f64) == SQRT_2);
- assert(sqrtf64(4f64) == 2f64);
- assert(sqrtf64(16f64) == 4f64);
- assert(sqrtf64(65536f64) == 256f64);
- assert(sqrtf64(powf64(123f64, 2f64)) == 123f64);
- assert(sqrtf64(0f64) == 0f64);
- assert(isnan(sqrtf64(NAN)));
- assert(sqrtf64(INF) == INF);
- assert(isnan(sqrtf64(-2f64)));
-};
-
fn is_f64_odd_int(x: f64) bool = {
const x_int_frac = modfracf64(x);
const x_int = x_int_frac.0;
@@ -887,98 +788,6 @@ export fn powf64(x: f64, p: f64) f64 = {
return ldexpf64(res_mantissa, res_exp);
};
-@test fn powf64() void = {
- for (let idx = 0z; idx < len(TEST_INPUTS); idx += 1) {
- assert(eqwithin(
- powf64(10f64, TEST_INPUTS[idx]),
- TEST_POW[idx],
- 1e-8f64));
- };
- // Positive integer
- assert(powf64(2f64, 2f64) == 4f64);
- assert(powf64(3f64, 3f64) == 27f64);
- // Very large positive integer
- assert(!isinf(powf64(2f64, 1020f64)));
- assert(isinf(powf64(2f64, 1050f64)));
- // Negative integer
- assert(powf64(2f64, -1f64) == 0.5f64);
- assert(powf64(2f64, -2f64) == 0.25f64);
- // Very small negative integer
- assert(powf64(2f64, -1020f64) > 0f64);
- assert(powf64(2f64, -1080f64) == 0f64);
- // Positive fractional powers
- assert(eqwithin(powf64(2f64, 1.5f64),
- 2.8284271247461900976033774f64,
- 1e-10f64));
- assert(eqwithin(powf64(2f64, 5.5f64),
- 45.254833995939041561654039f64,
- 1e-10f64));
- // Negative fractional powers
- assert(eqwithin(powf64(2f64, -1.5f64),
- 0.3535533905932737622004221f64,
- 1e-10f64));
- assert(eqwithin(powf64(2f64, -5.5f64),
- 0.0220970869120796101375263f64,
- 1e-10f64));
-
- // Special cases
- // pow(x, ±0) = 1 for any x
- assert(powf64(123f64, 0f64) == 1f64);
- // pow(1, y) = 1 for any y
- assert(powf64(1f64, 123f64) == 1f64);
- // pow(x, 1) = x for any x
- assert(powf64(123f64, 1f64) == 123f64);
- // pow(NaN, y) = NaN
- assert(isnan(powf64(NAN, 123f64)));
- // pow(x, NaN) = NaN
- assert(isnan(powf64(123f64, NAN)));
- // pow(±0, y) = ±Inf for y an odd integer < 0
- assert(powf64(0f64, -3f64) == INF);
- assert(powf64(-0f64, -3f64) == -INF);
- // pow(±0, -Inf) = +Inf
- assert(powf64(0f64, -INF) == INF);
- assert(powf64(-0f64, -INF) == INF);
- // pow(±0, +Inf) = +0
- assert(powf64(0f64, INF) == 0f64);
- assert(powf64(-0f64, INF) == 0f64);
- // pow(±0, y) = +Inf for finite y < 0 and not an odd integer
- assert(powf64(0f64, -2f64) == INF);
- assert(powf64(0f64, -2f64) == INF);
- //pow(±0, y) = ±0 for y an odd integer > 0
- assert(powf64(0f64, 123f64) == 0f64);
- const neg_zero = powf64(-0f64, 123f64);
- assert(neg_zero == 0f64);
- assert(isnegative(neg_zero));
- // pow(±0, y) = +0 for finite y > 0 and not an odd integer
- assert(powf64(0f64, 8f64) == 0f64);
- // pow(-1, ±Inf) = 1
- assert(powf64(-1f64, INF) == 1f64);
- assert(powf64(-1f64, -INF) == 1f64);
- // pow(x, +Inf) = +Inf for |x| > 1
- assert(powf64(123f64, INF) == INF);
- // pow(x, -Inf) = +0 for |x| > 1
- assert(powf64(123f64, -INF) == 0f64);
- // pow(x, +Inf) = +0 for |x| < 1
- assert(powf64(0.5f64, INF) == 0f64);
- assert(powf64(-0.5f64, INF) == 0f64);
- // pow(x, -Inf) = +Inf for |x| < 1
- assert(powf64(0.5f64, -INF) == INF);
- assert(powf64(-0.5f64, -INF) == INF);
- // pow(+Inf, y) = +Inf for y > 0
- assert(powf64(INF, 123f64) == INF);
- // pow(+Inf, y) = +0 for y < 0
- assert(powf64(INF, -1f64) == 0f64);
- // pow(-Inf, y) = pow(-0, -y)
- assert(powf64(-INF, 123f64) == powf64(-0f64, -123f64));
- // pow(x, y) = NaN for finite x < 0 and finite non-integer y
- assert(isnan(powf64(-2f64, 1.23f64)));
- // sqrt
- assert(powf64(4f64, 0.5f64) == sqrtf64(4f64));
- assert(powf64(4f64, 0.5f64) == 2f64);
- assert(powf64(4f64, -0.5f64) == (1f64 / sqrtf64(4f64)));
- assert(powf64(4f64, -0.5f64) == (1f64 / 2f64));
-};
-
// Returns the greatest integer value less than or equal to x.
export fn floorf64(x: f64) f64 = {
if (x == 0f64 || isnan(x) || isinf(x)) {
@@ -997,35 +806,9 @@ export fn floorf64(x: f64) f64 = {
return (modfrac_res.0: f64);
};
-@test fn floor() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- floorf64(TEST_INPUTS[idx]),
- TEST_FLOOR[idx]));
- };
- assert(floorf64(-INF) == -INF);
- assert(floorf64(-0f64) == -0f64);
- assert(floorf64(0f64) == 0f64);
- assert(floorf64(INF) == INF);
- assert(isnan(floorf64(NAN)));
-};
-
// Returns the least integer value greater than or equal to x.
export fn ceilf64(x: f64) f64 = -floorf64(-x);
-@test fn ceil() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- ceilf64(TEST_INPUTS[idx]),
- TEST_CEIL[idx]));
- };
- assert(ceilf64(-INF) == -INF);
- assert(ceilf64(-0f64) == -0f64);
- assert(ceilf64(0f64) == 0f64);
- assert(ceilf64(INF) == INF);
- assert(isnan(ceilf64(NAN)));
-};
-
// Returns the integer value of x.
export fn truncf64(x: f64) f64 = {
if (x == 0f64 || isnan(x) || isinf(x)) {
@@ -1035,19 +818,6 @@ export fn truncf64(x: f64) f64 = {
return (modfrac_res.0: f64);
};
-@test fn trunc() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- truncf64(TEST_INPUTS[idx]),
- TEST_TRUNC[idx]));
- };
- assert(truncf64(-INF) == -INF);
- assert(truncf64(-0f64) == -0f64);
- assert(truncf64(0f64) == 0f64);
- assert(truncf64(INF) == INF);
- assert(isnan(truncf64(NAN)));
-};
-
// Returns the nearest integer, rounding half away from zero.
export fn roundf64(x: f64) f64 = {
let bits = f64bits(x);
@@ -1071,19 +841,6 @@ export fn roundf64(x: f64) f64 = {
return f64frombits(bits);
};
-@test fn round() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- roundf64(TEST_INPUTS[idx]),
- TEST_ROUND[idx]));
- };
- assert(roundf64(-INF) == -INF);
- assert(roundf64(-0f64) == -0f64);
- assert(roundf64(0f64) == 0f64);
- assert(roundf64(INF) == INF);
- assert(isnan(roundf64(NAN)));
-};
-
// Returns the floating-point remainder of x / y. The magnitude of the result
// is less than y and its sign agrees with that of x.
export fn modf64(x: f64, y: f64) f64 = {
@@ -1118,48 +875,3 @@ export fn modf64(x: f64, y: f64) f64 = {
};
return r;
};
-
-@test fn modf64() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- modf64(10f64, TEST_INPUTS[idx]),
- TEST_MODF[idx]));
- };
-
- assert(isnan(modf64(-INF, -INF)));
- assert(isnan(modf64(-INF, -PI)));
- assert(isnan(modf64(-INF, 0f64)));
- assert(isnan(modf64(-INF, PI)));
- assert(isnan(modf64(-INF, INF)));
- assert(isnan(modf64(-INF, NAN)));
- assert(modf64(-PI, -INF) == -PI);
- assert(isnan(modf64(-PI, 0f64)));
- assert(modf64(-PI, INF) == -PI);
- assert(isnan(modf64(-PI, NAN)));
- assert(modf64(-0f64, -INF) == -0f64);
- assert(isnan(modf64(-0f64, 0f64)));
- assert(modf64(-0f64, INF) == -0f64);
- assert(isnan(modf64(-0f64, NAN)));
- assert(modf64(0f64, -INF) == 0f64);
- assert(isnan(modf64(0f64, 0f64)));
- assert(modf64(0f64, INF) == 0f64);
- assert(isnan(modf64(0f64, NAN)));
- assert(modf64(PI, -INF) == PI);
- assert(isnan(modf64(PI, 0f64)));
- assert(modf64(PI, INF) == PI);
- assert(isnan(modf64(PI, NAN)));
- assert(isnan(modf64(INF, -INF)));
- assert(isnan(modf64(INF, -PI)));
- assert(isnan(modf64(INF, 0f64)));
- assert(isnan(modf64(INF, PI)));
- assert(isnan(modf64(INF, INF)));
- assert(isnan(modf64(INF, NAN)));
- assert(isnan(modf64(NAN, -INF)));
- assert(isnan(modf64(NAN, -PI)));
- assert(isnan(modf64(NAN, 0f64)));
- assert(isnan(modf64(NAN, PI)));
- assert(isnan(modf64(NAN, INF)));
- assert(isnan(modf64(NAN, NAN)));
- assert(modf64(5.9790119248836734e+200, 1.1258465975523544) ==
- 0.6447968302508578);
-};
diff --git a/math/trig.ha b/math/trig.ha
@@ -201,18 +201,6 @@ fn trig_reduce(x: f64) (u64, f64) = {
return (j, z * PI4);
};
-@test fn trig_reduce() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- const reduced = trig_reduce(TEST_INPUTS[idx]);
- const j = reduced.0;
- const z = reduced.1;
- const xred = (j: i64: f64) * (PI / 4f64) + z;
- assert(isclose(
- sinf64(TEST_INPUTS[idx]),
- sinf64(xred)));
- };
-};
-
// cos.c
//
// Circular cosine
@@ -305,16 +293,6 @@ export fn cosf64(x: f64) f64 = {
return y;
};
-@test fn cos() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- cosf64(TEST_INPUTS[idx]), TEST_COS[idx]));
- };
- assert(isnan(cosf64(-INF)));
- assert(isnan(cosf64(INF)));
- assert(isnan(cosf64(NAN)));
-};
-
// sin.c
//
// Circular sine
@@ -416,18 +394,6 @@ export fn sinf64(x: f64) f64 = {
return y;
};
-@test fn sin() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- sinf64(TEST_INPUTS[idx]), TEST_SIN[idx]));
- };
- assert(isnan(sinf64(-INF)));
- assert(sinf64(-0f64) == -0f64);
- assert(sinf64(0f64) == 0f64);
- assert(isnan(sinf64(INF)));
- assert(isnan(sinf64(NAN)));
-};
-
// tan.c
//
// Circular tangent
@@ -527,18 +493,6 @@ export fn tanf64(x: f64) f64 = {
return y;
};
-@test fn tan() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- tanf64(TEST_INPUTS[idx]), TEST_TAN[idx]));
- };
- assert(isnan(sinf64(-INF)));
- assert(sinf64(-0f64) == -0f64);
- assert(sinf64(0f64) == 0f64);
- assert(isnan(sinf64(INF)));
- assert(isnan(sinf64(NAN)));
-};
-
// Evaluates a series valid in the range [0, 0.66].
fn xatan(x: f64) f64 = {
const P0 = -8.750608600031904122785e-01;
@@ -602,36 +556,11 @@ export fn asinf64(x: f64) f64 = {
return temp;
};
-@test fn asin() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- asinf64(TEST_INPUTS[idx] / 10f64),
- TEST_ASIN[idx]));
- };
- assert(isnan(asinf64(-PI)));
- assert(asinf64(-0f64) == -0f64);
- assert(asinf64(0f64) == 0f64);
- assert(isnan(asinf64(PI)));
- assert(isnan(asinf64(NAN)));
-};
-
// Returns the arccosine, in radians, of x.
export fn acosf64(x: f64) f64 = {
return PI / 2f64 - asinf64(x);
};
-@test fn acos() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- acosf64(TEST_INPUTS[idx] / 10f64),
- TEST_ACOS[idx]));
- };
- assert(isnan(acosf64(-PI)));
- assert(acosf64(1f64) == 0f64);
- assert(isnan(acosf64(PI)));
- assert(isnan(acosf64(NAN)));
-};
-
// atan.c
// Inverse circular tangent (arctangent)
//
@@ -663,19 +592,6 @@ export fn atanf64(x: f64) f64 = {
return -satan(-x);
};
-@test fn atan() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- atanf64(TEST_INPUTS[idx]),
- TEST_ATAN[idx]));
- };
- assert(atanf64(-INF) == -PI / 2f64);
- assert(atanf64(-0f64) == -0f64);
- assert(atanf64(0f64) == 0f64);
- assert(atanf64(INF) == PI / 2f64);
- assert(isnan(atanf64(NAN)));
-};
-
// Floating-point hyperbolic sine and cosine.
// The exponential func is called for arguments greater in magnitude than 0.5.
// A series is used for arguments smaller in magnitude than 0.5.
@@ -717,20 +633,6 @@ export fn sinhf64(x: f64) f64 = {
return temp;
};
-@test fn sinh() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(eqwithin(
- sinhf64(TEST_INPUTS[idx]),
- TEST_SINH[idx],
- 1e-6f64));
- };
- assert(sinhf64(-INF) == -INF);
- assert(sinhf64(-0f64) == -0f64);
- assert(sinhf64(0f64) == 0f64);
- assert(sinhf64(INF) == INF);
- assert(isnan(sinhf64(NAN)));
-};
-
// Returns the hyperbolic cosine of x.
export fn coshf64(x: f64) f64 = {
x = absf64(x);
@@ -741,19 +643,6 @@ export fn coshf64(x: f64) f64 = {
return (ex + 1f64 / ex) * 0.5f64;
};
-@test fn cosh() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- coshf64(TEST_INPUTS[idx]),
- TEST_COSH[idx]));
- };
- assert(coshf64(-INF) == INF);
- assert(coshf64(-0f64) == 1f64);
- assert(coshf64(0f64) == 1f64);
- assert(coshf64(INF) == INF);
- assert(isnan(coshf64(NAN)));
-};
-
// tanh.c
//
// Hyperbolic tangent
@@ -819,19 +708,6 @@ export fn tanhf64(x: f64) f64 = {
return z;
};
-@test fn tanh() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- tanhf64(TEST_INPUTS[idx]),
- TEST_TANH[idx]));
- };
- assert(tanhf64(-INF) == -1f64);
- assert(tanhf64(-0f64) == -0f64);
- assert(tanhf64(0f64) == 0f64);
- assert(tanhf64(INF) == 1f64);
- assert(isnan(tanhf64(NAN)));
-};
-
// asinh(x)
// Method :
// Based on
@@ -881,19 +757,6 @@ export fn asinhf64(x: f64) f64 = {
return temp;
};
-@test fn asinh() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- asinhf64(TEST_INPUTS[idx]),
- TEST_ASINH[idx]));
- };
- assert(asinhf64(-INF) == -INF);
- assert(asinhf64(-0f64) == -0f64);
- assert(asinhf64(0f64) == 0f64);
- assert(asinhf64(INF) == INF);
- assert(isnan(asinhf64(NAN)));
-};
-
// __ieee754_acosh(x)
// Method :
// Based on
@@ -929,19 +792,6 @@ export fn acoshf64(x: f64) f64 = {
return log1pf64(t + sqrtf64(2f64 * t + t * t));
};
-@test fn acosh() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- acoshf64(1f64 + absf64(TEST_INPUTS[idx])),
- TEST_ACOSH[idx]));
- };
- assert(isnan(acoshf64(-INF)));
- assert(isnan(acoshf64(0.5f64)));
- assert(acoshf64(1f64) == 0f64);
- assert(acoshf64(INF) == INF);
- assert(isnan(acoshf64(NAN)));
-};
-
// __ieee754_atanh(x)
// Method :
// 1. Reduce x to positive by atanh(-x) = -atanh(x)
@@ -996,23 +846,6 @@ export fn atanhf64(x: f64) f64 = {
return temp;
};
-@test fn atanh() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- atanhf64(TEST_INPUTS[idx] / 10f64),
- TEST_ATANH[idx]));
- };
- assert(isnan(atanhf64(-INF)));
- assert(isnan(atanhf64(-PI)));
- assert(atanhf64(-1f64) == -INF);
- assert(atanhf64(-0f64) == -0f64);
- assert(atanhf64(0f64) == 0f64);
- assert(atanhf64(1f64) == INF);
- assert(isnan(atanhf64(PI)));
- assert(isnan(atanhf64(INF)));
- assert(isnan(atanhf64(NAN)));
-};
-
// Returns the arctangent, in radians, of y / x.
export fn atan2f64(y: f64, x: f64) f64 = {
if (isnan(y) || isnan(x)) {
@@ -1041,31 +874,6 @@ export fn atan2f64(y: f64, x: f64) f64 = {
return q;
};
-@test fn atan2() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- assert(isclose(
- atan2f64(10f64, TEST_INPUTS[idx]),
- TEST_ATAN2[idx]));
- };
- assert(isnan(atan2f64(-INF, NAN)));
- assert(atan2f64(-PI, INF) == -0f64);
- assert(isnan(atan2f64(-PI, NAN)));
- assert(atan2f64(-0f64, 0f64) == -0f64);
- assert(atan2f64(-0f64, PI) == -0f64);
- assert(atan2f64(-0f64, INF) == -0f64);
- assert(isnan(atan2f64(-0f64, NAN)));
- assert(atan2f64(0f64, 0f64) == 0f64);
- assert(atan2f64(0f64, PI) == 0f64);
- assert(atan2f64(0f64, INF) == 0f64);
- assert(isnan(atan2f64(0f64, NAN)));
- assert(atan2f64(PI, INF) == 0f64);
- assert(atan2f64(1f64, INF) == 0f64);
- assert(atan2f64(-1f64, INF) == -0f64);
- assert(isnan(atan2f64(PI, NAN)));
- assert(isnan(atan2f64(INF, NAN)));
- assert(isnan(atan2f64(NAN, NAN)));
-};
-
// Returns the square root of a*a + b*b, taking care to avoid unnecessary
// overflow and underflow.
export fn hypotf64(a: f64, b: f64) f64 = {
@@ -1088,31 +896,3 @@ export fn hypotf64(a: f64, b: f64) f64 = {
return a * sqrtf64(1f64 + b * b);
};
-@test fn hypot() void = {
- for (let idx = 0z; idx < 10; idx += 1) {
- const a = absf64(1e200f64 * TEST_TANH[idx] * SQRT_2);
- assert(isclose(
- hypotf64(1e200f64 * TEST_TANH[idx],
- 1e200f64 * TEST_TANH[idx]),
- a));
- };
- assert(hypotf64(-INF, -INF) == INF);
- assert(hypotf64(-INF, 0f64) == INF);
- assert(hypotf64(-INF, INF) == INF);
- assert(hypotf64(-INF, NAN) == INF);
- assert(hypotf64(-0f64, -0f64) == 0f64);
- assert(hypotf64(-0f64, 0f64) == 0f64);
- assert(hypotf64(0f64, -0f64) == 0f64);
- assert(hypotf64(0f64, 0f64) == 0f64);
- assert(hypotf64(0f64, -INF) == INF);
- assert(hypotf64(0f64, INF) == INF);
- assert(isnan(hypotf64(0f64, NAN)));
- assert(hypotf64(INF, -INF) == INF);
- assert(hypotf64(INF, 0f64) == INF);
- assert(hypotf64(INF, INF) == INF);
- assert(hypotf64(INF, NAN) == INF);
- assert(hypotf64(NAN, -INF) == INF);
- assert(isnan(hypotf64(NAN, 0f64)));
- assert(hypotf64(NAN, INF) == INF);
- assert(isnan(hypotf64(NAN, NAN)));
-};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -972,7 +972,11 @@ math() {
if [ $testing -eq 0 ]; then
gensrcs_math
else
- gensrcs_math data+test.ha
+ gensrcs_math \
+ +test/data.ha \
+ +test/math.ha \
+ +test/floats.ha \
+ +test/trig.ha
fi
gen_ssa math types rt
}
diff --git a/stdlib.mk b/stdlib.mk
@@ -3821,7 +3821,10 @@ testlib_math_any_srcs = \
$(STDLIB)/math/ints.ha \
$(STDLIB)/math/uints.ha \
$(STDLIB)/math/trig.ha \
- $(STDLIB)/math/data+test.ha
+ $(STDLIB)/math/+test/data.ha \
+ $(STDLIB)/math/+test/math.ha \
+ $(STDLIB)/math/+test/floats.ha \
+ $(STDLIB)/math/+test/trig.ha
$(TESTCACHE)/math/math-any.ssa: $(testlib_math_any_srcs) $(testlib_rt) $(testlib_types_$(PLATFORM)) $(testlib_rt_$(PLATFORM))
@printf 'HAREC \t$@\n'