in src/backend/serial/u32/field.rs [330:376]
fn reduce(mut z: [u64; 10]) -> FieldElement2625 {
const LOW_25_BITS: u64 = (1 << 25) - 1;
const LOW_26_BITS: u64 = (1 << 26) - 1;
/// Carry the value from limb i = 0..8 to limb i+1
#[inline(always)]
fn carry(z: &mut [u64; 10], i: usize) {
debug_assert!(i < 9);
if i % 2 == 0 {
// Even limbs have 26 bits
z[i+1] += z[i] >> 26;
z[i] &= LOW_26_BITS;
} else {
// Odd limbs have 25 bits
z[i+1] += z[i] >> 25;
z[i] &= LOW_25_BITS;
}
}
// Perform two halves of the carry chain in parallel.
carry(&mut z, 0); carry(&mut z, 4);
carry(&mut z, 1); carry(&mut z, 5);
carry(&mut z, 2); carry(&mut z, 6);
carry(&mut z, 3); carry(&mut z, 7);
// Since z[3] < 2^64, c < 2^(64-25) = 2^39,
// so z[4] < 2^26 + 2^39 < 2^39.0002
carry(&mut z, 4); carry(&mut z, 8);
// Now z[4] < 2^26
// and z[5] < 2^25 + 2^13.0002 < 2^25.0004 (good enough)
// Last carry has a multiplication by 19:
z[0] += 19*(z[9] >> 25);
z[9] &= LOW_25_BITS;
// Since z[9] < 2^64, c < 2^(64-25) = 2^39,
// so z[0] + 19*c < 2^26 + 2^43.248 < 2^43.249.
carry(&mut z, 0);
// Now z[1] < 2^25 - 2^(43.249 - 26)
// < 2^25.007 (good enough)
// and we're done.
FieldElement2625([
z[0] as u32, z[1] as u32, z[2] as u32, z[3] as u32, z[4] as u32,
z[5] as u32, z[6] as u32, z[7] as u32, z[8] as u32, z[9] as u32,
])
}