DaisyChain-Train / web /test_nonfinite.js
Quazim0t0's picture
Refuse NaN/Inf at every int8 quantize; requant rounds half-up (retrained); bounded units; README for September
99509b7 verified
Raw History Blame Contribute Delete
1.55 kB
// A float -> int8 quantize has no answer for NaN/Inf. Before the guard, an Inf made the |max|
// scale Infinity and every value quantized to 0 ([0.5, Inf, 3] -> [0, 0, 0]), and a NaN was
// skipped by the |max| scan and then stored as 0 by the Int8Array -- training continued on
// zeros with no error. Every quantizer must now refuse, and finite inputs must be unchanged.
"use strict";
const V = require("./public/verified_core.js");
let fails = 0;
function ck(name, cond) { console.log((cond ? " ok " : " FAIL ") + name); if (!cond) fails++; }
function throwsNonFinite(fn) { try { fn(); return false; } catch (e) { return e.name === "NonFiniteError"; } }
const bad = [Float32Array.from([0.5, Infinity, 3, -1]), Float32Array.from([0.5, NaN, 3, -1]),
Float32Array.from([-Infinity, 1, 2, 3])];
for (const X of bad) {
const tag = Array.from(X).join(",");
ck("quantize refuses [" + tag + "]", throwsNonFinite(() => V.quantize(X)));
ck("quantizeRows refuses [" + tag + "]", throwsNonFinite(() => V.quantizeRows(X, 2, 2)));
ck("quantizeCols refuses [" + tag + "]", throwsNonFinite(() => V.quantizeCols(X, 2, 2)));
ck("rowAbsMax refuses [" + tag + "]", throwsNonFinite(() => V.rowAbsMax(X, 2, 2)));
}
const q = V.quantize(Float32Array.from([0.5, -1, 3]));
ck("finite input quantizes as before: [21, -42, 127]", Array.from(q.q).join() === "21,-42,127");
if (fails) { console.log("NONFINITE TEST FAILED: " + fails); process.exit(1); }
console.log("NONFINITE TEST PASSED — every quantizer refuses NaN/Inf instead of zeroing.");