authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-12 09:54:52+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-12 09:54:52+02:00
logab3825e026d96d99527e701674aabe3b9bae810f
treed847623632d2418c5a15eb9545baa22cc20f46f9
parent4ed10da2cf9d73c045b110d58c53a840ed9ae18d
parenta1363b3b5a2bfdd9609cf1baed176a613289d499

Merge pull request 'crypto.ff: avoid code duplication' (#37079) from jedisct1/zig:ff-fixes11 into master

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

1 files changed, 34 insertions(+), 26 deletions(-)

lib/std/crypto/ff.zig+34-26
......@@ -638,6 +638,28 @@ pub fn Modulus(comptime max_bits: comptime_int) type {
638638 return x.eql(mo);
639639 }
640640
641 // Computes -lo^-1 mod 2^t_bits for an odd `lo`.
642 fn computeM0Inv(lo: Limb) Limb {
643 var y = lo;
644 inline for (0..comptime math.log2_int(usize, t_bits)) |_| {
645 y = y *% (2 -% lo *% y);
646 }
647 return (@as(Limb, 1) << t_bits) - (@as(TLimb, @truncate(y)));
648 }
649
650 // Initialize without R2
651 fn initWithoutRR(v: FeUint, leading: usize, m0inv: Limb) Self {
652 var m = Self{
653 .zero = Fe{ .v = FeUint.zero },
654 .v = v,
655 .leading = leading,
656 .m0inv = m0inv,
657 .rr = undefined,
658 };
659 m.shrink(&m.zero) catch unreachable;
660 return m;
661 }
662
641663 /// Creates a new modulus from a `Uint` value.
642664 /// The modulus must be odd and larger than 2.
643665 pub fn fromUint(v_: FeUint) InvalidModulusError!Self {
......@@ -651,25 +673,8 @@ pub fn Modulus(comptime max_bits: comptime_int) type {
651673 return error.ModulusTooSmall;
652674 }
653675
654 const leading = @clz(hi) - carry_bits;
676 var m = initWithoutRR(v, @clz(hi) - carry_bits, computeM0Inv(lo));
655677
656 var y = lo;
657
658 inline for (0..comptime math.log2_int(usize, t_bits)) |_| {
659 y = y *% (2 -% lo *% y);
660 }
661 const m0inv = (@as(Limb, 1) << t_bits) - (@as(TLimb, @truncate(y)));
662
663 const zero = Fe{ .v = FeUint.zero };
664
665 var m = Self{
666 .zero = zero,
667 .v = v,
668 .leading = leading,
669 .m0inv = m0inv,
670 .rr = undefined, // will be computed right after
671 };
672 m.shrink(&m.zero) catch unreachable;
673678 computeRR(&m);
674679
675680 return m;
......@@ -759,15 +764,21 @@ pub fn Modulus(comptime max_bits: comptime_int) type {
759764 x.v.cmov(need_sub, d.v);
760765 }
761766
767 // Adds y to x. Returns whether reduction was needed.
768 fn addAndReduce(x: *FeUint, y: FeUint, bound: FeUint) bool {
769 const overflow = x.addWithOverflow(y);
770 const underflow: u1 = @bitCast(ct.limbsCmpLt(x.*, bound));
771 const need_sub = ct.eql(overflow, underflow);
772 _ = x.conditionalSubWithOverflow(need_sub, bound);
773 return need_sub;
774 }
775
762776 /// Adds two field elements (mod m).
763777 pub fn add(self: Self, x: Fe, y: Fe) Fe {
764778 var out = x;
765779 if (x.montgomery == y.montgomery) {
766780 @branchHint(.likely);
767 const overflow = out.v.addWithOverflow(y.v);
768 const underflow: u1 = @bitCast(ct.limbsCmpLt(out.v, self.v));
769 const need_sub = ct.eql(overflow, underflow);
770 _ = out.v.conditionalSubWithOverflow(need_sub, self.v);
781 _ = addAndReduce(&out.v, y.v, self.v);
771782 return out;
772783 } else {
773784 var y_ = y;
......@@ -776,10 +787,7 @@ pub fn Modulus(comptime max_bits: comptime_int) type {
776787 } else {
777788 self.toMontgomery(&y_) catch unreachable;
778789 }
779 const overflow = out.v.addWithOverflow(y_.v);
780 const underflow: u1 = @bitCast(ct.limbsCmpLt(out.v, self.v));
781 const need_sub = ct.eql(overflow, underflow);
782 _ = out.v.conditionalSubWithOverflow(need_sub, self.v);
790 _ = addAndReduce(&out.v, y_.v, self.v);
783791 return out;
784792 }
785793 }