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