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