numeric-leaves vectors gain two float32 rows; float32 integer rounding drops its redundant guard

An odd kept value just past exact pins the tie rule (the Stryker survivor). The excess <= 0 guard was equivalent to the
general path for the only values that reach it, so it is deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-11 08:45:48 +02:00
commit 26ff9d27e9
3 changed files with 3 additions and 3 deletions

View file

@ -88,11 +88,11 @@ export const int32 = integerCodec("System.Int32", "an int32", -(2n ** 31n), 2n *
export const int64 = integerCodec("System.Int64", "an int64", -(2n ** 63n), 2n ** 63n - 1n);
// A 64-bit integer to the nearest float32 in one rounding, ties to even, as the reference's cast does. Number(value)
// first would round to a double and then again, and the two roundings can disagree.
// first would round to a double and then again, and the two roundings can disagree. A bigint reaches here only beyond
// 2^53 (the wire reader returns a number for any smaller integer), so at least 30 bits are rounded away.
function bigintToFloat32(value: bigint): number {
const magnitude = value < 0n ? -value : value;
const excess = magnitude.toString(2).length - 24;
if (excess <= 0) return Number(value);
const kept = magnitude >> BigInt(excess);
const rest = magnitude - (kept << BigInt(excess));
const half = 1n << BigInt(excess - 1);

View file

@ -548,7 +548,7 @@ const isNaNBits = (bitsHex: string) => {
test("numeric leaves read and refuse exactly what the C# reference does", async () => {
const rows = readWire(new Uint8Array(await readFile(join(numericVectors, "reads.msgpack")))) as [string, Uint8Array, boolean, Uint8Array][];
assert.equal(rows.length, 148);
assert.equal(rows.length, 156);
let accepted = 0;
let refused = 0;
for (const [leaf, payload, wasAccepted, bits] of rows) {