struct Scalar [src]

A scalar in unpacked representation

Fields

limbs: Limbs = undefined

Members

Source

pub const Scalar = struct { const Limbs = [5]u64; limbs: Limbs = undefined, /// Unpack a 32-byte representation of a scalar pub fn fromBytes(bytes: CompressedScalar) Scalar { var scalar = ScalarDouble.fromBytes32(bytes); return scalar.reduce(5); } /// Unpack a 64-byte representation of a scalar pub fn fromBytes64(bytes: [64]u8) Scalar { var scalar = ScalarDouble.fromBytes64(bytes); return scalar.reduce(5); } /// Pack a scalar into bytes pub fn toBytes(expanded: *const Scalar) CompressedScalar { var bytes: CompressedScalar = undefined; var i: usize = 0; while (i < 4) : (i += 1) { mem.writeInt(u64, bytes[i * 7 ..][0..8], expanded.limbs[i], .little); } mem.writeInt(u32, bytes[i * 7 ..][0..4], @intCast(expanded.limbs[i]), .little); return bytes; } /// Return true if the scalar is zero pub fn isZero(n: Scalar) bool { const limbs = n.limbs; return (limbs[0] | limbs[1] | limbs[2] | limbs[3] | limbs[4]) == 0; } /// Return x+y (mod L) pub fn add(x: Scalar, y: Scalar) Scalar { const carry0 = (x.limbs[0] + y.limbs[0]) >> 56; const t0 = (x.limbs[0] + y.limbs[0]) & 0xffffffffffffff; const t00 = t0; const c0 = carry0; const carry1 = (x.limbs[1] + y.limbs[1] + c0) >> 56; const t1 = (x.limbs[1] + y.limbs[1] + c0) & 0xffffffffffffff; const t10 = t1; const c1 = carry1; const carry2 = (x.limbs[2] + y.limbs[2] + c1) >> 56; const t2 = (x.limbs[2] + y.limbs[2] + c1) & 0xffffffffffffff; const t20 = t2; const c2 = carry2; const carry = (x.limbs[3] + y.limbs[3] + c2) >> 56; const t3 = (x.limbs[3] + y.limbs[3] + c2) & 0xffffffffffffff; const t30 = t3; const c3 = carry; const t4 = x.limbs[4] + y.limbs[4] + c3; const y01: u64 = 5175514460705773; const y11: u64 = 70332060721272408; const y21: u64 = 5342; const y31: u64 = 0; const y41: u64 = 268435456; const b5 = (t00 -% y01) >> 63; const t5 = ((b5 << 56) + t00) -% y01; const b0 = b5; const t01 = t5; const b6 = (t10 -% (y11 + b0)) >> 63; const t6 = ((b6 << 56) + t10) -% (y11 + b0); const b1 = b6; const t11 = t6; const b7 = (t20 -% (y21 + b1)) >> 63; const t7 = ((b7 << 56) + t20) -% (y21 + b1); const b2 = b7; const t21 = t7; const b8 = (t30 -% (y31 + b2)) >> 63; const t8 = ((b8 << 56) + t30) -% (y31 + b2); const b3 = b8; const t31 = t8; const b = (t4 -% (y41 + b3)) >> 63; const t = ((b << 56) + t4) -% (y41 + b3); const b4 = b; const t41 = t; const mask = (b4 -% 1); const z00 = t00 ^ (mask & (t00 ^ t01)); const z10 = t10 ^ (mask & (t10 ^ t11)); const z20 = t20 ^ (mask & (t20 ^ t21)); const z30 = t30 ^ (mask & (t30 ^ t31)); const z40 = t4 ^ (mask & (t4 ^ t41)); return Scalar{ .limbs = .{ z00, z10, z20, z30, z40 } }; } /// Return x*r (mod L) pub fn mul(x: Scalar, y: Scalar) Scalar { const xy000 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[0]); const xy010 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[1]); const xy020 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[2]); const xy030 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[3]); const xy040 = @as(u128, x.limbs[0]) * @as(u128, y.limbs[4]); const xy100 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[0]); const xy110 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[1]); const xy120 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[2]); const xy130 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[3]); const xy140 = @as(u128, x.limbs[1]) * @as(u128, y.limbs[4]); const xy200 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[0]); const xy210 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[1]); const xy220 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[2]); const xy230 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[3]); const xy240 = @as(u128, x.limbs[2]) * @as(u128, y.limbs[4]); const xy300 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[0]); const xy310 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[1]); const xy320 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[2]); const xy330 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[3]); const xy340 = @as(u128, x.limbs[3]) * @as(u128, y.limbs[4]); const xy400 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[0]); const xy410 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[1]); const xy420 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[2]); const xy430 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[3]); const xy440 = @as(u128, x.limbs[4]) * @as(u128, y.limbs[4]); const z00 = xy000; const z10 = xy010 + xy100; const z20 = xy020 + xy110 + xy200; const z30 = xy030 + xy120 + xy210 + xy300; const z40 = xy040 + xy130 + xy220 + xy310 + xy400; const z50 = xy140 + xy230 + xy320 + xy410; const z60 = xy240 + xy330 + xy420; const z70 = xy340 + xy430; const z80 = xy440; const carry0 = z00 >> 56; const t10 = @as(u64, @truncate(z00)) & 0xffffffffffffff; const c00 = carry0; const t00 = t10; const carry1 = (z10 + c00) >> 56; const t11 = @as(u64, @truncate((z10 + c00))) & 0xffffffffffffff; const c10 = carry1; const t12 = t11; const carry2 = (z20 + c10) >> 56; const t13 = @as(u64, @truncate((z20 + c10))) & 0xffffffffffffff; const c20 = carry2; const t20 = t13; const carry3 = (z30 + c20) >> 56; const t14 = @as(u64, @truncate((z30 + c20))) & 0xffffffffffffff; const c30 = carry3; const t30 = t14; const carry4 = (z40 + c30) >> 56; const t15 = @as(u64, @truncate((z40 + c30))) & 0xffffffffffffff; const c40 = carry4; const t40 = t15; const carry5 = (z50 + c40) >> 56; const t16 = @as(u64, @truncate((z50 + c40))) & 0xffffffffffffff; const c50 = carry5; const t50 = t16; const carry6 = (z60 + c50) >> 56; const t17 = @as(u64, @truncate((z60 + c50))) & 0xffffffffffffff; const c60 = carry6; const t60 = t17; const carry7 = (z70 + c60) >> 56; const t18 = @as(u64, @truncate((z70 + c60))) & 0xffffffffffffff; const c70 = carry7; const t70 = t18; const carry8 = (z80 + c70) >> 56; const t19 = @as(u64, @truncate((z80 + c70))) & 0xffffffffffffff; const c80 = carry8; const t80 = t19; const t90 = (@as(u64, @truncate(c80))); const r0 = t00; const r1 = t12; const r2 = t20; const r3 = t30; const r4 = t40; const r5 = t50; const r6 = t60; const r7 = t70; const r8 = t80; const r9 = t90; const m0: u64 = 5175514460705773; const m1: u64 = 70332060721272408; const m2: u64 = 5342; const m3: u64 = 0; const m4: u64 = 268435456; const mu0: u64 = 44162584779952923; const mu1: u64 = 9390964836247533; const mu2: u64 = 72057594036560134; const mu3: u64 = 72057594037927935; const mu4: u64 = 68719476735; const y_ = (r5 & 0xffffff) << 32; const x_ = r4 >> 24; const z01 = (x_ | y_); const y_0 = (r6 & 0xffffff) << 32; const x_0 = r5 >> 24; const z11 = (x_0 | y_0); const y_1 = (r7 & 0xffffff) << 32; const x_1 = r6 >> 24; const z21 = (x_1 | y_1); const y_2 = (r8 & 0xffffff) << 32; const x_2 = r7 >> 24; const z31 = (x_2 | y_2); const y_3 = (r9 & 0xffffff) << 32; const x_3 = r8 >> 24; const z41 = (x_3 | y_3); const q0 = z01; const q1 = z11; const q2 = z21; const q3 = z31; const q4 = z41; const xy001 = @as(u128, q0) * @as(u128, mu0); const xy011 = @as(u128, q0) * @as(u128, mu1); const xy021 = @as(u128, q0) * @as(u128, mu2); const xy031 = @as(u128, q0) * @as(u128, mu3); const xy041 = @as(u128, q0) * @as(u128, mu4); const xy101 = @as(u128, q1) * @as(u128, mu0); const xy111 = @as(u128, q1) * @as(u128, mu1); const xy121 = @as(u128, q1) * @as(u128, mu2); const xy131 = @as(u128, q1) * @as(u128, mu3); const xy14 = @as(u128, q1) * @as(u128, mu4); const xy201 = @as(u128, q2) * @as(u128, mu0); const xy211 = @as(u128, q2) * @as(u128, mu1); const xy221 = @as(u128, q2) * @as(u128, mu2); const xy23 = @as(u128, q2) * @as(u128, mu3); const xy24 = @as(u128, q2) * @as(u128, mu4); const xy301 = @as(u128, q3) * @as(u128, mu0); const xy311 = @as(u128, q3) * @as(u128, mu1); const xy32 = @as(u128, q3) * @as(u128, mu2); const xy33 = @as(u128, q3) * @as(u128, mu3); const xy34 = @as(u128, q3) * @as(u128, mu4); const xy401 = @as(u128, q4) * @as(u128, mu0); const xy41 = @as(u128, q4) * @as(u128, mu1); const xy42 = @as(u128, q4) * @as(u128, mu2); const xy43 = @as(u128, q4) * @as(u128, mu3); const xy44 = @as(u128, q4) * @as(u128, mu4); const z02 = xy001; const z12 = xy011 + xy101; const z22 = xy021 + xy111 + xy201; const z32 = xy031 + xy121 + xy211 + xy301; const z42 = xy041 + xy131 + xy221 + xy311 + xy401; const z5 = xy14 + xy23 + xy32 + xy41; const z6 = xy24 + xy33 + xy42; const z7 = xy34 + xy43; const z8 = xy44; const carry9 = z02 >> 56; const c01 = carry9; const carry10 = (z12 + c01) >> 56; const c11 = carry10; const carry11 = (z22 + c11) >> 56; const c21 = carry11; const carry12 = (z32 + c21) >> 56; const c31 = carry12; const carry13 = (z42 + c31) >> 56; const t24 = @as(u64, @truncate(z42 + c31)) & 0xffffffffffffff; const c41 = carry13; const t41 = t24; const carry14 = (z5 + c41) >> 56; const t25 = @as(u64, @truncate(z5 + c41)) & 0xffffffffffffff; const c5 = carry14; const t5 = t25; const carry15 = (z6 + c5) >> 56; const t26 = @as(u64, @truncate(z6 + c5)) & 0xffffffffffffff; const c6 = carry15; const t6 = t26; const carry16 = (z7 + c6) >> 56; const t27 = @as(u64, @truncate(z7 + c6)) & 0xffffffffffffff; const c7 = carry16; const t7 = t27; const carry17 = (z8 + c7) >> 56; const t28 = @as(u64, @truncate(z8 + c7)) & 0xffffffffffffff; const c8 = carry17; const t8 = t28; const t9 = @as(u64, @truncate(c8)); const qmu4_ = t41; const qmu5_ = t5; const qmu6_ = t6; const qmu7_ = t7; const qmu8_ = t8; const qmu9_ = t9; const y_4 = (qmu5_ & 0xffffffffff) << 16; const x_4 = qmu4_ >> 40; const z03 = (x_4 | y_4); const y_5 = (qmu6_ & 0xffffffffff) << 16; const x_5 = qmu5_ >> 40; const z13 = (x_5 | y_5); const y_6 = (qmu7_ & 0xffffffffff) << 16; const x_6 = qmu6_ >> 40; const z23 = (x_6 | y_6); const y_7 = (qmu8_ & 0xffffffffff) << 16; const x_7 = qmu7_ >> 40; const z33 = (x_7 | y_7); const y_8 = (qmu9_ & 0xffffffffff) << 16; const x_8 = qmu8_ >> 40; const z43 = (x_8 | y_8); const qdiv0 = z03; const qdiv1 = z13; const qdiv2 = z23; const qdiv3 = z33; const qdiv4 = z43; const r01 = r0; const r11 = r1; const r21 = r2; const r31 = r3; const r41 = (r4 & 0xffffffffff); const xy00 = @as(u128, qdiv0) * @as(u128, m0); const xy01 = @as(u128, qdiv0) * @as(u128, m1); const xy02 = @as(u128, qdiv0) * @as(u128, m2); const xy03 = @as(u128, qdiv0) * @as(u128, m3); const xy04 = @as(u128, qdiv0) * @as(u128, m4); const xy10 = @as(u128, qdiv1) * @as(u128, m0); const xy11 = @as(u128, qdiv1) * @as(u128, m1); const xy12 = @as(u128, qdiv1) * @as(u128, m2); const xy13 = @as(u128, qdiv1) * @as(u128, m3); const xy20 = @as(u128, qdiv2) * @as(u128, m0); const xy21 = @as(u128, qdiv2) * @as(u128, m1); const xy22 = @as(u128, qdiv2) * @as(u128, m2); const xy30 = @as(u128, qdiv3) * @as(u128, m0); const xy31 = @as(u128, qdiv3) * @as(u128, m1); const xy40 = @as(u128, qdiv4) * @as(u128, m0); const carry18 = xy00 >> 56; const t29 = @as(u64, @truncate(xy00)) & 0xffffffffffffff; const c0 = carry18; const t01 = t29; const carry19 = (xy01 + xy10 + c0) >> 56; const t31 = @as(u64, @truncate(xy01 + xy10 + c0)) & 0xffffffffffffff; const c12 = carry19; const t110 = t31; const carry20 = (xy02 + xy11 + xy20 + c12) >> 56; const t32 = @as(u64, @truncate(xy02 + xy11 + xy20 + c12)) & 0xffffffffffffff; const c22 = carry20; const t210 = t32; const carry = (xy03 + xy12 + xy21 + xy30 + c22) >> 56; const t33 = @as(u64, @truncate(xy03 + xy12 + xy21 + xy30 + c22)) & 0xffffffffffffff; const c32 = carry; const t34 = t33; const t42 = @as(u64, @truncate(xy04 + xy13 + xy22 + xy31 + xy40 + c32)) & 0xffffffffff; const qmul0 = t01; const qmul1 = t110; const qmul2 = t210; const qmul3 = t34; const qmul4 = t42; const b5 = (r01 -% qmul0) >> 63; const t35 = ((b5 << 56) + r01) -% qmul0; const c1 = b5; const t02 = t35; const b6 = (r11 -% (qmul1 + c1)) >> 63; const t36 = ((b6 << 56) + r11) -% (qmul1 + c1); const c2 = b6; const t111 = t36; const b7 = (r21 -% (qmul2 + c2)) >> 63; const t37 = ((b7 << 56) + r21) -% (qmul2 + c2); const c3 = b7; const t211 = t37; const b8 = (r31 -% (qmul3 + c3)) >> 63; const t38 = ((b8 << 56) + r31) -% (qmul3 + c3); const c4 = b8; const t39 = t38; const b9 = (r41 -% (qmul4 + c4)) >> 63; const t43 = ((b9 << 40) + r41) -% (qmul4 + c4); const t44 = t43; const s0 = t02; const s1 = t111; const s2 = t211; const s3 = t39; const s4 = t44; const y01: u64 = 5175514460705773; const y11: u64 = 70332060721272408; const y21: u64 = 5342; const y31: u64 = 0; const y41: u64 = 268435456; const b10 = (s0 -% y01) >> 63; const t45 = ((b10 << 56) + s0) -% y01; const b0 = b10; const t0 = t45; const b11 = (s1 -% (y11 + b0)) >> 63; const t46 = ((b11 << 56) + s1) -% (y11 + b0); const b1 = b11; const t1 = t46; const b12 = (s2 -% (y21 + b1)) >> 63; const t47 = ((b12 << 56) + s2) -% (y21 + b1); const b2 = b12; const t2 = t47; const b13 = (s3 -% (y31 + b2)) >> 63; const t48 = ((b13 << 56) + s3) -% (y31 + b2); const b3 = b13; const t3 = t48; const b = (s4 -% (y41 + b3)) >> 63; const t = ((b << 56) + s4) -% (y41 + b3); const b4 = b; const t4 = t; const mask = (b4 -% @as(u64, @intCast(((1))))); const z04 = s0 ^ (mask & (s0 ^ t0)); const z14 = s1 ^ (mask & (s1 ^ t1)); const z24 = s2 ^ (mask & (s2 ^ t2)); const z34 = s3 ^ (mask & (s3 ^ t3)); const z44 = s4 ^ (mask & (s4 ^ t4)); return Scalar{ .limbs = .{ z04, z14, z24, z34, z44 } }; } /// Return x^2 (mod L) pub fn sq(x: Scalar) Scalar { return x.mul(x); } /// Square a scalar `n` times inline fn sqn(x: Scalar, comptime n: comptime_int) Scalar { var i: usize = 0; var t = x; while (i < n) : (i += 1) { t = t.sq(); } return t; } /// Square and multiply fn sqn_mul(x: Scalar, comptime n: comptime_int, y: Scalar) Scalar { return x.sqn(n).mul(y); } /// Return the inverse of a scalar (mod L), or 0 if x=0. pub fn invert(x: Scalar) Scalar { const _10 = x.sq(); const _11 = x.mul(_10); const _100 = x.mul(_11); const _1000 = _100.sq(); const _1010 = _10.mul(_1000); const _1011 = x.mul(_1010); const _10000 = _1000.sq(); const _10110 = _1011.sq(); const _100000 = _1010.mul(_10110); const _100110 = _10000.mul(_10110); const _1000000 = _100000.sq(); const _1010000 = _10000.mul(_1000000); const _1010011 = _11.mul(_1010000); const _1100011 = _10000.mul(_1010011); const _1100111 = _100.mul(_1100011); const _1101011 = _100.mul(_1100111); const _10010011 = _1000000.mul(_1010011); const _10010111 = _100.mul(_10010011); const _10111101 = _100110.mul(_10010111); const _11010011 = _10110.mul(_10111101); const _11100111 = _1010000.mul(_10010111); const _11101011 = _100.mul(_11100111); const _11110101 = _1010.mul(_11101011); return _1011.mul(_11110101).sqn_mul(126, _1010011).sqn_mul(9, _10).mul(_11110101) .sqn_mul(7, _1100111).sqn_mul(9, _11110101).sqn_mul(11, _10111101).sqn_mul(8, _11100111) .sqn_mul(9, _1101011).sqn_mul(6, _1011).sqn_mul(14, _10010011).sqn_mul(10, _1100011) .sqn_mul(9, _10010111).sqn_mul(10, _11110101).sqn_mul(8, _11010011).sqn_mul(8, _11101011); } /// Return a random scalar < L. pub fn random() Scalar { var s: [64]u8 = undefined; while (true) { crypto.random.bytes(&s); const n = Scalar.fromBytes64(s); if (!n.isZero()) { return n; } } } }