// โโ Field โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
//
// Goldilocks arithmetic (p = 2^64 - 2^32 + 1) emulated as u32 pairs.
// Matches rs/src/field.rs exactly.
fn add64(a_lo: u32, a_hi: u32, b_lo: u32, b_hi: u32) -> vec2<u32> {
let lo = a_lo + b_lo;
let carry = select(0u, 1u, lo < a_lo);
let hi = a_hi + b_hi + carry;
return vec2<u32>(lo, hi);
}
fn sub64(a_lo: u32, a_hi: u32, b_lo: u32, b_hi: u32) -> vec2<u32> {
let borrow = select(0u, 1u, a_lo < b_lo);
let lo = a_lo - b_lo;
let hi = a_hi - b_hi - borrow;
return vec2<u32>(lo, hi);
}
fn gte64(a_lo: u32, a_hi: u32, b_lo: u32, b_hi: u32) -> bool {
if a_hi > b_hi { return true; }
if a_hi < b_hi { return false; }
return a_lo >= b_lo;
}
fn reduce(lo: u32, hi: u32) -> vec2<u32> {
if gte64(lo, hi, P_LO, P_HI) {
return sub64(lo, hi, P_LO, P_HI);
}
return vec2<u32>(lo, hi);
}
fn gl_add(a_lo: u32, a_hi: u32, b_lo: u32, b_hi: u32) -> vec2<u32> {
let sum = add64(a_lo, a_hi, b_lo, b_hi);
let overflow = (sum.y < a_hi) || (sum.y == a_hi && sum.x < a_lo);
if overflow {
let adj = add64(sum.x, sum.y, NEG_ORDER, 0u);
let overflow2 = (adj.y < sum.y) || (adj.y == sum.y && adj.x < sum.x);
if overflow2 {
let adj2 = add64(adj.x, adj.y, NEG_ORDER, 0u);
return reduce(adj2.x, adj2.y);
}
return reduce(adj.x, adj.y);
}
return reduce(sum.x, sum.y);
}
fn gl_sub(a_lo: u32, a_hi: u32, b_lo: u32, b_hi: u32) -> vec2<u32> {
let diff = sub64(a_lo, a_hi, b_lo, b_hi);
let underflow = (a_hi < b_hi) || (a_hi == b_hi && a_lo < b_lo);
if underflow {
let adj = sub64(diff.x, diff.y, NEG_ORDER, 0u);
let underflow2 = (diff.y == 0u && diff.x < NEG_ORDER);
if underflow2 {
let adj2 = sub64(adj.x, adj.y, NEG_ORDER, 0u);
return adj2;
}
return adj;
}
return diff;
}
fn mul32(a: u32, b: u32) -> vec2<u32> {
let a_lo = a & 0xFFFFu;
let a_hi = a >> 16u;
let b_lo = b & 0xFFFFu;
let b_hi = b >> 16u;
let ll = a_lo * b_lo;
let lh = a_lo * b_hi;
let hl = a_hi * b_lo;
let hh = a_hi * b_hi;
let mid = lh + (ll >> 16u);
let mid2 = (mid & 0xFFFFu) + hl;
let lo = (mid2 << 16u) | (ll & 0xFFFFu);
let hi = hh + (mid >> 16u) + (mid2 >> 16u);
return vec2<u32>(lo, hi);
}
// Exact reduce128 matching CPU field.rs
fn gl_mul(a_lo: u32, a_hi: u32, b_lo: u32, b_hi: u32) -> vec2<u32> {
let ll = mul32(a_lo, b_lo);
let lh = mul32(a_lo, b_hi);
let hl = mul32(a_hi, b_lo);
let hh = mul32(a_hi, b_hi);
let r0 = ll.x;
let t1 = add64(ll.y, 0u, lh.x, 0u);
let t2 = add64(t1.x, t1.y, hl.x, 0u);
let r1 = t2.x;
let carry1 = t2.y;
let t3 = add64(lh.y, 0u, hl.y, 0u);
let t4 = add64(t3.x, t3.y, hh.x, 0u);
let t5 = add64(t4.x, t4.y, carry1, 0u);
let r2 = t5.x;
let carry2 = t5.y;
let r3 = hh.y + carry2;
let sub_borrow = select(0u, 1u, r0 < r3);
var t0_lo = r0 - r3;
var t0_hi = r1 - sub_borrow;
let real_borrow = (r1 == 0u && r0 < r3) || (r1 < sub_borrow);
if real_borrow {
let sub2_borrow = select(0u, 1u, t0_lo < NEG_ORDER);
t0_lo = t0_lo - NEG_ORDER;
t0_hi = t0_hi - sub2_borrow;
}
let t1_val = mul32(r2, NEG_ORDER);
let res = add64(t0_lo, t0_hi, t1_val.x, t1_val.y);
let add_carry = (res.y < t0_hi) || (res.y == t0_hi && res.x < t0_lo);
if add_carry {
let final_val = add64(res.x, res.y, NEG_ORDER, 0u);
return final_val;
}
return vec2<u32>(res.x, res.y);
}
fn gl_double(x_lo: u32, x_hi: u32) -> vec2<u32> {
return gl_add(x_lo, x_hi, x_lo, x_hi);
}
fn gl_pow7(x_lo: u32, x_hi: u32) -> vec2<u32> {
let x2 = gl_mul(x_lo, x_hi, x_lo, x_hi);
let x3 = gl_mul(x2.x, x2.y, x_lo, x_hi);
let x4 = gl_mul(x2.x, x2.y, x2.x, x2.y);
let x7 = gl_mul(x3.x, x3.y, x4.x, x4.y);
return x7;
}
hemera/wgsl/src/shaders/field.wgsl
ฯ 0.0%