Skip to content

Instantly share code, notes, and snippets.

@cf
Created October 26, 2023 14:49
Show Gist options
  • Save cf/2eb9ebec84dffb74ae5b6ce049f5eb9b to your computer and use it in GitHub Desktop.
Save cf/2eb9ebec84dffb74ae5b6ce049f5eb9b to your computer and use it in GitHub Desktop.
[Metal] Goldilocks add and mul
#include <metal_stdlib>
/*
Goldilocks add and mul with ❤️ from Carter (Public Domain)
*/
inline ulong reduce128(ulong x_hi, ulong x_lo){
ulong x_hi_hi = x_hi>>32;
ulong x_hi_lo = x_hi & 0xffffffff;
ulong t0 = x_lo - x_hi_hi;
if(t0 > x_lo){
t0 -= 0xffffffff;
}
ulong t1 = x_hi_lo*0xffffffff;
ulong t2 = t0 + t1;
if(t2 < t1){
t2 += 0xffffffff;
}
return t2;
}
inline ulong goldilocks_mul(ulong x, ulong y) {
ulong a = x >> 32;
ulong b = x & 0xFFFFFFFF;
ulong c = y >> 32;
ulong d = y & 0xFFFFFFFF;
ulong ad = a * d;
ulong bd = b * d;
ulong adbc = ad + (b * c);
ulong adbc_carry = adbc < ad ? 1 : 0;
ulong product_lo = bd + (adbc << 32);
ulong product_lo_carry = product_lo < bd ? 1 : 0;
ulong product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
return reduce128(product_hi, product_lo)%0xffffffff00000001;
}
inline ulong goldilocks_add(ulong x, ulong y){
ulong x_plus_y = x+y;
if(x_plus_y < x){
ulong c = x_plus_y + 0xffffffff;
if(c<x_plus_y){
return c+0xffffffff;
}
return c;
}
return x_plus_y;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment