Skip to content

Commit 14763e5

Browse files
committed
basic addition and subtraction
1 parent 38544f5 commit 14763e5

File tree

3 files changed

+128
-1
lines changed

3 files changed

+128
-1
lines changed

src/polynomial_ring/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
pub mod pr;
1+
pub mod poly;

src/polynomial_ring/pr.rs renamed to src/polynomial_ring/poly.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![allow(dead_code)] // for now
22

33
use fp2::traits::Fp as FpTrait;
4+
use rand_core::{CryptoRng, RngCore};
45

56
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
67
use std::{
@@ -31,6 +32,16 @@ pub struct Polynomial<Fp: FpTrait> {
3132
}
3233

3334
impl<Fp: FpTrait> Polynomial<Fp> {
35+
/// Create a polynomial from a finite field element.
36+
pub fn new_from_ele(a: &Fp) -> Self {
37+
Self { coeffs: vec![*a] }
38+
}
39+
40+
/// Create a polynomial from a slice of finite field elements.
41+
pub fn new_from_slice(a: &[Fp]) -> Self {
42+
Self { coeffs: a.to_vec() }
43+
}
44+
3445
/// The length of the polynomial. TODO: should we trim trailing zeros? If so, how often?
3546
fn len(&self) -> usize {
3647
self.coeffs.len()
@@ -59,6 +70,31 @@ impl<Fp: FpTrait> Polynomial<Fp> {
5970
r
6071
}
6172

73+
/// Return 0xFFFFFFFF if self and other represent the same polynomial.
74+
/// Otherwise, return 0x00000000.
75+
pub fn equals(&self, other: &Self) -> u32 {
76+
// TODO: do I want this constant time?
77+
// eg: let mut equals = ct_u32_eq(self.len() as u32, other.len() as u32);
78+
if self.len() != other.len() {
79+
return 0;
80+
}
81+
82+
let mut equals = u32::MAX;
83+
for i in 0..self.len() {
84+
equals &= self.coeffs[i].equals(&other[i]);
85+
}
86+
equals
87+
}
88+
89+
/// Return 0xFFFFFFFF if self is zero, otherwise, return 0x00000000.
90+
pub fn is_zero(&self) -> u32 {
91+
let mut is_zero = u32::MAX;
92+
for i in 0..self.len() {
93+
is_zero &= self.coeffs[i].is_zero();
94+
}
95+
is_zero
96+
}
97+
6298
/// Set self to it's negative.
6399
fn set_neg(&mut self) {
64100
for x in self.coeffs.iter_mut() {
@@ -133,6 +169,22 @@ impl<Fp: FpTrait> Polynomial<Fp> {
133169
r.scale_small_into(k);
134170
r
135171
}
172+
173+
/// Set self to a random value
174+
pub fn set_rand<R: CryptoRng + RngCore>(&mut self, rng: &mut R) {
175+
for x in self.coeffs.iter_mut() {
176+
x.set_rand(rng);
177+
}
178+
}
179+
180+
/// Return a new random polynomial with length d
181+
pub fn rand<R: CryptoRng + RngCore>(rng: &mut R, d: usize) -> Self {
182+
let mut r = Self {
183+
coeffs: vec![Fp::ZERO; d],
184+
};
185+
r.set_rand(rng);
186+
r
187+
}
136188
}
137189

138190
impl<Fp: FpTrait> Poly for Polynomial<Fp> {}
@@ -173,6 +225,17 @@ impl<Fp: FpTrait> Add for Polynomial<Fp> {
173225
}
174226
}
175227

228+
impl<Fp: FpTrait> Add for &Polynomial<Fp> {
229+
type Output = Polynomial<Fp>;
230+
231+
#[inline(always)]
232+
fn add(self, other: &Polynomial<Fp>) -> Polynomial<Fp> {
233+
let mut r = self.clone();
234+
r.set_add(&other);
235+
r
236+
}
237+
}
238+
176239
impl<Fp: FpTrait> AddAssign for Polynomial<Fp> {
177240
#[inline(always)]
178241
fn add_assign(&mut self, other: Polynomial<Fp>) {
@@ -191,6 +254,17 @@ impl<Fp: FpTrait> Sub for Polynomial<Fp> {
191254
}
192255
}
193256

257+
impl<Fp: FpTrait> Sub for &Polynomial<Fp> {
258+
type Output = Polynomial<Fp>;
259+
260+
#[inline(always)]
261+
fn sub(self, other: &Polynomial<Fp>) -> Polynomial<Fp> {
262+
let mut r = self.clone();
263+
r.set_sub(&other);
264+
r
265+
}
266+
}
267+
194268
impl<Fp: FpTrait> SubAssign for Polynomial<Fp> {
195269
#[inline(always)]
196270
fn sub_assign(&mut self, other: Polynomial<Fp>) {

tests/test_poly.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#[cfg(test)]
2+
mod test_polynomial_arithmetic {
3+
4+
use isogeny::fields::sqisign::SqiField248Base as Fp;
5+
use isogeny::{polynomial_ring::poly::Polynomial, utilities::test_utils::drng::DRNG};
6+
7+
type PR = Polynomial<Fp>;
8+
9+
#[test]
10+
fn test_addition() {
11+
let mut rng = DRNG::from_seed("polynomial_addition".as_bytes());
12+
13+
let f = PR::rand(&mut rng, 5);
14+
let g = PR::rand(&mut rng, 5);
15+
let h = PR::rand(&mut rng, 5);
16+
17+
let t1 = &(&f + &g) + &h;
18+
let t2 = &f + &(&g + &h);
19+
20+
assert!(t1.equals(&t2) == u32::MAX);
21+
22+
let mut t1 = f.clone();
23+
t1 += g;
24+
t1 += h;
25+
assert!(t1.equals(&t2) == u32::MAX);
26+
27+
let zero = PR::new_from_ele(&Fp::ZERO);
28+
let t1 = &f + &zero;
29+
assert!(t1.equals(&f) == u32::MAX);
30+
}
31+
32+
#[test]
33+
fn test_subtraction() {
34+
let mut rng = DRNG::from_seed("polynomial_subtraction".as_bytes());
35+
36+
let f = PR::rand(&mut rng, 5);
37+
let g = PR::rand(&mut rng, 5);
38+
let h = PR::rand(&mut rng, 5);
39+
40+
let t1 = &(&f - &g) - &h;
41+
let t2 = &f - &(&g + &h);
42+
43+
assert!(t1.equals(&t2) == u32::MAX);
44+
45+
let mut t1 = f.clone();
46+
t1 -= g;
47+
t1 -= h;
48+
assert!(t1.equals(&t2) == u32::MAX);
49+
50+
let zero = &f - &f;
51+
assert!(zero.is_zero() == u32::MAX);
52+
}
53+
}

0 commit comments

Comments
 (0)