Browse Source

mv arithmetic arith

pull/1/head
arnaucube 3 months ago
parent
commit
19457c98dd
12 changed files with 30 additions and 32 deletions
  1. +1
    -1
      Cargo.toml
  2. +0
    -0
      arith/.gitignore
  3. +1
    -1
      arith/Cargo.toml
  4. +0
    -0
      arith/README.md
  5. +0
    -0
      arith/src/lib.rs
  6. +2
    -2
      arith/src/naive_ntt.rs
  7. +0
    -0
      arith/src/ntt.rs
  8. +2
    -2
      arith/src/ring.rs
  9. +3
    -3
      arith/src/ringq.rs
  10. +1
    -5
      arith/src/zq.rs
  11. +1
    -1
      bfv/Cargo.toml
  12. +19
    -17
      bfv/src/lib.rs

+ 1
- 1
Cargo.toml

@ -1,7 +1,7 @@
[workspace] [workspace]
members = [ members = [
"bfv", "bfv",
"arithmetic"
"arith"
] ]
resolver = "2" resolver = "2"

arithmetic/.gitignore → arith/.gitignore


arithmetic/Cargo.toml → arith/Cargo.toml

@ -1,5 +1,5 @@
[package] [package]
name = "arithmetic"
name = "arith"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"

arithmetic/README.md → arith/README.md


arithmetic/src/lib.rs → arith/src/lib.rs


arithmetic/src/naive_ntt.rs → arith/src/naive_ntt.rs

