Make a CTNegateable trait with a generic impl for better ergonomics

This commit is contained in:
Henry de Valence 2017-02-20 14:39:55 -08:00
parent 5f4de0074d
commit 8a1c13ef49
2 changed files with 20 additions and 9 deletions

View file

@ -803,7 +803,7 @@ impl FieldElement {
mod test { mod test {
use field::*; use field::*;
use test::Bencher; use test::Bencher;
use util::conditional_negate; use util::CTNegateable;
#[bench] #[bench]
fn bench_fieldelement_a_mul_a(b: &mut Bencher) { fn bench_fieldelement_a_mul_a(b: &mut Bencher) {
@ -939,11 +939,11 @@ mod test {
let one = FieldElement([ 1,0,0,0,0,0,0,0,0,0]); let one = FieldElement([ 1,0,0,0,0,0,0,0,0,0]);
let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]); let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]);
let mut x = one; let mut x = one;
conditional_negate(&mut x,1u8); x.conditional_negate(1u8);
assert_eq!(x, minus_one); assert_eq!(x, minus_one);
conditional_negate(&mut x,0u8); x.conditional_negate(0u8);
assert_eq!(x, minus_one); assert_eq!(x, minus_one);
conditional_negate(&mut x,1u8); x.conditional_negate(1u8);
assert_eq!(x, one); assert_eq!(x, one);
} }
} }

View file

@ -21,13 +21,24 @@ pub trait CTAssignable {
fn conditional_assign(&mut self, other: &Self, choice: u8); fn conditional_assign(&mut self, other: &Self, choice: u8);
} }
/// Conditionally negate an element if `choice == 1u8`. /// Trait for items which can be conditionally negated in constant time.
pub fn conditional_negate<T>(x: &mut T, choice: u8) ///
/// Note: it is not necessary to implement this trait, as a generic
/// implementation is provided.
pub trait CTNegateable
{
/// Conditionally negate an element if `choice == 1u8`.
fn conditional_negate(&mut self, choice: u8);
}
impl<T> CTNegateable for T
where T: CTAssignable, for<'a> &'a T: Neg<Output=T> where T: CTAssignable, for<'a> &'a T: Neg<Output=T>
{ {
// Need to cast to discard mutability fn conditional_negate(&mut self, choice: u8) {
let x_neg = -(x as &T); // Need to cast to eliminate mutability
x.conditional_assign(&x_neg, choice); let self_neg: T = -(self as &T);
self.conditional_assign(&self_neg, choice);
}
} }
/// Check equality of two bytes in constant time. /// Check equality of two bytes in constant time.