authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-19 15:44:33+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-19 15:44:33+02:00
loge85c5928ac4ee993edefe42984411a90d0fbbf52
tree3ae7ea19605cc34b3ec6354466b1ab34b67ba016
parent187d0bf9e48338c8db8c4a0dbc613c768367876e
parentbd33e1fd714ed4d0c0c2f4fa30044e66e7d3ce89

Merge pull request 'crypto.ff: compute Montgomery R2 with doubling and squaring' (#37271) from jedisct1/zig:ff-fixes13 into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/37271

1 files changed, 40 insertions(+), 6 deletions(-)

lib/std/crypto/ff.zig+40-6
......@@ -724,15 +724,49 @@ pub fn Modulus(comptime max_bits: comptime_int) type {
724724 fe.v.limbs_len = new_len;
725725 }
726726
727 // Doubles modulo m without using `rr`, so it can be used for modulus construction.
728 fn double(self: Self, x: *Fe) void {
729 const y = x.v;
730 _ = addAndReduce(&x.v, y, self.v);
731 }
732
727733 // Computes R^2 for the Montgomery representation.
728734 fn computeRR(self: *Self) void {
729 self.rr = self.zero;
730 const n = self.rr.limbs_count();
731 self.rr.v.limbs()[n - 1] = 1;
732 for ((n - 1)..(2 * n)) |_| {
733 self.shiftIn(&self.rr, 0);
735 const n = self.limbs_count();
736 var rr = self.zero;
737
738 if (n < 3) {
739 rr.v.limbs()[n - 1] = 1;
740 for ((n - 1)..(2 * n)) |_| {
741 self.shiftIn(&rr, 0);
742 }
743 self.rr = rr;
744 return;
745 }
746
747 const start = self.bits() - 1; // largest power of two < m.
748 const log_r = n * t_bits;
749 rr.v.limbs()[start / t_bits] = math.shl(Limb, 1, start % t_bits);
750 for (start..log_r) |_| {
751 self.double(&rr);
734752 }
735 self.shrink(&self.rr) catch unreachable;
753
754 const threshold = n / 4;
755 var i: usize = math.log2_int(usize, log_r);
756 while (i > 0 and math.shr(usize, log_r, i) <= threshold) i -= 1;
757 for (0..math.shr(usize, log_r, i)) |_| {
758 self.double(&rr);
759 }
760 while (i > 0) {
761 rr = self.montgomerySq(rr);
762 i -= 1;
763 if (math.shr(usize, log_r, i) & 1 != 0) {
764 self.double(&rr);
765 }
766 }
767
768 rr.montgomery = false;
769 self.rr = rr;
736770 }
737771
738772 /// Computes x << t_bits + y (mod m)