diff --git a/Cargo.toml b/Cargo.toml index 0642edd..2bf8179 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +lll-rs = "0.2.0" +rug = "1.27.0" diff --git a/src/matrix.rs b/src/matrix.rs index 8098da6..0029e04 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -1,7 +1,14 @@ -type Element = f64; - +use rug::ops::Pow; use std::ops::{Index, IndexMut}; +type Element = rug::Integer; + +macro_rules! int { + ($x:expr) => { + rug::Integer::from($x) + }; +} + #[derive(Debug, PartialEq)] pub struct Matrix { pub n: usize, @@ -22,14 +29,14 @@ impl Matrix { let mut values = Vec::with_capacity(n * n); // First row: [2^noise_bits, ciphertexts[1], ..., ciphertexts[t]] - values.push((2.0f64).powi(noise_bits as i32)); + values.push(int!(2u64).pow(noise_bits as u32)); values.extend_from_slice(&ciphertexts[1..]); // -x0 on diagonal, 0 everywhere else - let x0 = ciphertexts[0]; + let x0 = &ciphertexts[0]; for i in 0..n - 1 { - let mut row = vec![0.0; n]; - row[i] = -x0; + let mut row = vec![int!(0); n]; + row[i] = -x0.clone(); values.extend(row); } @@ -38,7 +45,7 @@ impl Matrix { } impl Index<(usize, usize)> for Matrix { - type Output = f64; + type Output = Element; fn index(&self, index: (usize, usize)) -> &Self::Output { &self.values[(self.n * index.0) + index.1] } @@ -58,31 +65,40 @@ mod tests { assert_eq!( Matrix { n: 2, - values: Vec::from([1.0, 2.0, 3.0, 4.0]) + values: vec![int!(1), int!(2), int!(3), int!(4)], }, - Matrix::new(2, Vec::from([1.0, 2.0, 3.0, 4.0])).unwrap() + Matrix::new(2, vec![int!(1), int!(2), int!(3), int!(4)]).unwrap() ); - assert!(Matrix::new(3, Vec::from([1.0, 2.0])).is_none()); + assert!(Matrix::new(3, vec![int!(1), int!(2)]).is_none()); } + #[test] fn indexes() { - let mut m = Matrix::new(2, vec![1.0, 2.0, 3.0, 4.0]).unwrap(); - assert_eq!(m[(0, 0)], 1.0); - assert_eq!(m[(1, 0)], 3.0); + let mut m = Matrix::new(2, vec![int!(1), int!(2), int!(3), int!(4)]).unwrap(); - m[(1, 0)] = 5.0; - assert_eq!(m[(1, 0)], 5.0); + assert_eq!(m[(0, 0)], int!(1)); + assert_eq!(m[(1, 0)], int!(3)); + + m[(1, 0)] = int!(5); + assert_eq!(m[(1, 0)], int!(5)); } + #[test] fn test_new_lattice() { - let ciphertexts = vec![5.0, 8.0, 12.0]; // x0=5.0, x1=8.0, x2=12.0 + let ciphertexts = vec![int!(5), int!(8), int!(12)]; let noise_bits = 2; - // Expected matrix (3x3): - // [ 2^2, x1, x2 ] = [4.0, 8.0, 12.0] - // [ -x0, 0, 0 ] = [-5.0, 0.0, 0.0] - // [ 0, -x0, 0 ] = [0.0, -5.0, 0.0] - let expected_values = vec![4.0, 8.0, 12.0, -5.0, 0.0, 0.0, 0.0, -5.0, 0.0]; + let expected_values = vec![ + int!(4), + int!(8), + int!(12), + int!(-5), + int!(0), + int!(0), + int!(0), + int!(-5), + int!(0), + ]; let lattice = Matrix::new_lattice(noise_bits, ciphertexts).unwrap(); assert_eq!(lattice.n, 3);