he_ring/
lib.rs

1#![feature(never_type)]
2#![feature(fn_traits)]
3#![feature(unboxed_closures)]
4#![feature(test)]
5#![feature(const_type_name)]
6#![feature(allocator_api)]
7#![feature(ptr_alignment_type)]
8#![feature(associated_type_defaults)]
9#![feature(generic_arg_infer)]
10#![feature(min_specialization)]
11#![feature(array_chunks)]
12#![feature(mapped_lock_guards)]
13
14#![allow(non_snake_case)]
15#![allow(type_alias_bounds)]
16#![allow(non_camel_case_types)]
17#![allow(non_upper_case_globals)]
18
19#![doc = include_str!("../Readme.md")]
20
21use std::alloc::Global;
22use std::time::Instant;
23
24use feanor_math::integer::BigIntRing;
25use feanor_math::primitive_int::*;
26use feanor_math::ring::*;
27use feanor_math::rings::zn::zn_64::Zn;
28
29extern crate feanor_math;
30#[cfg(feature = "use_hexl")]
31extern crate feanor_math_hexl;
32extern crate test;
33extern crate thread_local;
34extern crate serde;
35extern crate rand;
36extern crate rand_distr;
37
38///
39/// Simple way to create a ring element from a list of its coefficients as `i32`.
40/// 
41#[cfg(test)]
42fn ring_literal<R>(ring: R, data: &[i32]) -> El<R>
43    where R: RingStore,
44        R::Type: feanor_math::rings::extension::FreeAlgebra
45{
46    use feanor_math::homomorphism::*;
47    use feanor_math::rings::extension::*;
48
49    ring.from_canonical_basis(data.iter().map(|x| ring.base_ring().int_hom().map(*x)))
50}
51
52///
53/// The default convolution algorithm that will be used by all tests and benchmarks.
54/// It is also a good choice when instantiating homomorphic encryption as a user.
55/// 
56/// By default, it will point to a pure-rust implementation of convolution (currently
57/// [`crate::ntt::ntt_convolution::NTTConv`]), but can be changed by using the feature
58/// `use_hexl`.
59/// 
60#[cfg(feature = "use_hexl")]
61pub type DefaultConvolution = feanor_math_hexl::conv::HEXLConvolution;
62
63///
64/// The default convolution algorithm that will be used by all tests and benchmarks.
65/// It is also a good choice when instantiating homomorphic encryption as a user.
66/// 
67/// By default, it will point to a pure-rust implementation of convolution (currently
68/// [`crate::ntt::ntt_convolution::NTTConv`]), but can be changed by using the feature
69/// `use_hexl`.
70/// 
71#[cfg(not(feature = "use_hexl"))]
72pub type DefaultConvolution = crate::ntt::ntt_convolution::NTTConv<Zn>;
73
74///
75/// The default algorithm for computing negacyclic NTTs that will be used by 
76/// all tests and benchmarks. It is also a good choice when instantiating homomorphic 
77/// encryption as a user.
78/// 
79/// By default, it will point to a pure-rust implementation of the negacyclic NTT
80/// (currently [`crate::number_ring::pow2_cyclotomic::RustNegacyclicNTT`]), but can be 
81/// changed by using the feature `use_hexl`.
82/// 
83#[cfg(feature = "use_hexl")]
84pub type DefaultNegacyclicNTT = feanor_math_hexl::hexl::HEXLNegacyclicNTT;
85
86///
87/// The default algorithm for computing negacyclic NTTs that will be used by 
88/// all tests and benchmarks. It is also a good choice when instantiating homomorphic 
89/// encryption as a user.
90/// 
91/// By default, it will point to a pure-rust implementation of the negacyclic NTT
92/// (currently [`crate::number_ring::pow2_cyclotomic::RustNegacyclicNTT`]), but can be 
93/// changed by using the feature `use_hexl`.
94/// 
95#[cfg(not(feature = "use_hexl"))]
96pub type DefaultNegacyclicNTT = crate::number_ring::pow2_cyclotomic::RustNegacyclicNTT<Zn>;
97
98///
99/// The default allocator for ciphertext ring elements, which will be used by all tests and
100/// benchmarks. It is also a good choice when instantiating homomorphic encryption as a user.
101/// 
102/// Currently, this is always [`std::alloc::Global`].
103/// 
104pub type DefaultCiphertextAllocator = Global;
105
106///
107/// Euler's totient function.
108/// 
109#[allow(unused)]
110fn euler_phi(factorization: &[(i64, usize)]) -> i64 {
111    StaticRing::<i64>::RING.prod(factorization.iter().map(|(p, e)| (p - 1) * StaticRing::<i64>::RING.pow(*p, e - 1)))
112}
113
114///
115/// Euler's totient function.
116/// 
117/// It takes a list of all distinct prime factors of `n`, and returns `phi(n)`.
118/// 
119fn euler_phi_squarefree(factorization: &[i64]) -> i64 {
120    StaticRing::<i64>::RING.prod(factorization.iter().map(|p| p - 1))
121}
122
123///
124/// Runs the given function. If `LOG` is true, its running time is printed to stdout.
125/// 
126pub fn log_time<F, T, const LOG: bool, const COUNTER_VAR_COUNT: usize>(description: &str, step_fn: F) -> T
127    where F: FnOnce(&mut [usize; COUNTER_VAR_COUNT]) -> T
128{
129    if LOG {
130        println!("{}", description);
131    }
132    let mut counters = [0; COUNTER_VAR_COUNT];
133    let start = Instant::now();
134    let result = step_fn(&mut counters);
135    let end = Instant::now();
136    if LOG {
137        println!("done in {} ms, {:?}", (end - start).as_millis(), counters);
138    }
139    return result;
140}
141
142///
143/// The ring of integers, implemented using arbitrary precision
144/// 
145const ZZbig: BigIntRing = BigIntRing::RING;
146///
147/// The ring of integers, implemented using 64-bit integers
148/// 
149const ZZi64: StaticRing<i64> = StaticRing::<i64>::RING;
150///
151/// The ring of integers, implemented using 128-bit integers
152/// 
153const ZZi128: StaticRing<i128> = StaticRing::<i128>::RING;
154
155///
156/// Contains some macros that mimic `#[derive(Deserialize)]` but for [`serde::de::DeserializeSeed`].
157/// 
158mod serialization_helper;
159
160///
161/// Contains an abstraction for NTTs and convolutions, which can then be
162/// used to configure the ring implementations in this crate.
163/// 
164pub mod ntt;
165
166///
167/// Defines the trait [`cyclotomic::CyclotomicRing`] for rings of the form `R[X]/(Phi_n)`, where `R` is any base ring.
168/// 
169pub mod cyclotomic;
170
171///
172/// Implementation of fast RNS conversion algorithms.
173/// 
174pub mod rnsconv;
175
176///
177/// Contains an HE-specific abstraction for number rings.
178/// 
179pub mod number_ring;
180
181///
182/// Implementation of rings using double-RNS representation.
183/// 
184pub mod ciphertext_ring;
185
186///
187/// Contains an implementation of "gadget products", which are a form of inner
188/// products that are commonly used in HE to compute multiplications of noisy values
189/// in a way that reduces the increase in noise.
190/// 
191pub mod gadget_product;
192
193///
194/// Contains an implementation of the BFV scheme.
195/// 
196pub mod bfv;
197
198///
199/// The implementation of arithmetic-galois circuits (i.e. circuits built
200/// from linear combination, multiplication and galois gates).
201/// 
202pub mod circuit;
203
204///
205/// Contains algorithms to compute linear transformations and represent
206/// them as linear combination of Galois automorphisms, as required for
207/// (second-generation) HE schemes.
208/// 
209pub mod lintransform;
210
211///
212/// Contains algorithms to build arithmetic circuits, with a focus on
213/// digit extraction polynomials.
214/// 
215pub mod digitextract;
216
217///
218/// Contains an implementation of the BGV scheme.
219/// 
220pub mod bgv;
221
222///
223/// This is a workaround for displaying examples on `docs.rs`.
224/// 
225/// Contains an empty submodule for each example, whose documentation gives
226/// a guide to the corresponding concepts of HE-Ring.
227/// 
228/// Note that this module is only included when building the documentation,
229/// you cannot use it when importing `he-ring` as a crate.
230/// 
231#[cfg(any(doc, doctest))]
232pub mod examples {
233    #[doc = include_str!("../examples/bfv_basics/Readme.md")]
234    pub mod bfv_basics {}
235    #[doc = include_str!("../examples/bgv_basics/Readme.md")]
236    pub mod bgv_basics {}
237    #[doc = include_str!("../examples/bfv_impl_v1/Readme.md")]
238    pub mod bfv_impl_v1 {}
239    #[doc = include_str!("../examples/bfv_impl_v2/Readme.md")]
240    pub mod bfv_impl_v2 {}
241}