testFloat32-correctness.js (8015B)
1 setJitCompilerOption("ion.warmup.trigger", 50); 2 3 var f32 = new Float32Array(10); 4 5 function test(setup, f) { 6 if (f === undefined) { 7 f = setup; 8 setup = function(){}; 9 } 10 setup(); 11 for(var n = 200; n; --n) { 12 f(); 13 } 14 } 15 16 // Basic arithmetic 17 function setupBasicArith() { 18 f32[0] = -Infinity; 19 f32[1] = -1; 20 f32[2] = -0; 21 f32[3] = 0; 22 f32[4] = 1.337; 23 f32[5] = 42; 24 f32[6] = Infinity; 25 f32[7] = NaN; 26 } 27 function basicArith() { 28 for (var i = 0; i < 7; ++i) { 29 var opf = Math.fround(f32[i] + f32[i+1]); 30 var opd = (1 / (1 / f32[i])) + f32[i+1]; 31 assertFloat32(opf, true); 32 assertFloat32(opd, false); 33 assertEq(opf, Math.fround(opd)); 34 35 opf = Math.fround(f32[i] - f32[i+1]); 36 opd = (1 / (1 / f32[i])) - f32[i+1]; 37 assertFloat32(opf, true); 38 assertFloat32(opd, false); 39 assertEq(opf, Math.fround(opd)); 40 41 opf = Math.fround(f32[i] * f32[i+1]); 42 opd = (1 / (1 / f32[i])) * f32[i+1]; 43 assertFloat32(opf, true); 44 assertFloat32(opd, false); 45 assertEq(opf, Math.fround(opd)); 46 47 opf = Math.fround(f32[i] / f32[i+1]); 48 opd = (1 / (1 / f32[i])) / f32[i+1]; 49 assertFloat32(opf, true); 50 assertFloat32(opd, false); 51 assertEq(opf, Math.fround(opd)); 52 } 53 } 54 test(setupBasicArith, basicArith); 55 56 // MAbs 57 function setupAbs() { 58 f32[0] = -0; 59 f32[1] = 0; 60 f32[2] = -3.14159; 61 f32[3] = 3.14159; 62 f32[4] = -Infinity; 63 f32[5] = Infinity; 64 f32[6] = NaN; 65 } 66 function abs() { 67 for(var i = 0; i < 7; ++i) { 68 assertEq( Math.fround(Math.abs(f32[i])), Math.abs(f32[i]) ); 69 } 70 } 71 test(setupAbs, abs); 72 73 // MSqrt 74 function setupSqrt() { 75 f32[0] = 0; 76 f32[1] = 1; 77 f32[2] = 4; 78 f32[3] = -1; 79 f32[4] = Infinity; 80 f32[5] = NaN; 81 f32[6] = 13.37; 82 } 83 function sqrt() { 84 for(var i = 0; i < 7; ++i) { 85 var sqrtf = Math.fround(Math.sqrt(f32[i])); 86 var sqrtd = 1 + Math.sqrt(f32[i]) - 1; // force no float32 by chaining arith ops 87 assertEq( sqrtf, Math.fround(sqrtd) ); 88 } 89 } 90 test(setupSqrt, sqrt); 91 92 // MMinMax 93 function setupMinMax() { 94 f32[0] = -0; 95 f32[1] = 0; 96 f32[2] = 1; 97 f32[3] = 4; 98 f32[4] = -1; 99 f32[5] = Infinity; 100 f32[6] = NaN; 101 f32[7] = 13.37; 102 f32[8] = -Infinity; 103 f32[9] = Math.pow(2,31) - 1; 104 } 105 function minMax() { 106 for(var i = 0; i < 9; ++i) { 107 for(var j = 0; j < 9; j++) { 108 var minf = Math.fround(Math.min(f32[i], f32[j])); 109 var mind = 1 / (1 / Math.min(f32[i], f32[j])); // force no float32 by chaining arith ops 110 assertFloat32(minf, true); 111 assertFloat32(mind, false); 112 assertEq( minf, Math.fround(mind) ); 113 114 var maxf = Math.fround(Math.max(f32[i], f32[j])); 115 var maxd = 1 / (1 / Math.max(f32[i], f32[j])); // force no float32 by chaining arith ops 116 assertFloat32(maxf, true); 117 assertFloat32(maxd, false); 118 assertEq( maxf, Math.fround(maxd) ); 119 } 120 } 121 } 122 test(setupMinMax, minMax); 123 124 // MTruncateToInt32 125 // The only way to get a MTruncateToInt32 with a Float32 input is to use Math.imul 126 function setupTruncateToInt32() { 127 f32[0] = -1; 128 f32[1] = 4; 129 f32[2] = 5.13; 130 } 131 function truncateToInt32() { 132 assertEq( Math.imul(f32[0], f32[1]), Math.imul(-1, 4) ); 133 assertEq( Math.imul(f32[1], f32[2]), Math.imul(4, 5) ); 134 } 135 test(setupTruncateToInt32, truncateToInt32); 136 137 // MCompare 138 function comp() { 139 for(var i = 0; i < 9; ++i) { 140 assertEq( f32[i] < f32[i+1], true ); 141 } 142 } 143 function setupComp() { 144 f32[0] = -Infinity; 145 f32[1] = -1; 146 f32[2] = -0.01; 147 f32[3] = 0; 148 f32[4] = 0.01; 149 f32[5] = 1; 150 f32[6] = 10; 151 f32[7] = 13.37; 152 f32[8] = 42; 153 f32[9] = Infinity; 154 } 155 test(setupComp, comp); 156 157 // MNot 158 function setupNot() { 159 f32[0] = -0; 160 f32[1] = 0; 161 f32[2] = 1; 162 f32[3] = NaN; 163 f32[4] = Infinity; 164 f32[5] = 42; 165 f32[6] = -23; 166 } 167 function not() { 168 assertEq( !f32[0], true ); 169 assertEq( !f32[1], true ); 170 assertEq( !f32[2], false ); 171 assertEq( !f32[3], true ); 172 assertEq( !f32[4], false ); 173 assertEq( !f32[5], false ); 174 assertEq( !f32[6], false ); 175 } 176 test(setupNot, not); 177 178 // MToNumberInt32 179 var str = "can haz cheezburger? okthxbye;"; 180 function setupToInt32() { 181 f32[0] = 0; 182 f32[1] = 1; 183 f32[2] = 2; 184 f32[3] = 4; 185 f32[4] = 5; 186 } 187 function testToInt32() { 188 assertEq(str[f32[0]], 'c'); 189 assertEq(str[f32[1]], 'a'); 190 assertEq(str[f32[2]], 'n'); 191 assertEq(str[f32[3]], 'h'); 192 assertEq(str[f32[4]], 'a'); 193 } 194 test(setupToInt32, testToInt32); 195 196 function setupBailoutToInt32() { 197 f32[0] = .5; 198 } 199 function testBailoutToInt32() { 200 assertEq(typeof str[f32[0]], 'undefined'); 201 } 202 test(setupBailoutToInt32, testBailoutToInt32); 203 204 // MMath (no trigo - see also testFloat32-trigo.js 205 function assertNear(a, b) { 206 var r = (a != a && b != b) || Math.abs(a-b) < 1e-1 || a === b; 207 if (!r) { 208 print('Precision error: '); 209 print(new Error().stack); 210 print('Got', a, ', expected near', b); 211 assertEq(false, true); 212 } 213 } 214 215 function setupOtherMath() { 216 setupComp(); 217 f32[8] = 4.2; 218 } 219 function otherMath() { 220 for (var i = 0; i < 9; ++i) { 221 assertNear(Math.fround(Math.exp(f32[i])), Math.exp(f32[i])); 222 assertNear(Math.fround(Math.log(f32[i])), Math.log(f32[i])); 223 } 224 }; 225 test(setupOtherMath, otherMath); 226 227 function setupFloor() { 228 f32[0] = -5.5; 229 f32[1] = -0.5; 230 f32[2] = 0; 231 f32[3] = 1.5; 232 } 233 function setupFloorDouble() { 234 f32[4] = NaN; 235 f32[5] = -0; 236 f32[6] = Infinity; 237 f32[7] = -Infinity; 238 f32[8] = Math.pow(2,31); // too big to fit into a int 239 } 240 function testFloor() { 241 for (var i = 0; i < 4; ++i) { 242 var f = Math.floor(f32[i]); 243 assertFloat32(f, false); // f is an int32 244 245 var g = Math.floor(-0 + f32[i]); 246 assertFloat32(g, false); 247 248 assertEq(f, g); 249 } 250 } 251 function testFloorDouble() { 252 for (var i = 4; i < 9; ++i) { 253 var f = Math.fround(Math.floor(f32[i])); 254 assertFloat32(f, true); 255 256 var g = Math.floor(-0 + f32[i]); 257 assertFloat32(g, false); 258 259 assertEq(f, g); 260 } 261 } 262 test(setupFloor, testFloor); 263 test(setupFloorDouble, testFloorDouble); 264 265 function setupRound() { 266 f32[0] = -5.5; 267 f32[1] = -0.6; 268 f32[2] = 1.5; 269 f32[3] = 1; 270 } 271 function setupRoundDouble() { 272 f32[4] = NaN; 273 f32[5] = -0.49; // rounded to -0 274 f32[6] = Infinity; 275 f32[7] = -Infinity; 276 f32[8] = Math.pow(2,31); // too big to fit into a int 277 f32[9] = -0; 278 } 279 function testRound() { 280 for (var i = 0; i < 4; ++i) { 281 var r32 = Math.round(f32[i]); 282 assertFloat32(r32, false); // r32 is an int32 283 284 var r64 = Math.round(-0 + f32[i]); 285 assertFloat32(r64, false); 286 287 assertEq(r32, r64); 288 } 289 } 290 function testRoundDouble() { 291 for (var i = 4; i < 10; ++i) { 292 var r32 = Math.fround(Math.round(f32[i])); 293 assertFloat32(r32, true); 294 295 var r64 = Math.round(-0 + f32[i]); 296 assertFloat32(r64, false); 297 298 assertEq(r32, r64); 299 } 300 } 301 test(setupRound, testRound); 302 test(setupRoundDouble, testRoundDouble); 303 304 function setupCeil() { 305 f32[0] = -5.5; 306 f32[1] = -1.5; 307 f32[2] = 0; 308 f32[3] = 1.5; 309 } 310 function setupCeilDouble() { 311 f32[4] = NaN; 312 f32[5] = -0; 313 f32[6] = Infinity; 314 f32[7] = -Infinity; 315 f32[8] = Math.pow(2,31); // too big to fit into a int 316 } 317 function testCeil() { 318 for(var i = 0; i < 2; ++i) { 319 var f = Math.ceil(f32[i]); 320 assertFloat32(f, false); 321 322 var g = Math.ceil(-0 + f32[i]); 323 assertFloat32(g, false); 324 325 assertEq(f, g); 326 } 327 } 328 function testCeilDouble() { 329 for(var i = 4; i < 9; ++i) { 330 var f = Math.fround(Math.ceil(f32[i])); 331 assertFloat32(f, true); 332 333 var g = Math.ceil(-0 + f32[i]); 334 assertFloat32(g, false); 335 336 assertEq(f, g); 337 } 338 } 339 test(setupCeil, testCeil); 340 test(setupCeilDouble, testCeilDouble);