From 9b4bfa55c7a780b65d7fe233380ca3a9f36a8a7c Mon Sep 17 00:00:00 2001 From: NoCtrlZ Date: Thu, 30 Jun 2022 21:37:30 +0900 Subject: [PATCH] replace double with bit shift --- src/fields/fp.rs | 34 ++++++++++++++++++++++++++++++++-- src/fields/fq.rs | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/fields/fp.rs b/src/fields/fp.rs index 6d8db0d..bf46141 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -262,8 +262,21 @@ impl Fp { /// Doubles this field element. #[inline] pub const fn double(&self) -> Fp { - // TODO: This can be achieved more efficiently with a bitshift. - self.add(self) + let r1 = self.0[0] << 1; + + let c = self.0[0] >> 63; + let tmp = self.0[1] << 1; + let r2 = tmp | c; + + let c = self.0[1] >> 63; + let tmp = self.0[2] << 1; + let r3 = tmp | c; + + let c = self.0[2] >> 63; + let tmp = self.0[3] << 1; + let r4 = tmp | c; + + (&Fp([r1, r2, r3, r4])).sub(&MODULUS) } fn from_u512(limbs: [u64; 8]) -> Fp { @@ -788,6 +801,23 @@ impl ec_gpu::GpuField for Fp { #[cfg(test)] use ff::Field; +#[cfg(test)] +use rand_xorshift::XorShiftRng; + +#[cfg(test)] +use rand::SeedableRng; + +#[test] +fn test_add_and_double() { + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); + let a = Fp::random(&mut rng); + let b = a.clone(); + assert_eq!(a.double(), a.add(b)) +} + #[test] fn test_inv() { // Compute -(r^{-1} mod 2^64) mod 2^64 by exponentiating diff --git a/src/fields/fq.rs b/src/fields/fq.rs index 0a08718..d872295 100644 --- a/src/fields/fq.rs +++ b/src/fields/fq.rs @@ -262,8 +262,21 @@ impl Fq { /// Doubles this field element. #[inline] pub const fn double(&self) -> Fq { - // TODO: This can be achieved more efficiently with a bitshift. - self.add(self) + let r1 = self.0[0] << 1; + + let c = self.0[0] >> 63; + let tmp = self.0[1] << 1; + let r2 = tmp | c; + + let c = self.0[1] >> 63; + let tmp = self.0[2] << 1; + let r3 = tmp | c; + + let c = self.0[2] >> 63; + let tmp = self.0[3] << 1; + let r4 = tmp | c; + + (&Fq([r1, r2, r3, r4])).sub(&MODULUS) } fn from_u512(limbs: [u64; 8]) -> Fq { @@ -787,6 +800,23 @@ impl ec_gpu::GpuField for Fq { #[cfg(test)] use ff::Field; +#[cfg(test)] +use rand_xorshift::XorShiftRng; + +#[cfg(test)] +use rand::SeedableRng; + +#[test] +fn test_add_and_double() { + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); + let a = Fq::random(&mut rng); + let b = a.clone(); + assert_eq!(a.double(), a.add(b)) +} + #[test] fn test_inv() { // Compute -(r^{-1} mod 2^64) mod 2^64 by exponentiating