min-max-foldsTo-3.js (5516B)
1 with ({}); // Don't inline anything into the top-level script. 2 3 const numbers = [ 4 -Infinity, -10, -5, -2, -1, -0.5, 0, 0.5, 1, 2, 5, 10, Infinity, NaN, 5 ]; 6 7 // Test all supported types (Int32, Float32, Float64). 8 const converters = [ 9 x => `${x}`, 10 x => `(${x}|0)`, 11 x => `Math.fround(${x})`, 12 x => `numberToDouble(${x})`, 13 ]; 14 15 // Fold min(x, min(x, y)) to min(x, y). 16 for (let cvt of converters) { 17 let x = cvt("x"); 18 let y = cvt("y"); 19 let c = Function("a", `return ${cvt("a")}`); 20 21 let min1 = Function("x, y", `return Math.min(${x}, Math.min(${x}, ${y}))`); 22 let min2 = Function("x, y", `return Math.min(${y}, Math.min(${x}, ${y}))`); 23 let min3 = Function("x, y", `return Math.min(Math.min(${x}, ${y}), ${x})`); 24 let min4 = Function("x, y", `return Math.min(Math.min(${x}, ${y}), ${y})`); 25 26 for (let i = 0; i < 20; ++i) { 27 for (let j = 0; j < numbers.length; ++j) { 28 for (let k = 0; k < numbers.length; ++k) { 29 let x = numbers[j]; 30 let y = numbers[k] 31 let r1 = min1(x, y); 32 let r2 = min2(x, y); 33 let r3 = min3(x, y); 34 let r4 = min4(x, y); 35 36 // Convert to the correct type before computing the expected results. 37 x = c(x); 38 y = c(y); 39 40 assertEq(r1, Math.min(x, Math.min(x, y))); 41 assertEq(r1, Math.min(x, y)); 42 43 assertEq(r2, Math.min(y, Math.min(x, y))); 44 assertEq(r2, Math.min(x, y)); 45 46 assertEq(r3, Math.min(Math.min(x, y), x)); 47 assertEq(r3, Math.min(x, y)); 48 49 assertEq(r4, Math.min(Math.min(x, y), y)); 50 assertEq(r4, Math.min(x, y)); 51 } 52 } 53 } 54 } 55 56 // Fold max(x, max(x, y)) to max(x, y). 57 for (let cvt of converters) { 58 let x = cvt("x"); 59 let y = cvt("y"); 60 let c = Function("a", `return ${cvt("a")}`); 61 62 let max1 = Function("x, y", `return Math.max(${x}, Math.max(${x}, ${y}))`); 63 let max2 = Function("x, y", `return Math.max(${y}, Math.max(${x}, ${y}))`); 64 let max3 = Function("x, y", `return Math.max(Math.max(${x}, ${y}), ${x})`); 65 let max4 = Function("x, y", `return Math.max(Math.max(${x}, ${y}), ${y})`); 66 67 for (let i = 0; i < 20; ++i) { 68 for (let j = 0; j < numbers.length; ++j) { 69 for (let k = 0; k < numbers.length; ++k) { 70 let x = numbers[j]; 71 let y = numbers[k] 72 let r1 = max1(x, y); 73 let r2 = max2(x, y); 74 let r3 = max3(x, y); 75 let r4 = max4(x, y); 76 77 // Convert to the correct type before computing the expected results. 78 x = c(x); 79 y = c(y); 80 81 assertEq(r1, Math.max(x, Math.max(x, y))); 82 assertEq(r1, Math.max(x, y)); 83 84 assertEq(r2, Math.max(y, Math.max(x, y))); 85 assertEq(r2, Math.max(x, y)); 86 87 assertEq(r3, Math.max(Math.max(x, y), x)); 88 assertEq(r3, Math.max(x, y)); 89 90 assertEq(r4, Math.max(Math.max(x, y), y)); 91 assertEq(r4, Math.max(x, y)); 92 } 93 } 94 } 95 } 96 97 // Fold max(x, min(x, y)) = x. 98 for (let cvt of converters) { 99 let x = cvt("x"); 100 let y = cvt("y"); 101 let c = Function("a", `return ${cvt("a")}`); 102 103 let maxmin1 = Function("x, y", `return Math.max(${x}, Math.min(${x}, ${y}))`); 104 let maxmin2 = Function("x, y", `return Math.max(${y}, Math.min(${x}, ${y}))`); 105 let maxmin3 = Function("x, y", `return Math.max(Math.min(${x}, ${y}), ${x})`); 106 let maxmin4 = Function("x, y", `return Math.max(Math.min(${x}, ${y}), ${y})`); 107 108 for (let i = 0; i < 20; ++i) { 109 for (let j = 0; j < numbers.length; ++j) { 110 for (let k = 0; k < numbers.length; ++k) { 111 let x = numbers[j]; 112 let y = numbers[k] 113 let r1 = maxmin1(x, y); 114 let r2 = maxmin2(x, y); 115 let r3 = maxmin3(x, y); 116 let r4 = maxmin4(x, y); 117 118 // Convert to the correct type before computing the expected results. 119 x = c(x); 120 y = c(y); 121 122 assertEq(r1, Math.max(x, Math.min(x, y))); 123 assertEq(r1, Number.isNaN(y) ? NaN : x); 124 125 assertEq(r2, Math.max(y, Math.min(x, y))); 126 assertEq(r2, Number.isNaN(x) ? NaN : y); 127 128 assertEq(r3, Math.max(Math.min(x, y), x)); 129 assertEq(r3, Number.isNaN(y) ? NaN : x); 130 131 assertEq(r4, Math.max(Math.min(x, y), y)); 132 assertEq(r4, Number.isNaN(x) ? NaN : y); 133 } 134 } 135 } 136 } 137 138 // Fold min(x, max(x, y)) = x. 139 for (let cvt of converters) { 140 let x = cvt("x"); 141 let y = cvt("y"); 142 let c = Function("a", `return ${cvt("a")}`); 143 144 let minmax1 = Function("x, y", `return Math.min(${x}, Math.max(${x}, ${y}))`); 145 let minmax2 = Function("x, y", `return Math.min(${y}, Math.max(${x}, ${y}))`); 146 let minmax3 = Function("x, y", `return Math.min(Math.max(${x}, ${y}), ${x})`); 147 let minmax4 = Function("x, y", `return Math.min(Math.max(${x}, ${y}), ${y})`); 148 149 for (let i = 0; i < 20; ++i) { 150 for (let j = 0; j < numbers.length; ++j) { 151 for (let k = 0; k < numbers.length; ++k) { 152 let x = numbers[j]; 153 let y = numbers[k] 154 let r1 = minmax1(x, y); 155 let r2 = minmax2(x, y); 156 let r3 = minmax3(x, y); 157 let r4 = minmax4(x, y); 158 159 // Convert to the correct type before computing the expected results. 160 x = c(x); 161 y = c(y); 162 163 assertEq(r1, Math.min(x, Math.max(x, y))); 164 assertEq(r1, Number.isNaN(y) ? NaN : x); 165 166 assertEq(r2, Math.min(y, Math.max(x, y))); 167 assertEq(r2, Number.isNaN(x) ? NaN : y); 168 169 assertEq(r3, Math.min(Math.max(x, y), x)); 170 assertEq(r3, Number.isNaN(y) ? NaN : x); 171 172 assertEq(r4, Math.min(Math.max(x, y), y)); 173 assertEq(r4, Number.isNaN(x) ? NaN : y); 174 } 175 } 176 } 177 }