Rearrange signs to avoid a subtraction

This commit is contained in:
Henry de Valence 2017-12-07 10:21:20 -08:00
parent 7d2d87441b
commit d62fc7caf1
3 changed files with 29 additions and 36 deletions

View file

@ -237,17 +237,19 @@ impl<'a, 'b> Add<&'b ExtendedPoint> for &'a ExtendedPoint {
// set t2 = (S0*S2 S1*S3 Z1*Z2 T1*T2) = (S4 S5 S6 S7)
let mut t2 = &t0 * &t1;
// set t2 = (S8 S9 S10 S11)
//// set t2 = (S8 S9 S10 S11)
// set t2 = (121666*S4 121666*S5 2*121666*S6 2*121665*S7)
// = ( S8 S9 S10 -S11)
t2.scale_by_curve_constants();
// set t2 = (S8 S9 S11 S10)
// set t2 = (S8 S9 -S11 S10)
t2.swap_CD();
// set t2 = (S9-S8 S9+S8 S10-S11 S10+S11) = (S12 S13 S14 S15)
// set t2 = (S9-S8 S9+S8 S10+S11 S10-S11) = (S12 S13 S15 S14)
t2.diff_sum();
let c0 = u32x8::new(0,5,2,7,5,0,7,2); // (ABCD) -> (ADDA)
let c1 = u32x8::new(4,1,6,3,4,1,6,3); // (ABCD) -> (CBCB)
let c0 = u32x8::new(0,4,2,6,4,0,6,2); // (ABCD) -> (ACCA)
let c1 = u32x8::new(5,1,7,3,5,1,7,3); // (ABCD) -> (DBDB)
// set t0 = (S12 S15 S15 S12)
// set t1 = (S14 S13 S14 S13)

View file

@ -203,48 +203,35 @@ impl FieldElement32x4 {
/// Let `self` \\(= (A, B, C, D) \\).
///
/// Compute
/// $$( 121666A, 121666B, 2\cdot 121666C, -2\cdot 121665 D).$$
/// $$( 121666A, 121666B, 2\cdot 121666C, 2\cdot 121665 D).$$
pub fn scale_by_curve_constants(&mut self) {
let mut b = [u64x4::splat(0); 10];
let consts = u32x8::new(121666, 0, 121666, 0, 2*121666, 0, 2*121665, 0);
let low__p20 = u64x4::splat(0x3ffffed << 20);
let even_p20 = u64x4::splat(0x3ffffff << 20);
let odd__p20 = u64x4::splat(0x1ffffff << 20);
unsafe {
use stdsimd::vendor::_mm256_mul_epu32;
use stdsimd::vendor::_mm256_blend_epi32;
let (b0, b1) = unpack_pair(self.0[0]);
let b0 = _mm256_mul_epu32(b0, consts); // need a new binding since now
let b1 = _mm256_mul_epu32(b1, consts); // b0 has type u64x4
b[0] = _mm256_blend_epi32(b0.into(), (low__p20 - b0).into(), 0b11_00_00_00).into();
b[1] = _mm256_blend_epi32(b1.into(), (odd__p20 - b1).into(), 0b11_00_00_00).into();
b[0] = _mm256_mul_epu32(b0, consts);
b[1] = _mm256_mul_epu32(b1, consts);
let (b2, b3) = unpack_pair(self.0[1]);
let b2 = _mm256_mul_epu32(b2, consts);
let b3 = _mm256_mul_epu32(b3, consts);
b[2] = _mm256_blend_epi32(b2.into(), (even_p20 - b2).into(), 0b11_00_00_00).into();
b[3] = _mm256_blend_epi32(b3.into(), (odd__p20 - b3).into(), 0b11_00_00_00).into();
b[2] = _mm256_mul_epu32(b2, consts);
b[3] = _mm256_mul_epu32(b3, consts);
let (b4, b5) = unpack_pair(self.0[2]);
let b4 = _mm256_mul_epu32(b4, consts);
let b5 = _mm256_mul_epu32(b5, consts);
b[4] = _mm256_blend_epi32(b4.into(), (even_p20 - b4).into(), 0b11_00_00_00).into();
b[5] = _mm256_blend_epi32(b5.into(), (odd__p20 - b5).into(), 0b11_00_00_00).into();
b[4] = _mm256_mul_epu32(b4, consts);
b[5] = _mm256_mul_epu32(b5, consts);
let (b6, b7) = unpack_pair(self.0[3]);
let b6 = _mm256_mul_epu32(b6, consts);
let b7 = _mm256_mul_epu32(b7, consts);
b[6] = _mm256_blend_epi32(b6.into(), (even_p20 - b6).into(), 0b11_00_00_00).into();
b[7] = _mm256_blend_epi32(b7.into(), (odd__p20 - b7).into(), 0b11_00_00_00).into();
b[6] = _mm256_mul_epu32(b6, consts);
b[7] = _mm256_mul_epu32(b7, consts);
let (b8, b9) = unpack_pair(self.0[4]);
let b8 = _mm256_mul_epu32(b8, consts);
let b9 = _mm256_mul_epu32(b9, consts);
b[8] = _mm256_blend_epi32(b8.into(), (even_p20 - b8).into(), 0b11_00_00_00).into();
b[9] = _mm256_blend_epi32(b9.into(), (odd__p20 - b9).into(), 0b11_00_00_00).into();
b[8] = _mm256_mul_epu32(b8, consts);
b[9] = _mm256_mul_epu32(b9, consts);
}
*self = FieldElement32x4::reduce64(b);
@ -539,7 +526,7 @@ mod test {
assert_eq!(xs[0], FieldElement64([ 121666,0,0,0,0]));
assert_eq!(xs[1], FieldElement64([ 121666,0,0,0,0]));
assert_eq!(xs[2], FieldElement64([2*121666,0,0,0,0]));
assert_eq!(xs[3], -&FieldElement64([2*121665,0,0,0,0]));
assert_eq!(xs[3], FieldElement64([2*121665,0,0,0,0]));
}
#[test]

View file

@ -87,9 +87,9 @@
//! Hamburg. Ignoring the sign for the moment, since
//! \\(2 \cdot 121666 < 2\^{18}\\), all these constants fit in 32 bits,
//! so this can be done in parallel as a scaling by \\( (121666, 121666,
//! 2\cdot 121665, 2\cdot 121666) \\). To handle the sign, we use
//! masking to negate one of the field elements.
//! -2\cdot 121665, 2\cdot 121666) \\).
//!
//! How do we handle the sign?
//! Since we're primarily interested in Ristretto performance, not
//! Curve25519 performance, we could alternately work on the
//! \\(4\\)-isogenous "IsoEd25519" curve, which has \\(d = 121665\\).
@ -97,6 +97,7 @@
//! one field element by a 32-bit constant is not much easier than
//! multiplying four field elements by 32-bit constants, and it would
//! prevent accelerating Curve25519, so we don't make this choice.
//! Instead, we flip the sign later by swapping two intermediate variables (see below).
//!
//! The 4-wide formulas of the HWCD paper do not seem to have been
//! implemented using SIMD before. The HWCD paper also describes and
@ -186,7 +187,7 @@
//! S\_8 &\gets S\_4 \cdot 121666 \\\\
//! S\_9 &\gets S\_5 \cdot 121666 \\\\
//! S\_{10} &\gets S\_6 \cdot 2 \cdot 121666 \\\\
//! S\_{11} &\gets S\_7 \cdot 2 \cdot (-121665)
//! S\_{11} &\gets S\_7 \cdot 2 \cdot 121665
//! \end{aligned}
//! $$
//!
@ -194,8 +195,8 @@
//! \begin{aligned}
//! S\_{12} &\gets S\_9 - S\_8 \\\\
//! S\_{13} &\gets S\_9 + S\_8 \\\\
//! S\_{14} &\gets S\_{10} - S\_{11} \\\\
//! S\_{15} &\gets S\_{10} + S\_{11}
//! S\_{15} &\gets S\_{10} - S\_{11} \\\\
//! S\_{14} &\gets S\_{10} + S\_{11}
//! \end{aligned}
//! $$
//!
@ -208,7 +209,10 @@
//! \end{aligned}
//! $$
//!
//! to obtain \\( P\_3 = (X\_3 : Y\_3 : Z\_3 : T\_3) = P\_1 + P\_2 \\).
//! to obtain \\( P\_3 = (X\_3 : Y\_3 : Z\_3 : T\_3) = P\_1 + P\_2 \\). Notice that by multiplying
//! \\( S\_{11} \\) by \\(121665\\) instead of by \\(-121665\\), we save a negation; since we use
//! \\( S\_{11} \\) to compute \\( S\_{10} \pm S\_{11} \\), flipping the sign of \\( S\_{11} \\)
//! swaps \\( S\_{14} \\) and \\( S\_{15} \\).
//!
//! ## Doubling
//!