in src/webgpu/util/compare.ts [94:165]
function compareValue(got: Value, expected: Value): Comparison {
{
// Check types
const gTy = got.type;
const eTy = expected.type;
const bothFloatTypes = isFloatValue(got) && isFloatValue(expected);
if (gTy !== eTy && !bothFloatTypes) {
return {
matched: false,
got: `${Colors.red(gTy.toString())}(${got})`,
expected: `${Colors.red(eTy.toString())}(${expected})`,
};
}
}
if (isScalarValue(got)) {
const g = got;
const e = expected as ScalarValue;
const isFloat = g.type.kind === 'f64' || g.type.kind === 'f32' || g.type.kind === 'f16';
const matched =
(isFloat && (g.value as number) === (e.value as number)) || (!isFloat && g.value === e.value);
return {
matched,
got: g.toString(),
expected: matched ? Colors.green(e.toString()) : Colors.red(e.toString()),
};
}
if (got instanceof VectorValue || got instanceof ArrayValue) {
const e = expected as VectorValue | ArrayValue;
const gLen = got.elements.length;
const eLen = e.elements.length;
let matched = gLen === eLen;
if (matched) {
// Iterating and calling compare instead of just using objectEquals to use the FP specific logic from above
matched = got.elements.every((_, i) => {
return compare(got.elements[i], e.elements[i]).matched;
});
}
return {
matched,
got: `${got.toString()}`,
expected: matched ? Colors.green(e.toString()) : Colors.red(e.toString()),
};
}
if (got instanceof MatrixValue) {
const e = expected as MatrixValue;
const gCols = got.type.cols;
const eCols = e.type.cols;
const gRows = got.type.rows;
const eRows = e.type.rows;
let matched = gCols === eCols && gRows === eRows;
if (matched) {
// Iterating and calling compare instead of just using objectEquals to use the FP specific logic from above
matched = got.elements.every((c, i) => {
return c.every((_, j) => {
return compare(got.elements[i][j], e.elements[i][j]).matched;
});
});
}
return {
matched,
got: `${got.toString()}`,
expected: matched ? Colors.green(e.toString()) : Colors.red(e.toString()),
};
}
throw new Error(`unhandled type '${typeof got}'`);
}