test(v4.0.0): execute the in-line constants Q.1, Q.0 and Q.SCALE
DECOMPOSITION.md 5.26 gives them fate IN: the compiler places two literals, low cell first. Q.1 and Q.SCALE are `65536 0`, Q.0 is `0 0`; v3's are 65536, 0 and 65536. Each expansion is assembled and run, and checked against v3's value; then in use: Q.1 Q.TO-INT is 1, 1 Q.FROM-INT is Q.1, and q Q.1 Q.* and q Q.0 Q.+ return q for 2000 pseudo-random q plus 0, Q max and Q min. At 32- and 64-bit cells, optimised and ASan+UBSan (`make test`, `make sanitize`). A wrong value in any of the three fails. Test results on the amd64 host only. This is a development check, not acceptance (JUSTIFICATION.md section 16). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8235078b3b
commit
13ec4b1b6c
@@ -34,7 +34,8 @@
|
||||
* for 0 with NODE-ERROR at or below zero.
|
||||
* (Q.REDUCE), Q.SIN and Q.COS are checked bit for bit against v3's
|
||||
* q48_reduce_angle, q48_sin_approx and q48_cos_approx on angles of every
|
||||
* size and sign. Every word is
|
||||
* size and sign. The in-line constants Q.1, Q.0 and Q.SCALE are checked
|
||||
* against v3's values and in use. Every word is
|
||||
* also probed for how much of the 10- and 9-deep circular stacks (D-2) it
|
||||
* leaves to its caller.
|
||||
*
|
||||
@@ -79,7 +80,8 @@ static v4_cell w_nip, w_swap, w_or, w_negate, w_rot, w_zless, w_zequal,
|
||||
w_slashmod, w_mplus, w_dminus, w_d0equal, w_dequal,
|
||||
w_qfromint, w_qtoint, w_less, w_equal, w_dless, w_2swap, w_2over,
|
||||
w_dmax, w_dmin, w_qgt_doc, w_qgt, w_dltkeep, w_qstar, w_d2starc, w_uqdiv, w_qslash, w_qexp, w_qsqrt, w_qlog,
|
||||
w_qreduce, w_qsin, l_trig, w_qcos;
|
||||
w_qreduce, w_qsin, l_trig, w_qcos,
|
||||
w_q1, w_q0, w_qscale, w_q1_times, w_q0_plus, w_q1_toint, w_one_fromint;
|
||||
|
||||
#define O(name) v4_asm_op(&as, V4_OP_##name)
|
||||
#define LIT(v) v4_asm_lit(&as, (v4_cell)(v))
|
||||
@@ -1301,6 +1303,28 @@ static void build(void)
|
||||
#undef HERE_
|
||||
#undef FWD
|
||||
|
||||
/* Q.1, Q.0, Q.SCALE 5.26, fate IN
|
||||
* In-line double-cell constants: the compiler places two literals, low
|
||||
* cell first. Q.1 and Q.SCALE are `65536 0` (1.0), Q.0 is `0 0`; v3's
|
||||
* are 65536, 0 and 65536. Each expansion is assembled here followed by
|
||||
* `;` so that it can be run, and then in the middle of a definition, as
|
||||
* it would be used:
|
||||
* Q.1 Q.* ( q -- q ) Q.0 Q.+ ( q -- q )
|
||||
* Q.1 Q.TO-INT ( -- 1 ) 1 Q.FROM-INT ( -- q ), which must be Q.1 */
|
||||
#define Q_ONE() do { LIT(65536); LIT(0); } while (0)
|
||||
#define Q_ZERO() do { LIT(0); LIT(0); } while (0)
|
||||
#define Q_SCALE() do { LIT(65536); LIT(0); } while (0)
|
||||
w_q1 = v4_asm_label(&as); Q_ONE(); O(SEMI);
|
||||
w_q0 = v4_asm_label(&as); Q_ZERO(); O(SEMI);
|
||||
w_qscale = v4_asm_label(&as); Q_SCALE(); O(SEMI);
|
||||
w_q1_times = v4_asm_label(&as); Q_ONE(); CALL(w_qstar); O(SEMI);
|
||||
w_q0_plus = v4_asm_label(&as); Q_ZERO(); CALL(w_dplus); O(SEMI);
|
||||
w_q1_toint = v4_asm_label(&as); Q_ONE(); CALL(w_qtoint); O(SEMI);
|
||||
w_one_fromint = v4_asm_label(&as); LIT(1); CALL(w_qfromint); O(SEMI);
|
||||
#undef Q_SCALE
|
||||
#undef Q_ZERO
|
||||
#undef Q_ONE
|
||||
|
||||
CHECK(v4_asm_ok(&as), "foundation words assemble");
|
||||
}
|
||||
|
||||
@@ -2540,6 +2564,31 @@ int main(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Q.1, Q.0 and Q.SCALE: v3's values, and how they behave in use. */
|
||||
{
|
||||
v4_cell ol, oh, zl, zh;
|
||||
uint64_t x = 0x8EBC6AF09C88C6E3u;
|
||||
qcells(65536u, &ol, &oh); /* v3 Q.1 and Q.SCALE */
|
||||
qcells(0u, &zl, &zh); /* v3 Q.0 */
|
||||
CHECK(call(w_q1, 0, 0, 0, 0) && left2(ol, oh), "Q.1 is v3's 65536");
|
||||
CHECK(call(w_q0, 0, 0, 0, 0) && left2(zl, zh), "Q.0 is v3's 0");
|
||||
CHECK(call(w_qscale, 0, 0, 0, 0) && left2(ol, oh), "Q.SCALE is v3's 65536");
|
||||
CHECK(call(w_q1_toint, 0, 0, 0, 0) && left1(1), "Q.1 Q.TO-INT is 1");
|
||||
CHECK(call(w_one_fromint, 0, 0, 0, 0) && left2(ol, oh), "1 Q.FROM-INT is Q.1");
|
||||
for (unsigned i = 0; i < 2000; i++) {
|
||||
uint64_t q;
|
||||
v4_cell ql, qh;
|
||||
x ^= x << 13; x ^= x >> 7; x ^= x << 17;
|
||||
q = asr64(x, (unsigned)(x & 63u));
|
||||
if (i == 0) q = 0;
|
||||
if (i == 1) q = ((uint64_t)1 << 63) - 1u;
|
||||
if (i == 2) q = (uint64_t)1 << 63;
|
||||
qcells(q, &ql, &qh);
|
||||
CHECK(call(w_q1_times, 2, ql, qh, 0) && left2(ql, qh), "q Q.1 Q.* is q [%u]", i);
|
||||
CHECK(call(w_q0_plus, 2, ql, qh, 0) && left2(ql, qh), "q Q.0 Q.+ is q [%u]", i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Q./ at the overflow boundary: |a| * 2^16 against |b| * 2^(2N-1), for
|
||||
* divisors around 2^16 and 2^17, every sign. */
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user