From 234ccb4a5088cd6fa06144d7ba1aceab0596f1cc Mon Sep 17 00:00:00 2001 From: Frank Denis <124872+jedisct1@users.noreply.github.com> Date: Wed, 29 Jun 2022 15:11:33 +0200 Subject: [PATCH] std.crypto.ecc: add support for the secp256k1 curve (#11880) std.crypto.ecc: add support for the secp256k1 curve Usage of the secp256k1 elliptic curve recently grew exponentially, since this is the curve used by Bitcoin and other popular blockchains such as Ethereum. With this, Zig has support for all the widely deployed elliptic curves today. --- lib/std/crypto.zig | 2 + lib/std/crypto/pcurves/common.zig | 11 + lib/std/crypto/pcurves/secp256k1.zig | 556 +++++ lib/std/crypto/pcurves/secp256k1/field.zig | 12 + lib/std/crypto/pcurves/secp256k1/scalar.zig | 227 ++ .../crypto/pcurves/secp256k1/secp256k1_64.zig | 1964 ++++++++++++++++ .../pcurves/secp256k1/secp256k1_scalar_64.zig | 2024 +++++++++++++++++ lib/std/crypto/pcurves/tests/secp256k1.zig | 137 ++ 8 files changed, 4933 insertions(+) create mode 100644 lib/std/crypto/pcurves/secp256k1.zig create mode 100644 lib/std/crypto/pcurves/secp256k1/field.zig create mode 100644 lib/std/crypto/pcurves/secp256k1/scalar.zig create mode 100644 lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig create mode 100644 lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig create mode 100644 lib/std/crypto/pcurves/tests/secp256k1.zig diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig index b9191585ece3..522a545fcf34 100644 --- a/lib/std/crypto.zig +++ b/lib/std/crypto.zig @@ -64,6 +64,7 @@ pub const ecc = struct { pub const P256 = @import("crypto/pcurves/p256.zig").P256; pub const P384 = @import("crypto/pcurves/p384.zig").P384; pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; + pub const Secp256k1 = @import("crypto/pcurves/secp256k1.zig").Secp256k1; }; /// Hash functions. @@ -205,6 +206,7 @@ test { _ = ecc.P256; _ = ecc.P384; _ = ecc.Ristretto255; + _ = ecc.Secp256k1; _ = hash.blake2; _ = hash.Blake3; diff --git a/lib/std/crypto/pcurves/common.zig b/lib/std/crypto/pcurves/common.zig index 1160334fe48f..5abc6d348fc6 100644 --- a/lib/std/crypto/pcurves/common.zig +++ b/lib/std/crypto/pcurves/common.zig @@ -295,6 +295,17 @@ pub fn Field(comptime params: FieldParams) type { const x63 = x32.sqn(31).mul(x31); const x126 = x63.sqn(63).mul(x63); return x126.sqn(126).mul(x126).sqn(3).mul(t111).sqn(33).mul(x32).sqn(64).mul(x2).sqn(30); + } else if (field_order == 115792089237316195423570985008687907853269984665640564039457584007908834671663) { + const t11 = x2.mul(x2.sq()); + const t1111 = t11.mul(t11.sqn(2)); + const t11111 = x2.mul(t1111.sq()); + const t1111111 = t11.mul(t11111.sqn(2)); + const x11 = t1111111.sqn(4).mul(t1111); + const x22 = x11.sqn(11).mul(x11); + const x27 = x22.sqn(5).mul(t11111); + const x54 = x27.sqn(27).mul(x27); + const x108 = x54.sqn(54).mul(x54); + return x108.sqn(108).mul(x108).sqn(7).mul(t1111111).sqn(23).mul(x22).sqn(6).mul(t11).sqn(2); } else { return x2.pow(std.meta.Int(.unsigned, field_bits), (field_order + 1) / 4); } diff --git a/lib/std/crypto/pcurves/secp256k1.zig b/lib/std/crypto/pcurves/secp256k1.zig new file mode 100644 index 000000000000..79698bd7dd38 --- /dev/null +++ b/lib/std/crypto/pcurves/secp256k1.zig @@ -0,0 +1,556 @@ +const std = @import("std"); +const crypto = std.crypto; +const math = std.math; +const mem = std.mem; +const meta = std.meta; + +const EncodingError = crypto.errors.EncodingError; +const IdentityElementError = crypto.errors.IdentityElementError; +const NonCanonicalError = crypto.errors.NonCanonicalError; +const NotSquareError = crypto.errors.NotSquareError; + +/// Group operations over secp256k1. +pub const Secp256k1 = struct { + /// The underlying prime field. + pub const Fe = @import("secp256k1/field.zig").Fe; + /// Field arithmetic mod the order of the main subgroup. + pub const scalar = @import("secp256k1/scalar.zig"); + + x: Fe, + y: Fe, + z: Fe = Fe.one, + + is_base: bool = false, + + /// The secp256k1 base point. + pub const basePoint = Secp256k1{ + .x = Fe.fromInt(55066263022277343669578718895168534326250603453777594175500187360389116729240) catch unreachable, + .y = Fe.fromInt(32670510020758816978083085130507043184471273380659243275938904335757337482424) catch unreachable, + .z = Fe.one, + .is_base = true, + }; + + /// The secp256k1 neutral element. + pub const identityElement = Secp256k1{ .x = Fe.zero, .y = Fe.one, .z = Fe.zero }; + + pub const B = Fe.fromInt(7) catch unreachable; + + pub const Endormorphism = struct { + const lambda: u256 = 37718080363155996902926221483475020450927657555482586988616620542887997980018; + const beta: u256 = 55594575648329892869085402983802832744385952214688224221778511981742606582254; + + const lambda_s = s: { + var buf: [32]u8 = undefined; + mem.writeIntLittle(u256, &buf, Endormorphism.lambda); + break :s buf; + }; + + pub const SplitScalar = struct { + r1: [32]u8, + r2: [32]u8, + }; + + /// Compute r1 and r2 so that k = r1 + r2*lambda (mod L). + pub fn splitScalar(s: [32]u8, endian: std.builtin.Endian) SplitScalar { + const b1_neg_s = comptime s: { + var buf: [32]u8 = undefined; + mem.writeIntLittle(u256, &buf, 303414439467246543595250775667605759171); + break :s buf; + }; + const b2_neg_s = comptime s: { + var buf: [32]u8 = undefined; + mem.writeIntLittle(u256, &buf, scalar.field_order - 64502973549206556628585045361533709077); + break :s buf; + }; + const k = mem.readInt(u256, &s, endian); + + const t1 = math.mulWide(u256, k, 21949224512762693861512883645436906316123769664773102907882521278123970637873); + const t2 = math.mulWide(u256, k, 103246583619904461035481197785446227098457807945486720222659797044629401272177); + + const c1 = @truncate(u128, t1 >> 384) + @truncate(u1, t1 >> 383); + const c2 = @truncate(u128, t2 >> 384) + @truncate(u1, t2 >> 383); + + var buf: [32]u8 = undefined; + + mem.writeIntLittle(u256, &buf, c1); + const c1x = scalar.mul(buf, b1_neg_s, .Little) catch unreachable; + + mem.writeIntLittle(u256, &buf, c2); + const c2x = scalar.mul(buf, b2_neg_s, .Little) catch unreachable; + + const r2 = scalar.add(c1x, c2x, .Little) catch unreachable; + + var r1 = scalar.mul(r2, lambda_s, .Little) catch unreachable; + r1 = scalar.sub(s, r1, .Little) catch unreachable; + + return SplitScalar{ .r1 = r1, .r2 = r2 }; + } + }; + + /// Reject the neutral element. + pub fn rejectIdentity(p: Secp256k1) IdentityElementError!void { + if (p.x.isZero()) { + return error.IdentityElement; + } + } + + /// Create a point from affine coordinates after checking that they match the curve equation. + pub fn fromAffineCoordinates(p: AffineCoordinates) EncodingError!Secp256k1 { + const x = p.x; + const y = p.y; + const x3B = x.sq().mul(x).add(B); + const yy = y.sq(); + const on_curve = @boolToInt(x3B.equivalent(yy)); + const is_identity = @boolToInt(x.equivalent(AffineCoordinates.identityElement.x)) & @boolToInt(y.equivalent(AffineCoordinates.identityElement.y)); + if ((on_curve | is_identity) == 0) { + return error.InvalidEncoding; + } + var ret = Secp256k1{ .x = x, .y = y, .z = Fe.one }; + ret.z.cMov(Secp256k1.identityElement.z, is_identity); + return ret; + } + + /// Create a point from serialized affine coordinates. + pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!Secp256k1 { + const x = try Fe.fromBytes(xs, endian); + const y = try Fe.fromBytes(ys, endian); + return fromAffineCoordinates(.{ .x = x, .y = y }); + } + + /// Recover the Y coordinate from the X coordinate. + pub fn recoverY(x: Fe, is_odd: bool) NotSquareError!Fe { + const x3B = x.sq().mul(x).add(B); + var y = try x3B.sqrt(); + const yn = y.neg(); + y.cMov(yn, @boolToInt(is_odd) ^ @boolToInt(y.isOdd())); + return y; + } + + /// Deserialize a SEC1-encoded point. + pub fn fromSec1(s: []const u8) (EncodingError || NotSquareError || NonCanonicalError)!Secp256k1 { + if (s.len < 1) return error.InvalidEncoding; + const encoding_type = s[0]; + const encoded = s[1..]; + switch (encoding_type) { + 0 => { + if (encoded.len != 0) return error.InvalidEncoding; + return Secp256k1.identityElement; + }, + 2, 3 => { + if (encoded.len != 32) return error.InvalidEncoding; + const x = try Fe.fromBytes(encoded[0..32].*, .Big); + const y_is_odd = (encoding_type == 3); + const y = try recoverY(x, y_is_odd); + return Secp256k1{ .x = x, .y = y }; + }, + 4 => { + if (encoded.len != 64) return error.InvalidEncoding; + const x = try Fe.fromBytes(encoded[0..32].*, .Big); + const y = try Fe.fromBytes(encoded[32..64].*, .Big); + return Secp256k1.fromAffineCoordinates(.{ .x = x, .y = y }); + }, + else => return error.InvalidEncoding, + } + } + + /// Serialize a point using the compressed SEC-1 format. + pub fn toCompressedSec1(p: Secp256k1) [33]u8 { + var out: [33]u8 = undefined; + const xy = p.affineCoordinates(); + out[0] = if (xy.y.isOdd()) 3 else 2; + mem.copy(u8, out[1..], &xy.x.toBytes(.Big)); + return out; + } + + /// Serialize a point using the uncompressed SEC-1 format. + pub fn toUncompressedSec1(p: Secp256k1) [65]u8 { + var out: [65]u8 = undefined; + out[0] = 4; + const xy = p.affineCoordinates(); + mem.copy(u8, out[1..33], &xy.x.toBytes(.Big)); + mem.copy(u8, out[33..65], &xy.y.toBytes(.Big)); + return out; + } + + /// Return a random point. + pub fn random() Secp256k1 { + const n = scalar.random(.Little); + return basePoint.mul(n, .Little) catch unreachable; + } + + /// Flip the sign of the X coordinate. + pub fn neg(p: Secp256k1) Secp256k1 { + return .{ .x = p.x, .y = p.y.neg(), .z = p.z }; + } + + /// Double a secp256k1 point. + // Algorithm 9 from https://eprint.iacr.org/2015/1060.pdf + pub fn dbl(p: Secp256k1) Secp256k1 { + var t0 = p.y.sq(); + var Z3 = t0.dbl(); + Z3 = Z3.dbl(); + Z3 = Z3.dbl(); + var t1 = p.y.mul(p.z); + var t2 = p.z.sq(); + // b3 = (2^2)^2 + 2^2 + 1 + const t2_4 = t2.dbl().dbl(); + t2 = t2_4.dbl().dbl().add(t2_4).add(t2); + var X3 = t2.mul(Z3); + var Y3 = t0.add(t2); + Z3 = t1.mul(Z3); + t1 = t2.dbl(); + t2 = t1.add(t2); + t0 = t0.sub(t2); + Y3 = t0.mul(Y3); + Y3 = X3.add(Y3); + t1 = p.x.mul(p.y); + X3 = t0.mul(t1); + X3 = X3.dbl(); + return .{ + .x = X3, + .y = Y3, + .z = Z3, + }; + } + + /// Add secp256k1 points, the second being specified using affine coordinates. + // Algorithm 8 from https://eprint.iacr.org/2015/1060.pdf + pub fn addMixed(p: Secp256k1, q: AffineCoordinates) Secp256k1 { + var t0 = p.x.mul(q.x); + var t1 = p.y.mul(q.y); + var t3 = q.x.add(q.y); + var t4 = p.x.add(p.y1); + t3 = t3.mul(t4); + t4 = t0.add(t1); + t3 = t3.sub(t4); + t4 = q.y.mul(p.z); + t4 = t4.add(p.y); + var Y3 = q.x.mul(p.z); + Y3 = Y3.add(p.x); + var X3 = t0.dbl(); + t0 = X3.add(t0); + // b3 = (2^2)^2 + 2^2 + 1 + const t2_4 = p.z.dbl().dbl(); + var t2 = t2_4.dbl().dbl().add(t2_4).add(p.z); + var Z3 = t1.add(t2); + t1 = t1.sub(t2); + const Y3_4 = Y3.dbl().dbl(); + Y3 = Y3_4.dbl().dbl().add(Y3_4).add(Y3); + X3 = t4.mul(Y3); + t2 = t3.mul(t1); + X3 = t2.sub(X3); + Y3 = Y3.mul(t0); + t1 = t1.mul(Z3); + Y3 = t1.add(Y3); + t0 = t0.mul(t3); + Z3 = Z3.mul(t4); + Z3 = Z3.add(t0); + + var ret = Secp256k1{ + .x = X3, + .y = Y3, + .z = Z3, + }; + ret.cMov(p, @boolToInt(q.x.isZero())); + return ret; + } + + /// Add secp256k1 points. + // Algorithm 7 from https://eprint.iacr.org/2015/1060.pdf + pub fn add(p: Secp256k1, q: Secp256k1) Secp256k1 { + var t0 = p.x.mul(q.x); + var t1 = p.y.mul(q.y); + var t2 = p.z.mul(q.z); + var t3 = p.x.add(p.y); + var t4 = q.x.add(q.y); + t3 = t3.mul(t4); + t4 = t0.add(t1); + t3 = t3.sub(t4); + t4 = p.y.add(p.z); + var X3 = q.y.add(q.z); + t4 = t4.mul(X3); + X3 = t1.add(t2); + t4 = t4.sub(X3); + X3 = p.x.add(p.z); + var Y3 = q.x.add(q.z); + X3 = X3.mul(Y3); + Y3 = t0.add(t2); + Y3 = X3.sub(Y3); + X3 = t0.dbl(); + t0 = X3.add(t0); + // b3 = (2^2)^2 + 2^2 + 1 + const t2_4 = t2.dbl().dbl(); + t2 = t2_4.dbl().dbl().add(t2_4).add(t2); + var Z3 = t1.add(t2); + t1 = t1.sub(t2); + const Y3_4 = Y3.dbl().dbl(); + Y3 = Y3_4.dbl().dbl().add(Y3_4).add(Y3); + X3 = t4.mul(Y3); + t2 = t3.mul(t1); + X3 = t2.sub(X3); + Y3 = Y3.mul(t0); + t1 = t1.mul(Z3); + Y3 = t1.add(Y3); + t0 = t0.mul(t3); + Z3 = Z3.mul(t4); + Z3 = Z3.add(t0); + + return .{ + .x = X3, + .y = Y3, + .z = Z3, + }; + } + + /// Subtract secp256k1 points. + pub fn sub(p: Secp256k1, q: Secp256k1) Secp256k1 { + return p.add(q.neg()); + } + + /// Subtract secp256k1 points, the second being specified using affine coordinates. + pub fn subMixed(p: Secp256k1, q: AffineCoordinates) Secp256k1 { + return p.addMixed(q.neg()); + } + + /// Return affine coordinates. + pub fn affineCoordinates(p: Secp256k1) AffineCoordinates { + const zinv = p.z.invert(); + var ret = AffineCoordinates{ + .x = p.x.mul(zinv), + .y = p.y.mul(zinv), + }; + ret.cMov(AffineCoordinates.identityElement, @boolToInt(p.x.isZero())); + return ret; + } + + /// Return true if both coordinate sets represent the same point. + pub fn equivalent(a: Secp256k1, b: Secp256k1) bool { + if (a.sub(b).rejectIdentity()) { + return false; + } else |_| { + return true; + } + } + + fn cMov(p: *Secp256k1, a: Secp256k1, c: u1) void { + p.x.cMov(a.x, c); + p.y.cMov(a.y, c); + p.z.cMov(a.z, c); + } + + fn pcSelect(comptime n: usize, pc: *const [n]Secp256k1, b: u8) Secp256k1 { + var t = Secp256k1.identityElement; + comptime var i: u8 = 1; + inline while (i < pc.len) : (i += 1) { + t.cMov(pc[i], @truncate(u1, (@as(usize, b ^ i) -% 1) >> 8)); + } + return t; + } + + fn slide(s: [32]u8) [2 * 32 + 1]i8 { + var e: [2 * 32 + 1]i8 = undefined; + for (s) |x, i| { + e[i * 2 + 0] = @as(i8, @truncate(u4, x)); + e[i * 2 + 1] = @as(i8, @truncate(u4, x >> 4)); + } + // Now, e[0..63] is between 0 and 15, e[63] is between 0 and 7 + var carry: i8 = 0; + for (e[0..64]) |*x| { + x.* += carry; + carry = (x.* + 8) >> 4; + x.* -= carry * 16; + std.debug.assert(x.* >= -8 and x.* <= 8); + } + e[64] = carry; + // Now, e[*] is between -8 and 8, including e[64] + std.debug.assert(carry >= -8 and carry <= 8); + return e; + } + + fn pcMul(pc: *const [9]Secp256k1, s: [32]u8, comptime vartime: bool) IdentityElementError!Secp256k1 { + std.debug.assert(vartime); + const e = slide(s); + var q = Secp256k1.identityElement; + var pos = e.len - 1; + while (true) : (pos -= 1) { + const slot = e[pos]; + if (slot > 0) { + q = q.add(pc[@intCast(usize, slot)]); + } else if (slot < 0) { + q = q.sub(pc[@intCast(usize, -slot)]); + } + if (pos == 0) break; + q = q.dbl().dbl().dbl().dbl(); + } + try q.rejectIdentity(); + return q; + } + + fn pcMul16(pc: *const [16]Secp256k1, s: [32]u8, comptime vartime: bool) IdentityElementError!Secp256k1 { + var q = Secp256k1.identityElement; + var pos: usize = 252; + while (true) : (pos -= 4) { + const slot = @truncate(u4, (s[pos >> 3] >> @truncate(u3, pos))); + if (vartime) { + if (slot != 0) { + q = q.add(pc[slot]); + } + } else { + q = q.add(pcSelect(16, pc, slot)); + } + if (pos == 0) break; + q = q.dbl().dbl().dbl().dbl(); + } + try q.rejectIdentity(); + return q; + } + + fn precompute(p: Secp256k1, comptime count: usize) [1 + count]Secp256k1 { + var pc: [1 + count]Secp256k1 = undefined; + pc[0] = Secp256k1.identityElement; + pc[1] = p; + var i: usize = 2; + while (i <= count) : (i += 1) { + pc[i] = if (i % 2 == 0) pc[i / 2].dbl() else pc[i - 1].add(p); + } + return pc; + } + + const basePointPc = pc: { + @setEvalBranchQuota(50000); + break :pc precompute(Secp256k1.basePoint, 15); + }; + + /// Multiply an elliptic curve point by a scalar. + /// Return error.IdentityElement if the result is the identity element. + pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 { + const s = if (endian == .Little) s_ else Fe.orderSwap(s_); + if (p.is_base) { + return pcMul16(&basePointPc, s, false); + } + try p.rejectIdentity(); + const pc = precompute(p, 15); + return pcMul16(&pc, s, false); + } + + /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* + /// This can be used for signature verification. + pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 { + const s = if (endian == .Little) s_ else Fe.orderSwap(s_); + const zero = comptime scalar.Scalar.zero.toBytes(.Little); + if (mem.eql(u8, &zero, &s)) { + return error.IdentityElement; + } + const pc = precompute(p, 8); + var lambda_p = try pcMul(&pc, Endormorphism.lambda_s, true); + var split_scalar = Endormorphism.splitScalar(s, .Little); + var px = p; + + // If a key is negative, flip the sign to keep it half-sized, + // and flip the sign of the Y point coordinate to compensate. + if (split_scalar.r1[split_scalar.r1.len / 2] != 0) { + split_scalar.r1 = scalar.neg(split_scalar.r1, .Little) catch zero; + px = px.neg(); + } + if (split_scalar.r2[split_scalar.r2.len / 2] != 0) { + split_scalar.r2 = scalar.neg(split_scalar.r2, .Little) catch zero; + lambda_p = lambda_p.neg(); + } + return mulDoubleBasePublicEndo(px, split_scalar.r1, lambda_p, split_scalar.r2); + } + + // Half-size double-base public multiplication when using the curve endomorphism. + // Scalars must be in little-endian. + // The second point is unlikely to be the generator, so don't even try to use the comptime table for it. + fn mulDoubleBasePublicEndo(p1: Secp256k1, s1: [32]u8, p2: Secp256k1, s2: [32]u8) IdentityElementError!Secp256k1 { + var pc1_array: [9]Secp256k1 = undefined; + const pc1 = if (p1.is_base) basePointPc[0..9] else pc: { + pc1_array = precompute(p1, 8); + break :pc &pc1_array; + }; + const pc2 = precompute(p2, 8); + std.debug.assert(s1[s1.len / 2] == 0); + std.debug.assert(s2[s2.len / 2] == 0); + const e1 = slide(s1); + const e2 = slide(s2); + var q = Secp256k1.identityElement; + var pos: usize = 2 * 32 / 2; // second half is all zero + while (true) : (pos -= 1) { + const slot1 = e1[pos]; + if (slot1 > 0) { + q = q.add(pc1[@intCast(usize, slot1)]); + } else if (slot1 < 0) { + q = q.sub(pc1[@intCast(usize, -slot1)]); + } + const slot2 = e2[pos]; + if (slot2 > 0) { + q = q.add(pc2[@intCast(usize, slot2)]); + } else if (slot2 < 0) { + q = q.sub(pc2[@intCast(usize, -slot2)]); + } + if (pos == 0) break; + q = q.dbl().dbl().dbl().dbl(); + } + try q.rejectIdentity(); + return q; + } + + /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* + /// This can be used for signature verification. + pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 { + const s1 = if (endian == .Little) s1_ else Fe.orderSwap(s1_); + const s2 = if (endian == .Little) s2_ else Fe.orderSwap(s2_); + try p1.rejectIdentity(); + var pc1_array: [9]Secp256k1 = undefined; + const pc1 = if (p1.is_base) basePointPc[0..9] else pc: { + pc1_array = precompute(p1, 8); + break :pc &pc1_array; + }; + try p2.rejectIdentity(); + var pc2_array: [9]Secp256k1 = undefined; + const pc2 = if (p2.is_base) basePointPc[0..9] else pc: { + pc2_array = precompute(p2, 8); + break :pc &pc2_array; + }; + const e1 = slide(s1); + const e2 = slide(s2); + var q = Secp256k1.identityElement; + var pos: usize = 2 * 32; + while (true) : (pos -= 1) { + const slot1 = e1[pos]; + if (slot1 > 0) { + q = q.add(pc1[@intCast(usize, slot1)]); + } else if (slot1 < 0) { + q = q.sub(pc1[@intCast(usize, -slot1)]); + } + const slot2 = e2[pos]; + if (slot2 > 0) { + q = q.add(pc2[@intCast(usize, slot2)]); + } else if (slot2 < 0) { + q = q.sub(pc2[@intCast(usize, -slot2)]); + } + if (pos == 0) break; + q = q.dbl().dbl().dbl().dbl(); + } + try q.rejectIdentity(); + return q; + } +}; + +/// A point in affine coordinates. +pub const AffineCoordinates = struct { + x: Secp256k1.Fe, + y: Secp256k1.Fe, + + /// Identity element in affine coordinates. + pub const identityElement = AffineCoordinates{ .x = Secp256k1.identityElement.x, .y = Secp256k1.identityElement.y }; + + fn cMov(p: *AffineCoordinates, a: AffineCoordinates, c: u1) void { + p.x.cMov(a.x, c); + p.y.cMov(a.y, c); + } +}; + +test "secp256k1" { + _ = @import("tests/secp256k1.zig"); +} diff --git a/lib/std/crypto/pcurves/secp256k1/field.zig b/lib/std/crypto/pcurves/secp256k1/field.zig new file mode 100644 index 000000000000..e8113196c6dd --- /dev/null +++ b/lib/std/crypto/pcurves/secp256k1/field.zig @@ -0,0 +1,12 @@ +const std = @import("std"); +const common = @import("../common.zig"); + +const Field = common.Field; + +pub const Fe = Field(.{ + .fiat = @import("secp256k1_64.zig"), + .field_order = 115792089237316195423570985008687907853269984665640564039457584007908834671663, + .field_bits = 256, + .saturated_bits = 256, + .encoded_length = 32, +}); diff --git a/lib/std/crypto/pcurves/secp256k1/scalar.zig b/lib/std/crypto/pcurves/secp256k1/scalar.zig new file mode 100644 index 000000000000..2d91f8bc99b6 --- /dev/null +++ b/lib/std/crypto/pcurves/secp256k1/scalar.zig @@ -0,0 +1,227 @@ +const std = @import("std"); +const common = @import("../common.zig"); +const crypto = std.crypto; +const debug = std.debug; +const math = std.math; +const mem = std.mem; + +const Field = common.Field; + +const NonCanonicalError = std.crypto.errors.NonCanonicalError; +const NotSquareError = std.crypto.errors.NotSquareError; + +/// Number of bytes required to encode a scalar. +pub const encoded_length = 32; + +/// A compressed scalar, in canonical form. +pub const CompressedScalar = [encoded_length]u8; + +const Fe = Field(.{ + .fiat = @import("secp256k1_scalar_64.zig"), + .field_order = 115792089237316195423570985008687907852837564279074904382605163141518161494337, + .field_bits = 256, + .saturated_bits = 256, + .encoded_length = encoded_length, +}); + +/// The scalar field order. +pub const field_order = Fe.field_order; + +/// Reject a scalar whose encoding is not canonical. +pub fn rejectNonCanonical(s: CompressedScalar, endian: std.builtin.Endian) NonCanonicalError!void { + return Fe.rejectNonCanonical(s, endian); +} + +/// Reduce a 48-bytes scalar to the field size. +pub fn reduce48(s: [48]u8, endian: std.builtin.Endian) CompressedScalar { + return Scalar.fromBytes48(s, endian).toBytes(endian); +} + +/// Reduce a 64-bytes scalar to the field size. +pub fn reduce64(s: [64]u8, endian: std.builtin.Endian) CompressedScalar { + return ScalarDouble.fromBytes64(s, endian).toBytes(endian); +} + +/// Return a*b (mod L) +pub fn mul(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) NonCanonicalError!CompressedScalar { + return (try Scalar.fromBytes(a, endian)).mul(try Scalar.fromBytes(b, endian)).toBytes(endian); +} + +/// Return a*b+c (mod L) +pub fn mulAdd(a: CompressedScalar, b: CompressedScalar, c: CompressedScalar, endian: std.builtin.Endian) NonCanonicalError!CompressedScalar { + return (try Scalar.fromBytes(a, endian)).mul(try Scalar.fromBytes(b, endian)).add(try Scalar.fromBytes(c, endian)).toBytes(endian); +} + +/// Return a+b (mod L) +pub fn add(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) NonCanonicalError!CompressedScalar { + return (try Scalar.fromBytes(a, endian)).add(try Scalar.fromBytes(b, endian)).toBytes(endian); +} + +/// Return -s (mod L) +pub fn neg(s: CompressedScalar, endian: std.builtin.Endian) NonCanonicalError!CompressedScalar { + return (try Scalar.fromBytes(s, endian)).neg().toBytes(endian); +} + +/// Return (a-b) (mod L) +pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) NonCanonicalError!CompressedScalar { + return (try Scalar.fromBytes(a, endian)).sub(try Scalar.fromBytes(b, endian)).toBytes(endian); +} + +/// Return a random scalar +pub fn random(endian: std.builtin.Endian) CompressedScalar { + return Scalar.random().toBytes(endian); +} + +/// A scalar in unpacked representation. +pub const Scalar = struct { + fe: Fe, + + /// Zero. + pub const zero = Scalar{ .fe = Fe.zero }; + + /// One. + pub const one = Scalar{ .fe = Fe.one }; + + /// Unpack a serialized representation of a scalar. + pub fn fromBytes(s: CompressedScalar, endian: std.builtin.Endian) NonCanonicalError!Scalar { + return Scalar{ .fe = try Fe.fromBytes(s, endian) }; + } + + /// Reduce a 384 bit input to the field size. + pub fn fromBytes48(s: [48]u8, endian: std.builtin.Endian) Scalar { + const t = ScalarDouble.fromBytes(384, s, endian); + return t.reduce(384); + } + + /// Reduce a 512 bit input to the field size. + pub fn fromBytes64(s: [64]u8, endian: std.builtin.Endian) Scalar { + const t = ScalarDouble.fromBytes(512, s, endian); + return t.reduce(512); + } + + /// Pack a scalar into bytes. + pub fn toBytes(n: Scalar, endian: std.builtin.Endian) CompressedScalar { + return n.fe.toBytes(endian); + } + + /// Return true if the scalar is zero.. + pub fn isZero(n: Scalar) bool { + return n.fe.isZero(); + } + + /// Return true if a and b are equivalent. + pub fn equivalent(a: Scalar, b: Scalar) bool { + return a.fe.equivalent(b.fe); + } + + /// Compute x+y (mod L) + pub fn add(x: Scalar, y: Scalar) Scalar { + return Scalar{ .fe = x.fe.add(y.fe) }; + } + + /// Compute x-y (mod L) + pub fn sub(x: Scalar, y: Scalar) Scalar { + return Scalar{ .fe = x.fe.sub(y.fe) }; + } + + /// Compute 2n (mod L) + pub fn dbl(n: Scalar) Scalar { + return Scalar{ .fe = n.fe.dbl() }; + } + + /// Compute x*y (mod L) + pub fn mul(x: Scalar, y: Scalar) Scalar { + return Scalar{ .fe = x.fe.mul(y.fe) }; + } + + /// Compute x^2 (mod L) + pub fn sq(n: Scalar) Scalar { + return Scalar{ .fe = n.fe.sq() }; + } + + /// Compute x^n (mod L) + pub fn pow(a: Scalar, comptime T: type, comptime n: T) Scalar { + return Scalar{ .fe = a.fe.pow(n) }; + } + + /// Compute -x (mod L) + pub fn neg(n: Scalar) Scalar { + return Scalar{ .fe = n.fe.neg() }; + } + + /// Compute x^-1 (mod L) + pub fn invert(n: Scalar) Scalar { + return Scalar{ .fe = n.fe.invert() }; + } + + /// Return true if n is a quadratic residue mod L. + pub fn isSquare(n: Scalar) Scalar { + return n.fe.isSquare(); + } + + /// Return the square root of L, or NotSquare if there isn't any solutions. + pub fn sqrt(n: Scalar) NotSquareError!Scalar { + return Scalar{ .fe = try n.fe.sqrt() }; + } + + /// Return a random scalar < L. + pub fn random() Scalar { + var s: [48]u8 = undefined; + while (true) { + crypto.random.bytes(&s); + const n = Scalar.fromBytes48(s, .Little); + if (!n.isZero()) { + return n; + } + } + } +}; + +const ScalarDouble = struct { + x1: Fe, + x2: Fe, + x3: Fe, + + fn fromBytes(comptime bits: usize, s_: [bits / 8]u8, endian: std.builtin.Endian) ScalarDouble { + debug.assert(bits > 0 and bits <= 512 and bits >= Fe.saturated_bits and bits <= Fe.saturated_bits * 3); + + var s = s_; + if (endian == .Big) { + for (s_) |x, i| s[s.len - 1 - i] = x; + } + var t = ScalarDouble{ .x1 = undefined, .x2 = Fe.zero, .x3 = Fe.zero }; + { + var b = [_]u8{0} ** encoded_length; + const len = math.min(s.len, 24); + mem.copy(u8, b[0..len], s[0..len]); + t.x1 = Fe.fromBytes(b, .Little) catch unreachable; + } + if (s_.len >= 24) { + var b = [_]u8{0} ** encoded_length; + const len = math.min(s.len - 24, 24); + mem.copy(u8, b[0..len], s[24..][0..len]); + t.x2 = Fe.fromBytes(b, .Little) catch unreachable; + } + if (s_.len >= 48) { + var b = [_]u8{0} ** encoded_length; + const len = s.len - 48; + mem.copy(u8, b[0..len], s[48..][0..len]); + t.x3 = Fe.fromBytes(b, .Little) catch unreachable; + } + return t; + } + + fn reduce(expanded: ScalarDouble, comptime bits: usize) Scalar { + debug.assert(bits > 0 and bits <= Fe.saturated_bits * 3 and bits <= 512); + var fe = expanded.x1; + if (bits >= 192) { + const st1 = Fe.fromInt(1 << 192) catch unreachable; + fe = fe.add(expanded.x2.mul(st1)); + if (bits >= 384) { + const st2 = st1.sq(); + fe = fe.add(expanded.x3.mul(st2)); + } + } + return Scalar{ .fe = fe }; + } +}; diff --git a/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig b/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig new file mode 100644 index 000000000000..2309b48ac97f --- /dev/null +++ b/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig @@ -0,0 +1,1964 @@ +// Autogenerated: 'src/ExtractionOCaml/word_by_word_montgomery' --lang Zig --internal-static --public-function-case camelCase --private-function-case camelCase --public-type-case UpperCamelCase --private-type-case UpperCamelCase --no-prefix-fiat --package-name secp256k1 '' 64 '2^256 - 2^32 - 977' mul square add sub opp from_montgomery to_montgomery nonzero selectznz to_bytes from_bytes one msat divstep divstep_precomp +// curve description (via package name): secp256k1 +// machine_wordsize = 64 (from "64") +// requested operations: mul, square, add, sub, opp, from_montgomery, to_montgomery, nonzero, selectznz, to_bytes, from_bytes, one, msat, divstep, divstep_precomp +// m = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f (from "2^256 - 2^32 - 977") +// +// NOTE: In addition to the bounds specified above each function, all +// functions synthesized for this Montgomery arithmetic require the +// input to be strictly less than the prime modulus (m), and also +// require the input to be in the unique saturated representation. +// All functions also ensure that these two properties are true of +// return values. +// +// Computed values: +// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) +// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) +// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in +// if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 + +const std = @import("std"); +const mode = @import("builtin").mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels + +// The type MontgomeryDomainFieldElement is a field element in the Montgomery domain. +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub const MontgomeryDomainFieldElement = [4]u64; + +// The type NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub const NonMontgomeryDomainFieldElement = [4]u64; + +/// The function addcarryxU64 is an addition with carry. +/// +/// Postconditions: +/// out1 = (arg1 + arg2 + arg3) mod 2^64 +/// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋ +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0x1] +/// arg2: [0x0 ~> 0xffffffffffffffff] +/// arg3: [0x0 ~> 0xffffffffffffffff] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +/// out2: [0x0 ~> 0x1] +inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { + @setRuntimeSafety(mode == .Debug); + + var t: u64 = undefined; + const carry1 = @addWithOverflow(u64, arg2, arg3, &t); + const carry2 = @addWithOverflow(u64, t, arg1, out1); + out2.* = @boolToInt(carry1) | @boolToInt(carry2); +} + +/// The function subborrowxU64 is a subtraction with borrow. +/// +/// Postconditions: +/// out1 = (-arg1 + arg2 + -arg3) mod 2^64 +/// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋ +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0x1] +/// arg2: [0x0 ~> 0xffffffffffffffff] +/// arg3: [0x0 ~> 0xffffffffffffffff] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +/// out2: [0x0 ~> 0x1] +inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { + @setRuntimeSafety(mode == .Debug); + + var t: u64 = undefined; + const carry1 = @subWithOverflow(u64, arg2, arg3, &t); + const carry2 = @subWithOverflow(u64, t, arg1, out1); + out2.* = @boolToInt(carry1) | @boolToInt(carry2); +} + +/// The function mulxU64 is a multiplication, returning the full double-width result. +/// +/// Postconditions: +/// out1 = (arg1 * arg2) mod 2^64 +/// out2 = ⌊arg1 * arg2 / 2^64⌋ +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0xffffffffffffffff] +/// arg2: [0x0 ~> 0xffffffffffffffff] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +/// out2: [0x0 ~> 0xffffffffffffffff] +inline fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { + @setRuntimeSafety(mode == .Debug); + + const x = @as(u128, arg1) * @as(u128, arg2); + out1.* = @truncate(u64, x); + out2.* = @truncate(u64, x >> 64); +} + +/// The function cmovznzU64 is a single-word conditional move. +/// +/// Postconditions: +/// out1 = (if arg1 = 0 then arg2 else arg3) +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0x1] +/// arg2: [0x0 ~> 0xffffffffffffffff] +/// arg3: [0x0 ~> 0xffffffffffffffff] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { + @setRuntimeSafety(mode == .Debug); + + const mask = 0 -% @as(u64, arg1); + out1.* = (mask & arg3) | ((~mask) & arg2); +} + +/// The function mul multiplies two field elements in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// 0 ≤ eval arg2 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m +/// 0 ≤ eval out1 < m +/// +pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[1]); + const x2 = (arg1[2]); + const x3 = (arg1[3]); + const x4 = (arg1[0]); + var x5: u64 = undefined; + var x6: u64 = undefined; + mulxU64(&x5, &x6, x4, (arg2[3])); + var x7: u64 = undefined; + var x8: u64 = undefined; + mulxU64(&x7, &x8, x4, (arg2[2])); + var x9: u64 = undefined; + var x10: u64 = undefined; + mulxU64(&x9, &x10, x4, (arg2[1])); + var x11: u64 = undefined; + var x12: u64 = undefined; + mulxU64(&x11, &x12, x4, (arg2[0])); + var x13: u64 = undefined; + var x14: u1 = undefined; + addcarryxU64(&x13, &x14, 0x0, x12, x9); + var x15: u64 = undefined; + var x16: u1 = undefined; + addcarryxU64(&x15, &x16, x14, x10, x7); + var x17: u64 = undefined; + var x18: u1 = undefined; + addcarryxU64(&x17, &x18, x16, x8, x5); + const x19 = (@as(u64, x18) + x6); + var x20: u64 = undefined; + var x21: u64 = undefined; + mulxU64(&x20, &x21, x11, 0xd838091dd2253531); + var x22: u64 = undefined; + var x23: u64 = undefined; + mulxU64(&x22, &x23, x20, 0xffffffffffffffff); + var x24: u64 = undefined; + var x25: u64 = undefined; + mulxU64(&x24, &x25, x20, 0xffffffffffffffff); + var x26: u64 = undefined; + var x27: u64 = undefined; + mulxU64(&x26, &x27, x20, 0xffffffffffffffff); + var x28: u64 = undefined; + var x29: u64 = undefined; + mulxU64(&x28, &x29, x20, 0xfffffffefffffc2f); + var x30: u64 = undefined; + var x31: u1 = undefined; + addcarryxU64(&x30, &x31, 0x0, x29, x26); + var x32: u64 = undefined; + var x33: u1 = undefined; + addcarryxU64(&x32, &x33, x31, x27, x24); + var x34: u64 = undefined; + var x35: u1 = undefined; + addcarryxU64(&x34, &x35, x33, x25, x22); + const x36 = (@as(u64, x35) + x23); + var x37: u64 = undefined; + var x38: u1 = undefined; + addcarryxU64(&x37, &x38, 0x0, x11, x28); + var x39: u64 = undefined; + var x40: u1 = undefined; + addcarryxU64(&x39, &x40, x38, x13, x30); + var x41: u64 = undefined; + var x42: u1 = undefined; + addcarryxU64(&x41, &x42, x40, x15, x32); + var x43: u64 = undefined; + var x44: u1 = undefined; + addcarryxU64(&x43, &x44, x42, x17, x34); + var x45: u64 = undefined; + var x46: u1 = undefined; + addcarryxU64(&x45, &x46, x44, x19, x36); + var x47: u64 = undefined; + var x48: u64 = undefined; + mulxU64(&x47, &x48, x1, (arg2[3])); + var x49: u64 = undefined; + var x50: u64 = undefined; + mulxU64(&x49, &x50, x1, (arg2[2])); + var x51: u64 = undefined; + var x52: u64 = undefined; + mulxU64(&x51, &x52, x1, (arg2[1])); + var x53: u64 = undefined; + var x54: u64 = undefined; + mulxU64(&x53, &x54, x1, (arg2[0])); + var x55: u64 = undefined; + var x56: u1 = undefined; + addcarryxU64(&x55, &x56, 0x0, x54, x51); + var x57: u64 = undefined; + var x58: u1 = undefined; + addcarryxU64(&x57, &x58, x56, x52, x49); + var x59: u64 = undefined; + var x60: u1 = undefined; + addcarryxU64(&x59, &x60, x58, x50, x47); + const x61 = (@as(u64, x60) + x48); + var x62: u64 = undefined; + var x63: u1 = undefined; + addcarryxU64(&x62, &x63, 0x0, x39, x53); + var x64: u64 = undefined; + var x65: u1 = undefined; + addcarryxU64(&x64, &x65, x63, x41, x55); + var x66: u64 = undefined; + var x67: u1 = undefined; + addcarryxU64(&x66, &x67, x65, x43, x57); + var x68: u64 = undefined; + var x69: u1 = undefined; + addcarryxU64(&x68, &x69, x67, x45, x59); + var x70: u64 = undefined; + var x71: u1 = undefined; + addcarryxU64(&x70, &x71, x69, @as(u64, x46), x61); + var x72: u64 = undefined; + var x73: u64 = undefined; + mulxU64(&x72, &x73, x62, 0xd838091dd2253531); + var x74: u64 = undefined; + var x75: u64 = undefined; + mulxU64(&x74, &x75, x72, 0xffffffffffffffff); + var x76: u64 = undefined; + var x77: u64 = undefined; + mulxU64(&x76, &x77, x72, 0xffffffffffffffff); + var x78: u64 = undefined; + var x79: u64 = undefined; + mulxU64(&x78, &x79, x72, 0xffffffffffffffff); + var x80: u64 = undefined; + var x81: u64 = undefined; + mulxU64(&x80, &x81, x72, 0xfffffffefffffc2f); + var x82: u64 = undefined; + var x83: u1 = undefined; + addcarryxU64(&x82, &x83, 0x0, x81, x78); + var x84: u64 = undefined; + var x85: u1 = undefined; + addcarryxU64(&x84, &x85, x83, x79, x76); + var x86: u64 = undefined; + var x87: u1 = undefined; + addcarryxU64(&x86, &x87, x85, x77, x74); + const x88 = (@as(u64, x87) + x75); + var x89: u64 = undefined; + var x90: u1 = undefined; + addcarryxU64(&x89, &x90, 0x0, x62, x80); + var x91: u64 = undefined; + var x92: u1 = undefined; + addcarryxU64(&x91, &x92, x90, x64, x82); + var x93: u64 = undefined; + var x94: u1 = undefined; + addcarryxU64(&x93, &x94, x92, x66, x84); + var x95: u64 = undefined; + var x96: u1 = undefined; + addcarryxU64(&x95, &x96, x94, x68, x86); + var x97: u64 = undefined; + var x98: u1 = undefined; + addcarryxU64(&x97, &x98, x96, x70, x88); + const x99 = (@as(u64, x98) + @as(u64, x71)); + var x100: u64 = undefined; + var x101: u64 = undefined; + mulxU64(&x100, &x101, x2, (arg2[3])); + var x102: u64 = undefined; + var x103: u64 = undefined; + mulxU64(&x102, &x103, x2, (arg2[2])); + var x104: u64 = undefined; + var x105: u64 = undefined; + mulxU64(&x104, &x105, x2, (arg2[1])); + var x106: u64 = undefined; + var x107: u64 = undefined; + mulxU64(&x106, &x107, x2, (arg2[0])); + var x108: u64 = undefined; + var x109: u1 = undefined; + addcarryxU64(&x108, &x109, 0x0, x107, x104); + var x110: u64 = undefined; + var x111: u1 = undefined; + addcarryxU64(&x110, &x111, x109, x105, x102); + var x112: u64 = undefined; + var x113: u1 = undefined; + addcarryxU64(&x112, &x113, x111, x103, x100); + const x114 = (@as(u64, x113) + x101); + var x115: u64 = undefined; + var x116: u1 = undefined; + addcarryxU64(&x115, &x116, 0x0, x91, x106); + var x117: u64 = undefined; + var x118: u1 = undefined; + addcarryxU64(&x117, &x118, x116, x93, x108); + var x119: u64 = undefined; + var x120: u1 = undefined; + addcarryxU64(&x119, &x120, x118, x95, x110); + var x121: u64 = undefined; + var x122: u1 = undefined; + addcarryxU64(&x121, &x122, x120, x97, x112); + var x123: u64 = undefined; + var x124: u1 = undefined; + addcarryxU64(&x123, &x124, x122, x99, x114); + var x125: u64 = undefined; + var x126: u64 = undefined; + mulxU64(&x125, &x126, x115, 0xd838091dd2253531); + var x127: u64 = undefined; + var x128: u64 = undefined; + mulxU64(&x127, &x128, x125, 0xffffffffffffffff); + var x129: u64 = undefined; + var x130: u64 = undefined; + mulxU64(&x129, &x130, x125, 0xffffffffffffffff); + var x131: u64 = undefined; + var x132: u64 = undefined; + mulxU64(&x131, &x132, x125, 0xffffffffffffffff); + var x133: u64 = undefined; + var x134: u64 = undefined; + mulxU64(&x133, &x134, x125, 0xfffffffefffffc2f); + var x135: u64 = undefined; + var x136: u1 = undefined; + addcarryxU64(&x135, &x136, 0x0, x134, x131); + var x137: u64 = undefined; + var x138: u1 = undefined; + addcarryxU64(&x137, &x138, x136, x132, x129); + var x139: u64 = undefined; + var x140: u1 = undefined; + addcarryxU64(&x139, &x140, x138, x130, x127); + const x141 = (@as(u64, x140) + x128); + var x142: u64 = undefined; + var x143: u1 = undefined; + addcarryxU64(&x142, &x143, 0x0, x115, x133); + var x144: u64 = undefined; + var x145: u1 = undefined; + addcarryxU64(&x144, &x145, x143, x117, x135); + var x146: u64 = undefined; + var x147: u1 = undefined; + addcarryxU64(&x146, &x147, x145, x119, x137); + var x148: u64 = undefined; + var x149: u1 = undefined; + addcarryxU64(&x148, &x149, x147, x121, x139); + var x150: u64 = undefined; + var x151: u1 = undefined; + addcarryxU64(&x150, &x151, x149, x123, x141); + const x152 = (@as(u64, x151) + @as(u64, x124)); + var x153: u64 = undefined; + var x154: u64 = undefined; + mulxU64(&x153, &x154, x3, (arg2[3])); + var x155: u64 = undefined; + var x156: u64 = undefined; + mulxU64(&x155, &x156, x3, (arg2[2])); + var x157: u64 = undefined; + var x158: u64 = undefined; + mulxU64(&x157, &x158, x3, (arg2[1])); + var x159: u64 = undefined; + var x160: u64 = undefined; + mulxU64(&x159, &x160, x3, (arg2[0])); + var x161: u64 = undefined; + var x162: u1 = undefined; + addcarryxU64(&x161, &x162, 0x0, x160, x157); + var x163: u64 = undefined; + var x164: u1 = undefined; + addcarryxU64(&x163, &x164, x162, x158, x155); + var x165: u64 = undefined; + var x166: u1 = undefined; + addcarryxU64(&x165, &x166, x164, x156, x153); + const x167 = (@as(u64, x166) + x154); + var x168: u64 = undefined; + var x169: u1 = undefined; + addcarryxU64(&x168, &x169, 0x0, x144, x159); + var x170: u64 = undefined; + var x171: u1 = undefined; + addcarryxU64(&x170, &x171, x169, x146, x161); + var x172: u64 = undefined; + var x173: u1 = undefined; + addcarryxU64(&x172, &x173, x171, x148, x163); + var x174: u64 = undefined; + var x175: u1 = undefined; + addcarryxU64(&x174, &x175, x173, x150, x165); + var x176: u64 = undefined; + var x177: u1 = undefined; + addcarryxU64(&x176, &x177, x175, x152, x167); + var x178: u64 = undefined; + var x179: u64 = undefined; + mulxU64(&x178, &x179, x168, 0xd838091dd2253531); + var x180: u64 = undefined; + var x181: u64 = undefined; + mulxU64(&x180, &x181, x178, 0xffffffffffffffff); + var x182: u64 = undefined; + var x183: u64 = undefined; + mulxU64(&x182, &x183, x178, 0xffffffffffffffff); + var x184: u64 = undefined; + var x185: u64 = undefined; + mulxU64(&x184, &x185, x178, 0xffffffffffffffff); + var x186: u64 = undefined; + var x187: u64 = undefined; + mulxU64(&x186, &x187, x178, 0xfffffffefffffc2f); + var x188: u64 = undefined; + var x189: u1 = undefined; + addcarryxU64(&x188, &x189, 0x0, x187, x184); + var x190: u64 = undefined; + var x191: u1 = undefined; + addcarryxU64(&x190, &x191, x189, x185, x182); + var x192: u64 = undefined; + var x193: u1 = undefined; + addcarryxU64(&x192, &x193, x191, x183, x180); + const x194 = (@as(u64, x193) + x181); + var x195: u64 = undefined; + var x196: u1 = undefined; + addcarryxU64(&x195, &x196, 0x0, x168, x186); + var x197: u64 = undefined; + var x198: u1 = undefined; + addcarryxU64(&x197, &x198, x196, x170, x188); + var x199: u64 = undefined; + var x200: u1 = undefined; + addcarryxU64(&x199, &x200, x198, x172, x190); + var x201: u64 = undefined; + var x202: u1 = undefined; + addcarryxU64(&x201, &x202, x200, x174, x192); + var x203: u64 = undefined; + var x204: u1 = undefined; + addcarryxU64(&x203, &x204, x202, x176, x194); + const x205 = (@as(u64, x204) + @as(u64, x177)); + var x206: u64 = undefined; + var x207: u1 = undefined; + subborrowxU64(&x206, &x207, 0x0, x197, 0xfffffffefffffc2f); + var x208: u64 = undefined; + var x209: u1 = undefined; + subborrowxU64(&x208, &x209, x207, x199, 0xffffffffffffffff); + var x210: u64 = undefined; + var x211: u1 = undefined; + subborrowxU64(&x210, &x211, x209, x201, 0xffffffffffffffff); + var x212: u64 = undefined; + var x213: u1 = undefined; + subborrowxU64(&x212, &x213, x211, x203, 0xffffffffffffffff); + var x214: u64 = undefined; + var x215: u1 = undefined; + subborrowxU64(&x214, &x215, x213, x205, 0x0); + var x216: u64 = undefined; + cmovznzU64(&x216, x215, x206, x197); + var x217: u64 = undefined; + cmovznzU64(&x217, x215, x208, x199); + var x218: u64 = undefined; + cmovznzU64(&x218, x215, x210, x201); + var x219: u64 = undefined; + cmovznzU64(&x219, x215, x212, x203); + out1[0] = x216; + out1[1] = x217; + out1[2] = x218; + out1[3] = x219; +} + +/// The function square squares a field element in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m +/// 0 ≤ eval out1 < m +/// +pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[1]); + const x2 = (arg1[2]); + const x3 = (arg1[3]); + const x4 = (arg1[0]); + var x5: u64 = undefined; + var x6: u64 = undefined; + mulxU64(&x5, &x6, x4, (arg1[3])); + var x7: u64 = undefined; + var x8: u64 = undefined; + mulxU64(&x7, &x8, x4, (arg1[2])); + var x9: u64 = undefined; + var x10: u64 = undefined; + mulxU64(&x9, &x10, x4, (arg1[1])); + var x11: u64 = undefined; + var x12: u64 = undefined; + mulxU64(&x11, &x12, x4, (arg1[0])); + var x13: u64 = undefined; + var x14: u1 = undefined; + addcarryxU64(&x13, &x14, 0x0, x12, x9); + var x15: u64 = undefined; + var x16: u1 = undefined; + addcarryxU64(&x15, &x16, x14, x10, x7); + var x17: u64 = undefined; + var x18: u1 = undefined; + addcarryxU64(&x17, &x18, x16, x8, x5); + const x19 = (@as(u64, x18) + x6); + var x20: u64 = undefined; + var x21: u64 = undefined; + mulxU64(&x20, &x21, x11, 0xd838091dd2253531); + var x22: u64 = undefined; + var x23: u64 = undefined; + mulxU64(&x22, &x23, x20, 0xffffffffffffffff); + var x24: u64 = undefined; + var x25: u64 = undefined; + mulxU64(&x24, &x25, x20, 0xffffffffffffffff); + var x26: u64 = undefined; + var x27: u64 = undefined; + mulxU64(&x26, &x27, x20, 0xffffffffffffffff); + var x28: u64 = undefined; + var x29: u64 = undefined; + mulxU64(&x28, &x29, x20, 0xfffffffefffffc2f); + var x30: u64 = undefined; + var x31: u1 = undefined; + addcarryxU64(&x30, &x31, 0x0, x29, x26); + var x32: u64 = undefined; + var x33: u1 = undefined; + addcarryxU64(&x32, &x33, x31, x27, x24); + var x34: u64 = undefined; + var x35: u1 = undefined; + addcarryxU64(&x34, &x35, x33, x25, x22); + const x36 = (@as(u64, x35) + x23); + var x37: u64 = undefined; + var x38: u1 = undefined; + addcarryxU64(&x37, &x38, 0x0, x11, x28); + var x39: u64 = undefined; + var x40: u1 = undefined; + addcarryxU64(&x39, &x40, x38, x13, x30); + var x41: u64 = undefined; + var x42: u1 = undefined; + addcarryxU64(&x41, &x42, x40, x15, x32); + var x43: u64 = undefined; + var x44: u1 = undefined; + addcarryxU64(&x43, &x44, x42, x17, x34); + var x45: u64 = undefined; + var x46: u1 = undefined; + addcarryxU64(&x45, &x46, x44, x19, x36); + var x47: u64 = undefined; + var x48: u64 = undefined; + mulxU64(&x47, &x48, x1, (arg1[3])); + var x49: u64 = undefined; + var x50: u64 = undefined; + mulxU64(&x49, &x50, x1, (arg1[2])); + var x51: u64 = undefined; + var x52: u64 = undefined; + mulxU64(&x51, &x52, x1, (arg1[1])); + var x53: u64 = undefined; + var x54: u64 = undefined; + mulxU64(&x53, &x54, x1, (arg1[0])); + var x55: u64 = undefined; + var x56: u1 = undefined; + addcarryxU64(&x55, &x56, 0x0, x54, x51); + var x57: u64 = undefined; + var x58: u1 = undefined; + addcarryxU64(&x57, &x58, x56, x52, x49); + var x59: u64 = undefined; + var x60: u1 = undefined; + addcarryxU64(&x59, &x60, x58, x50, x47); + const x61 = (@as(u64, x60) + x48); + var x62: u64 = undefined; + var x63: u1 = undefined; + addcarryxU64(&x62, &x63, 0x0, x39, x53); + var x64: u64 = undefined; + var x65: u1 = undefined; + addcarryxU64(&x64, &x65, x63, x41, x55); + var x66: u64 = undefined; + var x67: u1 = undefined; + addcarryxU64(&x66, &x67, x65, x43, x57); + var x68: u64 = undefined; + var x69: u1 = undefined; + addcarryxU64(&x68, &x69, x67, x45, x59); + var x70: u64 = undefined; + var x71: u1 = undefined; + addcarryxU64(&x70, &x71, x69, @as(u64, x46), x61); + var x72: u64 = undefined; + var x73: u64 = undefined; + mulxU64(&x72, &x73, x62, 0xd838091dd2253531); + var x74: u64 = undefined; + var x75: u64 = undefined; + mulxU64(&x74, &x75, x72, 0xffffffffffffffff); + var x76: u64 = undefined; + var x77: u64 = undefined; + mulxU64(&x76, &x77, x72, 0xffffffffffffffff); + var x78: u64 = undefined; + var x79: u64 = undefined; + mulxU64(&x78, &x79, x72, 0xffffffffffffffff); + var x80: u64 = undefined; + var x81: u64 = undefined; + mulxU64(&x80, &x81, x72, 0xfffffffefffffc2f); + var x82: u64 = undefined; + var x83: u1 = undefined; + addcarryxU64(&x82, &x83, 0x0, x81, x78); + var x84: u64 = undefined; + var x85: u1 = undefined; + addcarryxU64(&x84, &x85, x83, x79, x76); + var x86: u64 = undefined; + var x87: u1 = undefined; + addcarryxU64(&x86, &x87, x85, x77, x74); + const x88 = (@as(u64, x87) + x75); + var x89: u64 = undefined; + var x90: u1 = undefined; + addcarryxU64(&x89, &x90, 0x0, x62, x80); + var x91: u64 = undefined; + var x92: u1 = undefined; + addcarryxU64(&x91, &x92, x90, x64, x82); + var x93: u64 = undefined; + var x94: u1 = undefined; + addcarryxU64(&x93, &x94, x92, x66, x84); + var x95: u64 = undefined; + var x96: u1 = undefined; + addcarryxU64(&x95, &x96, x94, x68, x86); + var x97: u64 = undefined; + var x98: u1 = undefined; + addcarryxU64(&x97, &x98, x96, x70, x88); + const x99 = (@as(u64, x98) + @as(u64, x71)); + var x100: u64 = undefined; + var x101: u64 = undefined; + mulxU64(&x100, &x101, x2, (arg1[3])); + var x102: u64 = undefined; + var x103: u64 = undefined; + mulxU64(&x102, &x103, x2, (arg1[2])); + var x104: u64 = undefined; + var x105: u64 = undefined; + mulxU64(&x104, &x105, x2, (arg1[1])); + var x106: u64 = undefined; + var x107: u64 = undefined; + mulxU64(&x106, &x107, x2, (arg1[0])); + var x108: u64 = undefined; + var x109: u1 = undefined; + addcarryxU64(&x108, &x109, 0x0, x107, x104); + var x110: u64 = undefined; + var x111: u1 = undefined; + addcarryxU64(&x110, &x111, x109, x105, x102); + var x112: u64 = undefined; + var x113: u1 = undefined; + addcarryxU64(&x112, &x113, x111, x103, x100); + const x114 = (@as(u64, x113) + x101); + var x115: u64 = undefined; + var x116: u1 = undefined; + addcarryxU64(&x115, &x116, 0x0, x91, x106); + var x117: u64 = undefined; + var x118: u1 = undefined; + addcarryxU64(&x117, &x118, x116, x93, x108); + var x119: u64 = undefined; + var x120: u1 = undefined; + addcarryxU64(&x119, &x120, x118, x95, x110); + var x121: u64 = undefined; + var x122: u1 = undefined; + addcarryxU64(&x121, &x122, x120, x97, x112); + var x123: u64 = undefined; + var x124: u1 = undefined; + addcarryxU64(&x123, &x124, x122, x99, x114); + var x125: u64 = undefined; + var x126: u64 = undefined; + mulxU64(&x125, &x126, x115, 0xd838091dd2253531); + var x127: u64 = undefined; + var x128: u64 = undefined; + mulxU64(&x127, &x128, x125, 0xffffffffffffffff); + var x129: u64 = undefined; + var x130: u64 = undefined; + mulxU64(&x129, &x130, x125, 0xffffffffffffffff); + var x131: u64 = undefined; + var x132: u64 = undefined; + mulxU64(&x131, &x132, x125, 0xffffffffffffffff); + var x133: u64 = undefined; + var x134: u64 = undefined; + mulxU64(&x133, &x134, x125, 0xfffffffefffffc2f); + var x135: u64 = undefined; + var x136: u1 = undefined; + addcarryxU64(&x135, &x136, 0x0, x134, x131); + var x137: u64 = undefined; + var x138: u1 = undefined; + addcarryxU64(&x137, &x138, x136, x132, x129); + var x139: u64 = undefined; + var x140: u1 = undefined; + addcarryxU64(&x139, &x140, x138, x130, x127); + const x141 = (@as(u64, x140) + x128); + var x142: u64 = undefined; + var x143: u1 = undefined; + addcarryxU64(&x142, &x143, 0x0, x115, x133); + var x144: u64 = undefined; + var x145: u1 = undefined; + addcarryxU64(&x144, &x145, x143, x117, x135); + var x146: u64 = undefined; + var x147: u1 = undefined; + addcarryxU64(&x146, &x147, x145, x119, x137); + var x148: u64 = undefined; + var x149: u1 = undefined; + addcarryxU64(&x148, &x149, x147, x121, x139); + var x150: u64 = undefined; + var x151: u1 = undefined; + addcarryxU64(&x150, &x151, x149, x123, x141); + const x152 = (@as(u64, x151) + @as(u64, x124)); + var x153: u64 = undefined; + var x154: u64 = undefined; + mulxU64(&x153, &x154, x3, (arg1[3])); + var x155: u64 = undefined; + var x156: u64 = undefined; + mulxU64(&x155, &x156, x3, (arg1[2])); + var x157: u64 = undefined; + var x158: u64 = undefined; + mulxU64(&x157, &x158, x3, (arg1[1])); + var x159: u64 = undefined; + var x160: u64 = undefined; + mulxU64(&x159, &x160, x3, (arg1[0])); + var x161: u64 = undefined; + var x162: u1 = undefined; + addcarryxU64(&x161, &x162, 0x0, x160, x157); + var x163: u64 = undefined; + var x164: u1 = undefined; + addcarryxU64(&x163, &x164, x162, x158, x155); + var x165: u64 = undefined; + var x166: u1 = undefined; + addcarryxU64(&x165, &x166, x164, x156, x153); + const x167 = (@as(u64, x166) + x154); + var x168: u64 = undefined; + var x169: u1 = undefined; + addcarryxU64(&x168, &x169, 0x0, x144, x159); + var x170: u64 = undefined; + var x171: u1 = undefined; + addcarryxU64(&x170, &x171, x169, x146, x161); + var x172: u64 = undefined; + var x173: u1 = undefined; + addcarryxU64(&x172, &x173, x171, x148, x163); + var x174: u64 = undefined; + var x175: u1 = undefined; + addcarryxU64(&x174, &x175, x173, x150, x165); + var x176: u64 = undefined; + var x177: u1 = undefined; + addcarryxU64(&x176, &x177, x175, x152, x167); + var x178: u64 = undefined; + var x179: u64 = undefined; + mulxU64(&x178, &x179, x168, 0xd838091dd2253531); + var x180: u64 = undefined; + var x181: u64 = undefined; + mulxU64(&x180, &x181, x178, 0xffffffffffffffff); + var x182: u64 = undefined; + var x183: u64 = undefined; + mulxU64(&x182, &x183, x178, 0xffffffffffffffff); + var x184: u64 = undefined; + var x185: u64 = undefined; + mulxU64(&x184, &x185, x178, 0xffffffffffffffff); + var x186: u64 = undefined; + var x187: u64 = undefined; + mulxU64(&x186, &x187, x178, 0xfffffffefffffc2f); + var x188: u64 = undefined; + var x189: u1 = undefined; + addcarryxU64(&x188, &x189, 0x0, x187, x184); + var x190: u64 = undefined; + var x191: u1 = undefined; + addcarryxU64(&x190, &x191, x189, x185, x182); + var x192: u64 = undefined; + var x193: u1 = undefined; + addcarryxU64(&x192, &x193, x191, x183, x180); + const x194 = (@as(u64, x193) + x181); + var x195: u64 = undefined; + var x196: u1 = undefined; + addcarryxU64(&x195, &x196, 0x0, x168, x186); + var x197: u64 = undefined; + var x198: u1 = undefined; + addcarryxU64(&x197, &x198, x196, x170, x188); + var x199: u64 = undefined; + var x200: u1 = undefined; + addcarryxU64(&x199, &x200, x198, x172, x190); + var x201: u64 = undefined; + var x202: u1 = undefined; + addcarryxU64(&x201, &x202, x200, x174, x192); + var x203: u64 = undefined; + var x204: u1 = undefined; + addcarryxU64(&x203, &x204, x202, x176, x194); + const x205 = (@as(u64, x204) + @as(u64, x177)); + var x206: u64 = undefined; + var x207: u1 = undefined; + subborrowxU64(&x206, &x207, 0x0, x197, 0xfffffffefffffc2f); + var x208: u64 = undefined; + var x209: u1 = undefined; + subborrowxU64(&x208, &x209, x207, x199, 0xffffffffffffffff); + var x210: u64 = undefined; + var x211: u1 = undefined; + subborrowxU64(&x210, &x211, x209, x201, 0xffffffffffffffff); + var x212: u64 = undefined; + var x213: u1 = undefined; + subborrowxU64(&x212, &x213, x211, x203, 0xffffffffffffffff); + var x214: u64 = undefined; + var x215: u1 = undefined; + subborrowxU64(&x214, &x215, x213, x205, 0x0); + var x216: u64 = undefined; + cmovznzU64(&x216, x215, x206, x197); + var x217: u64 = undefined; + cmovznzU64(&x217, x215, x208, x199); + var x218: u64 = undefined; + cmovznzU64(&x218, x215, x210, x201); + var x219: u64 = undefined; + cmovznzU64(&x219, x215, x212, x203); + out1[0] = x216; + out1[1] = x217; + out1[2] = x218; + out1[3] = x219; +} + +/// The function add adds two field elements in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// 0 ≤ eval arg2 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m +/// 0 ≤ eval out1 < m +/// +pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + var x2: u1 = undefined; + addcarryxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); + var x3: u64 = undefined; + var x4: u1 = undefined; + addcarryxU64(&x3, &x4, x2, (arg1[1]), (arg2[1])); + var x5: u64 = undefined; + var x6: u1 = undefined; + addcarryxU64(&x5, &x6, x4, (arg1[2]), (arg2[2])); + var x7: u64 = undefined; + var x8: u1 = undefined; + addcarryxU64(&x7, &x8, x6, (arg1[3]), (arg2[3])); + var x9: u64 = undefined; + var x10: u1 = undefined; + subborrowxU64(&x9, &x10, 0x0, x1, 0xfffffffefffffc2f); + var x11: u64 = undefined; + var x12: u1 = undefined; + subborrowxU64(&x11, &x12, x10, x3, 0xffffffffffffffff); + var x13: u64 = undefined; + var x14: u1 = undefined; + subborrowxU64(&x13, &x14, x12, x5, 0xffffffffffffffff); + var x15: u64 = undefined; + var x16: u1 = undefined; + subborrowxU64(&x15, &x16, x14, x7, 0xffffffffffffffff); + var x17: u64 = undefined; + var x18: u1 = undefined; + subborrowxU64(&x17, &x18, x16, @as(u64, x8), 0x0); + var x19: u64 = undefined; + cmovznzU64(&x19, x18, x9, x1); + var x20: u64 = undefined; + cmovznzU64(&x20, x18, x11, x3); + var x21: u64 = undefined; + cmovznzU64(&x21, x18, x13, x5); + var x22: u64 = undefined; + cmovznzU64(&x22, x18, x15, x7); + out1[0] = x19; + out1[1] = x20; + out1[2] = x21; + out1[3] = x22; +} + +/// The function sub subtracts two field elements in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// 0 ≤ eval arg2 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m +/// 0 ≤ eval out1 < m +/// +pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + var x2: u1 = undefined; + subborrowxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); + var x3: u64 = undefined; + var x4: u1 = undefined; + subborrowxU64(&x3, &x4, x2, (arg1[1]), (arg2[1])); + var x5: u64 = undefined; + var x6: u1 = undefined; + subborrowxU64(&x5, &x6, x4, (arg1[2]), (arg2[2])); + var x7: u64 = undefined; + var x8: u1 = undefined; + subborrowxU64(&x7, &x8, x6, (arg1[3]), (arg2[3])); + var x9: u64 = undefined; + cmovznzU64(&x9, x8, 0x0, 0xffffffffffffffff); + var x10: u64 = undefined; + var x11: u1 = undefined; + addcarryxU64(&x10, &x11, 0x0, x1, (x9 & 0xfffffffefffffc2f)); + var x12: u64 = undefined; + var x13: u1 = undefined; + addcarryxU64(&x12, &x13, x11, x3, x9); + var x14: u64 = undefined; + var x15: u1 = undefined; + addcarryxU64(&x14, &x15, x13, x5, x9); + var x16: u64 = undefined; + var x17: u1 = undefined; + addcarryxU64(&x16, &x17, x15, x7, x9); + out1[0] = x10; + out1[1] = x12; + out1[2] = x14; + out1[3] = x16; +} + +/// The function opp negates a field element in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m +/// 0 ≤ eval out1 < m +/// +pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + var x2: u1 = undefined; + subborrowxU64(&x1, &x2, 0x0, 0x0, (arg1[0])); + var x3: u64 = undefined; + var x4: u1 = undefined; + subborrowxU64(&x3, &x4, x2, 0x0, (arg1[1])); + var x5: u64 = undefined; + var x6: u1 = undefined; + subborrowxU64(&x5, &x6, x4, 0x0, (arg1[2])); + var x7: u64 = undefined; + var x8: u1 = undefined; + subborrowxU64(&x7, &x8, x6, 0x0, (arg1[3])); + var x9: u64 = undefined; + cmovznzU64(&x9, x8, 0x0, 0xffffffffffffffff); + var x10: u64 = undefined; + var x11: u1 = undefined; + addcarryxU64(&x10, &x11, 0x0, x1, (x9 & 0xfffffffefffffc2f)); + var x12: u64 = undefined; + var x13: u1 = undefined; + addcarryxU64(&x12, &x13, x11, x3, x9); + var x14: u64 = undefined; + var x15: u1 = undefined; + addcarryxU64(&x14, &x15, x13, x5, x9); + var x16: u64 = undefined; + var x17: u1 = undefined; + addcarryxU64(&x16, &x17, x15, x7, x9); + out1[0] = x10; + out1[1] = x12; + out1[2] = x14; + out1[3] = x16; +} + +/// The function fromMontgomery translates a field element out of the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m +/// 0 ≤ eval out1 < m +/// +pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[0]); + var x2: u64 = undefined; + var x3: u64 = undefined; + mulxU64(&x2, &x3, x1, 0xd838091dd2253531); + var x4: u64 = undefined; + var x5: u64 = undefined; + mulxU64(&x4, &x5, x2, 0xffffffffffffffff); + var x6: u64 = undefined; + var x7: u64 = undefined; + mulxU64(&x6, &x7, x2, 0xffffffffffffffff); + var x8: u64 = undefined; + var x9: u64 = undefined; + mulxU64(&x8, &x9, x2, 0xffffffffffffffff); + var x10: u64 = undefined; + var x11: u64 = undefined; + mulxU64(&x10, &x11, x2, 0xfffffffefffffc2f); + var x12: u64 = undefined; + var x13: u1 = undefined; + addcarryxU64(&x12, &x13, 0x0, x11, x8); + var x14: u64 = undefined; + var x15: u1 = undefined; + addcarryxU64(&x14, &x15, x13, x9, x6); + var x16: u64 = undefined; + var x17: u1 = undefined; + addcarryxU64(&x16, &x17, x15, x7, x4); + var x18: u64 = undefined; + var x19: u1 = undefined; + addcarryxU64(&x18, &x19, 0x0, x1, x10); + var x20: u64 = undefined; + var x21: u1 = undefined; + addcarryxU64(&x20, &x21, x19, 0x0, x12); + var x22: u64 = undefined; + var x23: u1 = undefined; + addcarryxU64(&x22, &x23, x21, 0x0, x14); + var x24: u64 = undefined; + var x25: u1 = undefined; + addcarryxU64(&x24, &x25, x23, 0x0, x16); + var x26: u64 = undefined; + var x27: u1 = undefined; + addcarryxU64(&x26, &x27, x25, 0x0, (@as(u64, x17) + x5)); + var x28: u64 = undefined; + var x29: u1 = undefined; + addcarryxU64(&x28, &x29, 0x0, x20, (arg1[1])); + var x30: u64 = undefined; + var x31: u1 = undefined; + addcarryxU64(&x30, &x31, x29, x22, 0x0); + var x32: u64 = undefined; + var x33: u1 = undefined; + addcarryxU64(&x32, &x33, x31, x24, 0x0); + var x34: u64 = undefined; + var x35: u1 = undefined; + addcarryxU64(&x34, &x35, x33, x26, 0x0); + var x36: u64 = undefined; + var x37: u64 = undefined; + mulxU64(&x36, &x37, x28, 0xd838091dd2253531); + var x38: u64 = undefined; + var x39: u64 = undefined; + mulxU64(&x38, &x39, x36, 0xffffffffffffffff); + var x40: u64 = undefined; + var x41: u64 = undefined; + mulxU64(&x40, &x41, x36, 0xffffffffffffffff); + var x42: u64 = undefined; + var x43: u64 = undefined; + mulxU64(&x42, &x43, x36, 0xffffffffffffffff); + var x44: u64 = undefined; + var x45: u64 = undefined; + mulxU64(&x44, &x45, x36, 0xfffffffefffffc2f); + var x46: u64 = undefined; + var x47: u1 = undefined; + addcarryxU64(&x46, &x47, 0x0, x45, x42); + var x48: u64 = undefined; + var x49: u1 = undefined; + addcarryxU64(&x48, &x49, x47, x43, x40); + var x50: u64 = undefined; + var x51: u1 = undefined; + addcarryxU64(&x50, &x51, x49, x41, x38); + var x52: u64 = undefined; + var x53: u1 = undefined; + addcarryxU64(&x52, &x53, 0x0, x28, x44); + var x54: u64 = undefined; + var x55: u1 = undefined; + addcarryxU64(&x54, &x55, x53, x30, x46); + var x56: u64 = undefined; + var x57: u1 = undefined; + addcarryxU64(&x56, &x57, x55, x32, x48); + var x58: u64 = undefined; + var x59: u1 = undefined; + addcarryxU64(&x58, &x59, x57, x34, x50); + var x60: u64 = undefined; + var x61: u1 = undefined; + addcarryxU64(&x60, &x61, x59, (@as(u64, x35) + @as(u64, x27)), (@as(u64, x51) + x39)); + var x62: u64 = undefined; + var x63: u1 = undefined; + addcarryxU64(&x62, &x63, 0x0, x54, (arg1[2])); + var x64: u64 = undefined; + var x65: u1 = undefined; + addcarryxU64(&x64, &x65, x63, x56, 0x0); + var x66: u64 = undefined; + var x67: u1 = undefined; + addcarryxU64(&x66, &x67, x65, x58, 0x0); + var x68: u64 = undefined; + var x69: u1 = undefined; + addcarryxU64(&x68, &x69, x67, x60, 0x0); + var x70: u64 = undefined; + var x71: u64 = undefined; + mulxU64(&x70, &x71, x62, 0xd838091dd2253531); + var x72: u64 = undefined; + var x73: u64 = undefined; + mulxU64(&x72, &x73, x70, 0xffffffffffffffff); + var x74: u64 = undefined; + var x75: u64 = undefined; + mulxU64(&x74, &x75, x70, 0xffffffffffffffff); + var x76: u64 = undefined; + var x77: u64 = undefined; + mulxU64(&x76, &x77, x70, 0xffffffffffffffff); + var x78: u64 = undefined; + var x79: u64 = undefined; + mulxU64(&x78, &x79, x70, 0xfffffffefffffc2f); + var x80: u64 = undefined; + var x81: u1 = undefined; + addcarryxU64(&x80, &x81, 0x0, x79, x76); + var x82: u64 = undefined; + var x83: u1 = undefined; + addcarryxU64(&x82, &x83, x81, x77, x74); + var x84: u64 = undefined; + var x85: u1 = undefined; + addcarryxU64(&x84, &x85, x83, x75, x72); + var x86: u64 = undefined; + var x87: u1 = undefined; + addcarryxU64(&x86, &x87, 0x0, x62, x78); + var x88: u64 = undefined; + var x89: u1 = undefined; + addcarryxU64(&x88, &x89, x87, x64, x80); + var x90: u64 = undefined; + var x91: u1 = undefined; + addcarryxU64(&x90, &x91, x89, x66, x82); + var x92: u64 = undefined; + var x93: u1 = undefined; + addcarryxU64(&x92, &x93, x91, x68, x84); + var x94: u64 = undefined; + var x95: u1 = undefined; + addcarryxU64(&x94, &x95, x93, (@as(u64, x69) + @as(u64, x61)), (@as(u64, x85) + x73)); + var x96: u64 = undefined; + var x97: u1 = undefined; + addcarryxU64(&x96, &x97, 0x0, x88, (arg1[3])); + var x98: u64 = undefined; + var x99: u1 = undefined; + addcarryxU64(&x98, &x99, x97, x90, 0x0); + var x100: u64 = undefined; + var x101: u1 = undefined; + addcarryxU64(&x100, &x101, x99, x92, 0x0); + var x102: u64 = undefined; + var x103: u1 = undefined; + addcarryxU64(&x102, &x103, x101, x94, 0x0); + var x104: u64 = undefined; + var x105: u64 = undefined; + mulxU64(&x104, &x105, x96, 0xd838091dd2253531); + var x106: u64 = undefined; + var x107: u64 = undefined; + mulxU64(&x106, &x107, x104, 0xffffffffffffffff); + var x108: u64 = undefined; + var x109: u64 = undefined; + mulxU64(&x108, &x109, x104, 0xffffffffffffffff); + var x110: u64 = undefined; + var x111: u64 = undefined; + mulxU64(&x110, &x111, x104, 0xffffffffffffffff); + var x112: u64 = undefined; + var x113: u64 = undefined; + mulxU64(&x112, &x113, x104, 0xfffffffefffffc2f); + var x114: u64 = undefined; + var x115: u1 = undefined; + addcarryxU64(&x114, &x115, 0x0, x113, x110); + var x116: u64 = undefined; + var x117: u1 = undefined; + addcarryxU64(&x116, &x117, x115, x111, x108); + var x118: u64 = undefined; + var x119: u1 = undefined; + addcarryxU64(&x118, &x119, x117, x109, x106); + var x120: u64 = undefined; + var x121: u1 = undefined; + addcarryxU64(&x120, &x121, 0x0, x96, x112); + var x122: u64 = undefined; + var x123: u1 = undefined; + addcarryxU64(&x122, &x123, x121, x98, x114); + var x124: u64 = undefined; + var x125: u1 = undefined; + addcarryxU64(&x124, &x125, x123, x100, x116); + var x126: u64 = undefined; + var x127: u1 = undefined; + addcarryxU64(&x126, &x127, x125, x102, x118); + var x128: u64 = undefined; + var x129: u1 = undefined; + addcarryxU64(&x128, &x129, x127, (@as(u64, x103) + @as(u64, x95)), (@as(u64, x119) + x107)); + var x130: u64 = undefined; + var x131: u1 = undefined; + subborrowxU64(&x130, &x131, 0x0, x122, 0xfffffffefffffc2f); + var x132: u64 = undefined; + var x133: u1 = undefined; + subborrowxU64(&x132, &x133, x131, x124, 0xffffffffffffffff); + var x134: u64 = undefined; + var x135: u1 = undefined; + subborrowxU64(&x134, &x135, x133, x126, 0xffffffffffffffff); + var x136: u64 = undefined; + var x137: u1 = undefined; + subborrowxU64(&x136, &x137, x135, x128, 0xffffffffffffffff); + var x138: u64 = undefined; + var x139: u1 = undefined; + subborrowxU64(&x138, &x139, x137, @as(u64, x129), 0x0); + var x140: u64 = undefined; + cmovznzU64(&x140, x139, x130, x122); + var x141: u64 = undefined; + cmovznzU64(&x141, x139, x132, x124); + var x142: u64 = undefined; + cmovznzU64(&x142, x139, x134, x126); + var x143: u64 = undefined; + cmovznzU64(&x143, x139, x136, x128); + out1[0] = x140; + out1[1] = x141; + out1[2] = x142; + out1[3] = x143; +} + +/// The function toMontgomery translates a field element into the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = eval arg1 mod m +/// 0 ≤ eval out1 < m +/// +pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[1]); + const x2 = (arg1[2]); + const x3 = (arg1[3]); + const x4 = (arg1[0]); + var x5: u64 = undefined; + var x6: u64 = undefined; + mulxU64(&x5, &x6, x4, 0x7a2000e90a1); + var x7: u64 = undefined; + var x8: u1 = undefined; + addcarryxU64(&x7, &x8, 0x0, x6, x4); + var x9: u64 = undefined; + var x10: u64 = undefined; + mulxU64(&x9, &x10, x5, 0xd838091dd2253531); + var x11: u64 = undefined; + var x12: u64 = undefined; + mulxU64(&x11, &x12, x9, 0xffffffffffffffff); + var x13: u64 = undefined; + var x14: u64 = undefined; + mulxU64(&x13, &x14, x9, 0xffffffffffffffff); + var x15: u64 = undefined; + var x16: u64 = undefined; + mulxU64(&x15, &x16, x9, 0xffffffffffffffff); + var x17: u64 = undefined; + var x18: u64 = undefined; + mulxU64(&x17, &x18, x9, 0xfffffffefffffc2f); + var x19: u64 = undefined; + var x20: u1 = undefined; + addcarryxU64(&x19, &x20, 0x0, x18, x15); + var x21: u64 = undefined; + var x22: u1 = undefined; + addcarryxU64(&x21, &x22, x20, x16, x13); + var x23: u64 = undefined; + var x24: u1 = undefined; + addcarryxU64(&x23, &x24, x22, x14, x11); + var x25: u64 = undefined; + var x26: u1 = undefined; + addcarryxU64(&x25, &x26, 0x0, x5, x17); + var x27: u64 = undefined; + var x28: u1 = undefined; + addcarryxU64(&x27, &x28, x26, x7, x19); + var x29: u64 = undefined; + var x30: u1 = undefined; + addcarryxU64(&x29, &x30, x28, @as(u64, x8), x21); + var x31: u64 = undefined; + var x32: u1 = undefined; + addcarryxU64(&x31, &x32, x30, 0x0, x23); + var x33: u64 = undefined; + var x34: u1 = undefined; + addcarryxU64(&x33, &x34, x32, 0x0, (@as(u64, x24) + x12)); + var x35: u64 = undefined; + var x36: u64 = undefined; + mulxU64(&x35, &x36, x1, 0x7a2000e90a1); + var x37: u64 = undefined; + var x38: u1 = undefined; + addcarryxU64(&x37, &x38, 0x0, x36, x1); + var x39: u64 = undefined; + var x40: u1 = undefined; + addcarryxU64(&x39, &x40, 0x0, x27, x35); + var x41: u64 = undefined; + var x42: u1 = undefined; + addcarryxU64(&x41, &x42, x40, x29, x37); + var x43: u64 = undefined; + var x44: u1 = undefined; + addcarryxU64(&x43, &x44, x42, x31, @as(u64, x38)); + var x45: u64 = undefined; + var x46: u1 = undefined; + addcarryxU64(&x45, &x46, x44, x33, 0x0); + var x47: u64 = undefined; + var x48: u64 = undefined; + mulxU64(&x47, &x48, x39, 0xd838091dd2253531); + var x49: u64 = undefined; + var x50: u64 = undefined; + mulxU64(&x49, &x50, x47, 0xffffffffffffffff); + var x51: u64 = undefined; + var x52: u64 = undefined; + mulxU64(&x51, &x52, x47, 0xffffffffffffffff); + var x53: u64 = undefined; + var x54: u64 = undefined; + mulxU64(&x53, &x54, x47, 0xffffffffffffffff); + var x55: u64 = undefined; + var x56: u64 = undefined; + mulxU64(&x55, &x56, x47, 0xfffffffefffffc2f); + var x57: u64 = undefined; + var x58: u1 = undefined; + addcarryxU64(&x57, &x58, 0x0, x56, x53); + var x59: u64 = undefined; + var x60: u1 = undefined; + addcarryxU64(&x59, &x60, x58, x54, x51); + var x61: u64 = undefined; + var x62: u1 = undefined; + addcarryxU64(&x61, &x62, x60, x52, x49); + var x63: u64 = undefined; + var x64: u1 = undefined; + addcarryxU64(&x63, &x64, 0x0, x39, x55); + var x65: u64 = undefined; + var x66: u1 = undefined; + addcarryxU64(&x65, &x66, x64, x41, x57); + var x67: u64 = undefined; + var x68: u1 = undefined; + addcarryxU64(&x67, &x68, x66, x43, x59); + var x69: u64 = undefined; + var x70: u1 = undefined; + addcarryxU64(&x69, &x70, x68, x45, x61); + var x71: u64 = undefined; + var x72: u1 = undefined; + addcarryxU64(&x71, &x72, x70, (@as(u64, x46) + @as(u64, x34)), (@as(u64, x62) + x50)); + var x73: u64 = undefined; + var x74: u64 = undefined; + mulxU64(&x73, &x74, x2, 0x7a2000e90a1); + var x75: u64 = undefined; + var x76: u1 = undefined; + addcarryxU64(&x75, &x76, 0x0, x74, x2); + var x77: u64 = undefined; + var x78: u1 = undefined; + addcarryxU64(&x77, &x78, 0x0, x65, x73); + var x79: u64 = undefined; + var x80: u1 = undefined; + addcarryxU64(&x79, &x80, x78, x67, x75); + var x81: u64 = undefined; + var x82: u1 = undefined; + addcarryxU64(&x81, &x82, x80, x69, @as(u64, x76)); + var x83: u64 = undefined; + var x84: u1 = undefined; + addcarryxU64(&x83, &x84, x82, x71, 0x0); + var x85: u64 = undefined; + var x86: u64 = undefined; + mulxU64(&x85, &x86, x77, 0xd838091dd2253531); + var x87: u64 = undefined; + var x88: u64 = undefined; + mulxU64(&x87, &x88, x85, 0xffffffffffffffff); + var x89: u64 = undefined; + var x90: u64 = undefined; + mulxU64(&x89, &x90, x85, 0xffffffffffffffff); + var x91: u64 = undefined; + var x92: u64 = undefined; + mulxU64(&x91, &x92, x85, 0xffffffffffffffff); + var x93: u64 = undefined; + var x94: u64 = undefined; + mulxU64(&x93, &x94, x85, 0xfffffffefffffc2f); + var x95: u64 = undefined; + var x96: u1 = undefined; + addcarryxU64(&x95, &x96, 0x0, x94, x91); + var x97: u64 = undefined; + var x98: u1 = undefined; + addcarryxU64(&x97, &x98, x96, x92, x89); + var x99: u64 = undefined; + var x100: u1 = undefined; + addcarryxU64(&x99, &x100, x98, x90, x87); + var x101: u64 = undefined; + var x102: u1 = undefined; + addcarryxU64(&x101, &x102, 0x0, x77, x93); + var x103: u64 = undefined; + var x104: u1 = undefined; + addcarryxU64(&x103, &x104, x102, x79, x95); + var x105: u64 = undefined; + var x106: u1 = undefined; + addcarryxU64(&x105, &x106, x104, x81, x97); + var x107: u64 = undefined; + var x108: u1 = undefined; + addcarryxU64(&x107, &x108, x106, x83, x99); + var x109: u64 = undefined; + var x110: u1 = undefined; + addcarryxU64(&x109, &x110, x108, (@as(u64, x84) + @as(u64, x72)), (@as(u64, x100) + x88)); + var x111: u64 = undefined; + var x112: u64 = undefined; + mulxU64(&x111, &x112, x3, 0x7a2000e90a1); + var x113: u64 = undefined; + var x114: u1 = undefined; + addcarryxU64(&x113, &x114, 0x0, x112, x3); + var x115: u64 = undefined; + var x116: u1 = undefined; + addcarryxU64(&x115, &x116, 0x0, x103, x111); + var x117: u64 = undefined; + var x118: u1 = undefined; + addcarryxU64(&x117, &x118, x116, x105, x113); + var x119: u64 = undefined; + var x120: u1 = undefined; + addcarryxU64(&x119, &x120, x118, x107, @as(u64, x114)); + var x121: u64 = undefined; + var x122: u1 = undefined; + addcarryxU64(&x121, &x122, x120, x109, 0x0); + var x123: u64 = undefined; + var x124: u64 = undefined; + mulxU64(&x123, &x124, x115, 0xd838091dd2253531); + var x125: u64 = undefined; + var x126: u64 = undefined; + mulxU64(&x125, &x126, x123, 0xffffffffffffffff); + var x127: u64 = undefined; + var x128: u64 = undefined; + mulxU64(&x127, &x128, x123, 0xffffffffffffffff); + var x129: u64 = undefined; + var x130: u64 = undefined; + mulxU64(&x129, &x130, x123, 0xffffffffffffffff); + var x131: u64 = undefined; + var x132: u64 = undefined; + mulxU64(&x131, &x132, x123, 0xfffffffefffffc2f); + var x133: u64 = undefined; + var x134: u1 = undefined; + addcarryxU64(&x133, &x134, 0x0, x132, x129); + var x135: u64 = undefined; + var x136: u1 = undefined; + addcarryxU64(&x135, &x136, x134, x130, x127); + var x137: u64 = undefined; + var x138: u1 = undefined; + addcarryxU64(&x137, &x138, x136, x128, x125); + var x139: u64 = undefined; + var x140: u1 = undefined; + addcarryxU64(&x139, &x140, 0x0, x115, x131); + var x141: u64 = undefined; + var x142: u1 = undefined; + addcarryxU64(&x141, &x142, x140, x117, x133); + var x143: u64 = undefined; + var x144: u1 = undefined; + addcarryxU64(&x143, &x144, x142, x119, x135); + var x145: u64 = undefined; + var x146: u1 = undefined; + addcarryxU64(&x145, &x146, x144, x121, x137); + var x147: u64 = undefined; + var x148: u1 = undefined; + addcarryxU64(&x147, &x148, x146, (@as(u64, x122) + @as(u64, x110)), (@as(u64, x138) + x126)); + var x149: u64 = undefined; + var x150: u1 = undefined; + subborrowxU64(&x149, &x150, 0x0, x141, 0xfffffffefffffc2f); + var x151: u64 = undefined; + var x152: u1 = undefined; + subborrowxU64(&x151, &x152, x150, x143, 0xffffffffffffffff); + var x153: u64 = undefined; + var x154: u1 = undefined; + subborrowxU64(&x153, &x154, x152, x145, 0xffffffffffffffff); + var x155: u64 = undefined; + var x156: u1 = undefined; + subborrowxU64(&x155, &x156, x154, x147, 0xffffffffffffffff); + var x157: u64 = undefined; + var x158: u1 = undefined; + subborrowxU64(&x157, &x158, x156, @as(u64, x148), 0x0); + var x159: u64 = undefined; + cmovznzU64(&x159, x158, x149, x141); + var x160: u64 = undefined; + cmovznzU64(&x160, x158, x151, x143); + var x161: u64 = undefined; + cmovznzU64(&x161, x158, x153, x145); + var x162: u64 = undefined; + cmovznzU64(&x162, x158, x155, x147); + out1[0] = x159; + out1[1] = x160; + out1[2] = x161; + out1[3] = x162; +} + +/// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0 +/// +/// Input Bounds: +/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +pub fn nonzero(out1: *u64, arg1: [4]u64) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); + out1.* = x1; +} + +/// The function selectznz is a multi-limb conditional select. +/// +/// Postconditions: +/// out1 = (if arg1 = 0 then arg2 else arg3) +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0x1] +/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// Output Bounds: +/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); + var x2: u64 = undefined; + cmovznzU64(&x2, arg1, (arg2[1]), (arg3[1])); + var x3: u64 = undefined; + cmovznzU64(&x3, arg1, (arg2[2]), (arg3[2])); + var x4: u64 = undefined; + cmovznzU64(&x4, arg1, (arg2[3]), (arg3[3])); + out1[0] = x1; + out1[1] = x2; + out1[2] = x3; + out1[3] = x4; +} + +/// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31] +/// +/// Input Bounds: +/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// Output Bounds: +/// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[3]); + const x2 = (arg1[2]); + const x3 = (arg1[1]); + const x4 = (arg1[0]); + const x5 = @truncate(u8, (x4 & 0xff)); + const x6 = (x4 >> 8); + const x7 = @truncate(u8, (x6 & 0xff)); + const x8 = (x6 >> 8); + const x9 = @truncate(u8, (x8 & 0xff)); + const x10 = (x8 >> 8); + const x11 = @truncate(u8, (x10 & 0xff)); + const x12 = (x10 >> 8); + const x13 = @truncate(u8, (x12 & 0xff)); + const x14 = (x12 >> 8); + const x15 = @truncate(u8, (x14 & 0xff)); + const x16 = (x14 >> 8); + const x17 = @truncate(u8, (x16 & 0xff)); + const x18 = @truncate(u8, (x16 >> 8)); + const x19 = @truncate(u8, (x3 & 0xff)); + const x20 = (x3 >> 8); + const x21 = @truncate(u8, (x20 & 0xff)); + const x22 = (x20 >> 8); + const x23 = @truncate(u8, (x22 & 0xff)); + const x24 = (x22 >> 8); + const x25 = @truncate(u8, (x24 & 0xff)); + const x26 = (x24 >> 8); + const x27 = @truncate(u8, (x26 & 0xff)); + const x28 = (x26 >> 8); + const x29 = @truncate(u8, (x28 & 0xff)); + const x30 = (x28 >> 8); + const x31 = @truncate(u8, (x30 & 0xff)); + const x32 = @truncate(u8, (x30 >> 8)); + const x33 = @truncate(u8, (x2 & 0xff)); + const x34 = (x2 >> 8); + const x35 = @truncate(u8, (x34 & 0xff)); + const x36 = (x34 >> 8); + const x37 = @truncate(u8, (x36 & 0xff)); + const x38 = (x36 >> 8); + const x39 = @truncate(u8, (x38 & 0xff)); + const x40 = (x38 >> 8); + const x41 = @truncate(u8, (x40 & 0xff)); + const x42 = (x40 >> 8); + const x43 = @truncate(u8, (x42 & 0xff)); + const x44 = (x42 >> 8); + const x45 = @truncate(u8, (x44 & 0xff)); + const x46 = @truncate(u8, (x44 >> 8)); + const x47 = @truncate(u8, (x1 & 0xff)); + const x48 = (x1 >> 8); + const x49 = @truncate(u8, (x48 & 0xff)); + const x50 = (x48 >> 8); + const x51 = @truncate(u8, (x50 & 0xff)); + const x52 = (x50 >> 8); + const x53 = @truncate(u8, (x52 & 0xff)); + const x54 = (x52 >> 8); + const x55 = @truncate(u8, (x54 & 0xff)); + const x56 = (x54 >> 8); + const x57 = @truncate(u8, (x56 & 0xff)); + const x58 = (x56 >> 8); + const x59 = @truncate(u8, (x58 & 0xff)); + const x60 = @truncate(u8, (x58 >> 8)); + out1[0] = x5; + out1[1] = x7; + out1[2] = x9; + out1[3] = x11; + out1[4] = x13; + out1[5] = x15; + out1[6] = x17; + out1[7] = x18; + out1[8] = x19; + out1[9] = x21; + out1[10] = x23; + out1[11] = x25; + out1[12] = x27; + out1[13] = x29; + out1[14] = x31; + out1[15] = x32; + out1[16] = x33; + out1[17] = x35; + out1[18] = x37; + out1[19] = x39; + out1[20] = x41; + out1[21] = x43; + out1[22] = x45; + out1[23] = x46; + out1[24] = x47; + out1[25] = x49; + out1[26] = x51; + out1[27] = x53; + out1[28] = x55; + out1[29] = x57; + out1[30] = x59; + out1[31] = x60; +} + +/// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. +/// +/// Preconditions: +/// 0 ≤ bytes_eval arg1 < m +/// Postconditions: +/// eval out1 mod m = bytes_eval arg1 mod m +/// 0 ≤ eval out1 < m +/// +/// Input Bounds: +/// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +/// Output Bounds: +/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (@as(u64, (arg1[31])) << 56); + const x2 = (@as(u64, (arg1[30])) << 48); + const x3 = (@as(u64, (arg1[29])) << 40); + const x4 = (@as(u64, (arg1[28])) << 32); + const x5 = (@as(u64, (arg1[27])) << 24); + const x6 = (@as(u64, (arg1[26])) << 16); + const x7 = (@as(u64, (arg1[25])) << 8); + const x8 = (arg1[24]); + const x9 = (@as(u64, (arg1[23])) << 56); + const x10 = (@as(u64, (arg1[22])) << 48); + const x11 = (@as(u64, (arg1[21])) << 40); + const x12 = (@as(u64, (arg1[20])) << 32); + const x13 = (@as(u64, (arg1[19])) << 24); + const x14 = (@as(u64, (arg1[18])) << 16); + const x15 = (@as(u64, (arg1[17])) << 8); + const x16 = (arg1[16]); + const x17 = (@as(u64, (arg1[15])) << 56); + const x18 = (@as(u64, (arg1[14])) << 48); + const x19 = (@as(u64, (arg1[13])) << 40); + const x20 = (@as(u64, (arg1[12])) << 32); + const x21 = (@as(u64, (arg1[11])) << 24); + const x22 = (@as(u64, (arg1[10])) << 16); + const x23 = (@as(u64, (arg1[9])) << 8); + const x24 = (arg1[8]); + const x25 = (@as(u64, (arg1[7])) << 56); + const x26 = (@as(u64, (arg1[6])) << 48); + const x27 = (@as(u64, (arg1[5])) << 40); + const x28 = (@as(u64, (arg1[4])) << 32); + const x29 = (@as(u64, (arg1[3])) << 24); + const x30 = (@as(u64, (arg1[2])) << 16); + const x31 = (@as(u64, (arg1[1])) << 8); + const x32 = (arg1[0]); + const x33 = (x31 + @as(u64, x32)); + const x34 = (x30 + x33); + const x35 = (x29 + x34); + const x36 = (x28 + x35); + const x37 = (x27 + x36); + const x38 = (x26 + x37); + const x39 = (x25 + x38); + const x40 = (x23 + @as(u64, x24)); + const x41 = (x22 + x40); + const x42 = (x21 + x41); + const x43 = (x20 + x42); + const x44 = (x19 + x43); + const x45 = (x18 + x44); + const x46 = (x17 + x45); + const x47 = (x15 + @as(u64, x16)); + const x48 = (x14 + x47); + const x49 = (x13 + x48); + const x50 = (x12 + x49); + const x51 = (x11 + x50); + const x52 = (x10 + x51); + const x53 = (x9 + x52); + const x54 = (x7 + @as(u64, x8)); + const x55 = (x6 + x54); + const x56 = (x5 + x55); + const x57 = (x4 + x56); + const x58 = (x3 + x57); + const x59 = (x2 + x58); + const x60 = (x1 + x59); + out1[0] = x39; + out1[1] = x46; + out1[2] = x53; + out1[3] = x60; +} + +/// The function setOne returns the field element one in the Montgomery domain. +/// +/// Postconditions: +/// eval (from_montgomery out1) mod m = 1 mod m +/// 0 ≤ eval out1 < m +/// +pub fn setOne(out1: *MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + out1[0] = 0x1000003d1; + out1[1] = 0x0; + out1[2] = 0x0; + out1[3] = 0x0; +} + +/// The function msat returns the saturated representation of the prime modulus. +/// +/// Postconditions: +/// twos_complement_eval out1 = m +/// 0 ≤ eval out1 < m +/// +/// Output Bounds: +/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn msat(out1: *[5]u64) void { + @setRuntimeSafety(mode == .Debug); + + out1[0] = 0xfffffffefffffc2f; + out1[1] = 0xffffffffffffffff; + out1[2] = 0xffffffffffffffff; + out1[3] = 0xffffffffffffffff; + out1[4] = 0x0; +} + +/// The function divstep computes a divstep. +/// +/// Preconditions: +/// 0 ≤ eval arg4 < m +/// 0 ≤ eval arg5 < m +/// Postconditions: +/// out1 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then 1 - arg1 else 1 + arg1) +/// twos_complement_eval out2 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then twos_complement_eval arg3 else twos_complement_eval arg2) +/// twos_complement_eval out3 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then ⌊(twos_complement_eval arg3 - twos_complement_eval arg2) / 2⌋ else ⌊(twos_complement_eval arg3 + (twos_complement_eval arg3 mod 2) * twos_complement_eval arg2) / 2⌋) +/// eval (from_montgomery out4) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (2 * eval (from_montgomery arg5)) mod m else (2 * eval (from_montgomery arg4)) mod m) +/// eval (from_montgomery out5) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (eval (from_montgomery arg4) - eval (from_montgomery arg4)) mod m else (eval (from_montgomery arg5) + (twos_complement_eval arg3 mod 2) * eval (from_montgomery arg4)) mod m) +/// 0 ≤ eval out5 < m +/// 0 ≤ eval out5 < m +/// 0 ≤ eval out2 < m +/// 0 ≤ eval out3 < m +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0xffffffffffffffff] +/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// arg4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// arg5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +/// out2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// out3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + var x2: u1 = undefined; + addcarryxU64(&x1, &x2, 0x0, (~arg1), 0x1); + const x3 = (@truncate(u1, (x1 >> 63)) & @truncate(u1, ((arg3[0]) & 0x1))); + var x4: u64 = undefined; + var x5: u1 = undefined; + addcarryxU64(&x4, &x5, 0x0, (~arg1), 0x1); + var x6: u64 = undefined; + cmovznzU64(&x6, x3, arg1, x4); + var x7: u64 = undefined; + cmovznzU64(&x7, x3, (arg2[0]), (arg3[0])); + var x8: u64 = undefined; + cmovznzU64(&x8, x3, (arg2[1]), (arg3[1])); + var x9: u64 = undefined; + cmovznzU64(&x9, x3, (arg2[2]), (arg3[2])); + var x10: u64 = undefined; + cmovznzU64(&x10, x3, (arg2[3]), (arg3[3])); + var x11: u64 = undefined; + cmovznzU64(&x11, x3, (arg2[4]), (arg3[4])); + var x12: u64 = undefined; + var x13: u1 = undefined; + addcarryxU64(&x12, &x13, 0x0, 0x1, (~(arg2[0]))); + var x14: u64 = undefined; + var x15: u1 = undefined; + addcarryxU64(&x14, &x15, x13, 0x0, (~(arg2[1]))); + var x16: u64 = undefined; + var x17: u1 = undefined; + addcarryxU64(&x16, &x17, x15, 0x0, (~(arg2[2]))); + var x18: u64 = undefined; + var x19: u1 = undefined; + addcarryxU64(&x18, &x19, x17, 0x0, (~(arg2[3]))); + var x20: u64 = undefined; + var x21: u1 = undefined; + addcarryxU64(&x20, &x21, x19, 0x0, (~(arg2[4]))); + var x22: u64 = undefined; + cmovznzU64(&x22, x3, (arg3[0]), x12); + var x23: u64 = undefined; + cmovznzU64(&x23, x3, (arg3[1]), x14); + var x24: u64 = undefined; + cmovznzU64(&x24, x3, (arg3[2]), x16); + var x25: u64 = undefined; + cmovznzU64(&x25, x3, (arg3[3]), x18); + var x26: u64 = undefined; + cmovznzU64(&x26, x3, (arg3[4]), x20); + var x27: u64 = undefined; + cmovznzU64(&x27, x3, (arg4[0]), (arg5[0])); + var x28: u64 = undefined; + cmovznzU64(&x28, x3, (arg4[1]), (arg5[1])); + var x29: u64 = undefined; + cmovznzU64(&x29, x3, (arg4[2]), (arg5[2])); + var x30: u64 = undefined; + cmovznzU64(&x30, x3, (arg4[3]), (arg5[3])); + var x31: u64 = undefined; + var x32: u1 = undefined; + addcarryxU64(&x31, &x32, 0x0, x27, x27); + var x33: u64 = undefined; + var x34: u1 = undefined; + addcarryxU64(&x33, &x34, x32, x28, x28); + var x35: u64 = undefined; + var x36: u1 = undefined; + addcarryxU64(&x35, &x36, x34, x29, x29); + var x37: u64 = undefined; + var x38: u1 = undefined; + addcarryxU64(&x37, &x38, x36, x30, x30); + var x39: u64 = undefined; + var x40: u1 = undefined; + subborrowxU64(&x39, &x40, 0x0, x31, 0xfffffffefffffc2f); + var x41: u64 = undefined; + var x42: u1 = undefined; + subborrowxU64(&x41, &x42, x40, x33, 0xffffffffffffffff); + var x43: u64 = undefined; + var x44: u1 = undefined; + subborrowxU64(&x43, &x44, x42, x35, 0xffffffffffffffff); + var x45: u64 = undefined; + var x46: u1 = undefined; + subborrowxU64(&x45, &x46, x44, x37, 0xffffffffffffffff); + var x47: u64 = undefined; + var x48: u1 = undefined; + subborrowxU64(&x47, &x48, x46, @as(u64, x38), 0x0); + const x49 = (arg4[3]); + const x50 = (arg4[2]); + const x51 = (arg4[1]); + const x52 = (arg4[0]); + var x53: u64 = undefined; + var x54: u1 = undefined; + subborrowxU64(&x53, &x54, 0x0, 0x0, x52); + var x55: u64 = undefined; + var x56: u1 = undefined; + subborrowxU64(&x55, &x56, x54, 0x0, x51); + var x57: u64 = undefined; + var x58: u1 = undefined; + subborrowxU64(&x57, &x58, x56, 0x0, x50); + var x59: u64 = undefined; + var x60: u1 = undefined; + subborrowxU64(&x59, &x60, x58, 0x0, x49); + var x61: u64 = undefined; + cmovznzU64(&x61, x60, 0x0, 0xffffffffffffffff); + var x62: u64 = undefined; + var x63: u1 = undefined; + addcarryxU64(&x62, &x63, 0x0, x53, (x61 & 0xfffffffefffffc2f)); + var x64: u64 = undefined; + var x65: u1 = undefined; + addcarryxU64(&x64, &x65, x63, x55, x61); + var x66: u64 = undefined; + var x67: u1 = undefined; + addcarryxU64(&x66, &x67, x65, x57, x61); + var x68: u64 = undefined; + var x69: u1 = undefined; + addcarryxU64(&x68, &x69, x67, x59, x61); + var x70: u64 = undefined; + cmovznzU64(&x70, x3, (arg5[0]), x62); + var x71: u64 = undefined; + cmovznzU64(&x71, x3, (arg5[1]), x64); + var x72: u64 = undefined; + cmovznzU64(&x72, x3, (arg5[2]), x66); + var x73: u64 = undefined; + cmovznzU64(&x73, x3, (arg5[3]), x68); + const x74 = @truncate(u1, (x22 & 0x1)); + var x75: u64 = undefined; + cmovznzU64(&x75, x74, 0x0, x7); + var x76: u64 = undefined; + cmovznzU64(&x76, x74, 0x0, x8); + var x77: u64 = undefined; + cmovznzU64(&x77, x74, 0x0, x9); + var x78: u64 = undefined; + cmovznzU64(&x78, x74, 0x0, x10); + var x79: u64 = undefined; + cmovznzU64(&x79, x74, 0x0, x11); + var x80: u64 = undefined; + var x81: u1 = undefined; + addcarryxU64(&x80, &x81, 0x0, x22, x75); + var x82: u64 = undefined; + var x83: u1 = undefined; + addcarryxU64(&x82, &x83, x81, x23, x76); + var x84: u64 = undefined; + var x85: u1 = undefined; + addcarryxU64(&x84, &x85, x83, x24, x77); + var x86: u64 = undefined; + var x87: u1 = undefined; + addcarryxU64(&x86, &x87, x85, x25, x78); + var x88: u64 = undefined; + var x89: u1 = undefined; + addcarryxU64(&x88, &x89, x87, x26, x79); + var x90: u64 = undefined; + cmovznzU64(&x90, x74, 0x0, x27); + var x91: u64 = undefined; + cmovznzU64(&x91, x74, 0x0, x28); + var x92: u64 = undefined; + cmovznzU64(&x92, x74, 0x0, x29); + var x93: u64 = undefined; + cmovznzU64(&x93, x74, 0x0, x30); + var x94: u64 = undefined; + var x95: u1 = undefined; + addcarryxU64(&x94, &x95, 0x0, x70, x90); + var x96: u64 = undefined; + var x97: u1 = undefined; + addcarryxU64(&x96, &x97, x95, x71, x91); + var x98: u64 = undefined; + var x99: u1 = undefined; + addcarryxU64(&x98, &x99, x97, x72, x92); + var x100: u64 = undefined; + var x101: u1 = undefined; + addcarryxU64(&x100, &x101, x99, x73, x93); + var x102: u64 = undefined; + var x103: u1 = undefined; + subborrowxU64(&x102, &x103, 0x0, x94, 0xfffffffefffffc2f); + var x104: u64 = undefined; + var x105: u1 = undefined; + subborrowxU64(&x104, &x105, x103, x96, 0xffffffffffffffff); + var x106: u64 = undefined; + var x107: u1 = undefined; + subborrowxU64(&x106, &x107, x105, x98, 0xffffffffffffffff); + var x108: u64 = undefined; + var x109: u1 = undefined; + subborrowxU64(&x108, &x109, x107, x100, 0xffffffffffffffff); + var x110: u64 = undefined; + var x111: u1 = undefined; + subborrowxU64(&x110, &x111, x109, @as(u64, x101), 0x0); + var x112: u64 = undefined; + var x113: u1 = undefined; + addcarryxU64(&x112, &x113, 0x0, x6, 0x1); + const x114 = ((x80 >> 1) | ((x82 << 63) & 0xffffffffffffffff)); + const x115 = ((x82 >> 1) | ((x84 << 63) & 0xffffffffffffffff)); + const x116 = ((x84 >> 1) | ((x86 << 63) & 0xffffffffffffffff)); + const x117 = ((x86 >> 1) | ((x88 << 63) & 0xffffffffffffffff)); + const x118 = ((x88 & 0x8000000000000000) | (x88 >> 1)); + var x119: u64 = undefined; + cmovznzU64(&x119, x48, x39, x31); + var x120: u64 = undefined; + cmovznzU64(&x120, x48, x41, x33); + var x121: u64 = undefined; + cmovznzU64(&x121, x48, x43, x35); + var x122: u64 = undefined; + cmovznzU64(&x122, x48, x45, x37); + var x123: u64 = undefined; + cmovznzU64(&x123, x111, x102, x94); + var x124: u64 = undefined; + cmovznzU64(&x124, x111, x104, x96); + var x125: u64 = undefined; + cmovznzU64(&x125, x111, x106, x98); + var x126: u64 = undefined; + cmovznzU64(&x126, x111, x108, x100); + out1.* = x112; + out2[0] = x7; + out2[1] = x8; + out2[2] = x9; + out2[3] = x10; + out2[4] = x11; + out3[0] = x114; + out3[1] = x115; + out3[2] = x116; + out3[3] = x117; + out3[4] = x118; + out4[0] = x119; + out4[1] = x120; + out4[2] = x121; + out4[3] = x122; + out5[0] = x123; + out5[1] = x124; + out5[2] = x125; + out5[3] = x126; +} + +/// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form). +/// +/// Postconditions: +/// eval (from_montgomery out1) = ⌊(m - 1) / 2⌋^(if ⌊log2 m⌋ + 1 < 46 then ⌊(49 * (⌊log2 m⌋ + 1) + 80) / 17⌋ else ⌊(49 * (⌊log2 m⌋ + 1) + 57) / 17⌋) +/// 0 ≤ eval out1 < m +/// +/// Output Bounds: +/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn divstepPrecomp(out1: *[4]u64) void { + @setRuntimeSafety(mode == .Debug); + + out1[0] = 0xf201a41831525e0a; + out1[1] = 0x9953f9ddcd648d85; + out1[2] = 0xe86029463db210a9; + out1[3] = 0x24fb8a3104b03709; +} diff --git a/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig b/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig new file mode 100644 index 000000000000..8e9687f0a1a3 --- /dev/null +++ b/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig @@ -0,0 +1,2024 @@ +// Autogenerated: 'src/ExtractionOCaml/word_by_word_montgomery' --lang Zig --internal-static --public-function-case camelCase --private-function-case camelCase --public-type-case UpperCamelCase --private-type-case UpperCamelCase --no-prefix-fiat --package-name secp256k1_scalar '' 64 '2^256 - 432420386565659656852420866394968145599' mul square add sub opp from_montgomery to_montgomery nonzero selectznz to_bytes from_bytes one msat divstep divstep_precomp +// curve description (via package name): secp256k1_scalar +// machine_wordsize = 64 (from "64") +// requested operations: mul, square, add, sub, opp, from_montgomery, to_montgomery, nonzero, selectznz, to_bytes, from_bytes, one, msat, divstep, divstep_precomp +// m = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 (from "2^256 - 432420386565659656852420866394968145599") +// +// NOTE: In addition to the bounds specified above each function, all +// functions synthesized for this Montgomery arithmetic require the +// input to be strictly less than the prime modulus (m), and also +// require the input to be in the unique saturated representation. +// All functions also ensure that these two properties are true of +// return values. +// +// Computed values: +// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) +// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) +// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in +// if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 + +const std = @import("std"); +const mode = @import("builtin").mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels + +// The type MontgomeryDomainFieldElement is a field element in the Montgomery domain. +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub const MontgomeryDomainFieldElement = [4]u64; + +// The type NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub const NonMontgomeryDomainFieldElement = [4]u64; + +/// The function addcarryxU64 is an addition with carry. +/// +/// Postconditions: +/// out1 = (arg1 + arg2 + arg3) mod 2^64 +/// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋ +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0x1] +/// arg2: [0x0 ~> 0xffffffffffffffff] +/// arg3: [0x0 ~> 0xffffffffffffffff] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +/// out2: [0x0 ~> 0x1] +inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { + @setRuntimeSafety(mode == .Debug); + + var t: u64 = undefined; + const carry1 = @addWithOverflow(u64, arg2, arg3, &t); + const carry2 = @addWithOverflow(u64, t, arg1, out1); + out2.* = @boolToInt(carry1) | @boolToInt(carry2); +} + +/// The function subborrowxU64 is a subtraction with borrow. +/// +/// Postconditions: +/// out1 = (-arg1 + arg2 + -arg3) mod 2^64 +/// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋ +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0x1] +/// arg2: [0x0 ~> 0xffffffffffffffff] +/// arg3: [0x0 ~> 0xffffffffffffffff] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +/// out2: [0x0 ~> 0x1] +inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { + @setRuntimeSafety(mode == .Debug); + + var t: u64 = undefined; + const carry1 = @subWithOverflow(u64, arg2, arg3, &t); + const carry2 = @subWithOverflow(u64, t, arg1, out1); + out2.* = @boolToInt(carry1) | @boolToInt(carry2); +} + +/// The function mulxU64 is a multiplication, returning the full double-width result. +/// +/// Postconditions: +/// out1 = (arg1 * arg2) mod 2^64 +/// out2 = ⌊arg1 * arg2 / 2^64⌋ +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0xffffffffffffffff] +/// arg2: [0x0 ~> 0xffffffffffffffff] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +/// out2: [0x0 ~> 0xffffffffffffffff] +inline fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { + @setRuntimeSafety(mode == .Debug); + + const x = @as(u128, arg1) * @as(u128, arg2); + out1.* = @truncate(u64, x); + out2.* = @truncate(u64, x >> 64); +} + +/// The function cmovznzU64 is a single-word conditional move. +/// +/// Postconditions: +/// out1 = (if arg1 = 0 then arg2 else arg3) +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0x1] +/// arg2: [0x0 ~> 0xffffffffffffffff] +/// arg3: [0x0 ~> 0xffffffffffffffff] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +inline fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { + @setRuntimeSafety(mode == .Debug); + + const mask = 0 -% @as(u64, arg1); + out1.* = (mask & arg3) | ((~mask) & arg2); +} + +/// The function mul multiplies two field elements in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// 0 ≤ eval arg2 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m +/// 0 ≤ eval out1 < m +/// +pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[1]); + const x2 = (arg1[2]); + const x3 = (arg1[3]); + const x4 = (arg1[0]); + var x5: u64 = undefined; + var x6: u64 = undefined; + mulxU64(&x5, &x6, x4, (arg2[3])); + var x7: u64 = undefined; + var x8: u64 = undefined; + mulxU64(&x7, &x8, x4, (arg2[2])); + var x9: u64 = undefined; + var x10: u64 = undefined; + mulxU64(&x9, &x10, x4, (arg2[1])); + var x11: u64 = undefined; + var x12: u64 = undefined; + mulxU64(&x11, &x12, x4, (arg2[0])); + var x13: u64 = undefined; + var x14: u1 = undefined; + addcarryxU64(&x13, &x14, 0x0, x12, x9); + var x15: u64 = undefined; + var x16: u1 = undefined; + addcarryxU64(&x15, &x16, x14, x10, x7); + var x17: u64 = undefined; + var x18: u1 = undefined; + addcarryxU64(&x17, &x18, x16, x8, x5); + const x19 = (@as(u64, x18) + x6); + var x20: u64 = undefined; + var x21: u64 = undefined; + mulxU64(&x20, &x21, x11, 0x4b0dff665588b13f); + var x22: u64 = undefined; + var x23: u64 = undefined; + mulxU64(&x22, &x23, x20, 0xffffffffffffffff); + var x24: u64 = undefined; + var x25: u64 = undefined; + mulxU64(&x24, &x25, x20, 0xfffffffffffffffe); + var x26: u64 = undefined; + var x27: u64 = undefined; + mulxU64(&x26, &x27, x20, 0xbaaedce6af48a03b); + var x28: u64 = undefined; + var x29: u64 = undefined; + mulxU64(&x28, &x29, x20, 0xbfd25e8cd0364141); + var x30: u64 = undefined; + var x31: u1 = undefined; + addcarryxU64(&x30, &x31, 0x0, x29, x26); + var x32: u64 = undefined; + var x33: u1 = undefined; + addcarryxU64(&x32, &x33, x31, x27, x24); + var x34: u64 = undefined; + var x35: u1 = undefined; + addcarryxU64(&x34, &x35, x33, x25, x22); + const x36 = (@as(u64, x35) + x23); + var x37: u64 = undefined; + var x38: u1 = undefined; + addcarryxU64(&x37, &x38, 0x0, x11, x28); + var x39: u64 = undefined; + var x40: u1 = undefined; + addcarryxU64(&x39, &x40, x38, x13, x30); + var x41: u64 = undefined; + var x42: u1 = undefined; + addcarryxU64(&x41, &x42, x40, x15, x32); + var x43: u64 = undefined; + var x44: u1 = undefined; + addcarryxU64(&x43, &x44, x42, x17, x34); + var x45: u64 = undefined; + var x46: u1 = undefined; + addcarryxU64(&x45, &x46, x44, x19, x36); + var x47: u64 = undefined; + var x48: u64 = undefined; + mulxU64(&x47, &x48, x1, (arg2[3])); + var x49: u64 = undefined; + var x50: u64 = undefined; + mulxU64(&x49, &x50, x1, (arg2[2])); + var x51: u64 = undefined; + var x52: u64 = undefined; + mulxU64(&x51, &x52, x1, (arg2[1])); + var x53: u64 = undefined; + var x54: u64 = undefined; + mulxU64(&x53, &x54, x1, (arg2[0])); + var x55: u64 = undefined; + var x56: u1 = undefined; + addcarryxU64(&x55, &x56, 0x0, x54, x51); + var x57: u64 = undefined; + var x58: u1 = undefined; + addcarryxU64(&x57, &x58, x56, x52, x49); + var x59: u64 = undefined; + var x60: u1 = undefined; + addcarryxU64(&x59, &x60, x58, x50, x47); + const x61 = (@as(u64, x60) + x48); + var x62: u64 = undefined; + var x63: u1 = undefined; + addcarryxU64(&x62, &x63, 0x0, x39, x53); + var x64: u64 = undefined; + var x65: u1 = undefined; + addcarryxU64(&x64, &x65, x63, x41, x55); + var x66: u64 = undefined; + var x67: u1 = undefined; + addcarryxU64(&x66, &x67, x65, x43, x57); + var x68: u64 = undefined; + var x69: u1 = undefined; + addcarryxU64(&x68, &x69, x67, x45, x59); + var x70: u64 = undefined; + var x71: u1 = undefined; + addcarryxU64(&x70, &x71, x69, @as(u64, x46), x61); + var x72: u64 = undefined; + var x73: u64 = undefined; + mulxU64(&x72, &x73, x62, 0x4b0dff665588b13f); + var x74: u64 = undefined; + var x75: u64 = undefined; + mulxU64(&x74, &x75, x72, 0xffffffffffffffff); + var x76: u64 = undefined; + var x77: u64 = undefined; + mulxU64(&x76, &x77, x72, 0xfffffffffffffffe); + var x78: u64 = undefined; + var x79: u64 = undefined; + mulxU64(&x78, &x79, x72, 0xbaaedce6af48a03b); + var x80: u64 = undefined; + var x81: u64 = undefined; + mulxU64(&x80, &x81, x72, 0xbfd25e8cd0364141); + var x82: u64 = undefined; + var x83: u1 = undefined; + addcarryxU64(&x82, &x83, 0x0, x81, x78); + var x84: u64 = undefined; + var x85: u1 = undefined; + addcarryxU64(&x84, &x85, x83, x79, x76); + var x86: u64 = undefined; + var x87: u1 = undefined; + addcarryxU64(&x86, &x87, x85, x77, x74); + const x88 = (@as(u64, x87) + x75); + var x89: u64 = undefined; + var x90: u1 = undefined; + addcarryxU64(&x89, &x90, 0x0, x62, x80); + var x91: u64 = undefined; + var x92: u1 = undefined; + addcarryxU64(&x91, &x92, x90, x64, x82); + var x93: u64 = undefined; + var x94: u1 = undefined; + addcarryxU64(&x93, &x94, x92, x66, x84); + var x95: u64 = undefined; + var x96: u1 = undefined; + addcarryxU64(&x95, &x96, x94, x68, x86); + var x97: u64 = undefined; + var x98: u1 = undefined; + addcarryxU64(&x97, &x98, x96, x70, x88); + const x99 = (@as(u64, x98) + @as(u64, x71)); + var x100: u64 = undefined; + var x101: u64 = undefined; + mulxU64(&x100, &x101, x2, (arg2[3])); + var x102: u64 = undefined; + var x103: u64 = undefined; + mulxU64(&x102, &x103, x2, (arg2[2])); + var x104: u64 = undefined; + var x105: u64 = undefined; + mulxU64(&x104, &x105, x2, (arg2[1])); + var x106: u64 = undefined; + var x107: u64 = undefined; + mulxU64(&x106, &x107, x2, (arg2[0])); + var x108: u64 = undefined; + var x109: u1 = undefined; + addcarryxU64(&x108, &x109, 0x0, x107, x104); + var x110: u64 = undefined; + var x111: u1 = undefined; + addcarryxU64(&x110, &x111, x109, x105, x102); + var x112: u64 = undefined; + var x113: u1 = undefined; + addcarryxU64(&x112, &x113, x111, x103, x100); + const x114 = (@as(u64, x113) + x101); + var x115: u64 = undefined; + var x116: u1 = undefined; + addcarryxU64(&x115, &x116, 0x0, x91, x106); + var x117: u64 = undefined; + var x118: u1 = undefined; + addcarryxU64(&x117, &x118, x116, x93, x108); + var x119: u64 = undefined; + var x120: u1 = undefined; + addcarryxU64(&x119, &x120, x118, x95, x110); + var x121: u64 = undefined; + var x122: u1 = undefined; + addcarryxU64(&x121, &x122, x120, x97, x112); + var x123: u64 = undefined; + var x124: u1 = undefined; + addcarryxU64(&x123, &x124, x122, x99, x114); + var x125: u64 = undefined; + var x126: u64 = undefined; + mulxU64(&x125, &x126, x115, 0x4b0dff665588b13f); + var x127: u64 = undefined; + var x128: u64 = undefined; + mulxU64(&x127, &x128, x125, 0xffffffffffffffff); + var x129: u64 = undefined; + var x130: u64 = undefined; + mulxU64(&x129, &x130, x125, 0xfffffffffffffffe); + var x131: u64 = undefined; + var x132: u64 = undefined; + mulxU64(&x131, &x132, x125, 0xbaaedce6af48a03b); + var x133: u64 = undefined; + var x134: u64 = undefined; + mulxU64(&x133, &x134, x125, 0xbfd25e8cd0364141); + var x135: u64 = undefined; + var x136: u1 = undefined; + addcarryxU64(&x135, &x136, 0x0, x134, x131); + var x137: u64 = undefined; + var x138: u1 = undefined; + addcarryxU64(&x137, &x138, x136, x132, x129); + var x139: u64 = undefined; + var x140: u1 = undefined; + addcarryxU64(&x139, &x140, x138, x130, x127); + const x141 = (@as(u64, x140) + x128); + var x142: u64 = undefined; + var x143: u1 = undefined; + addcarryxU64(&x142, &x143, 0x0, x115, x133); + var x144: u64 = undefined; + var x145: u1 = undefined; + addcarryxU64(&x144, &x145, x143, x117, x135); + var x146: u64 = undefined; + var x147: u1 = undefined; + addcarryxU64(&x146, &x147, x145, x119, x137); + var x148: u64 = undefined; + var x149: u1 = undefined; + addcarryxU64(&x148, &x149, x147, x121, x139); + var x150: u64 = undefined; + var x151: u1 = undefined; + addcarryxU64(&x150, &x151, x149, x123, x141); + const x152 = (@as(u64, x151) + @as(u64, x124)); + var x153: u64 = undefined; + var x154: u64 = undefined; + mulxU64(&x153, &x154, x3, (arg2[3])); + var x155: u64 = undefined; + var x156: u64 = undefined; + mulxU64(&x155, &x156, x3, (arg2[2])); + var x157: u64 = undefined; + var x158: u64 = undefined; + mulxU64(&x157, &x158, x3, (arg2[1])); + var x159: u64 = undefined; + var x160: u64 = undefined; + mulxU64(&x159, &x160, x3, (arg2[0])); + var x161: u64 = undefined; + var x162: u1 = undefined; + addcarryxU64(&x161, &x162, 0x0, x160, x157); + var x163: u64 = undefined; + var x164: u1 = undefined; + addcarryxU64(&x163, &x164, x162, x158, x155); + var x165: u64 = undefined; + var x166: u1 = undefined; + addcarryxU64(&x165, &x166, x164, x156, x153); + const x167 = (@as(u64, x166) + x154); + var x168: u64 = undefined; + var x169: u1 = undefined; + addcarryxU64(&x168, &x169, 0x0, x144, x159); + var x170: u64 = undefined; + var x171: u1 = undefined; + addcarryxU64(&x170, &x171, x169, x146, x161); + var x172: u64 = undefined; + var x173: u1 = undefined; + addcarryxU64(&x172, &x173, x171, x148, x163); + var x174: u64 = undefined; + var x175: u1 = undefined; + addcarryxU64(&x174, &x175, x173, x150, x165); + var x176: u64 = undefined; + var x177: u1 = undefined; + addcarryxU64(&x176, &x177, x175, x152, x167); + var x178: u64 = undefined; + var x179: u64 = undefined; + mulxU64(&x178, &x179, x168, 0x4b0dff665588b13f); + var x180: u64 = undefined; + var x181: u64 = undefined; + mulxU64(&x180, &x181, x178, 0xffffffffffffffff); + var x182: u64 = undefined; + var x183: u64 = undefined; + mulxU64(&x182, &x183, x178, 0xfffffffffffffffe); + var x184: u64 = undefined; + var x185: u64 = undefined; + mulxU64(&x184, &x185, x178, 0xbaaedce6af48a03b); + var x186: u64 = undefined; + var x187: u64 = undefined; + mulxU64(&x186, &x187, x178, 0xbfd25e8cd0364141); + var x188: u64 = undefined; + var x189: u1 = undefined; + addcarryxU64(&x188, &x189, 0x0, x187, x184); + var x190: u64 = undefined; + var x191: u1 = undefined; + addcarryxU64(&x190, &x191, x189, x185, x182); + var x192: u64 = undefined; + var x193: u1 = undefined; + addcarryxU64(&x192, &x193, x191, x183, x180); + const x194 = (@as(u64, x193) + x181); + var x195: u64 = undefined; + var x196: u1 = undefined; + addcarryxU64(&x195, &x196, 0x0, x168, x186); + var x197: u64 = undefined; + var x198: u1 = undefined; + addcarryxU64(&x197, &x198, x196, x170, x188); + var x199: u64 = undefined; + var x200: u1 = undefined; + addcarryxU64(&x199, &x200, x198, x172, x190); + var x201: u64 = undefined; + var x202: u1 = undefined; + addcarryxU64(&x201, &x202, x200, x174, x192); + var x203: u64 = undefined; + var x204: u1 = undefined; + addcarryxU64(&x203, &x204, x202, x176, x194); + const x205 = (@as(u64, x204) + @as(u64, x177)); + var x206: u64 = undefined; + var x207: u1 = undefined; + subborrowxU64(&x206, &x207, 0x0, x197, 0xbfd25e8cd0364141); + var x208: u64 = undefined; + var x209: u1 = undefined; + subborrowxU64(&x208, &x209, x207, x199, 0xbaaedce6af48a03b); + var x210: u64 = undefined; + var x211: u1 = undefined; + subborrowxU64(&x210, &x211, x209, x201, 0xfffffffffffffffe); + var x212: u64 = undefined; + var x213: u1 = undefined; + subborrowxU64(&x212, &x213, x211, x203, 0xffffffffffffffff); + var x214: u64 = undefined; + var x215: u1 = undefined; + subborrowxU64(&x214, &x215, x213, x205, 0x0); + var x216: u64 = undefined; + cmovznzU64(&x216, x215, x206, x197); + var x217: u64 = undefined; + cmovznzU64(&x217, x215, x208, x199); + var x218: u64 = undefined; + cmovznzU64(&x218, x215, x210, x201); + var x219: u64 = undefined; + cmovznzU64(&x219, x215, x212, x203); + out1[0] = x216; + out1[1] = x217; + out1[2] = x218; + out1[3] = x219; +} + +/// The function square squares a field element in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m +/// 0 ≤ eval out1 < m +/// +pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[1]); + const x2 = (arg1[2]); + const x3 = (arg1[3]); + const x4 = (arg1[0]); + var x5: u64 = undefined; + var x6: u64 = undefined; + mulxU64(&x5, &x6, x4, (arg1[3])); + var x7: u64 = undefined; + var x8: u64 = undefined; + mulxU64(&x7, &x8, x4, (arg1[2])); + var x9: u64 = undefined; + var x10: u64 = undefined; + mulxU64(&x9, &x10, x4, (arg1[1])); + var x11: u64 = undefined; + var x12: u64 = undefined; + mulxU64(&x11, &x12, x4, (arg1[0])); + var x13: u64 = undefined; + var x14: u1 = undefined; + addcarryxU64(&x13, &x14, 0x0, x12, x9); + var x15: u64 = undefined; + var x16: u1 = undefined; + addcarryxU64(&x15, &x16, x14, x10, x7); + var x17: u64 = undefined; + var x18: u1 = undefined; + addcarryxU64(&x17, &x18, x16, x8, x5); + const x19 = (@as(u64, x18) + x6); + var x20: u64 = undefined; + var x21: u64 = undefined; + mulxU64(&x20, &x21, x11, 0x4b0dff665588b13f); + var x22: u64 = undefined; + var x23: u64 = undefined; + mulxU64(&x22, &x23, x20, 0xffffffffffffffff); + var x24: u64 = undefined; + var x25: u64 = undefined; + mulxU64(&x24, &x25, x20, 0xfffffffffffffffe); + var x26: u64 = undefined; + var x27: u64 = undefined; + mulxU64(&x26, &x27, x20, 0xbaaedce6af48a03b); + var x28: u64 = undefined; + var x29: u64 = undefined; + mulxU64(&x28, &x29, x20, 0xbfd25e8cd0364141); + var x30: u64 = undefined; + var x31: u1 = undefined; + addcarryxU64(&x30, &x31, 0x0, x29, x26); + var x32: u64 = undefined; + var x33: u1 = undefined; + addcarryxU64(&x32, &x33, x31, x27, x24); + var x34: u64 = undefined; + var x35: u1 = undefined; + addcarryxU64(&x34, &x35, x33, x25, x22); + const x36 = (@as(u64, x35) + x23); + var x37: u64 = undefined; + var x38: u1 = undefined; + addcarryxU64(&x37, &x38, 0x0, x11, x28); + var x39: u64 = undefined; + var x40: u1 = undefined; + addcarryxU64(&x39, &x40, x38, x13, x30); + var x41: u64 = undefined; + var x42: u1 = undefined; + addcarryxU64(&x41, &x42, x40, x15, x32); + var x43: u64 = undefined; + var x44: u1 = undefined; + addcarryxU64(&x43, &x44, x42, x17, x34); + var x45: u64 = undefined; + var x46: u1 = undefined; + addcarryxU64(&x45, &x46, x44, x19, x36); + var x47: u64 = undefined; + var x48: u64 = undefined; + mulxU64(&x47, &x48, x1, (arg1[3])); + var x49: u64 = undefined; + var x50: u64 = undefined; + mulxU64(&x49, &x50, x1, (arg1[2])); + var x51: u64 = undefined; + var x52: u64 = undefined; + mulxU64(&x51, &x52, x1, (arg1[1])); + var x53: u64 = undefined; + var x54: u64 = undefined; + mulxU64(&x53, &x54, x1, (arg1[0])); + var x55: u64 = undefined; + var x56: u1 = undefined; + addcarryxU64(&x55, &x56, 0x0, x54, x51); + var x57: u64 = undefined; + var x58: u1 = undefined; + addcarryxU64(&x57, &x58, x56, x52, x49); + var x59: u64 = undefined; + var x60: u1 = undefined; + addcarryxU64(&x59, &x60, x58, x50, x47); + const x61 = (@as(u64, x60) + x48); + var x62: u64 = undefined; + var x63: u1 = undefined; + addcarryxU64(&x62, &x63, 0x0, x39, x53); + var x64: u64 = undefined; + var x65: u1 = undefined; + addcarryxU64(&x64, &x65, x63, x41, x55); + var x66: u64 = undefined; + var x67: u1 = undefined; + addcarryxU64(&x66, &x67, x65, x43, x57); + var x68: u64 = undefined; + var x69: u1 = undefined; + addcarryxU64(&x68, &x69, x67, x45, x59); + var x70: u64 = undefined; + var x71: u1 = undefined; + addcarryxU64(&x70, &x71, x69, @as(u64, x46), x61); + var x72: u64 = undefined; + var x73: u64 = undefined; + mulxU64(&x72, &x73, x62, 0x4b0dff665588b13f); + var x74: u64 = undefined; + var x75: u64 = undefined; + mulxU64(&x74, &x75, x72, 0xffffffffffffffff); + var x76: u64 = undefined; + var x77: u64 = undefined; + mulxU64(&x76, &x77, x72, 0xfffffffffffffffe); + var x78: u64 = undefined; + var x79: u64 = undefined; + mulxU64(&x78, &x79, x72, 0xbaaedce6af48a03b); + var x80: u64 = undefined; + var x81: u64 = undefined; + mulxU64(&x80, &x81, x72, 0xbfd25e8cd0364141); + var x82: u64 = undefined; + var x83: u1 = undefined; + addcarryxU64(&x82, &x83, 0x0, x81, x78); + var x84: u64 = undefined; + var x85: u1 = undefined; + addcarryxU64(&x84, &x85, x83, x79, x76); + var x86: u64 = undefined; + var x87: u1 = undefined; + addcarryxU64(&x86, &x87, x85, x77, x74); + const x88 = (@as(u64, x87) + x75); + var x89: u64 = undefined; + var x90: u1 = undefined; + addcarryxU64(&x89, &x90, 0x0, x62, x80); + var x91: u64 = undefined; + var x92: u1 = undefined; + addcarryxU64(&x91, &x92, x90, x64, x82); + var x93: u64 = undefined; + var x94: u1 = undefined; + addcarryxU64(&x93, &x94, x92, x66, x84); + var x95: u64 = undefined; + var x96: u1 = undefined; + addcarryxU64(&x95, &x96, x94, x68, x86); + var x97: u64 = undefined; + var x98: u1 = undefined; + addcarryxU64(&x97, &x98, x96, x70, x88); + const x99 = (@as(u64, x98) + @as(u64, x71)); + var x100: u64 = undefined; + var x101: u64 = undefined; + mulxU64(&x100, &x101, x2, (arg1[3])); + var x102: u64 = undefined; + var x103: u64 = undefined; + mulxU64(&x102, &x103, x2, (arg1[2])); + var x104: u64 = undefined; + var x105: u64 = undefined; + mulxU64(&x104, &x105, x2, (arg1[1])); + var x106: u64 = undefined; + var x107: u64 = undefined; + mulxU64(&x106, &x107, x2, (arg1[0])); + var x108: u64 = undefined; + var x109: u1 = undefined; + addcarryxU64(&x108, &x109, 0x0, x107, x104); + var x110: u64 = undefined; + var x111: u1 = undefined; + addcarryxU64(&x110, &x111, x109, x105, x102); + var x112: u64 = undefined; + var x113: u1 = undefined; + addcarryxU64(&x112, &x113, x111, x103, x100); + const x114 = (@as(u64, x113) + x101); + var x115: u64 = undefined; + var x116: u1 = undefined; + addcarryxU64(&x115, &x116, 0x0, x91, x106); + var x117: u64 = undefined; + var x118: u1 = undefined; + addcarryxU64(&x117, &x118, x116, x93, x108); + var x119: u64 = undefined; + var x120: u1 = undefined; + addcarryxU64(&x119, &x120, x118, x95, x110); + var x121: u64 = undefined; + var x122: u1 = undefined; + addcarryxU64(&x121, &x122, x120, x97, x112); + var x123: u64 = undefined; + var x124: u1 = undefined; + addcarryxU64(&x123, &x124, x122, x99, x114); + var x125: u64 = undefined; + var x126: u64 = undefined; + mulxU64(&x125, &x126, x115, 0x4b0dff665588b13f); + var x127: u64 = undefined; + var x128: u64 = undefined; + mulxU64(&x127, &x128, x125, 0xffffffffffffffff); + var x129: u64 = undefined; + var x130: u64 = undefined; + mulxU64(&x129, &x130, x125, 0xfffffffffffffffe); + var x131: u64 = undefined; + var x132: u64 = undefined; + mulxU64(&x131, &x132, x125, 0xbaaedce6af48a03b); + var x133: u64 = undefined; + var x134: u64 = undefined; + mulxU64(&x133, &x134, x125, 0xbfd25e8cd0364141); + var x135: u64 = undefined; + var x136: u1 = undefined; + addcarryxU64(&x135, &x136, 0x0, x134, x131); + var x137: u64 = undefined; + var x138: u1 = undefined; + addcarryxU64(&x137, &x138, x136, x132, x129); + var x139: u64 = undefined; + var x140: u1 = undefined; + addcarryxU64(&x139, &x140, x138, x130, x127); + const x141 = (@as(u64, x140) + x128); + var x142: u64 = undefined; + var x143: u1 = undefined; + addcarryxU64(&x142, &x143, 0x0, x115, x133); + var x144: u64 = undefined; + var x145: u1 = undefined; + addcarryxU64(&x144, &x145, x143, x117, x135); + var x146: u64 = undefined; + var x147: u1 = undefined; + addcarryxU64(&x146, &x147, x145, x119, x137); + var x148: u64 = undefined; + var x149: u1 = undefined; + addcarryxU64(&x148, &x149, x147, x121, x139); + var x150: u64 = undefined; + var x151: u1 = undefined; + addcarryxU64(&x150, &x151, x149, x123, x141); + const x152 = (@as(u64, x151) + @as(u64, x124)); + var x153: u64 = undefined; + var x154: u64 = undefined; + mulxU64(&x153, &x154, x3, (arg1[3])); + var x155: u64 = undefined; + var x156: u64 = undefined; + mulxU64(&x155, &x156, x3, (arg1[2])); + var x157: u64 = undefined; + var x158: u64 = undefined; + mulxU64(&x157, &x158, x3, (arg1[1])); + var x159: u64 = undefined; + var x160: u64 = undefined; + mulxU64(&x159, &x160, x3, (arg1[0])); + var x161: u64 = undefined; + var x162: u1 = undefined; + addcarryxU64(&x161, &x162, 0x0, x160, x157); + var x163: u64 = undefined; + var x164: u1 = undefined; + addcarryxU64(&x163, &x164, x162, x158, x155); + var x165: u64 = undefined; + var x166: u1 = undefined; + addcarryxU64(&x165, &x166, x164, x156, x153); + const x167 = (@as(u64, x166) + x154); + var x168: u64 = undefined; + var x169: u1 = undefined; + addcarryxU64(&x168, &x169, 0x0, x144, x159); + var x170: u64 = undefined; + var x171: u1 = undefined; + addcarryxU64(&x170, &x171, x169, x146, x161); + var x172: u64 = undefined; + var x173: u1 = undefined; + addcarryxU64(&x172, &x173, x171, x148, x163); + var x174: u64 = undefined; + var x175: u1 = undefined; + addcarryxU64(&x174, &x175, x173, x150, x165); + var x176: u64 = undefined; + var x177: u1 = undefined; + addcarryxU64(&x176, &x177, x175, x152, x167); + var x178: u64 = undefined; + var x179: u64 = undefined; + mulxU64(&x178, &x179, x168, 0x4b0dff665588b13f); + var x180: u64 = undefined; + var x181: u64 = undefined; + mulxU64(&x180, &x181, x178, 0xffffffffffffffff); + var x182: u64 = undefined; + var x183: u64 = undefined; + mulxU64(&x182, &x183, x178, 0xfffffffffffffffe); + var x184: u64 = undefined; + var x185: u64 = undefined; + mulxU64(&x184, &x185, x178, 0xbaaedce6af48a03b); + var x186: u64 = undefined; + var x187: u64 = undefined; + mulxU64(&x186, &x187, x178, 0xbfd25e8cd0364141); + var x188: u64 = undefined; + var x189: u1 = undefined; + addcarryxU64(&x188, &x189, 0x0, x187, x184); + var x190: u64 = undefined; + var x191: u1 = undefined; + addcarryxU64(&x190, &x191, x189, x185, x182); + var x192: u64 = undefined; + var x193: u1 = undefined; + addcarryxU64(&x192, &x193, x191, x183, x180); + const x194 = (@as(u64, x193) + x181); + var x195: u64 = undefined; + var x196: u1 = undefined; + addcarryxU64(&x195, &x196, 0x0, x168, x186); + var x197: u64 = undefined; + var x198: u1 = undefined; + addcarryxU64(&x197, &x198, x196, x170, x188); + var x199: u64 = undefined; + var x200: u1 = undefined; + addcarryxU64(&x199, &x200, x198, x172, x190); + var x201: u64 = undefined; + var x202: u1 = undefined; + addcarryxU64(&x201, &x202, x200, x174, x192); + var x203: u64 = undefined; + var x204: u1 = undefined; + addcarryxU64(&x203, &x204, x202, x176, x194); + const x205 = (@as(u64, x204) + @as(u64, x177)); + var x206: u64 = undefined; + var x207: u1 = undefined; + subborrowxU64(&x206, &x207, 0x0, x197, 0xbfd25e8cd0364141); + var x208: u64 = undefined; + var x209: u1 = undefined; + subborrowxU64(&x208, &x209, x207, x199, 0xbaaedce6af48a03b); + var x210: u64 = undefined; + var x211: u1 = undefined; + subborrowxU64(&x210, &x211, x209, x201, 0xfffffffffffffffe); + var x212: u64 = undefined; + var x213: u1 = undefined; + subborrowxU64(&x212, &x213, x211, x203, 0xffffffffffffffff); + var x214: u64 = undefined; + var x215: u1 = undefined; + subborrowxU64(&x214, &x215, x213, x205, 0x0); + var x216: u64 = undefined; + cmovznzU64(&x216, x215, x206, x197); + var x217: u64 = undefined; + cmovznzU64(&x217, x215, x208, x199); + var x218: u64 = undefined; + cmovznzU64(&x218, x215, x210, x201); + var x219: u64 = undefined; + cmovznzU64(&x219, x215, x212, x203); + out1[0] = x216; + out1[1] = x217; + out1[2] = x218; + out1[3] = x219; +} + +/// The function add adds two field elements in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// 0 ≤ eval arg2 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m +/// 0 ≤ eval out1 < m +/// +pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + var x2: u1 = undefined; + addcarryxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); + var x3: u64 = undefined; + var x4: u1 = undefined; + addcarryxU64(&x3, &x4, x2, (arg1[1]), (arg2[1])); + var x5: u64 = undefined; + var x6: u1 = undefined; + addcarryxU64(&x5, &x6, x4, (arg1[2]), (arg2[2])); + var x7: u64 = undefined; + var x8: u1 = undefined; + addcarryxU64(&x7, &x8, x6, (arg1[3]), (arg2[3])); + var x9: u64 = undefined; + var x10: u1 = undefined; + subborrowxU64(&x9, &x10, 0x0, x1, 0xbfd25e8cd0364141); + var x11: u64 = undefined; + var x12: u1 = undefined; + subborrowxU64(&x11, &x12, x10, x3, 0xbaaedce6af48a03b); + var x13: u64 = undefined; + var x14: u1 = undefined; + subborrowxU64(&x13, &x14, x12, x5, 0xfffffffffffffffe); + var x15: u64 = undefined; + var x16: u1 = undefined; + subborrowxU64(&x15, &x16, x14, x7, 0xffffffffffffffff); + var x17: u64 = undefined; + var x18: u1 = undefined; + subborrowxU64(&x17, &x18, x16, @as(u64, x8), 0x0); + var x19: u64 = undefined; + cmovznzU64(&x19, x18, x9, x1); + var x20: u64 = undefined; + cmovznzU64(&x20, x18, x11, x3); + var x21: u64 = undefined; + cmovznzU64(&x21, x18, x13, x5); + var x22: u64 = undefined; + cmovznzU64(&x22, x18, x15, x7); + out1[0] = x19; + out1[1] = x20; + out1[2] = x21; + out1[3] = x22; +} + +/// The function sub subtracts two field elements in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// 0 ≤ eval arg2 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m +/// 0 ≤ eval out1 < m +/// +pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + var x2: u1 = undefined; + subborrowxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); + var x3: u64 = undefined; + var x4: u1 = undefined; + subborrowxU64(&x3, &x4, x2, (arg1[1]), (arg2[1])); + var x5: u64 = undefined; + var x6: u1 = undefined; + subborrowxU64(&x5, &x6, x4, (arg1[2]), (arg2[2])); + var x7: u64 = undefined; + var x8: u1 = undefined; + subborrowxU64(&x7, &x8, x6, (arg1[3]), (arg2[3])); + var x9: u64 = undefined; + cmovznzU64(&x9, x8, 0x0, 0xffffffffffffffff); + var x10: u64 = undefined; + var x11: u1 = undefined; + addcarryxU64(&x10, &x11, 0x0, x1, (x9 & 0xbfd25e8cd0364141)); + var x12: u64 = undefined; + var x13: u1 = undefined; + addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xbaaedce6af48a03b)); + var x14: u64 = undefined; + var x15: u1 = undefined; + addcarryxU64(&x14, &x15, x13, x5, (x9 & 0xfffffffffffffffe)); + var x16: u64 = undefined; + var x17: u1 = undefined; + addcarryxU64(&x16, &x17, x15, x7, x9); + out1[0] = x10; + out1[1] = x12; + out1[2] = x14; + out1[3] = x16; +} + +/// The function opp negates a field element in the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m +/// 0 ≤ eval out1 < m +/// +pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + var x2: u1 = undefined; + subborrowxU64(&x1, &x2, 0x0, 0x0, (arg1[0])); + var x3: u64 = undefined; + var x4: u1 = undefined; + subborrowxU64(&x3, &x4, x2, 0x0, (arg1[1])); + var x5: u64 = undefined; + var x6: u1 = undefined; + subborrowxU64(&x5, &x6, x4, 0x0, (arg1[2])); + var x7: u64 = undefined; + var x8: u1 = undefined; + subborrowxU64(&x7, &x8, x6, 0x0, (arg1[3])); + var x9: u64 = undefined; + cmovznzU64(&x9, x8, 0x0, 0xffffffffffffffff); + var x10: u64 = undefined; + var x11: u1 = undefined; + addcarryxU64(&x10, &x11, 0x0, x1, (x9 & 0xbfd25e8cd0364141)); + var x12: u64 = undefined; + var x13: u1 = undefined; + addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xbaaedce6af48a03b)); + var x14: u64 = undefined; + var x15: u1 = undefined; + addcarryxU64(&x14, &x15, x13, x5, (x9 & 0xfffffffffffffffe)); + var x16: u64 = undefined; + var x17: u1 = undefined; + addcarryxU64(&x16, &x17, x15, x7, x9); + out1[0] = x10; + out1[1] = x12; + out1[2] = x14; + out1[3] = x16; +} + +/// The function fromMontgomery translates a field element out of the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m +/// 0 ≤ eval out1 < m +/// +pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[0]); + var x2: u64 = undefined; + var x3: u64 = undefined; + mulxU64(&x2, &x3, x1, 0x4b0dff665588b13f); + var x4: u64 = undefined; + var x5: u64 = undefined; + mulxU64(&x4, &x5, x2, 0xffffffffffffffff); + var x6: u64 = undefined; + var x7: u64 = undefined; + mulxU64(&x6, &x7, x2, 0xfffffffffffffffe); + var x8: u64 = undefined; + var x9: u64 = undefined; + mulxU64(&x8, &x9, x2, 0xbaaedce6af48a03b); + var x10: u64 = undefined; + var x11: u64 = undefined; + mulxU64(&x10, &x11, x2, 0xbfd25e8cd0364141); + var x12: u64 = undefined; + var x13: u1 = undefined; + addcarryxU64(&x12, &x13, 0x0, x11, x8); + var x14: u64 = undefined; + var x15: u1 = undefined; + addcarryxU64(&x14, &x15, x13, x9, x6); + var x16: u64 = undefined; + var x17: u1 = undefined; + addcarryxU64(&x16, &x17, x15, x7, x4); + var x18: u64 = undefined; + var x19: u1 = undefined; + addcarryxU64(&x18, &x19, 0x0, x1, x10); + var x20: u64 = undefined; + var x21: u1 = undefined; + addcarryxU64(&x20, &x21, x19, 0x0, x12); + var x22: u64 = undefined; + var x23: u1 = undefined; + addcarryxU64(&x22, &x23, x21, 0x0, x14); + var x24: u64 = undefined; + var x25: u1 = undefined; + addcarryxU64(&x24, &x25, x23, 0x0, x16); + var x26: u64 = undefined; + var x27: u1 = undefined; + addcarryxU64(&x26, &x27, x25, 0x0, (@as(u64, x17) + x5)); + var x28: u64 = undefined; + var x29: u1 = undefined; + addcarryxU64(&x28, &x29, 0x0, x20, (arg1[1])); + var x30: u64 = undefined; + var x31: u1 = undefined; + addcarryxU64(&x30, &x31, x29, x22, 0x0); + var x32: u64 = undefined; + var x33: u1 = undefined; + addcarryxU64(&x32, &x33, x31, x24, 0x0); + var x34: u64 = undefined; + var x35: u1 = undefined; + addcarryxU64(&x34, &x35, x33, x26, 0x0); + var x36: u64 = undefined; + var x37: u64 = undefined; + mulxU64(&x36, &x37, x28, 0x4b0dff665588b13f); + var x38: u64 = undefined; + var x39: u64 = undefined; + mulxU64(&x38, &x39, x36, 0xffffffffffffffff); + var x40: u64 = undefined; + var x41: u64 = undefined; + mulxU64(&x40, &x41, x36, 0xfffffffffffffffe); + var x42: u64 = undefined; + var x43: u64 = undefined; + mulxU64(&x42, &x43, x36, 0xbaaedce6af48a03b); + var x44: u64 = undefined; + var x45: u64 = undefined; + mulxU64(&x44, &x45, x36, 0xbfd25e8cd0364141); + var x46: u64 = undefined; + var x47: u1 = undefined; + addcarryxU64(&x46, &x47, 0x0, x45, x42); + var x48: u64 = undefined; + var x49: u1 = undefined; + addcarryxU64(&x48, &x49, x47, x43, x40); + var x50: u64 = undefined; + var x51: u1 = undefined; + addcarryxU64(&x50, &x51, x49, x41, x38); + var x52: u64 = undefined; + var x53: u1 = undefined; + addcarryxU64(&x52, &x53, 0x0, x28, x44); + var x54: u64 = undefined; + var x55: u1 = undefined; + addcarryxU64(&x54, &x55, x53, x30, x46); + var x56: u64 = undefined; + var x57: u1 = undefined; + addcarryxU64(&x56, &x57, x55, x32, x48); + var x58: u64 = undefined; + var x59: u1 = undefined; + addcarryxU64(&x58, &x59, x57, x34, x50); + var x60: u64 = undefined; + var x61: u1 = undefined; + addcarryxU64(&x60, &x61, x59, (@as(u64, x35) + @as(u64, x27)), (@as(u64, x51) + x39)); + var x62: u64 = undefined; + var x63: u1 = undefined; + addcarryxU64(&x62, &x63, 0x0, x54, (arg1[2])); + var x64: u64 = undefined; + var x65: u1 = undefined; + addcarryxU64(&x64, &x65, x63, x56, 0x0); + var x66: u64 = undefined; + var x67: u1 = undefined; + addcarryxU64(&x66, &x67, x65, x58, 0x0); + var x68: u64 = undefined; + var x69: u1 = undefined; + addcarryxU64(&x68, &x69, x67, x60, 0x0); + var x70: u64 = undefined; + var x71: u64 = undefined; + mulxU64(&x70, &x71, x62, 0x4b0dff665588b13f); + var x72: u64 = undefined; + var x73: u64 = undefined; + mulxU64(&x72, &x73, x70, 0xffffffffffffffff); + var x74: u64 = undefined; + var x75: u64 = undefined; + mulxU64(&x74, &x75, x70, 0xfffffffffffffffe); + var x76: u64 = undefined; + var x77: u64 = undefined; + mulxU64(&x76, &x77, x70, 0xbaaedce6af48a03b); + var x78: u64 = undefined; + var x79: u64 = undefined; + mulxU64(&x78, &x79, x70, 0xbfd25e8cd0364141); + var x80: u64 = undefined; + var x81: u1 = undefined; + addcarryxU64(&x80, &x81, 0x0, x79, x76); + var x82: u64 = undefined; + var x83: u1 = undefined; + addcarryxU64(&x82, &x83, x81, x77, x74); + var x84: u64 = undefined; + var x85: u1 = undefined; + addcarryxU64(&x84, &x85, x83, x75, x72); + var x86: u64 = undefined; + var x87: u1 = undefined; + addcarryxU64(&x86, &x87, 0x0, x62, x78); + var x88: u64 = undefined; + var x89: u1 = undefined; + addcarryxU64(&x88, &x89, x87, x64, x80); + var x90: u64 = undefined; + var x91: u1 = undefined; + addcarryxU64(&x90, &x91, x89, x66, x82); + var x92: u64 = undefined; + var x93: u1 = undefined; + addcarryxU64(&x92, &x93, x91, x68, x84); + var x94: u64 = undefined; + var x95: u1 = undefined; + addcarryxU64(&x94, &x95, x93, (@as(u64, x69) + @as(u64, x61)), (@as(u64, x85) + x73)); + var x96: u64 = undefined; + var x97: u1 = undefined; + addcarryxU64(&x96, &x97, 0x0, x88, (arg1[3])); + var x98: u64 = undefined; + var x99: u1 = undefined; + addcarryxU64(&x98, &x99, x97, x90, 0x0); + var x100: u64 = undefined; + var x101: u1 = undefined; + addcarryxU64(&x100, &x101, x99, x92, 0x0); + var x102: u64 = undefined; + var x103: u1 = undefined; + addcarryxU64(&x102, &x103, x101, x94, 0x0); + var x104: u64 = undefined; + var x105: u64 = undefined; + mulxU64(&x104, &x105, x96, 0x4b0dff665588b13f); + var x106: u64 = undefined; + var x107: u64 = undefined; + mulxU64(&x106, &x107, x104, 0xffffffffffffffff); + var x108: u64 = undefined; + var x109: u64 = undefined; + mulxU64(&x108, &x109, x104, 0xfffffffffffffffe); + var x110: u64 = undefined; + var x111: u64 = undefined; + mulxU64(&x110, &x111, x104, 0xbaaedce6af48a03b); + var x112: u64 = undefined; + var x113: u64 = undefined; + mulxU64(&x112, &x113, x104, 0xbfd25e8cd0364141); + var x114: u64 = undefined; + var x115: u1 = undefined; + addcarryxU64(&x114, &x115, 0x0, x113, x110); + var x116: u64 = undefined; + var x117: u1 = undefined; + addcarryxU64(&x116, &x117, x115, x111, x108); + var x118: u64 = undefined; + var x119: u1 = undefined; + addcarryxU64(&x118, &x119, x117, x109, x106); + var x120: u64 = undefined; + var x121: u1 = undefined; + addcarryxU64(&x120, &x121, 0x0, x96, x112); + var x122: u64 = undefined; + var x123: u1 = undefined; + addcarryxU64(&x122, &x123, x121, x98, x114); + var x124: u64 = undefined; + var x125: u1 = undefined; + addcarryxU64(&x124, &x125, x123, x100, x116); + var x126: u64 = undefined; + var x127: u1 = undefined; + addcarryxU64(&x126, &x127, x125, x102, x118); + var x128: u64 = undefined; + var x129: u1 = undefined; + addcarryxU64(&x128, &x129, x127, (@as(u64, x103) + @as(u64, x95)), (@as(u64, x119) + x107)); + var x130: u64 = undefined; + var x131: u1 = undefined; + subborrowxU64(&x130, &x131, 0x0, x122, 0xbfd25e8cd0364141); + var x132: u64 = undefined; + var x133: u1 = undefined; + subborrowxU64(&x132, &x133, x131, x124, 0xbaaedce6af48a03b); + var x134: u64 = undefined; + var x135: u1 = undefined; + subborrowxU64(&x134, &x135, x133, x126, 0xfffffffffffffffe); + var x136: u64 = undefined; + var x137: u1 = undefined; + subborrowxU64(&x136, &x137, x135, x128, 0xffffffffffffffff); + var x138: u64 = undefined; + var x139: u1 = undefined; + subborrowxU64(&x138, &x139, x137, @as(u64, x129), 0x0); + var x140: u64 = undefined; + cmovznzU64(&x140, x139, x130, x122); + var x141: u64 = undefined; + cmovznzU64(&x141, x139, x132, x124); + var x142: u64 = undefined; + cmovznzU64(&x142, x139, x134, x126); + var x143: u64 = undefined; + cmovznzU64(&x143, x139, x136, x128); + out1[0] = x140; + out1[1] = x141; + out1[2] = x142; + out1[3] = x143; +} + +/// The function toMontgomery translates a field element into the Montgomery domain. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// eval (from_montgomery out1) mod m = eval arg1 mod m +/// 0 ≤ eval out1 < m +/// +pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[1]); + const x2 = (arg1[2]); + const x3 = (arg1[3]); + const x4 = (arg1[0]); + var x5: u64 = undefined; + var x6: u64 = undefined; + mulxU64(&x5, &x6, x4, 0x9d671cd581c69bc5); + var x7: u64 = undefined; + var x8: u64 = undefined; + mulxU64(&x7, &x8, x4, 0xe697f5e45bcd07c6); + var x9: u64 = undefined; + var x10: u64 = undefined; + mulxU64(&x9, &x10, x4, 0x741496c20e7cf878); + var x11: u64 = undefined; + var x12: u64 = undefined; + mulxU64(&x11, &x12, x4, 0x896cf21467d7d140); + var x13: u64 = undefined; + var x14: u1 = undefined; + addcarryxU64(&x13, &x14, 0x0, x12, x9); + var x15: u64 = undefined; + var x16: u1 = undefined; + addcarryxU64(&x15, &x16, x14, x10, x7); + var x17: u64 = undefined; + var x18: u1 = undefined; + addcarryxU64(&x17, &x18, x16, x8, x5); + var x19: u64 = undefined; + var x20: u64 = undefined; + mulxU64(&x19, &x20, x11, 0x4b0dff665588b13f); + var x21: u64 = undefined; + var x22: u64 = undefined; + mulxU64(&x21, &x22, x19, 0xffffffffffffffff); + var x23: u64 = undefined; + var x24: u64 = undefined; + mulxU64(&x23, &x24, x19, 0xfffffffffffffffe); + var x25: u64 = undefined; + var x26: u64 = undefined; + mulxU64(&x25, &x26, x19, 0xbaaedce6af48a03b); + var x27: u64 = undefined; + var x28: u64 = undefined; + mulxU64(&x27, &x28, x19, 0xbfd25e8cd0364141); + var x29: u64 = undefined; + var x30: u1 = undefined; + addcarryxU64(&x29, &x30, 0x0, x28, x25); + var x31: u64 = undefined; + var x32: u1 = undefined; + addcarryxU64(&x31, &x32, x30, x26, x23); + var x33: u64 = undefined; + var x34: u1 = undefined; + addcarryxU64(&x33, &x34, x32, x24, x21); + var x35: u64 = undefined; + var x36: u1 = undefined; + addcarryxU64(&x35, &x36, 0x0, x11, x27); + var x37: u64 = undefined; + var x38: u1 = undefined; + addcarryxU64(&x37, &x38, x36, x13, x29); + var x39: u64 = undefined; + var x40: u1 = undefined; + addcarryxU64(&x39, &x40, x38, x15, x31); + var x41: u64 = undefined; + var x42: u1 = undefined; + addcarryxU64(&x41, &x42, x40, x17, x33); + var x43: u64 = undefined; + var x44: u1 = undefined; + addcarryxU64(&x43, &x44, x42, (@as(u64, x18) + x6), (@as(u64, x34) + x22)); + var x45: u64 = undefined; + var x46: u64 = undefined; + mulxU64(&x45, &x46, x1, 0x9d671cd581c69bc5); + var x47: u64 = undefined; + var x48: u64 = undefined; + mulxU64(&x47, &x48, x1, 0xe697f5e45bcd07c6); + var x49: u64 = undefined; + var x50: u64 = undefined; + mulxU64(&x49, &x50, x1, 0x741496c20e7cf878); + var x51: u64 = undefined; + var x52: u64 = undefined; + mulxU64(&x51, &x52, x1, 0x896cf21467d7d140); + var x53: u64 = undefined; + var x54: u1 = undefined; + addcarryxU64(&x53, &x54, 0x0, x52, x49); + var x55: u64 = undefined; + var x56: u1 = undefined; + addcarryxU64(&x55, &x56, x54, x50, x47); + var x57: u64 = undefined; + var x58: u1 = undefined; + addcarryxU64(&x57, &x58, x56, x48, x45); + var x59: u64 = undefined; + var x60: u1 = undefined; + addcarryxU64(&x59, &x60, 0x0, x37, x51); + var x61: u64 = undefined; + var x62: u1 = undefined; + addcarryxU64(&x61, &x62, x60, x39, x53); + var x63: u64 = undefined; + var x64: u1 = undefined; + addcarryxU64(&x63, &x64, x62, x41, x55); + var x65: u64 = undefined; + var x66: u1 = undefined; + addcarryxU64(&x65, &x66, x64, x43, x57); + var x67: u64 = undefined; + var x68: u64 = undefined; + mulxU64(&x67, &x68, x59, 0x4b0dff665588b13f); + var x69: u64 = undefined; + var x70: u64 = undefined; + mulxU64(&x69, &x70, x67, 0xffffffffffffffff); + var x71: u64 = undefined; + var x72: u64 = undefined; + mulxU64(&x71, &x72, x67, 0xfffffffffffffffe); + var x73: u64 = undefined; + var x74: u64 = undefined; + mulxU64(&x73, &x74, x67, 0xbaaedce6af48a03b); + var x75: u64 = undefined; + var x76: u64 = undefined; + mulxU64(&x75, &x76, x67, 0xbfd25e8cd0364141); + var x77: u64 = undefined; + var x78: u1 = undefined; + addcarryxU64(&x77, &x78, 0x0, x76, x73); + var x79: u64 = undefined; + var x80: u1 = undefined; + addcarryxU64(&x79, &x80, x78, x74, x71); + var x81: u64 = undefined; + var x82: u1 = undefined; + addcarryxU64(&x81, &x82, x80, x72, x69); + var x83: u64 = undefined; + var x84: u1 = undefined; + addcarryxU64(&x83, &x84, 0x0, x59, x75); + var x85: u64 = undefined; + var x86: u1 = undefined; + addcarryxU64(&x85, &x86, x84, x61, x77); + var x87: u64 = undefined; + var x88: u1 = undefined; + addcarryxU64(&x87, &x88, x86, x63, x79); + var x89: u64 = undefined; + var x90: u1 = undefined; + addcarryxU64(&x89, &x90, x88, x65, x81); + var x91: u64 = undefined; + var x92: u1 = undefined; + addcarryxU64(&x91, &x92, x90, ((@as(u64, x66) + @as(u64, x44)) + (@as(u64, x58) + x46)), (@as(u64, x82) + x70)); + var x93: u64 = undefined; + var x94: u64 = undefined; + mulxU64(&x93, &x94, x2, 0x9d671cd581c69bc5); + var x95: u64 = undefined; + var x96: u64 = undefined; + mulxU64(&x95, &x96, x2, 0xe697f5e45bcd07c6); + var x97: u64 = undefined; + var x98: u64 = undefined; + mulxU64(&x97, &x98, x2, 0x741496c20e7cf878); + var x99: u64 = undefined; + var x100: u64 = undefined; + mulxU64(&x99, &x100, x2, 0x896cf21467d7d140); + var x101: u64 = undefined; + var x102: u1 = undefined; + addcarryxU64(&x101, &x102, 0x0, x100, x97); + var x103: u64 = undefined; + var x104: u1 = undefined; + addcarryxU64(&x103, &x104, x102, x98, x95); + var x105: u64 = undefined; + var x106: u1 = undefined; + addcarryxU64(&x105, &x106, x104, x96, x93); + var x107: u64 = undefined; + var x108: u1 = undefined; + addcarryxU64(&x107, &x108, 0x0, x85, x99); + var x109: u64 = undefined; + var x110: u1 = undefined; + addcarryxU64(&x109, &x110, x108, x87, x101); + var x111: u64 = undefined; + var x112: u1 = undefined; + addcarryxU64(&x111, &x112, x110, x89, x103); + var x113: u64 = undefined; + var x114: u1 = undefined; + addcarryxU64(&x113, &x114, x112, x91, x105); + var x115: u64 = undefined; + var x116: u64 = undefined; + mulxU64(&x115, &x116, x107, 0x4b0dff665588b13f); + var x117: u64 = undefined; + var x118: u64 = undefined; + mulxU64(&x117, &x118, x115, 0xffffffffffffffff); + var x119: u64 = undefined; + var x120: u64 = undefined; + mulxU64(&x119, &x120, x115, 0xfffffffffffffffe); + var x121: u64 = undefined; + var x122: u64 = undefined; + mulxU64(&x121, &x122, x115, 0xbaaedce6af48a03b); + var x123: u64 = undefined; + var x124: u64 = undefined; + mulxU64(&x123, &x124, x115, 0xbfd25e8cd0364141); + var x125: u64 = undefined; + var x126: u1 = undefined; + addcarryxU64(&x125, &x126, 0x0, x124, x121); + var x127: u64 = undefined; + var x128: u1 = undefined; + addcarryxU64(&x127, &x128, x126, x122, x119); + var x129: u64 = undefined; + var x130: u1 = undefined; + addcarryxU64(&x129, &x130, x128, x120, x117); + var x131: u64 = undefined; + var x132: u1 = undefined; + addcarryxU64(&x131, &x132, 0x0, x107, x123); + var x133: u64 = undefined; + var x134: u1 = undefined; + addcarryxU64(&x133, &x134, x132, x109, x125); + var x135: u64 = undefined; + var x136: u1 = undefined; + addcarryxU64(&x135, &x136, x134, x111, x127); + var x137: u64 = undefined; + var x138: u1 = undefined; + addcarryxU64(&x137, &x138, x136, x113, x129); + var x139: u64 = undefined; + var x140: u1 = undefined; + addcarryxU64(&x139, &x140, x138, ((@as(u64, x114) + @as(u64, x92)) + (@as(u64, x106) + x94)), (@as(u64, x130) + x118)); + var x141: u64 = undefined; + var x142: u64 = undefined; + mulxU64(&x141, &x142, x3, 0x9d671cd581c69bc5); + var x143: u64 = undefined; + var x144: u64 = undefined; + mulxU64(&x143, &x144, x3, 0xe697f5e45bcd07c6); + var x145: u64 = undefined; + var x146: u64 = undefined; + mulxU64(&x145, &x146, x3, 0x741496c20e7cf878); + var x147: u64 = undefined; + var x148: u64 = undefined; + mulxU64(&x147, &x148, x3, 0x896cf21467d7d140); + var x149: u64 = undefined; + var x150: u1 = undefined; + addcarryxU64(&x149, &x150, 0x0, x148, x145); + var x151: u64 = undefined; + var x152: u1 = undefined; + addcarryxU64(&x151, &x152, x150, x146, x143); + var x153: u64 = undefined; + var x154: u1 = undefined; + addcarryxU64(&x153, &x154, x152, x144, x141); + var x155: u64 = undefined; + var x156: u1 = undefined; + addcarryxU64(&x155, &x156, 0x0, x133, x147); + var x157: u64 = undefined; + var x158: u1 = undefined; + addcarryxU64(&x157, &x158, x156, x135, x149); + var x159: u64 = undefined; + var x160: u1 = undefined; + addcarryxU64(&x159, &x160, x158, x137, x151); + var x161: u64 = undefined; + var x162: u1 = undefined; + addcarryxU64(&x161, &x162, x160, x139, x153); + var x163: u64 = undefined; + var x164: u64 = undefined; + mulxU64(&x163, &x164, x155, 0x4b0dff665588b13f); + var x165: u64 = undefined; + var x166: u64 = undefined; + mulxU64(&x165, &x166, x163, 0xffffffffffffffff); + var x167: u64 = undefined; + var x168: u64 = undefined; + mulxU64(&x167, &x168, x163, 0xfffffffffffffffe); + var x169: u64 = undefined; + var x170: u64 = undefined; + mulxU64(&x169, &x170, x163, 0xbaaedce6af48a03b); + var x171: u64 = undefined; + var x172: u64 = undefined; + mulxU64(&x171, &x172, x163, 0xbfd25e8cd0364141); + var x173: u64 = undefined; + var x174: u1 = undefined; + addcarryxU64(&x173, &x174, 0x0, x172, x169); + var x175: u64 = undefined; + var x176: u1 = undefined; + addcarryxU64(&x175, &x176, x174, x170, x167); + var x177: u64 = undefined; + var x178: u1 = undefined; + addcarryxU64(&x177, &x178, x176, x168, x165); + var x179: u64 = undefined; + var x180: u1 = undefined; + addcarryxU64(&x179, &x180, 0x0, x155, x171); + var x181: u64 = undefined; + var x182: u1 = undefined; + addcarryxU64(&x181, &x182, x180, x157, x173); + var x183: u64 = undefined; + var x184: u1 = undefined; + addcarryxU64(&x183, &x184, x182, x159, x175); + var x185: u64 = undefined; + var x186: u1 = undefined; + addcarryxU64(&x185, &x186, x184, x161, x177); + var x187: u64 = undefined; + var x188: u1 = undefined; + addcarryxU64(&x187, &x188, x186, ((@as(u64, x162) + @as(u64, x140)) + (@as(u64, x154) + x142)), (@as(u64, x178) + x166)); + var x189: u64 = undefined; + var x190: u1 = undefined; + subborrowxU64(&x189, &x190, 0x0, x181, 0xbfd25e8cd0364141); + var x191: u64 = undefined; + var x192: u1 = undefined; + subborrowxU64(&x191, &x192, x190, x183, 0xbaaedce6af48a03b); + var x193: u64 = undefined; + var x194: u1 = undefined; + subborrowxU64(&x193, &x194, x192, x185, 0xfffffffffffffffe); + var x195: u64 = undefined; + var x196: u1 = undefined; + subborrowxU64(&x195, &x196, x194, x187, 0xffffffffffffffff); + var x197: u64 = undefined; + var x198: u1 = undefined; + subborrowxU64(&x197, &x198, x196, @as(u64, x188), 0x0); + var x199: u64 = undefined; + cmovznzU64(&x199, x198, x189, x181); + var x200: u64 = undefined; + cmovznzU64(&x200, x198, x191, x183); + var x201: u64 = undefined; + cmovznzU64(&x201, x198, x193, x185); + var x202: u64 = undefined; + cmovznzU64(&x202, x198, x195, x187); + out1[0] = x199; + out1[1] = x200; + out1[2] = x201; + out1[3] = x202; +} + +/// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0 +/// +/// Input Bounds: +/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +pub fn nonzero(out1: *u64, arg1: [4]u64) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); + out1.* = x1; +} + +/// The function selectznz is a multi-limb conditional select. +/// +/// Postconditions: +/// out1 = (if arg1 = 0 then arg2 else arg3) +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0x1] +/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// Output Bounds: +/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); + var x2: u64 = undefined; + cmovznzU64(&x2, arg1, (arg2[1]), (arg3[1])); + var x3: u64 = undefined; + cmovznzU64(&x3, arg1, (arg2[2]), (arg3[2])); + var x4: u64 = undefined; + cmovznzU64(&x4, arg1, (arg2[3]), (arg3[3])); + out1[0] = x1; + out1[1] = x2; + out1[2] = x3; + out1[3] = x4; +} + +/// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. +/// +/// Preconditions: +/// 0 ≤ eval arg1 < m +/// Postconditions: +/// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31] +/// +/// Input Bounds: +/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// Output Bounds: +/// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (arg1[3]); + const x2 = (arg1[2]); + const x3 = (arg1[1]); + const x4 = (arg1[0]); + const x5 = @truncate(u8, (x4 & 0xff)); + const x6 = (x4 >> 8); + const x7 = @truncate(u8, (x6 & 0xff)); + const x8 = (x6 >> 8); + const x9 = @truncate(u8, (x8 & 0xff)); + const x10 = (x8 >> 8); + const x11 = @truncate(u8, (x10 & 0xff)); + const x12 = (x10 >> 8); + const x13 = @truncate(u8, (x12 & 0xff)); + const x14 = (x12 >> 8); + const x15 = @truncate(u8, (x14 & 0xff)); + const x16 = (x14 >> 8); + const x17 = @truncate(u8, (x16 & 0xff)); + const x18 = @truncate(u8, (x16 >> 8)); + const x19 = @truncate(u8, (x3 & 0xff)); + const x20 = (x3 >> 8); + const x21 = @truncate(u8, (x20 & 0xff)); + const x22 = (x20 >> 8); + const x23 = @truncate(u8, (x22 & 0xff)); + const x24 = (x22 >> 8); + const x25 = @truncate(u8, (x24 & 0xff)); + const x26 = (x24 >> 8); + const x27 = @truncate(u8, (x26 & 0xff)); + const x28 = (x26 >> 8); + const x29 = @truncate(u8, (x28 & 0xff)); + const x30 = (x28 >> 8); + const x31 = @truncate(u8, (x30 & 0xff)); + const x32 = @truncate(u8, (x30 >> 8)); + const x33 = @truncate(u8, (x2 & 0xff)); + const x34 = (x2 >> 8); + const x35 = @truncate(u8, (x34 & 0xff)); + const x36 = (x34 >> 8); + const x37 = @truncate(u8, (x36 & 0xff)); + const x38 = (x36 >> 8); + const x39 = @truncate(u8, (x38 & 0xff)); + const x40 = (x38 >> 8); + const x41 = @truncate(u8, (x40 & 0xff)); + const x42 = (x40 >> 8); + const x43 = @truncate(u8, (x42 & 0xff)); + const x44 = (x42 >> 8); + const x45 = @truncate(u8, (x44 & 0xff)); + const x46 = @truncate(u8, (x44 >> 8)); + const x47 = @truncate(u8, (x1 & 0xff)); + const x48 = (x1 >> 8); + const x49 = @truncate(u8, (x48 & 0xff)); + const x50 = (x48 >> 8); + const x51 = @truncate(u8, (x50 & 0xff)); + const x52 = (x50 >> 8); + const x53 = @truncate(u8, (x52 & 0xff)); + const x54 = (x52 >> 8); + const x55 = @truncate(u8, (x54 & 0xff)); + const x56 = (x54 >> 8); + const x57 = @truncate(u8, (x56 & 0xff)); + const x58 = (x56 >> 8); + const x59 = @truncate(u8, (x58 & 0xff)); + const x60 = @truncate(u8, (x58 >> 8)); + out1[0] = x5; + out1[1] = x7; + out1[2] = x9; + out1[3] = x11; + out1[4] = x13; + out1[5] = x15; + out1[6] = x17; + out1[7] = x18; + out1[8] = x19; + out1[9] = x21; + out1[10] = x23; + out1[11] = x25; + out1[12] = x27; + out1[13] = x29; + out1[14] = x31; + out1[15] = x32; + out1[16] = x33; + out1[17] = x35; + out1[18] = x37; + out1[19] = x39; + out1[20] = x41; + out1[21] = x43; + out1[22] = x45; + out1[23] = x46; + out1[24] = x47; + out1[25] = x49; + out1[26] = x51; + out1[27] = x53; + out1[28] = x55; + out1[29] = x57; + out1[30] = x59; + out1[31] = x60; +} + +/// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. +/// +/// Preconditions: +/// 0 ≤ bytes_eval arg1 < m +/// Postconditions: +/// eval out1 mod m = bytes_eval arg1 mod m +/// 0 ≤ eval out1 < m +/// +/// Input Bounds: +/// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +/// Output Bounds: +/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { + @setRuntimeSafety(mode == .Debug); + + const x1 = (@as(u64, (arg1[31])) << 56); + const x2 = (@as(u64, (arg1[30])) << 48); + const x3 = (@as(u64, (arg1[29])) << 40); + const x4 = (@as(u64, (arg1[28])) << 32); + const x5 = (@as(u64, (arg1[27])) << 24); + const x6 = (@as(u64, (arg1[26])) << 16); + const x7 = (@as(u64, (arg1[25])) << 8); + const x8 = (arg1[24]); + const x9 = (@as(u64, (arg1[23])) << 56); + const x10 = (@as(u64, (arg1[22])) << 48); + const x11 = (@as(u64, (arg1[21])) << 40); + const x12 = (@as(u64, (arg1[20])) << 32); + const x13 = (@as(u64, (arg1[19])) << 24); + const x14 = (@as(u64, (arg1[18])) << 16); + const x15 = (@as(u64, (arg1[17])) << 8); + const x16 = (arg1[16]); + const x17 = (@as(u64, (arg1[15])) << 56); + const x18 = (@as(u64, (arg1[14])) << 48); + const x19 = (@as(u64, (arg1[13])) << 40); + const x20 = (@as(u64, (arg1[12])) << 32); + const x21 = (@as(u64, (arg1[11])) << 24); + const x22 = (@as(u64, (arg1[10])) << 16); + const x23 = (@as(u64, (arg1[9])) << 8); + const x24 = (arg1[8]); + const x25 = (@as(u64, (arg1[7])) << 56); + const x26 = (@as(u64, (arg1[6])) << 48); + const x27 = (@as(u64, (arg1[5])) << 40); + const x28 = (@as(u64, (arg1[4])) << 32); + const x29 = (@as(u64, (arg1[3])) << 24); + const x30 = (@as(u64, (arg1[2])) << 16); + const x31 = (@as(u64, (arg1[1])) << 8); + const x32 = (arg1[0]); + const x33 = (x31 + @as(u64, x32)); + const x34 = (x30 + x33); + const x35 = (x29 + x34); + const x36 = (x28 + x35); + const x37 = (x27 + x36); + const x38 = (x26 + x37); + const x39 = (x25 + x38); + const x40 = (x23 + @as(u64, x24)); + const x41 = (x22 + x40); + const x42 = (x21 + x41); + const x43 = (x20 + x42); + const x44 = (x19 + x43); + const x45 = (x18 + x44); + const x46 = (x17 + x45); + const x47 = (x15 + @as(u64, x16)); + const x48 = (x14 + x47); + const x49 = (x13 + x48); + const x50 = (x12 + x49); + const x51 = (x11 + x50); + const x52 = (x10 + x51); + const x53 = (x9 + x52); + const x54 = (x7 + @as(u64, x8)); + const x55 = (x6 + x54); + const x56 = (x5 + x55); + const x57 = (x4 + x56); + const x58 = (x3 + x57); + const x59 = (x2 + x58); + const x60 = (x1 + x59); + out1[0] = x39; + out1[1] = x46; + out1[2] = x53; + out1[3] = x60; +} + +/// The function setOne returns the field element one in the Montgomery domain. +/// +/// Postconditions: +/// eval (from_montgomery out1) mod m = 1 mod m +/// 0 ≤ eval out1 < m +/// +pub fn setOne(out1: *MontgomeryDomainFieldElement) void { + @setRuntimeSafety(mode == .Debug); + + out1[0] = 0x402da1732fc9bebf; + out1[1] = 0x4551231950b75fc4; + out1[2] = 0x1; + out1[3] = 0x0; +} + +/// The function msat returns the saturated representation of the prime modulus. +/// +/// Postconditions: +/// twos_complement_eval out1 = m +/// 0 ≤ eval out1 < m +/// +/// Output Bounds: +/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn msat(out1: *[5]u64) void { + @setRuntimeSafety(mode == .Debug); + + out1[0] = 0xbfd25e8cd0364141; + out1[1] = 0xbaaedce6af48a03b; + out1[2] = 0xfffffffffffffffe; + out1[3] = 0xffffffffffffffff; + out1[4] = 0x0; +} + +/// The function divstep computes a divstep. +/// +/// Preconditions: +/// 0 ≤ eval arg4 < m +/// 0 ≤ eval arg5 < m +/// Postconditions: +/// out1 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then 1 - arg1 else 1 + arg1) +/// twos_complement_eval out2 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then twos_complement_eval arg3 else twos_complement_eval arg2) +/// twos_complement_eval out3 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then ⌊(twos_complement_eval arg3 - twos_complement_eval arg2) / 2⌋ else ⌊(twos_complement_eval arg3 + (twos_complement_eval arg3 mod 2) * twos_complement_eval arg2) / 2⌋) +/// eval (from_montgomery out4) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (2 * eval (from_montgomery arg5)) mod m else (2 * eval (from_montgomery arg4)) mod m) +/// eval (from_montgomery out5) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (eval (from_montgomery arg4) - eval (from_montgomery arg4)) mod m else (eval (from_montgomery arg5) + (twos_complement_eval arg3 mod 2) * eval (from_montgomery arg4)) mod m) +/// 0 ≤ eval out5 < m +/// 0 ≤ eval out5 < m +/// 0 ≤ eval out2 < m +/// 0 ≤ eval out3 < m +/// +/// Input Bounds: +/// arg1: [0x0 ~> 0xffffffffffffffff] +/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// arg4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// arg5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// Output Bounds: +/// out1: [0x0 ~> 0xffffffffffffffff] +/// out2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// out3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { + @setRuntimeSafety(mode == .Debug); + + var x1: u64 = undefined; + var x2: u1 = undefined; + addcarryxU64(&x1, &x2, 0x0, (~arg1), 0x1); + const x3 = (@truncate(u1, (x1 >> 63)) & @truncate(u1, ((arg3[0]) & 0x1))); + var x4: u64 = undefined; + var x5: u1 = undefined; + addcarryxU64(&x4, &x5, 0x0, (~arg1), 0x1); + var x6: u64 = undefined; + cmovznzU64(&x6, x3, arg1, x4); + var x7: u64 = undefined; + cmovznzU64(&x7, x3, (arg2[0]), (arg3[0])); + var x8: u64 = undefined; + cmovznzU64(&x8, x3, (arg2[1]), (arg3[1])); + var x9: u64 = undefined; + cmovznzU64(&x9, x3, (arg2[2]), (arg3[2])); + var x10: u64 = undefined; + cmovznzU64(&x10, x3, (arg2[3]), (arg3[3])); + var x11: u64 = undefined; + cmovznzU64(&x11, x3, (arg2[4]), (arg3[4])); + var x12: u64 = undefined; + var x13: u1 = undefined; + addcarryxU64(&x12, &x13, 0x0, 0x1, (~(arg2[0]))); + var x14: u64 = undefined; + var x15: u1 = undefined; + addcarryxU64(&x14, &x15, x13, 0x0, (~(arg2[1]))); + var x16: u64 = undefined; + var x17: u1 = undefined; + addcarryxU64(&x16, &x17, x15, 0x0, (~(arg2[2]))); + var x18: u64 = undefined; + var x19: u1 = undefined; + addcarryxU64(&x18, &x19, x17, 0x0, (~(arg2[3]))); + var x20: u64 = undefined; + var x21: u1 = undefined; + addcarryxU64(&x20, &x21, x19, 0x0, (~(arg2[4]))); + var x22: u64 = undefined; + cmovznzU64(&x22, x3, (arg3[0]), x12); + var x23: u64 = undefined; + cmovznzU64(&x23, x3, (arg3[1]), x14); + var x24: u64 = undefined; + cmovznzU64(&x24, x3, (arg3[2]), x16); + var x25: u64 = undefined; + cmovznzU64(&x25, x3, (arg3[3]), x18); + var x26: u64 = undefined; + cmovznzU64(&x26, x3, (arg3[4]), x20); + var x27: u64 = undefined; + cmovznzU64(&x27, x3, (arg4[0]), (arg5[0])); + var x28: u64 = undefined; + cmovznzU64(&x28, x3, (arg4[1]), (arg5[1])); + var x29: u64 = undefined; + cmovznzU64(&x29, x3, (arg4[2]), (arg5[2])); + var x30: u64 = undefined; + cmovznzU64(&x30, x3, (arg4[3]), (arg5[3])); + var x31: u64 = undefined; + var x32: u1 = undefined; + addcarryxU64(&x31, &x32, 0x0, x27, x27); + var x33: u64 = undefined; + var x34: u1 = undefined; + addcarryxU64(&x33, &x34, x32, x28, x28); + var x35: u64 = undefined; + var x36: u1 = undefined; + addcarryxU64(&x35, &x36, x34, x29, x29); + var x37: u64 = undefined; + var x38: u1 = undefined; + addcarryxU64(&x37, &x38, x36, x30, x30); + var x39: u64 = undefined; + var x40: u1 = undefined; + subborrowxU64(&x39, &x40, 0x0, x31, 0xbfd25e8cd0364141); + var x41: u64 = undefined; + var x42: u1 = undefined; + subborrowxU64(&x41, &x42, x40, x33, 0xbaaedce6af48a03b); + var x43: u64 = undefined; + var x44: u1 = undefined; + subborrowxU64(&x43, &x44, x42, x35, 0xfffffffffffffffe); + var x45: u64 = undefined; + var x46: u1 = undefined; + subborrowxU64(&x45, &x46, x44, x37, 0xffffffffffffffff); + var x47: u64 = undefined; + var x48: u1 = undefined; + subborrowxU64(&x47, &x48, x46, @as(u64, x38), 0x0); + const x49 = (arg4[3]); + const x50 = (arg4[2]); + const x51 = (arg4[1]); + const x52 = (arg4[0]); + var x53: u64 = undefined; + var x54: u1 = undefined; + subborrowxU64(&x53, &x54, 0x0, 0x0, x52); + var x55: u64 = undefined; + var x56: u1 = undefined; + subborrowxU64(&x55, &x56, x54, 0x0, x51); + var x57: u64 = undefined; + var x58: u1 = undefined; + subborrowxU64(&x57, &x58, x56, 0x0, x50); + var x59: u64 = undefined; + var x60: u1 = undefined; + subborrowxU64(&x59, &x60, x58, 0x0, x49); + var x61: u64 = undefined; + cmovznzU64(&x61, x60, 0x0, 0xffffffffffffffff); + var x62: u64 = undefined; + var x63: u1 = undefined; + addcarryxU64(&x62, &x63, 0x0, x53, (x61 & 0xbfd25e8cd0364141)); + var x64: u64 = undefined; + var x65: u1 = undefined; + addcarryxU64(&x64, &x65, x63, x55, (x61 & 0xbaaedce6af48a03b)); + var x66: u64 = undefined; + var x67: u1 = undefined; + addcarryxU64(&x66, &x67, x65, x57, (x61 & 0xfffffffffffffffe)); + var x68: u64 = undefined; + var x69: u1 = undefined; + addcarryxU64(&x68, &x69, x67, x59, x61); + var x70: u64 = undefined; + cmovznzU64(&x70, x3, (arg5[0]), x62); + var x71: u64 = undefined; + cmovznzU64(&x71, x3, (arg5[1]), x64); + var x72: u64 = undefined; + cmovznzU64(&x72, x3, (arg5[2]), x66); + var x73: u64 = undefined; + cmovznzU64(&x73, x3, (arg5[3]), x68); + const x74 = @truncate(u1, (x22 & 0x1)); + var x75: u64 = undefined; + cmovznzU64(&x75, x74, 0x0, x7); + var x76: u64 = undefined; + cmovznzU64(&x76, x74, 0x0, x8); + var x77: u64 = undefined; + cmovznzU64(&x77, x74, 0x0, x9); + var x78: u64 = undefined; + cmovznzU64(&x78, x74, 0x0, x10); + var x79: u64 = undefined; + cmovznzU64(&x79, x74, 0x0, x11); + var x80: u64 = undefined; + var x81: u1 = undefined; + addcarryxU64(&x80, &x81, 0x0, x22, x75); + var x82: u64 = undefined; + var x83: u1 = undefined; + addcarryxU64(&x82, &x83, x81, x23, x76); + var x84: u64 = undefined; + var x85: u1 = undefined; + addcarryxU64(&x84, &x85, x83, x24, x77); + var x86: u64 = undefined; + var x87: u1 = undefined; + addcarryxU64(&x86, &x87, x85, x25, x78); + var x88: u64 = undefined; + var x89: u1 = undefined; + addcarryxU64(&x88, &x89, x87, x26, x79); + var x90: u64 = undefined; + cmovznzU64(&x90, x74, 0x0, x27); + var x91: u64 = undefined; + cmovznzU64(&x91, x74, 0x0, x28); + var x92: u64 = undefined; + cmovznzU64(&x92, x74, 0x0, x29); + var x93: u64 = undefined; + cmovznzU64(&x93, x74, 0x0, x30); + var x94: u64 = undefined; + var x95: u1 = undefined; + addcarryxU64(&x94, &x95, 0x0, x70, x90); + var x96: u64 = undefined; + var x97: u1 = undefined; + addcarryxU64(&x96, &x97, x95, x71, x91); + var x98: u64 = undefined; + var x99: u1 = undefined; + addcarryxU64(&x98, &x99, x97, x72, x92); + var x100: u64 = undefined; + var x101: u1 = undefined; + addcarryxU64(&x100, &x101, x99, x73, x93); + var x102: u64 = undefined; + var x103: u1 = undefined; + subborrowxU64(&x102, &x103, 0x0, x94, 0xbfd25e8cd0364141); + var x104: u64 = undefined; + var x105: u1 = undefined; + subborrowxU64(&x104, &x105, x103, x96, 0xbaaedce6af48a03b); + var x106: u64 = undefined; + var x107: u1 = undefined; + subborrowxU64(&x106, &x107, x105, x98, 0xfffffffffffffffe); + var x108: u64 = undefined; + var x109: u1 = undefined; + subborrowxU64(&x108, &x109, x107, x100, 0xffffffffffffffff); + var x110: u64 = undefined; + var x111: u1 = undefined; + subborrowxU64(&x110, &x111, x109, @as(u64, x101), 0x0); + var x112: u64 = undefined; + var x113: u1 = undefined; + addcarryxU64(&x112, &x113, 0x0, x6, 0x1); + const x114 = ((x80 >> 1) | ((x82 << 63) & 0xffffffffffffffff)); + const x115 = ((x82 >> 1) | ((x84 << 63) & 0xffffffffffffffff)); + const x116 = ((x84 >> 1) | ((x86 << 63) & 0xffffffffffffffff)); + const x117 = ((x86 >> 1) | ((x88 << 63) & 0xffffffffffffffff)); + const x118 = ((x88 & 0x8000000000000000) | (x88 >> 1)); + var x119: u64 = undefined; + cmovznzU64(&x119, x48, x39, x31); + var x120: u64 = undefined; + cmovznzU64(&x120, x48, x41, x33); + var x121: u64 = undefined; + cmovznzU64(&x121, x48, x43, x35); + var x122: u64 = undefined; + cmovznzU64(&x122, x48, x45, x37); + var x123: u64 = undefined; + cmovznzU64(&x123, x111, x102, x94); + var x124: u64 = undefined; + cmovznzU64(&x124, x111, x104, x96); + var x125: u64 = undefined; + cmovznzU64(&x125, x111, x106, x98); + var x126: u64 = undefined; + cmovznzU64(&x126, x111, x108, x100); + out1.* = x112; + out2[0] = x7; + out2[1] = x8; + out2[2] = x9; + out2[3] = x10; + out2[4] = x11; + out3[0] = x114; + out3[1] = x115; + out3[2] = x116; + out3[3] = x117; + out3[4] = x118; + out4[0] = x119; + out4[1] = x120; + out4[2] = x121; + out4[3] = x122; + out5[0] = x123; + out5[1] = x124; + out5[2] = x125; + out5[3] = x126; +} + +/// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form). +/// +/// Postconditions: +/// eval (from_montgomery out1) = ⌊(m - 1) / 2⌋^(if ⌊log2 m⌋ + 1 < 46 then ⌊(49 * (⌊log2 m⌋ + 1) + 80) / 17⌋ else ⌊(49 * (⌊log2 m⌋ + 1) + 57) / 17⌋) +/// 0 ≤ eval out1 < m +/// +/// Output Bounds: +/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +pub fn divstepPrecomp(out1: *[4]u64) void { + @setRuntimeSafety(mode == .Debug); + + out1[0] = 0xd7431a4d2b9cb4e9; + out1[1] = 0xab67d35a32d9c503; + out1[2] = 0xadf6c7e5859ce35f; + out1[3] = 0x615441451df6c379; +} diff --git a/lib/std/crypto/pcurves/tests/secp256k1.zig b/lib/std/crypto/pcurves/tests/secp256k1.zig new file mode 100644 index 000000000000..32fca87691e0 --- /dev/null +++ b/lib/std/crypto/pcurves/tests/secp256k1.zig @@ -0,0 +1,137 @@ +const std = @import("std"); +const fmt = std.fmt; +const testing = std.testing; + +const Secp256k1 = @import("../secp256k1.zig").Secp256k1; + +test "secp256k1 ECDH key exchange" { + const dha = Secp256k1.scalar.random(.Little); + const dhb = Secp256k1.scalar.random(.Little); + const dhA = try Secp256k1.basePoint.mul(dha, .Little); + const dhB = try Secp256k1.basePoint.mul(dhb, .Little); + const shareda = try dhA.mul(dhb, .Little); + const sharedb = try dhB.mul(dha, .Little); + try testing.expect(shareda.equivalent(sharedb)); +} + +test "secp256k1 ECDH key exchange including public multiplication" { + const dha = Secp256k1.scalar.random(.Little); + const dhb = Secp256k1.scalar.random(.Little); + const dhA = try Secp256k1.basePoint.mul(dha, .Little); + const dhB = try Secp256k1.basePoint.mulPublic(dhb, .Little); + const shareda = try dhA.mul(dhb, .Little); + const sharedb = try dhB.mulPublic(dha, .Little); + try testing.expect(shareda.equivalent(sharedb)); +} + +test "secp256k1 point from affine coordinates" { + const xh = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"; + const yh = "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"; + var xs: [32]u8 = undefined; + _ = try fmt.hexToBytes(&xs, xh); + var ys: [32]u8 = undefined; + _ = try fmt.hexToBytes(&ys, yh); + var p = try Secp256k1.fromSerializedAffineCoordinates(xs, ys, .Big); + try testing.expect(p.equivalent(Secp256k1.basePoint)); +} + +test "secp256k1 test vectors" { + const expected = [_][]const u8{ + "0000000000000000000000000000000000000000000000000000000000000000", + "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13", + "2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4", + "fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556", + "5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc", + "2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01", + "acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe", + }; + var p = Secp256k1.identityElement; + for (expected) |xh| { + const x = p.affineCoordinates().x; + p = p.add(Secp256k1.basePoint); + var xs: [32]u8 = undefined; + _ = try fmt.hexToBytes(&xs, xh); + try testing.expectEqualSlices(u8, &x.toBytes(.Big), &xs); + } +} + +test "secp256k1 test vectors - doubling" { + const expected = [_][]const u8{ + "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13", + "2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01", + "e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + var p = Secp256k1.basePoint; + for (expected) |xh| { + const x = p.affineCoordinates().x; + p = p.dbl(); + var xs: [32]u8 = undefined; + _ = try fmt.hexToBytes(&xs, xh); + try testing.expectEqualSlices(u8, &x.toBytes(.Big), &xs); + } +} + +test "secp256k1 compressed sec1 encoding/decoding" { + const p = Secp256k1.random(); + const s = p.toCompressedSec1(); + const q = try Secp256k1.fromSec1(&s); + try testing.expect(p.equivalent(q)); +} + +test "secp256k1 uncompressed sec1 encoding/decoding" { + const p = Secp256k1.random(); + const s = p.toUncompressedSec1(); + const q = try Secp256k1.fromSec1(&s); + try testing.expect(p.equivalent(q)); +} + +test "secp256k1 public key is the neutral element" { + const n = Secp256k1.scalar.Scalar.zero.toBytes(.Little); + const p = Secp256k1.random(); + try testing.expectError(error.IdentityElement, p.mul(n, .Little)); +} + +test "secp256k1 public key is the neutral element (public verification)" { + const n = Secp256k1.scalar.Scalar.zero.toBytes(.Little); + const p = Secp256k1.random(); + try testing.expectError(error.IdentityElement, p.mulPublic(n, .Little)); +} + +test "secp256k1 field element non-canonical encoding" { + const s = [_]u8{0xff} ** 32; + try testing.expectError(error.NonCanonical, Secp256k1.Fe.fromBytes(s, .Little)); +} + +test "secp256k1 neutral element decoding" { + try testing.expectError(error.InvalidEncoding, Secp256k1.fromAffineCoordinates(.{ .x = Secp256k1.Fe.zero, .y = Secp256k1.Fe.zero })); + const p = try Secp256k1.fromAffineCoordinates(.{ .x = Secp256k1.Fe.zero, .y = Secp256k1.Fe.one }); + try testing.expectError(error.IdentityElement, p.rejectIdentity()); +} + +test "secp256k1 double base multiplication" { + const p1 = Secp256k1.basePoint; + const p2 = Secp256k1.basePoint.dbl(); + const s1 = [_]u8{0x01} ** 32; + const s2 = [_]u8{0x02} ** 32; + const pr1 = try Secp256k1.mulDoubleBasePublic(p1, s1, p2, s2, .Little); + const pr2 = (try p1.mul(s1, .Little)).add(try p2.mul(s2, .Little)); + try testing.expect(pr1.equivalent(pr2)); +} + +test "secp256k1 scalar inverse" { + const expected = "08d0684a0fe8ea978b68a29e4b4ffdbd19eeb59db25301cf23ecbe568e1f9822"; + var out: [32]u8 = undefined; + _ = try std.fmt.hexToBytes(&out, expected); + + const scalar = try Secp256k1.scalar.Scalar.fromBytes(.{ + 0x94, 0xa1, 0xbb, 0xb1, 0x4b, 0x90, 0x6a, 0x61, 0xa2, 0x80, 0xf2, 0x45, 0xf9, 0xe9, 0x3c, 0x7f, + 0x3b, 0x4a, 0x62, 0x47, 0x82, 0x4f, 0x5d, 0x33, 0xb9, 0x67, 0x07, 0x87, 0x64, 0x2a, 0x68, 0xde, + }, .Big); + const inverse = scalar.invert(); + try std.testing.expectEqualSlices(u8, &out, &inverse.toBytes(.Big)); +}