Source code

Revision control

Copy as Markdown

Other Tools

with ({}); // Don't inline anything into the top-level script.
const numbers = [
-Infinity, -10, -5, -2, -1, -0.5, 0, 0.5, 1, 2, 5, 10, Infinity, NaN,
];
// Test all supported types (Int32, Float32, Float64).
const converters = [
x => `${x}`,
x => `(${x}|0)`,
x => `Math.fround(${x})`,
x => `numberToDouble(${x})`,
];
// Fold min(x, min(x, y)) to min(x, y).
for (let cvt of converters) {
let x = cvt("x");
let y = cvt("y");
let c = Function("a", `return ${cvt("a")}`);
let min1 = Function("x, y", `return Math.min(${x}, Math.min(${x}, ${y}))`);
let min2 = Function("x, y", `return Math.min(${y}, Math.min(${x}, ${y}))`);
let min3 = Function("x, y", `return Math.min(Math.min(${x}, ${y}), ${x})`);
let min4 = Function("x, y", `return Math.min(Math.min(${x}, ${y}), ${y})`);
for (let i = 0; i < 20; ++i) {
for (let j = 0; j < numbers.length; ++j) {
for (let k = 0; k < numbers.length; ++k) {
let x = numbers[j];
let y = numbers[k]
let r1 = min1(x, y);
let r2 = min2(x, y);
let r3 = min3(x, y);
let r4 = min4(x, y);
// Convert to the correct type before computing the expected results.
x = c(x);
y = c(y);
assertEq(r1, Math.min(x, Math.min(x, y)));
assertEq(r1, Math.min(x, y));
assertEq(r2, Math.min(y, Math.min(x, y)));
assertEq(r2, Math.min(x, y));
assertEq(r3, Math.min(Math.min(x, y), x));
assertEq(r3, Math.min(x, y));
assertEq(r4, Math.min(Math.min(x, y), y));
assertEq(r4, Math.min(x, y));
}
}
}
}
// Fold max(x, max(x, y)) to max(x, y).
for (let cvt of converters) {
let x = cvt("x");
let y = cvt("y");
let c = Function("a", `return ${cvt("a")}`);
let max1 = Function("x, y", `return Math.max(${x}, Math.max(${x}, ${y}))`);
let max2 = Function("x, y", `return Math.max(${y}, Math.max(${x}, ${y}))`);
let max3 = Function("x, y", `return Math.max(Math.max(${x}, ${y}), ${x})`);
let max4 = Function("x, y", `return Math.max(Math.max(${x}, ${y}), ${y})`);
for (let i = 0; i < 20; ++i) {
for (let j = 0; j < numbers.length; ++j) {
for (let k = 0; k < numbers.length; ++k) {
let x = numbers[j];
let y = numbers[k]
let r1 = max1(x, y);
let r2 = max2(x, y);
let r3 = max3(x, y);
let r4 = max4(x, y);
// Convert to the correct type before computing the expected results.
x = c(x);
y = c(y);
assertEq(r1, Math.max(x, Math.max(x, y)));
assertEq(r1, Math.max(x, y));
assertEq(r2, Math.max(y, Math.max(x, y)));
assertEq(r2, Math.max(x, y));
assertEq(r3, Math.max(Math.max(x, y), x));
assertEq(r3, Math.max(x, y));
assertEq(r4, Math.max(Math.max(x, y), y));
assertEq(r4, Math.max(x, y));
}
}
}
}
// Fold max(x, min(x, y)) = x.
for (let cvt of converters) {
let x = cvt("x");
let y = cvt("y");
let c = Function("a", `return ${cvt("a")}`);
let maxmin1 = Function("x, y", `return Math.max(${x}, Math.min(${x}, ${y}))`);
let maxmin2 = Function("x, y", `return Math.max(${y}, Math.min(${x}, ${y}))`);
let maxmin3 = Function("x, y", `return Math.max(Math.min(${x}, ${y}), ${x})`);
let maxmin4 = Function("x, y", `return Math.max(Math.min(${x}, ${y}), ${y})`);
for (let i = 0; i < 20; ++i) {
for (let j = 0; j < numbers.length; ++j) {
for (let k = 0; k < numbers.length; ++k) {
let x = numbers[j];
let y = numbers[k]
let r1 = maxmin1(x, y);
let r2 = maxmin2(x, y);
let r3 = maxmin3(x, y);
let r4 = maxmin4(x, y);
// Convert to the correct type before computing the expected results.
x = c(x);
y = c(y);
assertEq(r1, Math.max(x, Math.min(x, y)));
assertEq(r1, Number.isNaN(y) ? NaN : x);
assertEq(r2, Math.max(y, Math.min(x, y)));
assertEq(r2, Number.isNaN(x) ? NaN : y);
assertEq(r3, Math.max(Math.min(x, y), x));
assertEq(r3, Number.isNaN(y) ? NaN : x);
assertEq(r4, Math.max(Math.min(x, y), y));
assertEq(r4, Number.isNaN(x) ? NaN : y);
}
}
}
}
// Fold min(x, max(x, y)) = x.
for (let cvt of converters) {
let x = cvt("x");
let y = cvt("y");
let c = Function("a", `return ${cvt("a")}`);
let minmax1 = Function("x, y", `return Math.min(${x}, Math.max(${x}, ${y}))`);
let minmax2 = Function("x, y", `return Math.min(${y}, Math.max(${x}, ${y}))`);
let minmax3 = Function("x, y", `return Math.min(Math.max(${x}, ${y}), ${x})`);
let minmax4 = Function("x, y", `return Math.min(Math.max(${x}, ${y}), ${y})`);
for (let i = 0; i < 20; ++i) {
for (let j = 0; j < numbers.length; ++j) {
for (let k = 0; k < numbers.length; ++k) {
let x = numbers[j];
let y = numbers[k]
let r1 = minmax1(x, y);
let r2 = minmax2(x, y);
let r3 = minmax3(x, y);
let r4 = minmax4(x, y);
// Convert to the correct type before computing the expected results.
x = c(x);
y = c(y);
assertEq(r1, Math.min(x, Math.max(x, y)));
assertEq(r1, Number.isNaN(y) ? NaN : x);
assertEq(r2, Math.min(y, Math.max(x, y)));
assertEq(r2, Number.isNaN(x) ? NaN : y);
assertEq(r3, Math.min(Math.max(x, y), x));
assertEq(r3, Number.isNaN(y) ? NaN : x);
assertEq(r4, Math.min(Math.max(x, y), y));
assertEq(r4, Number.isNaN(x) ? NaN : y);
}
}
}
}