==> 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}