Add muln() to PrimeFieldRepr along with tests for muln/divn.

This commit is contained in:
Sean Bowe 2017-07-29 23:20:59 -06:00
parent 9af0c7dd30
commit dcca363d1b
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
4 changed files with 111 additions and 11 deletions

View File

@ -325,6 +325,32 @@ impl PrimeFieldRepr for FqRepr {
}
}
#[inline(always)]
fn muln(&mut self, mut n: u32) {
if n >= 64 * 6 {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in self.0.iter_mut() {
::std::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in &mut self.0 {
let t2 = *i >> (64 - n);
*i <<= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn num_bits(&self) -> u32 {
let mut ret = (6 as u32) * 64;

View File

@ -161,6 +161,32 @@ impl PrimeFieldRepr for FrRepr {
}
}
#[inline(always)]
fn muln(&mut self, mut n: u32) {
if n >= 64 * 4 {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in self.0.iter_mut() {
::std::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in &mut self.0 {
let t2 = *i >> (64 - n);
*i <<= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn num_bits(&self) -> u32 {
let mut ret = (4 as u32) * 64;

View File

@ -352,7 +352,8 @@ pub trait PrimeFieldRepr: Sized +
/// Add another representation to this one, returning the carry bit.
fn add_nocarry(&mut self, other: &Self) -> bool;
/// Compute the number of bits needed to encode this number.
/// Compute the number of bits needed to encode this number. Always a
/// multiple of 64.
fn num_bits(&self) -> u32;
/// Returns true iff this number is zero.
@ -375,6 +376,9 @@ pub trait PrimeFieldRepr: Sized +
/// it by 2. Overflow is ignored.
fn mul2(&mut self);
/// Performs a leftwise bitshift of this number by some amount.
fn muln(&mut self, amt: u32);
/// Writes this `PrimeFieldRepr` as a big endian integer. Always writes
/// `(num_bits` / 8) bytes.
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {

View File

@ -2,20 +2,64 @@ use rand::{SeedableRng, XorShiftRng};
use ::{PrimeFieldRepr};
pub fn random_repr_tests<R: PrimeFieldRepr>() {
random_encoding_tests::<R>();
random_encoding_tests::<R>();
random_muln_tests::<R>();
random_divn_tests::<R>();
}
fn random_encoding_tests<R: PrimeFieldRepr>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..1000 {
let r = R::rand(&mut rng);
let mut rdecoded = R::default();
for _ in 0..1000 {
let r = R::rand(&mut rng);
let mut rdecoded = R::default();
let mut v: Vec<u8> = vec![];
r.write_be(&mut v).unwrap();
rdecoded.read_be(&v[0..]).unwrap();
let mut v: Vec<u8> = vec![];
r.write_be(&mut v).unwrap();
rdecoded.read_be(&v[0..]).unwrap();
assert_eq!(r, rdecoded);
}
assert_eq!(r, rdecoded);
}
}
fn random_muln_tests<R: PrimeFieldRepr>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..100 {
let r = R::rand(&mut rng);
for shift in 0..(r.num_bits()+1) {
let mut r1 = r;
let mut r2 = r;
for _ in 0..shift {
r1.mul2();
}
r2.muln(shift);
assert_eq!(r1, r2);
}
}
}
fn random_divn_tests<R: PrimeFieldRepr>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..100 {
let r = R::rand(&mut rng);
for shift in 0..(r.num_bits()+1) {
let mut r1 = r;
let mut r2 = r;
for _ in 0..shift {
r1.div2();
}
r2.divn(shift);
assert_eq!(r1, r2);
}
}
}