Skip to content

Instantly share code, notes, and snippets.

@BrendanEich
Last active May 22, 2022 14:43
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BrendanEich/4294d5c212a6d2254703 to your computer and use it in GitHub Desktop.
Save BrendanEich/4294d5c212a6d2254703 to your computer and use it in GitHub Desktop.

From Fabrice Bellard, with minor name change (umulh):

// return the high 32 bit part of the 64 bit addition of (hi0, lo0) and (hi1, lo1)
Math.iaddh(lo0, hi0, lo1, hi1)

// return the high 32 bit part of the 64 bit subtraction of (hi0, lo0) and (hi1, lo1)
Math.isubh(lo0, hi0, lo1, hi1)

// return the high 32 bit part of the signed 64 bit product of the 32 bit numbers a and b
Math.imulh(a, b)

// return the high 32 bit part of the unsigned 64 bit product of the 32 bit numbers a and b
Math.umulh(a, b)

All these functions convert their argument to 32 bit integers. They return a signed 32 bit integer.

With these functions, the 64 bit operations are easy to implement :

// (hi_res, lo_res) = (hi0, lo0) + (hi1, lo1) (64 bit addition):

lo_res = (lo0 + lo1) | 0;
hi_res = Math.iaddh(lo0, hi0, lo1, hi1);

// (hi_res, lo_res) = (hi0, lo0) - (hi1, lo1) (64 bit subtraction):

lo_res = (lo0 - lo1) | 0;
hi_res = Math.isubh(lo0, hi0, lo1, hi1);

// (hi_res, lo_res) = a * b (signed 64 bit product of 32 bit integers):

lo_res = Math.imul(a, b);
hi_res = Math.imulh(a, b);

// (hi_res, lo_res) = a * b (unsigned 64 bit product of 32 bit integers):

lo_res = Math.imul(a, b);
hi_res = Math.umulh(a, b);

// (hi_res, lo_res) = (hi0, lo0) * (hi1, lo1) (signed 64 bit product of 64 bit integers):

lo_res = Math.imul(lo0, lo1);
hi_res = (Math.imulh(lo0, lo1) + Math.imul(lo0, hi1)) | 0;
hi_res = (hi_res + Math.imul(lo1, hi0)) | 0;

// (hi_res, lo_res) = (hi0, lo0) * (hi1, lo1) (unsigned 64 bit product of 64 bit integers):

lo_res = Math.imul(lo0, lo1);
hi_res = (Math.umulh(lo0, lo1) + Math.imul(lo0, hi1)) | 0;
hi_res = (hi_res + Math.imul(lo1, hi0)) | 0;

Fabrice wrote:

"It is easy for the compiler to optimize the code because only 32 bit integers are used and because the functions have no side effect. Even if the compiler does not remove the duplicate operation for the low 32 bit parts, the overhead is very small on a 32 bit CPU (1 more instruction than the optimal code)."

UPDATE to provide 64x64=64 functions:

// (hi_res, lo_res) = (hi0, lo0) * (hi1, lo1) (signed 64 bit product of 64 bit integers):

lo_res = Math.imul(lo0, lo1);
hi_res = Math.imulx(lo0, hi0, lo1, hi1);

// (hi_res, lo_res) = (hi0, lo0) * (hi1, lo1) (unsigned 64 bit product of 64 bit integers):

lo_res = Math.imul(lo0, lo1);
hi_res = Math.umulx(lo0, hi0, lo1, hi1);

The x suffix is straw, it could be hx to connote hi_res is the result, or something longer.

/be

@BrendanEich
Copy link
Author

As noted on twitter, see also https://github.com/dherman/float.js for cracking JS 64-bit doubles via typed arrays and their aliasing powers.

/be

@billinghamj
Copy link

I'm finding the naming of these functions pretty confusing. Are they acronyms?

@tomjakubowski
Copy link

They're abbreviated: imulh is short for "integer, multiply, high bits". It's consistent with the naming of functions like Math.imul.

@lygstate
Copy link

lygstate commented Mar 2, 2016

I also suggest add Math.popcnt Math.popcnt64 support

https://msdn.microsoft.com/zh-cn/library/bb385231.aspx

@lygstate
Copy link

lygstate commented Mar 2, 2016

Maybe also Math.popcnt16 support

@fregante
Copy link

fregante commented Sep 23, 2016

Pardon my ignorance, but instead of these specific functions, wouldn't it be great to have custom types work with normal operators? I always thought that JS might benefit from more custom-ish types like matrixes and simply have them work with +-/*<>... operators instead of creating whole new objects/methods like Math.iaddh and SIMD.%type%.mul()

@zloirock
Copy link

@BrendanEich is this proposal alive or I should remove it from the next version of core-js? -)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment