mirror of
https://github.com/saymrwulf/risc0-curve25519-dalek-source.git
synced 2026-09-07 20:30:39 +00:00
Add squaring implementation.
This commit is contained in:
parent
a62571b003
commit
c4617b28a9
1 changed files with 147 additions and 1 deletions
|
|
@ -190,6 +190,120 @@ impl F51x4Reduced {
|
||||||
blend_lanes(self.0[4], other.0[4], control),
|
blend_lanes(self.0[4], other.0[4], control),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn square(&self) -> F51x4Unreduced {
|
||||||
|
unsafe {
|
||||||
|
let x = &self.0;
|
||||||
|
|
||||||
|
// Represent values with coeff. 2
|
||||||
|
let mut z0_2 = u64x4::splat(0);
|
||||||
|
let mut z1_2 = u64x4::splat(0);
|
||||||
|
let mut z2_2 = u64x4::splat(0);
|
||||||
|
let mut z3_2 = u64x4::splat(0);
|
||||||
|
let mut z4_2 = u64x4::splat(0);
|
||||||
|
let mut z5_2 = u64x4::splat(0);
|
||||||
|
let mut z6_2 = u64x4::splat(0);
|
||||||
|
let mut z7_2 = u64x4::splat(0);
|
||||||
|
let mut z9_2 = u64x4::splat(0);
|
||||||
|
|
||||||
|
// Represent values with coeff. 4
|
||||||
|
let mut z2_4 = u64x4::splat(0);
|
||||||
|
let mut z3_4 = u64x4::splat(0);
|
||||||
|
let mut z4_4 = u64x4::splat(0);
|
||||||
|
let mut z5_4 = u64x4::splat(0);
|
||||||
|
let mut z6_4 = u64x4::splat(0);
|
||||||
|
let mut z7_4 = u64x4::splat(0);
|
||||||
|
let mut z8_4 = u64x4::splat(0);
|
||||||
|
|
||||||
|
let mut z0_1 = u64x4::splat(0);
|
||||||
|
z0_1 = madd52lo(z0_1, x[0], x[0]);
|
||||||
|
|
||||||
|
let mut z1_1 = u64x4::splat(0);
|
||||||
|
z1_2 = madd52lo(z1_2, x[0], x[1]);
|
||||||
|
z1_2 = madd52hi(z1_2, x[0], x[0]);
|
||||||
|
|
||||||
|
z2_4 = madd52hi(z2_4, x[0], x[1]);
|
||||||
|
let mut z2_1 = z2_4 << 2;
|
||||||
|
z2_2 = madd52lo(z2_2, x[0], x[2]);
|
||||||
|
z2_1 = madd52lo(z2_1, x[1], x[1]);
|
||||||
|
|
||||||
|
z3_4 = madd52hi(z3_4, x[0], x[2]);
|
||||||
|
let mut z3_1 = z3_4 << 2;
|
||||||
|
z3_2 = madd52lo(z3_2, x[1], x[2]);
|
||||||
|
z3_2 = madd52lo(z3_2, x[0], x[3]);
|
||||||
|
z3_2 = madd52hi(z3_2, x[1], x[1]);
|
||||||
|
|
||||||
|
z4_4 = madd52hi(z4_4, x[1], x[2]);
|
||||||
|
z4_4 = madd52hi(z4_4, x[0], x[3]);
|
||||||
|
let mut z4_1 = z4_4 << 2;
|
||||||
|
z4_2 = madd52lo(z4_2, x[1], x[3]);
|
||||||
|
z4_2 = madd52lo(z4_2, x[0], x[4]);
|
||||||
|
z4_1 = madd52lo(z4_1, x[2], x[2]);
|
||||||
|
|
||||||
|
z5_4 = madd52hi(z5_4, x[1], x[3]);
|
||||||
|
z5_4 = madd52hi(z5_4, x[0], x[4]);
|
||||||
|
let mut z5_1 = z5_4 << 2;
|
||||||
|
z5_2 = madd52lo(z5_2, x[2], x[3]);
|
||||||
|
z5_2 = madd52lo(z5_2, x[1], x[4]);
|
||||||
|
z5_2 = madd52hi(z5_2, x[2], x[2]);
|
||||||
|
|
||||||
|
z6_4 = madd52hi(z6_4, x[2], x[3]);
|
||||||
|
z6_4 = madd52hi(z6_4, x[1], x[4]);
|
||||||
|
let mut z6_1 = z6_4 << 2;
|
||||||
|
z6_2 = madd52lo(z6_2, x[2], x[4]);
|
||||||
|
z6_1 = madd52lo(z6_1, x[3], x[3]);
|
||||||
|
|
||||||
|
z7_4 = madd52hi(z7_4, x[2], x[4]);
|
||||||
|
let mut z7_1 = z7_4 << 2;
|
||||||
|
z7_2 = madd52lo(z7_2, x[3], x[4]);
|
||||||
|
z7_2 = madd52hi(z7_2, x[3], x[3]);
|
||||||
|
|
||||||
|
z8_4 = madd52hi(z8_4, x[3], x[4]);
|
||||||
|
let mut z8_1 = z8_4 << 2;
|
||||||
|
z8_1 = madd52lo(z8_1, x[4], x[4]);
|
||||||
|
|
||||||
|
let mut z9_1 = u64x4::splat(0);
|
||||||
|
z9_2 = madd52hi(z9_2, x[4], x[4]);
|
||||||
|
|
||||||
|
z5_1 += z5_2 << 1;
|
||||||
|
z6_1 += z6_2 << 1;
|
||||||
|
z7_1 += z7_2 << 1;
|
||||||
|
z9_1 += z9_2 << 1;
|
||||||
|
|
||||||
|
let mut t0 = u64x4::splat(0);
|
||||||
|
let mut t1 = u64x4::splat(0);
|
||||||
|
let r19 = u64x4::splat(19);
|
||||||
|
|
||||||
|
t0 = madd52hi(t0, r19, z9_1);
|
||||||
|
t1 = madd52lo(t1, r19, z9_1 >> 52);
|
||||||
|
|
||||||
|
z4_2 = madd52lo(z4_2, r19, z8_1 >> 52);
|
||||||
|
z3_2 = madd52lo(z3_2, r19, z7_1 >> 52);
|
||||||
|
z2_2 = madd52lo(z2_2, r19, z6_1 >> 52);
|
||||||
|
z1_2 = madd52lo(z1_2, r19, z5_1 >> 52);
|
||||||
|
|
||||||
|
z0_2 = madd52lo(z0_2, r19, t0 + t1);
|
||||||
|
z1_2 = madd52hi(z1_2, r19, z5_1);
|
||||||
|
z2_2 = madd52hi(z2_2, r19, z6_1);
|
||||||
|
z3_2 = madd52hi(z3_2, r19, z7_1);
|
||||||
|
z4_2 = madd52hi(z4_2, r19, z8_1);
|
||||||
|
|
||||||
|
z0_1 = madd52lo(z0_1, r19, z5_1);
|
||||||
|
z1_1 = madd52lo(z1_1, r19, z6_1);
|
||||||
|
z2_1 = madd52lo(z2_1, r19, z7_1);
|
||||||
|
z3_1 = madd52lo(z3_1, r19, z8_1);
|
||||||
|
z4_1 = madd52lo(z4_1, r19, z9_1);
|
||||||
|
|
||||||
|
F51x4Unreduced([
|
||||||
|
z0_1 + z0_2 + z0_2,
|
||||||
|
z1_1 + z1_2 + z1_2,
|
||||||
|
z2_1 + z2_2 + z2_2,
|
||||||
|
z3_1 + z3_2 + z3_2,
|
||||||
|
z4_1 + z4_2 + z4_2,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<F51x4Reduced> for F51x4Unreduced {
|
impl From<F51x4Reduced> for F51x4Unreduced {
|
||||||
|
|
@ -250,7 +364,6 @@ impl<'a> Mul<(u32, u32, u32, u32)> for &'a F51x4Reduced {
|
||||||
scalars.2 as u64,
|
scalars.2 as u64,
|
||||||
scalars.3 as u64,
|
scalars.3 as u64,
|
||||||
);
|
);
|
||||||
let mask = u64x4::splat((1 << 51) - 1);
|
|
||||||
let r19 = u64x4::splat(19);
|
let r19 = u64x4::splat(19);
|
||||||
|
|
||||||
let mut z0lo = u64x4::splat(0);
|
let mut z0lo = u64x4::splat(0);
|
||||||
|
|
@ -546,6 +659,39 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn square_matches_mul() {
|
||||||
|
// Invert a small field element to get a big one
|
||||||
|
let a = FieldElement51([2438, 24, 243, 0, 0]).invert();
|
||||||
|
|
||||||
|
let ax4: F51x4Reduced = F51x4Unreduced::new(&a, &a, &a, &a).into();
|
||||||
|
let mut cx4 = &ax4 * &ax4;
|
||||||
|
let mut cx4_sq = ax4.square();
|
||||||
|
|
||||||
|
let splits = cx4.split();
|
||||||
|
let splits_sq = cx4_sq.split();
|
||||||
|
|
||||||
|
for i in 0..4 {
|
||||||
|
assert_eq!(splits_sq[i], splits[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn iterated_square_matches_serial() {
|
||||||
|
// Invert a small field element to get a big one
|
||||||
|
let mut a = FieldElement51([2438, 24, 243, 0, 0]).invert();
|
||||||
|
let mut ax4 = F51x4Unreduced::new(&a, &a, &a, &a);
|
||||||
|
for j in 0..1024 {
|
||||||
|
a = a.square();
|
||||||
|
ax4 = F51x4Reduced::from(ax4).square();
|
||||||
|
|
||||||
|
let splits = ax4.split();
|
||||||
|
for i in 0..4 {
|
||||||
|
assert_eq!(a, splits[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn iterated_u32_mul_matches_serial() {
|
fn iterated_u32_mul_matches_serial() {
|
||||||
// Invert a small field element to get a big one
|
// Invert a small field element to get a big one
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue