poulpy_core/layouts/
mod.rs

1mod gglwe;
2mod gglwe_to_ggsw_key;
3mod ggsw;
4mod glwe;
5mod glwe_automorphism_key;
6mod glwe_plaintext;
7mod glwe_public_key;
8mod glwe_secret;
9mod glwe_secret_tensor;
10mod glwe_switching_key;
11mod glwe_tensor;
12mod glwe_tensor_key;
13mod glwe_to_lwe_key;
14mod lwe;
15mod lwe_plaintext;
16mod lwe_secret;
17mod lwe_switching_key;
18mod lwe_to_glwe_key;
19
20pub mod compressed;
21pub mod prepared;
22
23pub use compressed::*;
24pub use gglwe::*;
25pub use gglwe_to_ggsw_key::*;
26pub use ggsw::*;
27pub use glwe::*;
28pub use glwe_automorphism_key::*;
29pub use glwe_plaintext::*;
30pub use glwe_public_key::*;
31pub use glwe_secret::*;
32pub use glwe_secret_tensor::*;
33pub use glwe_switching_key::*;
34pub use glwe_tensor::*;
35pub use glwe_tensor_key::*;
36pub use glwe_to_lwe_key::*;
37pub use lwe::*;
38pub use lwe_plaintext::*;
39pub use lwe_secret::*;
40pub use lwe_switching_key::*;
41pub use lwe_to_glwe_key::*;
42pub use prepared::*;
43
44use poulpy_hal::layouts::{Backend, Module};
45
46pub trait GetDegree {
47    fn ring_degree(&self) -> Degree;
48}
49
50impl<B: Backend> GetDegree for Module<B> {
51    fn ring_degree(&self) -> Degree {
52        Self::n(self).into()
53    }
54}
55
56/// Newtype over `u32` with arithmetic and comparisons against same type and `u32`.
57/// Arithmetic is **saturating** (add/sub/mul) to avoid debug-overflow panics.
58macro_rules! newtype_u32 {
59    ($name:ident) => {
60        #[repr(transparent)]
61        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
62        pub struct $name(pub u32);
63
64        // ----- Conversions -----
65        impl From<$name> for u32 {
66            #[inline]
67            fn from(v: $name) -> u32 {
68                v.0
69            }
70        }
71        impl From<$name> for usize {
72            #[inline]
73            fn from(v: $name) -> usize {
74                v.0 as usize
75            }
76        }
77
78        impl From<u32> for $name {
79            #[inline]
80            fn from(v: u32) -> $name {
81                $name(v)
82            }
83        }
84        impl From<usize> for $name {
85            #[inline]
86            fn from(v: usize) -> $name {
87                $name(v as u32)
88            }
89        }
90
91        // ----- Display -----
92        impl ::core::fmt::Display for $name {
93            #[inline]
94            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
95                write!(f, "{}", self.0)
96            }
97        }
98
99        // ===== Arithmetic (same type) =====
100        impl ::core::ops::Add for $name {
101            type Output = $name;
102            #[inline]
103            fn add(self, rhs: $name) -> $name {
104                $name(self.0.saturating_add(rhs.0))
105            }
106        }
107        impl ::core::ops::Sub for $name {
108            type Output = $name;
109            #[inline]
110            fn sub(self, rhs: $name) -> $name {
111                $name(self.0.saturating_sub(rhs.0))
112            }
113        }
114        impl ::core::ops::Mul for $name {
115            type Output = $name;
116            #[inline]
117            fn mul(self, rhs: $name) -> $name {
118                $name(self.0.saturating_mul(rhs.0))
119            }
120        }
121
122        // ===== Arithmetic (with u32) =====
123        impl ::core::ops::Add<u32> for $name {
124            type Output = $name;
125            #[inline]
126            fn add(self, rhs: u32) -> $name {
127                $name(self.0.saturating_add(rhs))
128            }
129        }
130        impl ::core::ops::Sub<u32> for $name {
131            type Output = $name;
132            #[inline]
133            fn sub(self, rhs: u32) -> $name {
134                $name(self.0.saturating_sub(rhs))
135            }
136        }
137        impl ::core::ops::Mul<u32> for $name {
138            type Output = $name;
139            #[inline]
140            fn mul(self, rhs: u32) -> $name {
141                $name(self.0.saturating_mul(rhs))
142            }
143        }
144
145        impl $name {
146            #[inline]
147            pub const fn as_u32(self) -> u32 {
148                self.0
149            }
150            #[inline]
151            pub const fn as_usize(self) -> usize {
152                self.0 as usize
153            }
154
155            #[inline]
156            pub fn div_ceil<T: Into<u32>>(self, rhs: T) -> u32 {
157                self.0.div_ceil(rhs.into())
158            }
159        }
160
161        // Optional symmetric forms: u32 (+|-|*) $name -> $name
162        impl ::core::ops::Add<$name> for u32 {
163            type Output = $name;
164            #[inline]
165            fn add(self, rhs: $name) -> $name {
166                $name(self.saturating_add(rhs.0))
167            }
168        }
169        impl ::core::ops::Sub<$name> for u32 {
170            type Output = $name;
171            #[inline]
172            fn sub(self, rhs: $name) -> $name {
173                $name(self.saturating_sub(rhs.0))
174            }
175        }
176        impl ::core::ops::Mul<$name> for u32 {
177            type Output = $name;
178            #[inline]
179            fn mul(self, rhs: $name) -> $name {
180                $name(self.saturating_mul(rhs.0))
181            }
182        }
183
184        // ===== Cross-type comparisons with u32 (both directions) =====
185        impl ::core::cmp::PartialEq<u32> for $name {
186            #[inline]
187            fn eq(&self, other: &u32) -> bool {
188                self.0 == *other
189            }
190        }
191        impl ::core::cmp::PartialEq<$name> for u32 {
192            #[inline]
193            fn eq(&self, other: &$name) -> bool {
194                *self == other.0
195            }
196        }
197
198        impl ::core::cmp::PartialOrd<u32> for $name {
199            #[inline]
200            fn partial_cmp(&self, other: &u32) -> Option<::core::cmp::Ordering> {
201                self.0.partial_cmp(other)
202            }
203        }
204        impl ::core::cmp::PartialOrd<$name> for u32 {
205            #[inline]
206            fn partial_cmp(&self, other: &$name) -> Option<::core::cmp::Ordering> {
207                self.partial_cmp(&other.0)
208            }
209        }
210    };
211}
212
213newtype_u32!(Degree);
214newtype_u32!(TorusPrecision);
215newtype_u32!(Base2K);
216newtype_u32!(Dnum);
217newtype_u32!(Rank);
218newtype_u32!(Dsize);
219
220impl Degree {
221    pub fn log2(&self) -> usize {
222        let n: usize = self.0 as usize;
223        (usize::BITS - (n - 1).leading_zeros()) as _
224    }
225}