diff --git a/src/backend/vector/ifma/edwards.rs b/src/backend/vector/ifma/edwards.rs index 1a16d42..9d218ca 100644 --- a/src/backend/vector/ifma/edwards.rs +++ b/src/backend/vector/ifma/edwards.rs @@ -11,7 +11,11 @@ use traits::Identity; use std::ops::{Add, Neg, Sub}; +use subtle::Choice; +use subtle::ConditionallySelectable; + use edwards; +use window::{LookupTable, NafLookupTable5, NafLookupTable8}; use super::field::{F51x4Reduced, F51x4Unreduced, Lanes, Shuffle}; @@ -132,6 +136,16 @@ impl<'a, 'b> Add<&'b CachedPoint> for &'a ExtendedPoint { } } +impl ConditionallySelectable for CachedPoint { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + CachedPoint(F51x4Reduced::conditional_select(&a.0, &b.0, choice)) + } + + fn conditional_assign(&mut self, other: &Self, choice: Choice) { + self.0.conditional_assign(&other.0, choice); + } +} + impl<'a> Neg for &'a CachedPoint { type Output = CachedPoint; @@ -150,6 +164,43 @@ impl<'a, 'b> Sub<&'b CachedPoint> for &'a ExtendedPoint { } } +impl<'a> From<&'a edwards::EdwardsPoint> for LookupTable { + fn from(point: &'a edwards::EdwardsPoint) -> Self { + let P = ExtendedPoint::from(*point); + let mut points = [CachedPoint::from(P); 8]; + for i in 0..7 { + points[i + 1] = (&P + &points[i]).into(); + } + LookupTable(points) + } +} + +impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable5 { + fn from(point: &'a edwards::EdwardsPoint) -> Self { + let A = ExtendedPoint::from(*point); + let mut Ai = [CachedPoint::from(A); 8]; + let A2 = A.double(); + for i in 0..7 { + Ai[i + 1] = (&A2 + &Ai[i]).into(); + } + // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] + NafLookupTable5(Ai) + } +} + +impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable8 { + fn from(point: &'a edwards::EdwardsPoint) -> Self { + let A = ExtendedPoint::from(*point); + let mut Ai = [CachedPoint::from(A); 64]; + let A2 = A.double(); + for i in 0..63 { + Ai[i + 1] = (&A2 + &Ai[i]).into(); + } + // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A, ..., 127A] + NafLookupTable8(Ai) + } +} + #[cfg(test)] mod test { use super::*; diff --git a/src/backend/vector/ifma/field.rs b/src/backend/vector/ifma/field.rs index fdc9d61..16d3b74 100644 --- a/src/backend/vector/ifma/field.rs +++ b/src/backend/vector/ifma/field.rs @@ -196,6 +196,39 @@ impl Neg for F51x4Reduced { } } +use subtle::Choice; +use subtle::ConditionallySelectable; + +impl ConditionallySelectable for F51x4Reduced { + #[inline] + fn conditional_select( + a: &F51x4Reduced, + b: &F51x4Reduced, + choice: Choice, + ) -> F51x4Reduced { + let mask = (-(choice.unwrap_u8() as i64)) as u64; + let mask_vec = u64x4::splat(mask); + F51x4Reduced([ + a.0[0] ^ (mask_vec & (a.0[0] ^ b.0[0])), + a.0[1] ^ (mask_vec & (a.0[1] ^ b.0[1])), + a.0[2] ^ (mask_vec & (a.0[2] ^ b.0[2])), + a.0[3] ^ (mask_vec & (a.0[3] ^ b.0[3])), + a.0[4] ^ (mask_vec & (a.0[4] ^ b.0[4])), + ]) + } + + #[inline] + fn conditional_assign(&mut self, other: &F51x4Reduced, choice: Choice) { + let mask = (-(choice.unwrap_u8() as i64)) as u64; + let mask_vec = u64x4::splat(mask); + self.0[0] ^= mask_vec & (self.0[0] ^ other.0[0]); + self.0[1] ^= mask_vec & (self.0[1] ^ other.0[1]); + self.0[2] ^= mask_vec & (self.0[2] ^ other.0[2]); + self.0[3] ^= mask_vec & (self.0[3] ^ other.0[3]); + self.0[4] ^= mask_vec & (self.0[4] ^ other.0[4]); + } +} + impl F51x4Reduced { #[inline] pub fn shuffle(&self, control: Shuffle) -> F51x4Reduced {