From 1af224d895b894ad03d528065865867c71ad3209 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 30 Sep 2021 10:17:51 -0700 Subject: [PATCH] Horner's method --- src/gates/arithmetic_u32.rs | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/gates/arithmetic_u32.rs b/src/gates/arithmetic_u32.rs index 69039fba..dddc35b2 100644 --- a/src/gates/arithmetic_u32.rs +++ b/src/gates/arithmetic_u32.rs @@ -84,7 +84,8 @@ impl, const D: usize> Gate for U32ArithmeticG let mut combined_low_limbs = F::Extension::ZERO; let mut combined_high_limbs = F::Extension::ZERO; let midpoint = Self::num_limbs() / 2; - for j in 0..Self::num_limbs() { + let base = F::Extension::from_canonical_u64(1u64 << Self::limb_bits()); + for j in (0..Self::num_limbs()).rev() { let this_limb = vars.local_wires[Self::wire_ith_output_jth_limb(i, j)]; let max_limb = 1 << Self::limb_bits(); let product = (0..max_limb) @@ -93,13 +94,9 @@ impl, const D: usize> Gate for U32ArithmeticG constraints.push(product); if j < midpoint { - let base = F::Extension::from_canonical_u64(1u64 << (j * Self::limb_bits())); - combined_low_limbs += base * this_limb; + combined_low_limbs = base * combined_low_limbs + this_limb; } else { - let base = F::Extension::from_canonical_u64( - 1u64 << ((j - midpoint) * Self::limb_bits()), - ); - combined_high_limbs += base * this_limb; + combined_high_limbs = base * combined_high_limbs + this_limb; } } constraints.push(combined_low_limbs - output_low); @@ -129,7 +126,8 @@ impl, const D: usize> Gate for U32ArithmeticG let mut combined_low_limbs = F::ZERO; let mut combined_high_limbs = F::ZERO; let midpoint = Self::num_limbs() / 2; - for j in 0..Self::num_limbs() { + let base = F::from_canonical_u64(1u64 << Self::limb_bits()); + for j in (0..Self::num_limbs()).rev() { let this_limb = vars.local_wires[Self::wire_ith_output_jth_limb(i, j)]; let max_limb = 1 << Self::limb_bits(); let product = (0..max_limb) @@ -138,11 +136,9 @@ impl, const D: usize> Gate for U32ArithmeticG constraints.push(product); if j < midpoint { - let base = F::from_canonical_u64(1u64 << (j * Self::limb_bits())); - combined_low_limbs += base * this_limb; + combined_low_limbs = base * combined_low_limbs + this_limb; } else { - let base = F::from_canonical_u64(1u64 << ((j - midpoint) * Self::limb_bits())); - combined_high_limbs += base * this_limb; + combined_high_limbs = base * combined_high_limbs + this_limb; } } constraints.push(combined_low_limbs - output_low); @@ -178,7 +174,9 @@ impl, const D: usize> Gate for U32ArithmeticG let mut combined_low_limbs = builder.zero_extension(); let mut combined_high_limbs = builder.zero_extension(); let midpoint = Self::num_limbs() / 2; - for j in 0..Self::num_limbs() { + let base = builder + .constant_extension(F::Extension::from_canonical_u64(1u64 << Self::limb_bits())); + for j in (0..Self::num_limbs()).rev() { let this_limb = vars.local_wires[Self::wire_ith_output_jth_limb(i, j)]; let max_limb = 1 << Self::limb_bits(); @@ -192,17 +190,11 @@ impl, const D: usize> Gate for U32ArithmeticG constraints.push(product); if j < midpoint { - let base = builder.constant_extension(F::Extension::from_canonical_u64( - 1u64 << (j * Self::limb_bits()), - )); combined_low_limbs = - builder.mul_add_extension(base, this_limb, combined_low_limbs); + builder.mul_add_extension(base, combined_low_limbs, this_limb); } else { - let base = builder.constant_extension(F::Extension::from_canonical_u64( - 1u64 << ((j - midpoint) * Self::limb_bits()), - )); combined_high_limbs = - builder.mul_add_extension(base, this_limb, combined_high_limbs); + builder.mul_add_extension(base, combined_high_limbs, this_limb); } }