skip to content
==> tests/numeric.c <==
1/* The numeric semantics: the spec's edge cases and wasmtime's canonical NaNs. */
2#include "mesh/check.h"
3#include "wasm/numeric.h"
4
5static uint32_t b32(float f) { return wasm_f32_bits(f); }
6static uint64_t b64(double d) { return wasm_f64_bits(d); }
7
8int main(void) {
9    float nanp = wasm_f32_from(0x7fa00001u), nann = wasm_f32_from(0xffc12345u);
10    /* Arithmetic NaNs are canonical, whatever the inputs' payloads. */
11    CHECK_U(b32(wasm_f32_add(nanp, 1.0f)), WASM_CANON_F32);
12    CHECK_U(b32(wasm_f32_mul(nann, nanp)), WASM_CANON_F32);
13    CHECK_U(b32(wasm_f32_sub(INFINITY, INFINITY)), WASM_CANON_F32);
14    CHECK_U(b32(wasm_f32_sqrt(-1.0f)), WASM_CANON_F32);
15    CHECK_U(b32(wasm_f32_min(nann, 1.0f)), WASM_CANON_F32);
16    CHECK_U(b32(wasm_f32_demote(wasm_f64_from(0xfff0000000000001ull))), WASM_CANON_F32);
17    CHECK_U(b64(wasm_f64_promote(nann)), WASM_CANON_F64);
18    CHECK_U(b64(wasm_f64_div(0.0, 0.0)), WASM_CANON_F64);
19    /* Bit operations keep payloads. */
20    CHECK_U(wasm_f32_neg(0x7fa00001u), 0xffa00001u);
21    CHECK_U(wasm_f32_abs(0xffc12345u), 0x7fc12345u);
22    CHECK_U(wasm_f32_copysign(0x7fa00001u, 0x80000000u), 0xffa00001u);
23    /* min/max of zeros, and ordinary values. */
24    CHECK_U(b32(wasm_f32_min(0.0f, -0.0f)), 0x80000000u);
25    CHECK_U(b32(wasm_f32_max(-0.0f, 0.0f)), 0x00000000u);
26    CHECK_U(b64(wasm_f64_min(-0.0, 0.0)), 0x8000000000000000ull);
27    CHECK(wasm_f32_min(1.0f, 2.0f) == 1.0f);
28    CHECK(wasm_f64_max(1.0, 2.0) == 2.0);
29    /* nearest is ties-to-even; trunc, ceil, floor; -0 survives. */
30    CHECK(wasm_f32_nearest(2.5f) == 2.0f);
31    CHECK(wasm_f32_nearest(3.5f) == 4.0f);
32    CHECK_U(b32(wasm_f32_nearest(-0.5f)), 0x80000000u);
33    CHECK(wasm_f64_nearest(-2.5) == -2.0);
34    CHECK_U(b32(wasm_f32_ceil(-0.5f)), 0x80000000u);
35    CHECK(wasm_f64_floor(-0.5) == -1.0);
36    CHECK(wasm_f32_trunc(-1.7f) == -1.0f);
37    /* Integer division and remainder traps. */
38    uint32_t r;
39    uint64_t q;
40    CHECK_I(wasm_i32_div_s(1, 0, &r), WASM_TRAP_INTEGER_DIVISION_BY_ZERO);
41    CHECK_I(wasm_i32_div_s(0x80000000u, 0xffffffffu, &r), WASM_TRAP_INTEGER_OVERFLOW);
42    CHECK_I(wasm_i32_rem_s(0x80000000u, 0xffffffffu, &r), WASM_NUM_OK);
43    CHECK_U(r, 0);
44    CHECK_I(wasm_i32_div_s((uint32_t)-7, 2, &r), WASM_NUM_OK);
45    CHECK_U(r, (uint32_t)-3);
46    CHECK_I(wasm_i32_rem_s((uint32_t)-7, 2, &r), WASM_NUM_OK);
47    CHECK_U(r, (uint32_t)-1);
48    CHECK_I(wasm_i64_div_s(0x8000000000000000ull, ~0ull, &q), WASM_TRAP_INTEGER_OVERFLOW);
49    CHECK_I(wasm_i64_rem_u(5, 0, &q), WASM_TRAP_INTEGER_DIVISION_BY_ZERO);
50    /* Bits. */
51    CHECK_U(wasm_i32_clz(0), 32);
52    CHECK_U(wasm_i32_ctz(0x80000000u), 31);
53    CHECK_U(wasm_i64_popcnt(~0ull), 64);
54    CHECK_U(wasm_i32_rotl(0x80000001u, 1), 3);
55    CHECK_U(wasm_i32_rotr(1, 33), 0x80000000u);
56    CHECK_U(wasm_i64_rotl(1, 64), 1);
57    CHECK_U(wasm_i32_shr_s(0x80000000u, 31), 0xffffffffu);
58    CHECK_U(wasm_i64_shr_s(0x8000000000000000ull, 64 + 4), 0xf800000000000000ull);
59    /* Trapping truncation: NaN, the exact bounds. */
60    CHECK_I(wasm_i32_trunc_f32_s(nanp, &r), WASM_TRAP_BAD_CONVERSION_TO_INTEGER);
61    CHECK_I(wasm_i32_trunc_f32_s(2147483648.0f, &r), WASM_TRAP_INTEGER_OVERFLOW);
62    CHECK_I(wasm_i32_trunc_f32_s(-2147483648.0f, &r), WASM_NUM_OK);
63    CHECK_U(r, 0x80000000u);
64    CHECK_I(wasm_i32_trunc_f64_s(-2147483648.9, &r), WASM_NUM_OK);
65    CHECK_U(r, 0x80000000u);
66    CHECK_I(wasm_i32_trunc_f64_s(-2147483649.0, &r), WASM_TRAP_INTEGER_OVERFLOW);
67    CHECK_I(wasm_i32_trunc_f32_u(-0.9f, &r), WASM_NUM_OK);
68    CHECK_U(r, 0);
69    CHECK_I(wasm_i32_trunc_f32_u(-1.0f, &r), WASM_TRAP_INTEGER_OVERFLOW);
70    CHECK_I(wasm_i32_trunc_f64_u(4294967295.9, &r), WASM_NUM_OK);
71    CHECK_U(r, 0xffffffffu);
72    CHECK_I(wasm_i64_trunc_f64_u(18446744073709551616.0, &q), WASM_TRAP_INTEGER_OVERFLOW);
73    CHECK_I(wasm_i64_trunc_f32_s(-9223372036854775808.0f, &q), WASM_NUM_OK);
74    CHECK_U(q, 0x8000000000000000ull);
75    /* Saturating truncation. */
76    CHECK_U(wasm_i32_trunc_sat_f32_s(nanp), 0);
77    CHECK_U(wasm_i32_trunc_sat_f32_s(3e9f), 0x7fffffffu);
78    CHECK_U(wasm_i32_trunc_sat_f32_s(-3e9f), 0x80000000u);
79    CHECK_U(wasm_i32_trunc_sat_f64_u(-5.0), 0);
80    CHECK_U(wasm_i32_trunc_sat_f64_u(1e10), 0xffffffffu);
81    CHECK_U(wasm_i64_trunc_sat_f64_s(1e19), 0x7fffffffffffffffull);
82    CHECK_U(wasm_i64_trunc_sat_f32_u(INFINITY), ~0ull);
83    CHECK_U(wasm_i64_trunc_sat_f64_u(123.9), 123);
84    CHECK_S(wasm_trap_message(WASM_TRAP_UNREACHABLE), "wasm `unreachable` instruction executed");
85    return mesh_check_done();
86}