@ -2,7 +2,7 @@
//! Vandermonde matrix. //! Vandermonde matrix.
use crate::zq::Zq; use crate::zq::Zq;
use anyhow::{anyhow, Result};
use anyhow::{Result, anyhow};
#[derive(Debug)] #[derive(Debug)]
pub struct NTT<const Q: u64, const N: usize> { pub struct NTT<const Q: u64, const N: usize> {
@ -101,8 +101,8 @@ mod tests {
use super::*; use super::*;
use rand_distr::Uniform; use rand_distr::Uniform;
use crate::ring::matrix_vec_product;
use crate::ring::Rq; use crate::ring::Rq;
use crate::ring::matrix_vec_product;
#[test] #[test]
fn roots_of_unity() -> Result<()> { fn roots_of_unity() -> Result<()> {

arithmetic/src/ntt.rs → arith/src/ntt.rs


arithmetic/src/ring.rs → arith/src/ring.rs

@ -1,8 +1,8 @@
//! Polynomial ring Z[X]/(X^N+1) //! Polynomial ring Z[X]/(X^N+1)
//! //!
use anyhow::{anyhow, Result};
use rand::{distributions::Distribution, Rng};
use anyhow::{Result, anyhow};
use rand::{Rng, distributions::Distribution};
use std::array; use std::array;
use std::fmt; use std::fmt;
use std::ops; use std::ops;

arithmetic/src/ringq.rs → arith/src/ringq.rs

@ -1,14 +1,14 @@
//! Polynomial ring Z_q[X]/(X^N+1) //! Polynomial ring Z_q[X]/(X^N+1)
//! //!
use rand::{distributions::Distribution, Rng};
use rand::{Rng, distributions::Distribution};
use std::array; use std::array;
use std::fmt; use std::fmt;
use std::ops; use std::ops;
use crate::ntt::NTT; use crate::ntt::NTT;
use crate::zq::{modulus_u64, Zq};
use anyhow::{anyhow, Result};
use crate::zq::{Zq, modulus_u64};
use anyhow::{Result, anyhow};
/// PolynomialRing element, where the PolynomialRing is R = Z_q[X]/(X^n +1) /// PolynomialRing element, where the PolynomialRing is R = Z_q[X]/(X^n +1)
/// The implementation assumes that q is prime. /// The implementation assumes that q is prime.

arithmetic/src/zq.rs → arith/src/zq.rs

@ -44,11 +44,7 @@ impl Zq {
// Zq(e as u64) // Zq(e as u64)
} }
pub fn from_bool(b: bool) -> Self { pub fn from_bool(b: bool) -> Self {
if b {
Zq(1)
} else {
Zq(0)
}
if b { Zq(1) } else { Zq(0) }
} }
pub fn zero() -> Self { pub fn zero() -> Self {
Zq(0u64) Zq(0u64)

+ 1
- 1
bfv/Cargo.toml

@ -9,4 +9,4 @@ rand = { workspace = true }
rand_distr = { workspace = true } rand_distr = { workspace = true }
itertools = { workspace = true } itertools = { workspace = true }
arithmetic = { path="../arithmetic" }
arith = { path="../arith" }

+ 19
- 17
bfv/src/lib.rs

@ -5,12 +5,12 @@
#![allow(clippy::upper_case_acronyms)] #![allow(clippy::upper_case_acronyms)]
#![allow(dead_code)] // TMP #![allow(dead_code)] // TMP
use anyhow::{anyhow, Result};
use anyhow::{Result, anyhow};
use rand::Rng; use rand::Rng;
use rand_distr::{Normal, Uniform}; use rand_distr::{Normal, Uniform};
use std::ops; use std::ops;
use arithmetic::{Rq, R};
use arith::{R, Rq};
// error deviation for the Gaussian(Normal) distribution // error deviation for the Gaussian(Normal) distribution
// sigma=3.2 from: https://eprint.iacr.org/2022/162.pdf page 5 // sigma=3.2 from: https://eprint.iacr.org/2022/162.pdf page 5
@ -57,7 +57,7 @@ impl RLWE {
let b1: R<N> = b.1.to_r(); let b1: R<N> = b.1.to_r();
// tensor (\in R) (2021-204 p.9) // tensor (\in R) (2021-204 p.9)
use arithmetic::ring::naive_mul;
use arith::ring::naive_mul;
// (here can use *, but want to make it explicit that we're using the naive mul) // (here can use *, but want to make it explicit that we're using the naive mul)
let c0: Vec<i64> = naive_mul(&a0, &b0); let c0: Vec<i64> = naive_mul(&a0, &b0);
let c1_l: Vec<i64> = naive_mul(&a0, &b1); let c1_l: Vec<i64> = naive_mul(&a0, &b1);
@ -66,9 +66,9 @@ impl RLWE {
let c2: Vec<i64> = naive_mul(&a1, &b1); let c2: Vec<i64> = naive_mul(&a1, &b1);
// scale down, then reduce module Q, so result is \in R_q // scale down, then reduce module Q, so result is \in R_q
let c0: Rq<Q, N> = arithmetic::ring::mul_div_round::<Q, N>(c0, T, Q);
let c1: Rq<Q, N> = arithmetic::ring::mul_div_round::<Q, N>(c1, T, Q);
let c2: Rq<Q, N> = arithmetic::ring::mul_div_round::<Q, N>(c2, T, Q);
let c0: Rq<Q, N> = arith::ring::mul_div_round::<Q, N>(c0, T, Q);
let c1: Rq<Q, N> = arith::ring::mul_div_round::<Q, N>(c1, T, Q);
let c2: Rq<Q, N> = arith::ring::mul_div_round::<Q, N>(c2, T, Q);
(c0, c1, c2) (c0, c1, c2)
} }
@ -106,7 +106,7 @@ impl RLWE {
} }
// naive mul in the ring Rq, reusing the ring::naive_mul and then applying mod(X^N +1) // naive mul in the ring Rq, reusing the ring::naive_mul and then applying mod(X^N +1)
fn tmp_naive_mul<const Q: u64, const N: usize>(a: Rq<Q, N>, b: Rq<Q, N>) -> Rq<Q, N> { fn tmp_naive_mul<const Q: u64, const N: usize>(a: Rq<Q, N>, b: Rq<Q, N>) -> Rq<Q, N> {
Rq::<Q, N>::from_vec_i64(arithmetic::ring::naive_mul(&a.to_r(), &b.to_r()))
Rq::<Q, N>::from_vec_i64(arith::ring::naive_mul(&a.to_r(), &b.to_r()))
} }
impl<const Q: u64, const N: usize> ops::Add<RLWE<Q, N>> for RLWE<Q, N> { impl<const Q: u64, const N: usize> ops::Add<RLWE<Q, N>> for RLWE<Q, N> {
@ -196,7 +196,7 @@ impl BFV {
let cs = c.0 + c.1 * sk.0; // done in mod q let cs = c.0 + c.1 * sk.0; // done in mod q
// let c1s = tmp_naive_mul(c.1, sk.0); // let c1s = tmp_naive_mul(c.1, sk.0);
// // let c1s = arithmetic::ring::naive_mul(&c.1.to_r(), &sk.0.to_r()); // TODO rm
// // let c1s = arith::ring::naive_mul(&c.1.to_r(), &sk.0.to_r()); // TODO rm
// // let c1s = Rq::<Q, N>::from_vec_i64(c1s); // // let c1s = Rq::<Q, N>::from_vec_i64(c1s);
// let cs = c.0 + c1s; // let cs = c.0 + c1s;
@ -293,12 +293,12 @@ impl BFV {
// let c2 = c2.to_r(); // let c2 = c2.to_r();
// let c2rlk0: Vec<f64> = (c2.remodule::<PQ>() * rlk.0) // let c2rlk0: Vec<f64> = (c2.remodule::<PQ>() * rlk.0)
use arithmetic::ring::naive_mul;
use arith::ring::naive_mul;
let c2rlk0: Vec<i64> = naive_mul(&c2.to_r(), &rlk.0.to_r()); let c2rlk0: Vec<i64> = naive_mul(&c2.to_r(), &rlk.0.to_r());
let c2rlk1: Vec<i64> = naive_mul(&c2.to_r(), &rlk.1.to_r()); let c2rlk1: Vec<i64> = naive_mul(&c2.to_r(), &rlk.1.to_r());
let r0: Rq<Q, N> = arithmetic::ring::mul_div_round::<Q, N>(c2rlk0, 1, P);
let r1: Rq<Q, N> = arithmetic::ring::mul_div_round::<Q, N>(c2rlk1, 1, P);
let r0: Rq<Q, N> = arith::ring::mul_div_round::<Q, N>(c2rlk0, 1, P);
let r1: Rq<Q, N> = arith::ring::mul_div_round::<Q, N>(c2rlk1, 1, P);
// let r0 = Rq::<Q, N>::from_vec_f64(c2rlk0); // let r0 = Rq::<Q, N>::from_vec_f64(c2rlk0);
// let r1 = Rq::<Q, N>::from_vec_f64(c2rlk1); // let r1 = Rq::<Q, N>::from_vec_f64(c2rlk1);
@ -409,7 +409,7 @@ mod tests {
fn test_tensor() -> Result<()> { fn test_tensor() -> Result<()> {
const Q: u64 = 2u64.pow(16) + 1; // q prime, and 2^q + 1 shape const Q: u64 = 2u64.pow(16) + 1; // q prime, and 2^q + 1 shape
const N: usize = 32; const N: usize = 32;
const T: u64 = 8; // plaintext modulus
const T: u64 = 2; // plaintext modulus
// const P: u64 = Q; // const P: u64 = Q;
const P: u64 = Q * Q; const P: u64 = Q * Q;
@ -442,10 +442,10 @@ mod tests {
// decrypt non-relinearized mul result // decrypt non-relinearized mul result
let m3: Rq<Q, N> = c_a + c_b * sk.0 + c_c * sk.0 * sk.0; let m3: Rq<Q, N> = c_a + c_b * sk.0 + c_c * sk.0 * sk.0;
// let m3: Rq<Q, N> = c_a // let m3: Rq<Q, N> = c_a
// + Rq::<Q, N>::from_vec_i64(arithmetic::ring::naive_mul(&c_b.to_r(), &sk.0.to_r()))
// + Rq::<Q, N>::from_vec_i64(arithmetic::ring::naive_mul(
// + Rq::<Q, N>::from_vec_i64(arith::ring::naive_mul(&c_b.to_r(), &sk.0.to_r()))
// + Rq::<Q, N>::from_vec_i64(arith::ring::naive_mul(
// &c_c.to_r(), // &c_c.to_r(),
// &R::<N>::from_vec(arithmetic::ring::naive_mul(&sk.0.to_r(), &sk.0.to_r())),
// &R::<N>::from_vec(arith::ring::naive_mul(&sk.0.to_r(), &sk.0.to_r())),
// )); // ));
let m3: Rq<Q, N> = m3.mul_div_round(T, Q); // descale let m3: Rq<Q, N> = m3.mul_div_round(T, Q); // descale
let m3 = m3.remodule::<T>(); let m3 = m3.remodule::<T>();
@ -543,11 +543,13 @@ mod tests {
let m3 = BFV::<Q, N, T>::decrypt(&sk, &c3); let m3 = BFV::<Q, N, T>::decrypt(&sk, &c3);
let naive = (m1.to_r() * m2.to_r()).to_rq::<T>(); let naive = (m1.to_r() * m2.to_r()).to_rq::<T>();
assert_eq!(m3.coeffs().to_vec(), naive.coeffs().to_vec(),
assert_eq!(
m3.coeffs().to_vec(),
naive.coeffs().to_vec(),
"\n\nfor testing:\nlet m1 = Rq::<T, N>::from_vec_u64(vec!{:?});\nlet m2 = Rq::<T, N>::from_vec_u64(vec!{:?});\n", "\n\nfor testing:\nlet m1 = Rq::<T, N>::from_vec_u64(vec!{:?});\nlet m2 = Rq::<T, N>::from_vec_u64(vec!{:?});\n",
m1.coeffs(), m1.coeffs(),
m2.coeffs() m2.coeffs()
);
);
Ok(()) Ok(())
} }

Loading…
Cancel
Save