| ... | ... | @@ -724,15 +724,49 @@ pub fn Modulus(comptime max_bits: comptime_int) type { |
| 724 | 724 | fe.v.limbs_len = new_len; |
| 725 | 725 | } |
| 726 | 726 | |
| 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 | |
| 727 | 733 | // Computes R^2 for the Montgomery representation. |
| 728 | 734 | 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); |
| 734 | 752 | } |
| 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; |
| 736 | 770 | } |
| 737 | 771 | |
| 738 | 772 | /// Computes x << t_bits + y (mod m) |