import assert from 'node:assert/strict'; import {conv2d, im2col, dot, outputSize, quantize, requantize} from './model.mjs'; const x = [[[1, 2, 3], [4, 5, 6], [7, 8, 9]]], w = [[[[1, 2], [3, 4]]]]; assert.deepEqual(conv2d(x, w), [[[37, 47], [67, 77]]]); assert.deepEqual(im2col(x, 2, 2).map(row => dot(row, [1, 2, 3, 4])), [37, 47, 67, 77]); assert.equal(conv2d(x, w, {pads:[1, 0, 0, 1]})[0][0][0], 11); assert.equal(conv2d(x, w, {dilation:2})[0][0][0], 64); assert.equal(outputSize(5, 3, 2, 1, 1, 1), 3); assert.equal(outputSize(5, 3, 2, 1, 1, 2), 2); assert.equal(quantize(0, 0.25, 128, 0, 255), 128); assert.equal(requantize(300, 1), 127); assert.equal(requantize(-300, 1), -128); const channels = [[[2]], [[3]]], groupWeights = [[[[4]]], [[[5]]]]; assert.deepEqual(conv2d(channels, groupWeights, {groups:2}), [[[8]], [[15]]]); assert.throws(() => conv2d(channels, groupWeights), /incompatible/); // Guard every arithmetic step: cancellation must not hide lost precision. const safe = Number.MAX_SAFE_INTEGER, pairWeights = [[[[1, 1]]]]; assert.throws(() => conv2d([[[2, -2]]], pairWeights, {bias:[safe]}), /partial sum/); assert.throws(() => conv2d([[[-2, 2]]], pairWeights, {bias:[-safe]}), /partial sum/); assert.throws(() => conv2d([[[safe + 1]]], [[[[1]]]]), /operands/); assert.throws(() => conv2d([[[0]]], [[[[safe + 1]]]]), /operands/); assert.throws(() => conv2d([[[-1]]], [[[[1]]]], {bias:[safe + 1]}), /bias/); assert.throws(() => conv2d([[[0.5]]], [[[[2]]]]), /operands/); assert.throws(() => conv2d([[[100000000]]], [[[[100000000]]]]), /product/); // Safe boundary arithmetic and zero output dimensions remain supported. assert.deepEqual(conv2d([[[2, -2]]], pairWeights, {bias:[safe - 2]}), [[[safe - 2]]]); assert.deepEqual(conv2d([[[1]]], [[[[1, 1], [1, 1]]]]), [[]]); assert.deepEqual(conv2d([[[1]]], pairWeights), [[[]]]); // The independent patch-dot path uses the same integer safety contract. assert.throws(() => dot([safe, 2, -2], [1, 1, 1]), /partial sum/); assert.throws(() => dot([safe + 1], [0]), /operands/); assert.throws(() => dot([100000000], [100000000]), /product/); assert.throws(() => dot([1], [1, 2]), /vectors/); assert.equal(dot([safe - 2, 2, -2], [1, 1, 1]), safe - 2); assert.equal(dot([], []), 0); console.log('corner-lab: 27 checks passed');