diff --git a/src/backend.rs b/src/backend.rs index 12bda4e..3352263 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,4 +1,23 @@ +use std::marker::PhantomData; + use itertools::izip; +use num_traits::{WrappingAdd, WrappingMul, WrappingSub}; + +pub trait Modulus { + type Element; + fn is_native() -> bool; + /// -1 in signed representaiton + fn neg_one(&self) -> Self::Element; + /// Largest unsigned value that fits in the modulus. That is, q - 1. + fn largest_unsigned_value(&self) -> Self::Element; + /// Smallest unsigned value that fits in the modulus + /// Always assmed to be 0. + fn smallest_unsigned_value(&self) -> Self::Element; + /// Max +value in signed representation + fn signed_max(&self) -> Self::Element; + /// Min -value in signed representation + fn signed_min(&self) -> Self::Element; +} pub trait ModInit { type Element; @@ -205,3 +224,27 @@ impl VectorOps for ModularOpsU64 { self.q } } + +pub struct WordSizeModulus { + _phantom: PhantomData, +} + +impl ModInit for WordSizeModulus { + type Element = T; + fn new(q: M) -> Self { + // For now assume ModulusOpsU64 is only used for u64 + Self { + _phantom: PhantomData, + } + } +} + +// impl ArithmeticOps for +// WordSizeModulus { fn add(&self, a: &Self::Element, b: &Self::Element) +// -> Self::Element { T::wrapping_add(*a, *b) +// } + +// fn modulus(&self) -> Self::Element { + +// } +// } diff --git a/src/bool/parameters.rs b/src/bool/parameters.rs index f9dc15b..4e59f89 100644 --- a/src/bool/parameters.rs +++ b/src/bool/parameters.rs @@ -2,9 +2,9 @@ use crate::decomposer::Decomposer; #[derive(Clone, PartialEq)] pub(super) struct BoolParameters { - rlwe_q: Modulus, - lwe_q: Modulus, - br_q: Modulus, + rlwe_q: CiphertextModulus, + lwe_q: CiphertextModulus, + br_q: CiphertextModulus, rlwe_n: PolynomialSize, lwe_n: LweDimension, lwe_decomposer_base: DecompostionLogBase, @@ -22,15 +22,15 @@ pub(super) struct BoolParameters { } impl BoolParameters { - pub(crate) fn rlwe_q(&self) -> &Modulus { + pub(crate) fn rlwe_q(&self) -> &CiphertextModulus { &self.rlwe_q } - pub(crate) fn lwe_q(&self) -> &Modulus { + pub(crate) fn lwe_q(&self) -> &CiphertextModulus { &self.lwe_q } - pub(crate) fn br_q(&self) -> &Modulus { + pub(crate) fn br_q(&self) -> &CiphertextModulus { &self.br_q } @@ -164,12 +164,12 @@ pub(crate) struct LweDimension(pub(crate) usize); #[derive(Clone, Copy, PartialEq)] pub(crate) struct PolynomialSize(pub(crate) usize); #[derive(Clone, Copy, PartialEq)] -pub(crate) struct Modulus(pub(crate) T); +pub(crate) struct CiphertextModulus(T); pub(super) const SP_BOOL_PARAMS: BoolParameters = BoolParameters:: { - rlwe_q: Modulus(268369921u64), - lwe_q: Modulus(1 << 16), - br_q: Modulus(1 << 10), + rlwe_q: CiphertextModulus(268369921u64), + lwe_q: CiphertextModulus(1 << 16), + br_q: CiphertextModulus(1 << 10), rlwe_n: PolynomialSize(1 << 10), lwe_n: LweDimension(493), lwe_decomposer_base: DecompostionLogBase(4), @@ -185,9 +185,9 @@ pub(super) const SP_BOOL_PARAMS: BoolParameters = BoolParameters:: { }; pub(super) const MP_BOOL_PARAMS: BoolParameters = BoolParameters:: { - rlwe_q: Modulus(1152921504606830593), - lwe_q: Modulus(1 << 20), - br_q: Modulus(1 << 11), + rlwe_q: CiphertextModulus(1152921504606830593), + lwe_q: CiphertextModulus(1 << 20), + br_q: CiphertextModulus(1 << 11), rlwe_n: PolynomialSize(1 << 11), lwe_n: LweDimension(500), lwe_decomposer_base: DecompostionLogBase(4), diff --git a/src/random.rs b/src/random.rs index a81152e..80820b6 100644 --- a/src/random.rs +++ b/src/random.rs @@ -1,11 +1,12 @@ use std::cell::RefCell; use itertools::izip; +use num_traits::PrimInt; use rand::{distributions::Uniform, thread_rng, CryptoRng, Rng, RngCore, SeedableRng}; use rand_chacha::ChaCha8Rng; -use rand_distr::Distribution; +use rand_distr::{uniform::SampleUniform, Distribution}; -use crate::utils::WithLocal; +use crate::{backend::Modulus, utils::WithLocal}; thread_local! { pub(crate) static DEFAULT_RNG: RefCell = RefCell::new(DefaultSecureRng::new_seeded([0u8;32])); @@ -32,6 +33,13 @@ where fn random_fill(&mut self, parameters: &Self::Parameters, container: &mut M); } +pub trait RandomUniformDist1 +where + M: ?Sized, +{ + fn random_fill(&mut self, modulus: &P, container: &mut M); +} + pub(crate) struct DefaultSecureRng { rng: ChaCha8Rng, } @@ -86,6 +94,25 @@ impl RandomUniformDist<[u32]> for DefaultSecureRng { } } +impl RandomUniformDist1<[T], C> for DefaultSecureRng +where + T: PrimInt + SampleUniform, + C: Modulus, +{ + fn random_fill(&mut self, modulus: &C, container: &mut [T]) { + izip!( + (&mut self.rng).sample_iter(Uniform::new_inclusive( + T::zero(), + modulus.largest_unsigned_value() + )), + container.iter_mut() + ) + .for_each(|(from, to)| { + *to = from; + }); + } +} + impl RandomUniformDist<[u64]> for DefaultSecureRng { type Parameters = u64; fn random_fill(&mut self, parameters: &Self::Parameters, container: &mut [u64]) {