Run details:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Chrome 128
Windows
Desktop
4 months ago
Test name Executions per second
Math.imul 554.3 Ops/sec
Polyfill a 544.0 Ops/sec
Polyfill b 554.1 Ops/sec
Script Preparation code:
x
 
var x = 0x12345678;
var y;
Math.imula = function(opA, opB) {
  opB |= 0; // ensure that opB is an integer. opA will automatically be coerced.
  // floating points give us 53 bits of precision to work with plus 1 sign bit
  // automatically handled for our convienence:
  // 1. 0x003fffff /*opA & 0x000fffff*/ * 0x7fffffff /*opB*/ = 0x1fffff7fc00001
  //    0x1fffff7fc00001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/
  var result = (opA & 0x003fffff) * opB;
  // 2. We can remove an integer coersion from the statement above because:
  //    0x1fffff7fc00001 + 0xffc00000 = 0x1fffffff800001
  //    0x1fffffff800001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/
  if (opA & 0xffc00000 /*!== 0*/) result += (opA & 0xffc00000) * opB |0;
  return result |0;
};
Math.imulb = function(a, b) {
  var aHi = (a >>> 16) & 0xffff;
  var aLo = a & 0xffff;
  var bHi = (b >>> 16) & 0xffff;
  var bLo = b & 0xffff;
  // the shift by 0 fixes the sign on the high part
  // the final |0 converts the unsigned value into a signed value
  return ((aLo * bLo) + (((aHi * bLo + aLo * bHi) << 16) >>> 0) | 0);
};
Tests:
  • Math.imul

     
    for (var i = 0i < 10000; ++i) {
      y = Math.imul(x, i);
    }
  • Polyfill a

     
    for (var i = 0i < 10000; ++i) {
      y = Math.imula(x, i);
    }
  • Polyfill b

     
    for (var i = 0i < 10000; ++i) {
      y = Math.imulb(x, i);
    }