1use std::alloc::{Allocator, Global};
2use std::sync::*;
3
4use feanor_math::algorithms::convolution::*;
5use feanor_math::algorithms::matmul::ComputeInnerProduct;
6use feanor_math::homomorphism::*;
7use feanor_math::integer::*;
8use feanor_math::matrix::*;
9use feanor_math::ring::*;
10use feanor_math::rings::extension::*;
11use feanor_math::rings::finite::FiniteRing;
12use feanor_math::rings::zn::*;
13use feanor_math::seq::VectorView;
14use feanor_math::serialization::{DeserializeSeedNewtype, DeserializeWithRing, SerializableElementRing, SerializableNewtype, SerializeWithRing};
15use feanor_math::specialization::{FiniteRingOperation, FiniteRingSpecializable};
16use serde::{Deserialize, Serialize};
17use serde::de::DeserializeSeed;
18use tracing::instrument;
19
20use crate::cyclotomic::CyclotomicGaloisGroupEl;
21use crate::cyclotomic::CyclotomicRing;
22use crate::number_ring::HECyclotomicNumberRing;
23use crate::number_ring::HENumberRing;
24
25use super::double_rns_ring::*;
26use super::single_rns_ring::*;
27use super::BGFVCiphertextRing;
28use super::PreparedMultiplicationRing;
29
30pub struct ManagedDoubleRNSRingBase<NumberRing, A = Global>
80 where NumberRing: HENumberRing,
81 A: Allocator + Clone
82{
83 base: DoubleRNSRingBase<NumberRing, A>,
84 zero: SmallBasisEl<NumberRing, A>
85}
86
87pub type ManagedDoubleRNSRing<NumberRing, A = Global> = RingValue<ManagedDoubleRNSRingBase<NumberRing, A>>;
88
89impl<NumberRing> ManagedDoubleRNSRingBase<NumberRing, Global>
90 where NumberRing: HENumberRing,
91{
92 pub fn new(number_ring: NumberRing, rns_base: zn_rns::Zn<zn_64::Zn, BigIntRing>) -> RingValue<Self> {
93 Self::new_with(number_ring, rns_base, Global)
94 }
95}
96
97enum ManagedDoubleRNSElRepresentation<'a, NumberRing, A>
98 where NumberRing: HENumberRing,
99 A: Allocator + Clone
100{
101 Sum(MappedRwLockReadGuard<'a, (SmallBasisEl<NumberRing, A>, DoubleRNSEl<NumberRing, A>)>),
102 SmallBasis(&'a SmallBasisEl<NumberRing, A>),
103 DoubleRNS(&'a DoubleRNSEl<NumberRing, A>),
104 Both(&'a SmallBasisEl<NumberRing, A>, &'a DoubleRNSEl<NumberRing, A>),
105 Zero
106}
107
108struct DoubleRNSElInternal<NumberRing, A = Global>
109 where NumberRing: HENumberRing,
110 A: Allocator + Clone
111{
112 small_basis_repr: OnceLock<SmallBasisEl<NumberRing, A>>,
113 double_rns_repr: OnceLock<DoubleRNSEl<NumberRing, A>>,
114 sum_repr: RwLock<Option<(SmallBasisEl<NumberRing, A>, DoubleRNSEl<NumberRing, A>)>>
115}
116
117impl<NumberRing, A> DoubleRNSElInternal<NumberRing, A>
118 where NumberRing: HENumberRing,
119 A: Allocator + Clone
120{
121 fn get_repr<'a>(&'a self) -> ManagedDoubleRNSElRepresentation<'a, NumberRing, A> {
122 let sum_repr = self.sum_repr.read().unwrap();
123 if sum_repr.is_some() {
124 return ManagedDoubleRNSElRepresentation::Sum(RwLockReadGuard::map(sum_repr, |sum_repr: &Option<_>| sum_repr.as_ref().unwrap()));
125 }
126 drop(sum_repr);
128 if let Some(small_basis_repr) = self.small_basis_repr.get() {
129 if let Some(double_rns_repr) = self.double_rns_repr.get() {
130 return ManagedDoubleRNSElRepresentation::Both(small_basis_repr, double_rns_repr);
131 } else {
132 return ManagedDoubleRNSElRepresentation::SmallBasis(small_basis_repr);
133 }
134 } else if let Some(double_rns_repr) = self.double_rns_repr.get() {
135 return ManagedDoubleRNSElRepresentation::DoubleRNS(double_rns_repr);
136 } else {
137 return ManagedDoubleRNSElRepresentation::Zero;
138 }
139 }
140}
141
142pub struct ManagedDoubleRNSEl<NumberRing, A = Global>
143 where NumberRing: HENumberRing,
144 A: Allocator + Clone
145{
146 internal: Arc<DoubleRNSElInternal<NumberRing, A>>
147}
148
149impl<NumberRing, A> Clone for ManagedDoubleRNSRingBase<NumberRing, A>
150 where NumberRing: HENumberRing + Clone,
151 A: Allocator + Clone
152{
153 fn clone(&self) -> Self {
154 Self {
155 base: self.base.clone(),
156 zero: self.base.zero_non_fft()
157 }
158 }
159}
160
161impl<NumberRing, A> ManagedDoubleRNSRingBase<NumberRing, A>
162 where NumberRing: HENumberRing,
163 A: Allocator + Clone
164{
165 pub fn new_with(number_ring: NumberRing, rns_base: zn_rns::Zn<zn_64::Zn, BigIntRing>, allocator: A) -> RingValue<ManagedDoubleRNSRingBase<NumberRing, A>> {
166 let result = DoubleRNSRingBase::new_with(number_ring, rns_base, allocator);
167 let zero = result.get_ring().zero_non_fft();
168 ManagedDoubleRNSRing::from(ManagedDoubleRNSRingBase { base: result.into(), zero: zero })
169 }
170
171 pub fn unmanaged_ring(&self) -> RingRef<DoubleRNSRingBase<NumberRing, A>> {
180 RingRef::new(&self.base)
181 }
182
183 pub fn to_small_basis<'a>(&self, value: &'a ManagedDoubleRNSEl<NumberRing, A>) -> Option<&'a SmallBasisEl<NumberRing, A>> {
188 match value.internal.get_repr() {
189 ManagedDoubleRNSElRepresentation::Sum(sum_repr) => {
190 drop(sum_repr);
191 let mut sum_repr_lock = value.internal.sum_repr.write().unwrap();
192 if sum_repr_lock.is_none() {
194 drop(sum_repr_lock);
195 return self.to_small_basis(value);
196 }
197 let sum_repr = std::mem::replace(&mut *sum_repr_lock, None).unwrap();
198 let mut result = sum_repr.0;
199 self.base.add_assign_non_fft(&mut result, &self.base.undo_fft(sum_repr.1));
200 value.internal.small_basis_repr.set(result).ok().unwrap();
203 drop(sum_repr_lock);
206 return Some(value.internal.small_basis_repr.get().unwrap());
207 },
208 ManagedDoubleRNSElRepresentation::SmallBasis(small_basis_repr) | ManagedDoubleRNSElRepresentation::Both(small_basis_repr, _) => {
209 return Some(small_basis_repr);
210 },
211 ManagedDoubleRNSElRepresentation::DoubleRNS(double_rns_repr) => {
212 let result = self.base.undo_fft(self.base.clone_el(double_rns_repr));
213 _ = value.internal.small_basis_repr.set(result);
215 return Some(value.internal.small_basis_repr.get().unwrap());
216 },
217 ManagedDoubleRNSElRepresentation::Zero => {
218 return None;
219 }
220 }
221 }
222
223 pub fn to_doublerns<'a>(&self, value: &'a ManagedDoubleRNSEl<NumberRing, A>) -> Option<&'a DoubleRNSEl<NumberRing, A>> {
228 match value.internal.get_repr() {
229 ManagedDoubleRNSElRepresentation::Sum(sum_repr) => {
230 drop(sum_repr);
231 let mut sum_repr_lock = value.internal.sum_repr.write().unwrap();
232 if sum_repr_lock.is_none() {
234 drop(sum_repr_lock);
235 return self.to_doublerns(value);
236 }
237 let sum_repr = std::mem::replace(&mut *sum_repr_lock, None).unwrap();
238 let mut result = sum_repr.1;
239 self.base.add_assign(&mut result, self.base.do_fft(sum_repr.0));
240 value.internal.double_rns_repr.set(result).ok().unwrap();
243 drop(sum_repr_lock);
246 return Some(value.internal.double_rns_repr.get().unwrap());
247 },
248 ManagedDoubleRNSElRepresentation::DoubleRNS(double_rns_repr) | ManagedDoubleRNSElRepresentation::Both(_, double_rns_repr) => {
249 return Some(double_rns_repr);
250 },
251 ManagedDoubleRNSElRepresentation::SmallBasis(small_basis_repr) => {
252 let result = self.base.do_fft(self.base.clone_el_non_fft(small_basis_repr));
253 _ = value.internal.double_rns_repr.set(result);
255 return Some(value.internal.double_rns_repr.get().unwrap());
256 },
257 ManagedDoubleRNSElRepresentation::Zero => {
258 return None;
259 }
260 }
261 }
262
263 fn new_element_sum(&self, small_basis_part: SmallBasisEl<NumberRing, A>, double_rns_part: DoubleRNSEl<NumberRing, A>) -> ManagedDoubleRNSEl<NumberRing, A> {
264 ManagedDoubleRNSEl {
265 internal: Arc::new(DoubleRNSElInternal {
266 small_basis_repr: OnceLock::new(),
267 double_rns_repr: OnceLock::new(),
268 sum_repr: RwLock::new(Some((small_basis_part, double_rns_part)))
269 })
270 }
271 }
272
273 pub fn from_small_basis_repr(&self, small_basis_repr: SmallBasisEl<NumberRing, A>) -> ManagedDoubleRNSEl<NumberRing, A> {
274 ManagedDoubleRNSEl {
275 internal: Arc::new(DoubleRNSElInternal {
276 small_basis_repr: {
277 let result = OnceLock::new();
278 result.set(small_basis_repr).ok().unwrap();
279 result
280 },
281 double_rns_repr: OnceLock::new(),
282 sum_repr: RwLock::new(None)
283 })
284 }
285 }
286
287 pub fn from_double_rns_repr(&self, double_rns_repr: DoubleRNSEl<NumberRing, A>) -> ManagedDoubleRNSEl<NumberRing, A> {
288 ManagedDoubleRNSEl {
289 internal: Arc::new(DoubleRNSElInternal {
290 small_basis_repr: OnceLock::new(),
291 double_rns_repr: {
292 let result = OnceLock::new();
293 result.set(double_rns_repr).ok().unwrap();
294 result
295 },
296 sum_repr: RwLock::new(None)
297 })
298 }
299 }
300
301 fn new_element_both(&self, small_basis_repr: SmallBasisEl<NumberRing, A>, double_rns_repr: DoubleRNSEl<NumberRing, A>) -> ManagedDoubleRNSEl<NumberRing, A> {
302 ManagedDoubleRNSEl {
303 internal: Arc::new(DoubleRNSElInternal {
304 small_basis_repr: {
305 let result = OnceLock::new();
306 result.set(small_basis_repr).ok().unwrap();
307 result
308 },
309 double_rns_repr: {
310 let result = OnceLock::new();
311 result.set(double_rns_repr).ok().unwrap();
312 result
313 },
314 sum_repr: RwLock::new(None)
315 })
316 }
317 }
318
319 fn apply_linear_operation<F_coeff_bin, F_doublerns_bin, F_coeff_un, F_doublerns_un>(
320 &self,
321 lhs: &ManagedDoubleRNSEl<NumberRing, A>,
322 rhs: &ManagedDoubleRNSEl<NumberRing, A>,
323 f1: F_coeff_bin,
324 f2: F_doublerns_bin,
325 f3: F_coeff_un,
326 f4: F_doublerns_un
327 ) -> ManagedDoubleRNSEl<NumberRing, A>
328 where F_coeff_bin: FnOnce(&mut SmallBasisEl<NumberRing, A>, &SmallBasisEl<NumberRing, A>),
329 F_doublerns_bin: FnOnce(&mut DoubleRNSEl<NumberRing, A>, &DoubleRNSEl<NumberRing, A>),
330 F_coeff_un: FnOnce(&mut SmallBasisEl<NumberRing, A>),
331 F_doublerns_un: FnOnce(&mut DoubleRNSEl<NumberRing, A>),
332 {
333 match (lhs.internal.get_repr(), rhs.internal.get_repr()) {
334 (_, ManagedDoubleRNSElRepresentation::Zero) => self.clone_el(lhs),
335 (ManagedDoubleRNSElRepresentation::Zero, ManagedDoubleRNSElRepresentation::DoubleRNS(rhs_double_rns_repr)) => {
336 let mut result_fft = self.base.clone_el(rhs_double_rns_repr);
337 f4(&mut result_fft);
338 return self.from_double_rns_repr(result_fft);
339 },
340 (ManagedDoubleRNSElRepresentation::Zero, ManagedDoubleRNSElRepresentation::SmallBasis(rhs_small_basis_repr)) => {
341 let mut result_coeff = self.base.clone_el_non_fft(rhs_small_basis_repr);
342 f3(&mut result_coeff);
343 return self.from_small_basis_repr(result_coeff);
344 },
345 (ManagedDoubleRNSElRepresentation::Zero, ManagedDoubleRNSElRepresentation::Sum(rhs_sum_repr)) => {
346 let mut result_fft = self.base.clone_el(&rhs_sum_repr.1);
347 let mut result_coeff = self.base.clone_el_non_fft(&rhs_sum_repr.0);
348 f3(&mut result_coeff);
349 f4(&mut result_fft);
350 return self.new_element_sum(result_coeff, result_fft);
351 },
352 (ManagedDoubleRNSElRepresentation::Zero, ManagedDoubleRNSElRepresentation::Both(rhs_small_basis_repr, rhs_double_rns_repr)) => {
353 let mut result_fft = self.base.clone_el(rhs_double_rns_repr);
354 let mut result_coeff = self.base.clone_el_non_fft(rhs_small_basis_repr);
355 f3(&mut result_coeff);
356 f4(&mut result_fft);
357 return self.new_element_both(result_coeff, result_fft);
358 },
359 (ManagedDoubleRNSElRepresentation::Sum(lhs_sum_repr), ManagedDoubleRNSElRepresentation::Sum(rhs_sum_repr)) => {
360 let mut result_fft = self.base.clone_el(&lhs_sum_repr.1);
361 let mut result_coeff = self.base.clone_el_non_fft(&lhs_sum_repr.0);
362 f1(&mut result_coeff, &rhs_sum_repr.0);
363 f2(&mut result_fft, &rhs_sum_repr.1);
364 return self.new_element_sum(result_coeff, result_fft);
365 },
366 (ManagedDoubleRNSElRepresentation::Sum(lhs_sum_repr), ManagedDoubleRNSElRepresentation::SmallBasis(rhs_small_basis_repr)) => {
367 let mut result_coeff = self.base.clone_el_non_fft(&lhs_sum_repr.0);
368 let result_fft = self.base.clone_el(&lhs_sum_repr.1);
369 f1(&mut result_coeff, rhs_small_basis_repr);
370 return self.new_element_sum(result_coeff, result_fft);
371 },
372 (ManagedDoubleRNSElRepresentation::Sum(lhs_sum_repr), ManagedDoubleRNSElRepresentation::DoubleRNS(rhs_double_rns_repr)) => {
373 let result_coeff = self.base.clone_el_non_fft(&lhs_sum_repr.0);
374 let mut result_fft = self.base.clone_el(&lhs_sum_repr.1);
375 f2(&mut result_fft, rhs_double_rns_repr);
376 return self.new_element_sum(result_coeff, result_fft);
377 },
378 (ManagedDoubleRNSElRepresentation::Sum(lhs_sum_repr), ManagedDoubleRNSElRepresentation::Both(rhs_small_basis_repr, _)) => {
379 let mut result_coeff = self.base.clone_el_non_fft(&lhs_sum_repr.0);
380 let result_fft = self.base.clone_el(&lhs_sum_repr.1);
381 f1(&mut result_coeff, rhs_small_basis_repr);
382 return self.new_element_sum(result_coeff, result_fft);
383 },
384 (ManagedDoubleRNSElRepresentation::SmallBasis(lhs_small_basis_repr), ManagedDoubleRNSElRepresentation::Sum(rhs_sum_repr)) => {
385 let mut result_fft = self.base.clone_el(&rhs_sum_repr.1);
386 let mut result_coeff = self.base.clone_el_non_fft(lhs_small_basis_repr);
387 f1(&mut result_coeff, &rhs_sum_repr.0);
388 f4(&mut result_fft);
389 return self.new_element_sum(result_coeff, result_fft);
390 },
391 (ManagedDoubleRNSElRepresentation::SmallBasis(lhs_small_basis_repr), ManagedDoubleRNSElRepresentation::SmallBasis(rhs_small_basis_repr)) |
392 (ManagedDoubleRNSElRepresentation::SmallBasis(lhs_small_basis_repr), ManagedDoubleRNSElRepresentation::Both(rhs_small_basis_repr, _)) |
393 (ManagedDoubleRNSElRepresentation::Both(lhs_small_basis_repr, _), ManagedDoubleRNSElRepresentation::SmallBasis(rhs_small_basis_repr)) =>
394 {
395 let mut result_coeff = self.base.clone_el_non_fft(lhs_small_basis_repr);
396 f1(&mut result_coeff, rhs_small_basis_repr);
397 return self.from_small_basis_repr(result_coeff);
398 },
399 (ManagedDoubleRNSElRepresentation::SmallBasis(lhs_small_basis_repr), ManagedDoubleRNSElRepresentation::DoubleRNS(rhs_double_rns_repr)) => {
400 let result_coeff = self.base.clone_el_non_fft(lhs_small_basis_repr);
401 let mut result_fft = self.base.clone_el(rhs_double_rns_repr);
402 f4(&mut result_fft);
403 return self.new_element_sum(result_coeff, result_fft);
404 },
405 (ManagedDoubleRNSElRepresentation::DoubleRNS(lhs_double_rns_repr), ManagedDoubleRNSElRepresentation::Sum(rhs_sum_repr)) => {
406 let mut result_fft = self.base.clone_el(lhs_double_rns_repr);
407 let mut result_coeff = self.base.clone_el_non_fft(&rhs_sum_repr.0);
408 f2(&mut result_fft, &rhs_sum_repr.1);
409 f3(&mut result_coeff);
410 return self.new_element_sum(result_coeff, result_fft);
411 },
412 (ManagedDoubleRNSElRepresentation::DoubleRNS(lhs_double_rns_repr), ManagedDoubleRNSElRepresentation::SmallBasis(rhs_small_basis_repr)) => {
413 let mut result_coeff = self.base.clone_el_non_fft(rhs_small_basis_repr);
414 let result_fft = self.base.clone_el(lhs_double_rns_repr);
415 f3(&mut result_coeff);
416 return self.new_element_sum(result_coeff, result_fft);
417 },
418 (ManagedDoubleRNSElRepresentation::DoubleRNS(lhs_double_rns_repr), ManagedDoubleRNSElRepresentation::DoubleRNS(rhs_double_rns_repr)) |
419 (ManagedDoubleRNSElRepresentation::DoubleRNS(lhs_double_rns_repr), ManagedDoubleRNSElRepresentation::Both(_, rhs_double_rns_repr)) |
420 (ManagedDoubleRNSElRepresentation::Both(_, lhs_double_rns_repr), ManagedDoubleRNSElRepresentation::DoubleRNS(rhs_double_rns_repr)) =>
421 {
422 let mut result_fft = self.base.clone_el(lhs_double_rns_repr);
423 f2(&mut result_fft, rhs_double_rns_repr);
424 return self.from_double_rns_repr(result_fft);
425 },
426 (ManagedDoubleRNSElRepresentation::Both(lhs_small_basis_repr, _), ManagedDoubleRNSElRepresentation::Sum(rhs_sum_repr)) => {
427 let mut result_fft = self.base.clone_el(&rhs_sum_repr.1);
428 let mut result_coeff = self.base.clone_el_non_fft(lhs_small_basis_repr);
429 f1(&mut result_coeff, &rhs_sum_repr.0);
430 f4(&mut result_fft);
431 return self.new_element_sum(result_coeff, result_fft);
432 },
433 (ManagedDoubleRNSElRepresentation::Both(lhs_small_basis_repr, lhs_double_rns_repr), ManagedDoubleRNSElRepresentation::Both(rhs_small_basis_repr, rhs_double_rns_repr)) => {
434 let mut result_fft = self.base.clone_el(lhs_double_rns_repr);
435 let mut result_coeff = self.base.clone_el_non_fft(lhs_small_basis_repr);
436 f1(&mut result_coeff, rhs_small_basis_repr);
437 f2(&mut result_fft, rhs_double_rns_repr);
438 return self.new_element_both(result_coeff, result_fft);
439 },
440 }
441 }
442}
443
444impl<NumberRing, A> PreparedMultiplicationRing for ManagedDoubleRNSRingBase<NumberRing, A>
445 where NumberRing: HECyclotomicNumberRing,
446 A: Allocator + Clone
447{
448 type PreparedMultiplicant = Self::Element;
449
450 fn mul_prepared(&self, lhs: &Self::PreparedMultiplicant, rhs: &Self::PreparedMultiplicant) -> Self::Element {
451 self.mul_ref(lhs, rhs)
452 }
453
454 fn prepare_multiplicant(&self, x: &Self::Element) -> Self::PreparedMultiplicant {
455 _ = self.to_doublerns(x);
456 return self.clone_el(x);
457 }
458
459 fn inner_product_prepared<'a, I>(&self, parts: I) -> Self::Element
460 where I: IntoIterator<Item = (&'a Self::PreparedMultiplicant, &'a Self::PreparedMultiplicant)>,
461 Self: 'a
462 {
463 <_ as ComputeInnerProduct>::inner_product_ref(self, parts.into_iter())
464 }
465}
466
467impl<NumberRing, A> BGFVCiphertextRing for ManagedDoubleRNSRingBase<NumberRing, A>
468 where NumberRing: HECyclotomicNumberRing,
469 A: Allocator + Clone
470{
471 type NumberRing = NumberRing;
472
473 fn number_ring(&self) -> &NumberRing {
474 self.base.number_ring()
475 }
476
477 fn drop_rns_factor(&self, drop_rns_factors: &[usize]) -> Self {
478 let new_base = self.base.drop_rns_factor(drop_rns_factors);
479 Self {
480 zero: new_base.get_ring().zero_non_fft(),
481 base: new_base.into()
482 }
483 }
484
485 fn drop_rns_factor_element(&self, from: &Self, dropped_rns_factors: &[usize], value: Self::Element) -> Self::Element {
486 match value.internal.get_repr() {
487 ManagedDoubleRNSElRepresentation::Zero => self.zero(),
488 ManagedDoubleRNSElRepresentation::Sum(sum_repr) => self.new_element_sum(
489 self.base.drop_rns_factor_non_fft_element(&from.base, dropped_rns_factors, &sum_repr.0),
490 self.base.drop_rns_factor_element(&from.base, dropped_rns_factors, &sum_repr.1)
491 ),
492 ManagedDoubleRNSElRepresentation::SmallBasis(small_basis_repr) => self.from_small_basis_repr(
493 self.base.drop_rns_factor_non_fft_element(&from.base, dropped_rns_factors, small_basis_repr)
494 ),
495 ManagedDoubleRNSElRepresentation::DoubleRNS(double_rns_repr) => self.from_double_rns_repr(
496 self.base.drop_rns_factor_element(&from.base, dropped_rns_factors, double_rns_repr)
497 ),
498 ManagedDoubleRNSElRepresentation::Both(small_basis_repr, double_rns_repr) => self.new_element_both(
499 self.base.drop_rns_factor_non_fft_element(&from.base, dropped_rns_factors, small_basis_repr),
500 self.base.drop_rns_factor_element(&from.base, dropped_rns_factors, double_rns_repr)
501 )
502 }
503 }
504
505 fn drop_rns_factor_prepared(&self, from: &Self, drop_factors: &[usize], value: Self::PreparedMultiplicant) -> Self::PreparedMultiplicant {
506 self.drop_rns_factor_element(from, drop_factors, value)
507 }
508
509 fn small_generating_set_len(&self) -> usize {
510 self.rank()
511 }
512
513 fn as_representation_wrt_small_generating_set<V>(&self, x: &Self::Element, mut output: SubmatrixMut<V, zn_64::ZnEl>)
514 where V: AsPointerToSlice<zn_64::ZnEl>
515 {
516 let matrix = self.base.as_matrix_wrt_small_basis(self.to_small_basis(x).unwrap_or(&self.zero));
517 assert_eq!(output.row_count(), matrix.row_count());
518 assert_eq!(output.col_count(), matrix.col_count());
519 for i in 0..matrix.row_count() {
520 for j in 0..matrix.col_count() {
521 *output.at_mut(i, j) = *matrix.at(i, j);
522 }
523 }
524 }
525
526 fn partial_representation_wrt_small_generating_set<V>(&self, x: &Self::Element, row_indices: &[usize], mut output: SubmatrixMut<V, zn_64::ZnEl>)
537 where V: AsPointerToSlice<zn_64::ZnEl>
538 {
539 assert_eq!(output.row_count(), row_indices.len());
540 assert_eq!(output.col_count(), self.base.rank());
541
542 match x.internal.get_repr() {
543 ManagedDoubleRNSElRepresentation::DoubleRNS(double_rns_repr) => self.base.undo_fft_partial(double_rns_repr, row_indices, output),
544 ManagedDoubleRNSElRepresentation::Sum(parts) => {
545 let small_basis_part = &parts.0;
546 let double_rns_part = &parts.1;
547 self.base.undo_fft_partial(double_rns_part, row_indices, output.reborrow());
548 let matrix = self.base.as_matrix_wrt_small_basis(small_basis_part);
549 for (i_out, i_in) in row_indices.iter().enumerate() {
550 for j in 0..matrix.col_count() {
551 self.base.base_ring().at(*i_in).add_assign(output.at_mut(i_out, j), *matrix.at(*i_in, j));
552 }
553 }
554 },
555 ManagedDoubleRNSElRepresentation::Both(small_basis_repr, _) | ManagedDoubleRNSElRepresentation::SmallBasis(small_basis_repr) => {
556 let matrix = self.base.as_matrix_wrt_small_basis(small_basis_repr);
557 for (i_out, i_in) in row_indices.iter().enumerate() {
558 for j in 0..matrix.col_count() {
559 *output.at_mut(i_out, j) = *matrix.at(*i_in, j);
560 }
561 }
562 },
563 ManagedDoubleRNSElRepresentation::Zero => {
564 for (i_out, i_in) in row_indices.iter().enumerate() {
565 for j in 0..self.base.rank() {
566 *output.at_mut(i_out, j) = self.base.base_ring().at(*i_in).zero();
567 }
568 }
569 }
570 }
571
572 }
573
574 fn from_representation_wrt_small_generating_set<V>(&self, data: Submatrix<V, zn_64::ZnEl>) -> Self::Element
575 where V: AsPointerToSlice<zn_64::ZnEl>
576 {
577 let mut x = self.base.zero_non_fft();
578 let mut x_as_matrix = self.base.as_matrix_wrt_small_basis_mut(&mut x);
579 assert_eq!(data.row_count(), x_as_matrix.row_count());
580 assert_eq!(data.col_count(), x_as_matrix.col_count());
581 for i in 0..data.row_count() {
582 for j in 0..data.col_count() {
583 *x_as_matrix.at_mut(i, j) = self.base.base_ring().at(i).clone_el(data.at(i, j));
584 }
585 }
586 return self.from_small_basis_repr(x);
587 }
588}
589
590impl<NumberRing, A> CyclotomicRing for ManagedDoubleRNSRingBase<NumberRing, A>
591 where NumberRing: HECyclotomicNumberRing,
592 A: Allocator + Clone
593{
594 fn n(&self) -> usize {
595 self.base.n()
596 }
597
598 fn apply_galois_action(&self, el: &Self::Element, g: CyclotomicGaloisGroupEl) -> Self::Element {
599 let result = if let Some(value) = self.to_doublerns(el) {
600 self.base.apply_galois_action(&*value, g)
601 } else {
602 return self.zero();
603 };
604 return self.from_double_rns_repr(result);
605 }
606}
607
608impl<NumberRing, A> PartialEq for ManagedDoubleRNSRingBase<NumberRing, A>
609 where NumberRing: HENumberRing,
610 A: Allocator + Clone
611{
612 fn eq(&self, other: &Self) -> bool {
613 self.base == other.base
614 }
615}
616
617impl<NumberRing, A> RingBase for ManagedDoubleRNSRingBase<NumberRing, A>
618 where NumberRing: HENumberRing,
619 A: Allocator + Clone
620{
621 type Element = ManagedDoubleRNSEl<NumberRing, A>;
622
623 fn clone_el(&self, val: &Self::Element) -> Self::Element {
624 ManagedDoubleRNSEl { internal: val.internal.clone() }
625 }
626
627 fn eq_el(&self, lhs: &Self::Element, rhs: &Self::Element) -> bool {
628 match (lhs.internal.get_repr(), rhs.internal.get_repr()) {
629 (ManagedDoubleRNSElRepresentation::Zero, _) | (_, ManagedDoubleRNSElRepresentation::Zero) => self.is_zero(lhs),
630 (ManagedDoubleRNSElRepresentation::SmallBasis(_), _) | (_, ManagedDoubleRNSElRepresentation::SmallBasis(_)) => self.base.eq_el_non_fft(&*self.to_small_basis(lhs).unwrap(), &*self.to_small_basis(rhs).unwrap()),
631 _ => self.base.eq_el(&*self.to_doublerns(lhs).unwrap(), &*self.to_doublerns(rhs).unwrap())
632 }
633 }
634
635 fn is_zero(&self, value: &Self::Element) -> bool {
636 match value.internal.get_repr() {
637 ManagedDoubleRNSElRepresentation::Zero => true,
638 ManagedDoubleRNSElRepresentation::Sum(_) | ManagedDoubleRNSElRepresentation::SmallBasis(_) | ManagedDoubleRNSElRepresentation::Both(_, _) => self.base.eq_el_non_fft(&*self.to_small_basis(value).unwrap(), &self.zero),
639 ManagedDoubleRNSElRepresentation::DoubleRNS(double_rns_repr) => self.base.is_zero(&double_rns_repr)
640 }
641 }
642
643 fn zero(&self) -> Self::Element {
644 ManagedDoubleRNSEl { internal: Arc::new(DoubleRNSElInternal {
645 sum_repr: RwLock::new(None),
646 small_basis_repr: OnceLock::new(),
647 double_rns_repr: OnceLock::new()
648 }) }
649 }
650
651 fn dbg_within<'a>(&self, value: &Self::Element, out: &mut std::fmt::Formatter<'a>, env: EnvBindingStrength) -> std::fmt::Result {
652 if let Some(nonzero) = self.to_doublerns(value) {
653 self.base.dbg_within(&*nonzero, out, env)
654 } else {
655 write!(out, "0")
656 }
657 }
658
659 fn square(&self, value: &mut Self::Element) {
660 let mut result = if let Some(nonzero) = self.to_doublerns(value) {
661 self.base.clone_el(&*nonzero)
662 } else {
663 return
664 };
665 self.base.square(&mut result);
666 *value = self.from_double_rns_repr(result);
667 }
668
669 fn negate(&self, value: Self::Element) -> Self::Element {
670 self.apply_linear_operation(
671 &self.zero(),
672 &value,
673 |_, _| unreachable!(),
674 |_, _| unreachable!(),
675 |a| self.base.negate_inplace_non_fft(a),
676 |a| self.base.negate_inplace(a)
677 )
678 }
679
680 #[instrument(skip_all)]
681 fn mul_int_ref(&self, lhs: &Self::Element, rhs: i32) -> Self::Element {
682 self.apply_linear_operation(
683 &self.zero(),
684 lhs,
685 |_, _| unreachable!(),
686 |_, _| unreachable!(),
687 |a| self.base.mul_scalar_assign_non_fft(a, &self.base_ring().int_hom().map(rhs)),
688 |a| self.base.mul_assign_int(a, rhs)
689 )
690 }
691
692 fn add_ref(&self, lhs: &Self::Element, rhs: &Self::Element) -> Self::Element {
693 self.apply_linear_operation(
694 lhs,
695 rhs,
696 |a, b| self.base.add_assign_non_fft(a, b),
697 |a, b| self.base.add_assign_ref(a, b),
698 |_| {},
699 |_| {}
700 )
701 }
702
703 fn sub_ref(&self, lhs: &Self::Element, rhs: &Self::Element) -> Self::Element {
704 self.apply_linear_operation(
705 lhs,
706 rhs,
707 |a, b| self.base.sub_assign_non_fft(a, b),
708 |a, b| self.base.sub_assign_ref(a, b),
709 |a| self.base.negate_inplace_non_fft(a),
710 |a| self.base.negate_inplace(a)
711 )
712 }
713
714 fn mul_ref(&self, lhs: &Self::Element, rhs: &Self::Element) -> Self::Element {
715 let result = if let (Some(lhs), Some(rhs)) = (self.to_doublerns(lhs), self.to_doublerns(rhs)) {
716 self.base.mul_ref(&*lhs, &*rhs)
717 } else {
718 return self.zero();
719 };
720 return self.from_double_rns_repr(result);
721 }
722
723 fn pow_gen<R: IntegerRingStore>(&self, x: Self::Element, power: &El<R>, integers: R) -> Self::Element
724 where R::Type: IntegerRing
725 {
726 let result = if let Some(nonzero) = self.to_doublerns(&x) {
727 self.base.pow_gen(self.base.clone_el(&*nonzero), power, integers)
728 } else {
729 return self.zero();
730 };
731 return self.from_double_rns_repr(result);
732 }
733
734 fn characteristic<I: IntegerRingStore + Copy>(&self, ZZ: I) -> Option<El<I>>
735 where I::Type: IntegerRing
736 {
737 self.base_ring().characteristic(ZZ)
738 }
739
740 fn add_assign_ref(&self, lhs: &mut Self::Element, rhs: &Self::Element) {
741 lhs.internal = self.add_ref(lhs, rhs).internal;
742 }
743
744 fn add_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) {
745 lhs.internal = self.add_ref(lhs, &rhs).internal;
746 }
747
748 fn sub_assign_ref(&self, lhs: &mut Self::Element, rhs: &Self::Element) {
749 lhs.internal = self.sub_ref(lhs, rhs).internal;
750 }
751
752 fn negate_inplace(&self, lhs: &mut Self::Element) {
753 lhs.internal = self.negate(self.clone_el(lhs)).internal;
754 }
755
756 fn mul_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) {
757 lhs.internal = self.mul_ref(lhs, &rhs).internal;
758 }
759
760 fn mul_assign_ref(&self, lhs: &mut Self::Element, rhs: &Self::Element) {
761 lhs.internal = self.mul_ref(lhs, rhs).internal;
762 }
763
764 fn is_commutative(&self) -> bool { true }
765 fn is_noetherian(&self) -> bool { true }
766 fn is_approximate(&self) -> bool { false }
767
768 fn from_int(&self, value: i32) -> Self::Element {
769 self.from(self.base_ring().get_ring().from_int(value))
770 }
771
772 fn dbg<'a>(&self, value: &Self::Element, out: &mut std::fmt::Formatter<'a>) -> std::fmt::Result {
773 self.dbg_within(value, out, EnvBindingStrength::Weakest)
774 }
775
776 fn sub_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) {
777 lhs.internal = self.sub_ref(lhs, &rhs).internal;
778 }
779
780 fn mul_assign_int(&self, lhs: &mut Self::Element, rhs: i32) {
781 lhs.internal = self.mul_int(self.clone_el(lhs), rhs).internal;
782 }
783
784 fn mul_int(&self, lhs: Self::Element, rhs: i32) -> Self::Element {
785 self.mul_int_ref(&lhs, rhs)
786 }
787
788 fn sub_self_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) {
789 lhs.internal = self.sub_ref(&rhs, lhs).internal;
790 }
791
792 fn sub_self_assign_ref(&self, lhs: &mut Self::Element, rhs: &Self::Element) {
793 lhs.internal = self.sub_ref(rhs, lhs).internal;
794 }
795
796 fn add_ref_fst(&self, lhs: &Self::Element, rhs: Self::Element) -> Self::Element {
797 self.add_ref(lhs, &rhs)
798 }
799
800 fn add_ref_snd(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
801 self.add_ref(&lhs, rhs)
802 }
803
804 fn add(&self, lhs: Self::Element, rhs: Self::Element) -> Self::Element {
805 self.add_ref(&lhs, &rhs)
806 }
807
808 fn sub_ref_fst(&self, lhs: &Self::Element, rhs: Self::Element) -> Self::Element {
809 self.sub_ref(lhs, &rhs)
810 }
811
812 fn sub_ref_snd(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
813 self.sub_ref(&lhs, rhs)
814 }
815
816 fn sub(&self, lhs: Self::Element, rhs: Self::Element) -> Self::Element {
817 self.sub_ref(&lhs, &rhs)
818 }
819
820 fn mul_ref_fst(&self, lhs: &Self::Element, rhs: Self::Element) -> Self::Element {
821 self.mul_ref(lhs, &rhs)
822 }
823
824 fn mul_ref_snd(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
825 self.mul_ref(&lhs, rhs)
826 }
827
828 fn mul(&self, lhs: Self::Element, rhs: Self::Element) -> Self::Element {
829 self.mul_ref(&lhs, &rhs)
830 }
831}
832
833impl<NumberRing, A> ComputeInnerProduct for ManagedDoubleRNSRingBase<NumberRing, A>
834 where NumberRing: HENumberRing,
835 A: Allocator + Clone
836{
837 default fn inner_product<I: Iterator<Item = (Self::Element, Self::Element)>>(&self, els: I) -> Self::Element {
838 let data = els.collect::<Vec<_>>();
839 return self.inner_product_ref(data.iter().map(|(l, r)| (l, r)));
840 }
841
842 default fn inner_product_ref<'a, I: Iterator<Item = (&'a Self::Element, &'a Self::Element)>>(&self, els: I) -> Self::Element
843 where Self: 'a
844 {
845 self.from_double_rns_repr(<_ as ComputeInnerProduct>::inner_product_ref(
846 &self.base,
847 els.map(|(l, r)| (self.to_doublerns(l), self.to_doublerns(r)))
848 .filter_map(|(l, r)| l.and_then(|l| r.map(|r| (l, r))))
849 ))
850 }
851
852 default fn inner_product_ref_fst<'a, I: Iterator<Item = (&'a Self::Element, Self::Element)>>(&self, els: I) -> Self::Element
853 where Self::Element: 'a,
854 Self: 'a
855 {
856 let data = els.collect::<Vec<_>>();
857 return self.inner_product_ref(data.iter().map(|(l, r)| (*l, r)));
858 }
859}
860
861impl<NumberRing, A> RingExtension for ManagedDoubleRNSRingBase<NumberRing, A>
862 where NumberRing: HENumberRing,
863 A: Allocator + Clone
864{
865 type BaseRing = <DoubleRNSRingBase<NumberRing, A> as RingExtension>::BaseRing;
866
867 fn base_ring<'a>(&'a self) -> &'a Self::BaseRing {
868 self.base.base_ring()
869 }
870
871 fn from(&self, x: El<Self::BaseRing>) -> Self::Element {
872 let result_fft = self.base.from(self.base_ring().clone_el(&x));
873 let result_coeff = self.base.from_non_fft(x);
874 return self.new_element_both(result_coeff, result_fft);
875 }
876
877 fn mul_assign_base(&self, lhs: &mut Self::Element, rhs: &El<Self::BaseRing>) {
878 *lhs = self.apply_linear_operation(
879 &self.zero(),
880 lhs,
881 |_, _| unreachable!(),
882 |_, _| unreachable!(),
883 |a| self.base.mul_scalar_assign_non_fft(a, rhs),
884 |a| self.base.mul_assign_base(a, rhs)
885 )
886 }
887}
888
889impl<NumberRing, A> FreeAlgebra for ManagedDoubleRNSRingBase<NumberRing, A>
890 where NumberRing: HENumberRing,
891 A: Allocator + Clone
892{
893 type VectorRepresentation<'a> = DoubleRNSRingBaseElVectorRepresentation<'a, NumberRing, A>
894 where Self: 'a;
895
896 fn canonical_gen(&self) -> Self::Element {
897 let result = self.base.canonical_gen();
898 return self.from_double_rns_repr(result);
899 }
900
901 fn rank(&self) -> usize {
902 self.base.rank()
903 }
904
905 fn wrt_canonical_basis<'a>(&'a self, el: &'a Self::Element) -> Self::VectorRepresentation<'a> {
906 if let Some(result) = self.to_small_basis(el) {
907 self.base.wrt_canonical_basis_non_fft(self.base.clone_el_non_fft(&result))
908 } else {
909 self.base.wrt_canonical_basis_non_fft(self.base.clone_el_non_fft(&self.zero))
910 }
911 }
912
913 fn from_canonical_basis<V>(&self, vec: V) -> Self::Element
914 where V: IntoIterator<Item = El<Self::BaseRing>>,
915 V::IntoIter: DoubleEndedIterator
916 {
917 let result = self.base.from_canonical_basis_non_fft(vec);
918 return self.from_small_basis_repr(result);
919 }
920}
921
922impl<NumberRing, A> FiniteRingSpecializable for ManagedDoubleRNSRingBase<NumberRing, A>
923 where NumberRing: HENumberRing,
924 A: Allocator + Clone
925{
926 fn specialize<O: FiniteRingOperation<Self>>(op: O) -> Result<O::Output, ()> {
927 Ok(op.execute())
928 }
929}
930
931impl<NumberRing, A> FiniteRing for ManagedDoubleRNSRingBase<NumberRing, A>
932 where NumberRing: HENumberRing,
933 A: Allocator + Clone
934{
935 type ElementsIter<'a> = std::iter::Map<<DoubleRNSRingBase<NumberRing, A> as FiniteRing>::ElementsIter<'a>, fn(DoubleRNSEl<NumberRing, A>) -> ManagedDoubleRNSEl<NumberRing, A>>
936 where Self: 'a;
937
938 fn elements<'a>(&'a self) -> Self::ElementsIter<'a> {
939 fn from_doublerns<NumberRing, A>(x: DoubleRNSEl<NumberRing, A>) -> ManagedDoubleRNSEl<NumberRing, A>
940 where NumberRing: HENumberRing,
941 A: Allocator + Clone
942 {
943 return ManagedDoubleRNSEl { internal: Arc::new(DoubleRNSElInternal {
944 double_rns_repr: {
945 let result = OnceLock::new();
946 result.set(x).ok().unwrap();
947 result
948 },
949 sum_repr: RwLock::new(None),
950 small_basis_repr: OnceLock::new()
951 })};
952 }
953 self.base.elements().map(from_doublerns)
954 }
955
956 fn random_element<G: FnMut() -> u64>(&self, rng: G) -> <Self as RingBase>::Element {
957 return self.from_double_rns_repr(self.base.random_element(rng));
958 }
959
960 fn size<I: IntegerRingStore + Copy>(&self, ZZ: I) -> Option<El<I>>
961 where I::Type: IntegerRing
962 {
963 self.base.size(ZZ)
964 }
965}
966
967impl<NumberRing, A> SerializableElementRing for ManagedDoubleRNSRingBase<NumberRing, A>
968 where NumberRing: HENumberRing,
969 A: Allocator + Clone
970{
971 fn serialize<S>(&self, el: &Self::Element, serializer: S) -> Result<S::Ok, S::Error>
972 where S: serde::Serializer
973 {
974 if serializer.is_human_readable() {
975 return SerializableNewtype::new("ManagedDoubleRNSEl", &SerializableSmallBasisElWithRing::new(&self.base, self.to_small_basis(el).unwrap_or(&self.zero))).serialize(serializer);
976 }
977 if let ManagedDoubleRNSElRepresentation::DoubleRNS(double_rns_repr) = el.internal.get_repr() {
978 serializer.serialize_newtype_variant("ManagedDoubleRNSEl", 0, "DoubleRNS", &SerializeWithRing::new(double_rns_repr, RingRef::new(&self.base)))
979 } else if let Some(small_basis_repr) = self.to_small_basis(el) {
980 serializer.serialize_newtype_variant("ManagedDoubleRNSEl", 1, "SmallBasis", &SerializableSmallBasisElWithRing::new(&self.base, small_basis_repr))
981 } else {
982 serializer.serialize_newtype_variant("ManagedDoubleRNSEl", 2, "Zero", &())
983 }
984 }
985
986 fn deserialize<'de, D>(&self, deserializer: D) -> Result<Self::Element, D::Error>
987 where D: serde::Deserializer<'de>
988 {
989 use serde::de::EnumAccess;
990 use serde::de::VariantAccess;
991
992 if deserializer.is_human_readable() {
993 return DeserializeSeedNewtype::new("ManagedDoubleRNSEl", DeserializeSeedSmallBasisElWithRing::new(&self.base)).deserialize(deserializer).map(|small_basis_repr| self.from_small_basis_repr(small_basis_repr));
994 }
995
996 struct ResultVisitor<'a, NumberRing, A>
997 where NumberRing: HENumberRing,
998 A: Allocator + Clone
999 {
1000 ring: &'a ManagedDoubleRNSRingBase<NumberRing, A>,
1001 }
1002 impl<'a, 'de, NumberRing, A> serde::de::Visitor<'de> for ResultVisitor<'a, NumberRing, A>
1003 where NumberRing: HENumberRing,
1004 A: Allocator + Clone
1005 {
1006 type Value = ManagedDoubleRNSEl<NumberRing, A>;
1007
1008 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1009 write!(f, "either ManagedDoubleRNSEl::DoubleRNS, ManagedDoubleRNSEl::SmallBasis or ManagedDoubleRNSEl::Zero")
1010 }
1011
1012 fn visit_enum<E>(self, data: E) -> Result<Self::Value, E::Error>
1013 where E: EnumAccess<'de>
1014 {
1015 enum Discriminant {
1016 DoubleRNS,
1017 SmallBasis,
1018 Zero
1019 }
1020 struct DiscriminantVisitor;
1021 impl<'de> serde::de::Visitor<'de> for DiscriminantVisitor {
1022 type Value = Discriminant;
1023 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1024 write!(f, "one of the enum discriminants `DoubleRNS` = 0, `SmallBasis` = 1 or `Zero` = 2")
1025 }
1026 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1027 where E: serde::de::Error
1028 {
1029 match v {
1030 "DoubleRNS" => Ok(Discriminant::DoubleRNS),
1031 "SmallBasis" => Ok(Discriminant::SmallBasis),
1032 "Zero" => Ok(Discriminant::Zero),
1033 _ => Err(serde::de::Error::unknown_variant(v, &["DoubleRNS", "SmallBasis", "Zero"]))
1034 }
1035 }
1036 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
1037 where E: serde::de::Error
1038 {
1039 match v {
1040 0 => Ok(Discriminant::DoubleRNS),
1041 1 => Ok(Discriminant::SmallBasis),
1042 2 => Ok(Discriminant::Zero),
1043 _ => Err(serde::de::Error::unknown_variant(format!("{}", v).as_str(), &["0", "1", "2"]))
1044 }
1045 }
1046 }
1047 impl<'de> Deserialize<'de> for Discriminant {
1048 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1049 where D: serde::Deserializer<'de>
1050 {
1051 deserializer.deserialize_identifier(DiscriminantVisitor)
1052 }
1053 }
1054 let (discriminant, variant): (Discriminant, _) = data.variant()?;
1055 match discriminant {
1056 Discriminant::DoubleRNS => variant.newtype_variant_seed(DeserializeWithRing::new(self.ring.unmanaged_ring())).map(|double_rns_repr| self.ring.from_double_rns_repr(double_rns_repr)),
1057 Discriminant::SmallBasis => variant.newtype_variant_seed(DeserializeSeedSmallBasisElWithRing::new(self.ring.unmanaged_ring().get_ring())).map(|small_basis_repr| self.ring.from_small_basis_repr(small_basis_repr)),
1058 Discriminant::Zero => variant.unit_variant().map(|()| self.ring.zero())
1059 }
1060 }
1061 }
1062 return deserializer.deserialize_enum("ManagedDoubleRNSEl", &["DoubleRNS", "SmallBasis", "Zero"], ResultVisitor { ring: self });
1063 }
1064}
1065
1066impl<NumberRing, A1, A2, C> CanHomFrom<SingleRNSRingBase<NumberRing, A1, C>> for ManagedDoubleRNSRingBase<NumberRing, A2>
1067 where NumberRing: HECyclotomicNumberRing,
1068 A1: Allocator + Clone,
1069 A2: Allocator + Clone,
1070 C: PreparedConvolutionAlgorithm<zn_64::ZnBase>
1071{
1072 type Homomorphism = <DoubleRNSRingBase<NumberRing, A2> as CanHomFrom<SingleRNSRingBase<NumberRing, A1, C>>>::Homomorphism;
1073
1074 fn has_canonical_hom(&self, from: &SingleRNSRingBase<NumberRing, A1, C>) -> Option<Self::Homomorphism> {
1075 self.base.has_canonical_hom(from)
1076 }
1077
1078 fn map_in(&self, from: &SingleRNSRingBase<NumberRing, A1, C>, el: <SingleRNSRingBase<NumberRing, A1, C> as RingBase>::Element, hom: &Self::Homomorphism) -> Self::Element {
1079 if from.is_zero(&el) {
1080 return self.zero();
1081 }
1082 return self.from_small_basis_repr(self.base.map_in_from_singlerns(from, el, hom));
1083 }
1084}
1085
1086impl<NumberRing, A1, A2> CanHomFrom<DoubleRNSRingBase<NumberRing, A1>> for ManagedDoubleRNSRingBase<NumberRing, A2>
1087 where NumberRing: HECyclotomicNumberRing,
1088 A1: Allocator + Clone,
1089 A2: Allocator + Clone
1090{
1091 type Homomorphism = <DoubleRNSRingBase<NumberRing, A2> as CanHomFrom<DoubleRNSRingBase<NumberRing, A2>>>::Homomorphism;
1092
1093 fn has_canonical_hom(&self, from: &DoubleRNSRingBase<NumberRing, A1>) -> Option<Self::Homomorphism> {
1094 self.base.has_canonical_hom(from)
1095 }
1096
1097 fn map_in(&self, from: &DoubleRNSRingBase<NumberRing, A1>, el: <DoubleRNSRingBase<NumberRing, A1> as RingBase>::Element, hom: &Self::Homomorphism) -> Self::Element {
1098 if from.is_zero(&el) {
1099 return self.zero();
1100 }
1101 return self.from_double_rns_repr(self.base.map_in(from, el, hom));
1102 }
1103}
1104
1105impl<NumberRing, A1, A2> CanHomFrom<ManagedDoubleRNSRingBase<NumberRing, A1>> for ManagedDoubleRNSRingBase<NumberRing, A2>
1106 where NumberRing: HECyclotomicNumberRing,
1107 A1: Allocator + Clone,
1108 A2: Allocator + Clone
1109{
1110 type Homomorphism = <DoubleRNSRingBase<NumberRing, A2> as CanHomFrom<DoubleRNSRingBase<NumberRing, A2>>>::Homomorphism;
1111
1112 fn has_canonical_hom(&self, from: &ManagedDoubleRNSRingBase<NumberRing, A1>) -> Option<Self::Homomorphism> {
1113 self.base.has_canonical_hom(&from.base)
1114 }
1115
1116 fn map_in_ref(&self, from: &ManagedDoubleRNSRingBase<NumberRing, A1>, el: &<ManagedDoubleRNSRingBase<NumberRing, A1> as RingBase>::Element, hom: &Self::Homomorphism) -> Self::Element {
1117 if let Some(el) = from.to_doublerns(el) {
1118 return self.from_double_rns_repr(self.base.map_in_ref(&from.base, &*el, hom));
1119 } else {
1120 self.zero()
1121 }
1122 }
1123
1124 fn map_in(&self, from: &ManagedDoubleRNSRingBase<NumberRing, A1>, el: <ManagedDoubleRNSRingBase<NumberRing, A1> as RingBase>::Element, hom: &Self::Homomorphism) -> Self::Element {
1125 self.map_in_ref(from, &el, hom)
1126 }
1127}
1128
1129impl<NumberRing, A1, A2, C> CanIsoFromTo<SingleRNSRingBase<NumberRing, A1, C>> for ManagedDoubleRNSRingBase<NumberRing, A2>
1130 where NumberRing: HECyclotomicNumberRing,
1131 A1: Allocator + Clone,
1132 A2: Allocator + Clone,
1133 C: PreparedConvolutionAlgorithm<zn_64::ZnBase>
1134{
1135 type Isomorphism = <DoubleRNSRingBase<NumberRing, A2> as CanIsoFromTo<SingleRNSRingBase<NumberRing, A1, C>>>::Isomorphism;
1136
1137 fn has_canonical_iso(&self, to: &SingleRNSRingBase<NumberRing, A1, C>) -> Option<Self::Isomorphism> {
1138 self.base.has_canonical_iso(to)
1139 }
1140
1141 fn map_out(&self, to: &SingleRNSRingBase<NumberRing, A1, C>, el: Self::Element, iso: &Self::Isomorphism) -> <SingleRNSRingBase<NumberRing, A1, C> as RingBase>::Element {
1142 if let Some(el) = self.to_small_basis(&el) {
1143 self.base.map_out_to_singlerns(to, self.base.clone_el_non_fft(&*&el), iso)
1144 } else {
1145 to.zero()
1146 }
1147 }
1148}
1149
1150impl<NumberRing, A1, A2> CanIsoFromTo<DoubleRNSRingBase<NumberRing, A1>> for ManagedDoubleRNSRingBase<NumberRing, A2>
1151 where NumberRing: HECyclotomicNumberRing,
1152 A1: Allocator + Clone,
1153 A2: Allocator + Clone
1154{
1155 type Isomorphism = <DoubleRNSRingBase<NumberRing, A2> as CanIsoFromTo<DoubleRNSRingBase<NumberRing, A2>>>::Isomorphism;
1156
1157 fn has_canonical_iso(&self, to: &DoubleRNSRingBase<NumberRing, A1>) -> Option<Self::Isomorphism> {
1158 self.base.has_canonical_iso(to)
1159 }
1160
1161 fn map_out(&self, to: &DoubleRNSRingBase<NumberRing, A1>, el: Self::Element, iso: &Self::Isomorphism) -> <DoubleRNSRingBase<NumberRing, A1> as RingBase>::Element {
1162 if let Some(el) = self.to_doublerns(&el) {
1163 self.base.map_out(to, self.base.clone_el(&*&el), iso)
1164 } else {
1165 to.zero()
1166 }
1167 }
1168}
1169
1170impl<NumberRing, A1, A2> CanIsoFromTo<ManagedDoubleRNSRingBase<NumberRing, A1>> for ManagedDoubleRNSRingBase<NumberRing, A2>
1171 where NumberRing: HECyclotomicNumberRing,
1172 A1: Allocator + Clone,
1173 A2: Allocator + Clone
1174{
1175 type Isomorphism = <DoubleRNSRingBase<NumberRing, A1> as CanHomFrom<DoubleRNSRingBase<NumberRing, A2>>>::Homomorphism;
1176
1177 fn has_canonical_iso(&self, to: &ManagedDoubleRNSRingBase<NumberRing, A1>) -> Option<Self::Isomorphism> {
1178 to.has_canonical_hom(self)
1179 }
1180
1181 fn map_out(&self, to: &ManagedDoubleRNSRingBase<NumberRing, A1>, el: Self::Element, iso: &Self::Isomorphism) -> <ManagedDoubleRNSRingBase<NumberRing, A1> as RingBase>::Element {
1182 to.map_in(self, el, iso)
1183 }
1184}
1185
1186#[cfg(test)]
1187use feanor_math::assert_el_eq;
1188#[cfg(test)]
1189use crate::number_ring::pow2_cyclotomic::*;
1190#[cfg(test)]
1191use crate::DefaultConvolution;
1192
1193#[cfg(test)]
1194fn ring_and_elements() -> (ManagedDoubleRNSRing<Pow2CyclotomicNumberRing>, Vec<El<ManagedDoubleRNSRing<Pow2CyclotomicNumberRing>>>) {
1195 let rns_base = zn_rns::Zn::new(vec![zn_64::Zn::new(17), zn_64::Zn::new(97)], BigIntRing::RING);
1196 let ring = ManagedDoubleRNSRingBase::new(Pow2CyclotomicNumberRing::new(16), rns_base);
1197
1198 let elements = vec![
1199 ring.zero(),
1200 ring.one(),
1201 ring.neg_one(),
1202 ring.int_hom().map(17),
1203 ring.int_hom().map(97),
1204 ring.canonical_gen(),
1205 ring.pow(ring.canonical_gen(), 15),
1206 ring.int_hom().mul_map(ring.canonical_gen(), 17),
1207 ring.int_hom().mul_map(ring.pow(ring.canonical_gen(), 15), 17),
1208 ring.add(ring.canonical_gen(), ring.one())
1209 ];
1210 return (ring, elements);
1211}
1212
1213#[test]
1214fn test_ring_axioms() {
1215 let (ring, elements) = ring_and_elements();
1216 feanor_math::ring::generic_tests::test_ring_axioms(&ring, elements.iter().map(|x| ring.clone_el(x)));
1217 feanor_math::ring::generic_tests::test_self_iso(&ring, elements.iter().map(|x| ring.clone_el(x)));
1218}
1219
1220#[test]
1221fn test_thread_safe() {
1222 let rns_base = zn_rns::Zn::new(vec![zn_64::Zn::new(17), zn_64::Zn::new(97)], BigIntRing::RING);
1223 let ring = Arc::new(ManagedDoubleRNSRingBase::new(Pow2CyclotomicNumberRing::new(16), rns_base));
1224
1225 let test_element = Arc::new(ring.get_ring().new_element_sum(
1226 ring.get_ring().base.from_non_fft(ring.get_ring().base.base_ring().int_hom().map(1)),
1227 ring.get_ring().base.from(ring.get_ring().base.base_ring().int_hom().map(10))
1228 ));
1229 let mut threads = Vec::new();
1230 let n = 5;
1231 let barrier = Arc::new(Barrier::new(n));
1232 for _ in 0..n {
1233 let barrier = barrier.clone();
1234 let test_element = test_element.clone();
1235 let ring = ring.clone();
1236 threads.push(std::thread::spawn(move || {
1237 barrier.wait();
1238 assert_el_eq!(ring, ring.int_hom().map(121), ring.pow(ring.clone_el(&*test_element), 2));
1239 }))
1240 }
1241 for future in threads {
1242 future.join().unwrap();
1243 }
1244}
1245
1246#[test]
1247fn test_canonical_hom_from_doublerns() {
1248 let rns_base = zn_rns::Zn::new(vec![zn_64::Zn::new(17), zn_64::Zn::new(97)], BigIntRing::RING);
1249 let ring = ManagedDoubleRNSRingBase::new(Pow2CyclotomicNumberRing::new(16), rns_base);
1250
1251 let doublerns_ring = RingRef::new(&ring.get_ring().base);
1252 let elements = vec![
1253 doublerns_ring.zero(),
1254 doublerns_ring.one(),
1255 doublerns_ring.neg_one(),
1256 doublerns_ring.int_hom().map(17),
1257 doublerns_ring.int_hom().map(97),
1258 doublerns_ring.canonical_gen(),
1259 doublerns_ring.pow(doublerns_ring.canonical_gen(), 15),
1260 doublerns_ring.int_hom().mul_map(doublerns_ring.canonical_gen(), 17),
1261 doublerns_ring.int_hom().mul_map(doublerns_ring.pow(doublerns_ring.canonical_gen(), 15), 17),
1262 doublerns_ring.add(doublerns_ring.canonical_gen(), doublerns_ring.one())
1263 ];
1264
1265 feanor_math::ring::generic_tests::test_hom_axioms(doublerns_ring, &ring, elements.iter().map(|x| doublerns_ring.clone_el(x)));
1266}
1267
1268#[test]
1269fn test_canonical_hom_from_singlerns() {
1270 let rns_base = zn_rns::Zn::new(vec![zn_64::Zn::new(97), zn_64::Zn::new(193)], BigIntRing::RING);
1271 let ring = ManagedDoubleRNSRingBase::new(Pow2CyclotomicNumberRing::new(16), rns_base.clone());
1272
1273 let singlerns_ring = SingleRNSRingBase::<_, _, DefaultConvolution>::new(Pow2CyclotomicNumberRing::new(16), rns_base);
1274 let elements = vec![
1275 singlerns_ring.zero(),
1276 singlerns_ring.one(),
1277 singlerns_ring.neg_one(),
1278 singlerns_ring.int_hom().map(97),
1279 singlerns_ring.int_hom().map(193),
1280 singlerns_ring.canonical_gen(),
1281 singlerns_ring.pow(singlerns_ring.canonical_gen(), 15),
1282 singlerns_ring.int_hom().mul_map(singlerns_ring.canonical_gen(), 97),
1283 singlerns_ring.int_hom().mul_map(singlerns_ring.pow(singlerns_ring.canonical_gen(), 15), 97),
1284 singlerns_ring.add(singlerns_ring.canonical_gen(), singlerns_ring.one())
1285 ];
1286
1287 feanor_math::ring::generic_tests::test_hom_axioms(&singlerns_ring, &ring, elements.iter().map(|x| singlerns_ring.clone_el(x)));
1288}
1289
1290#[test]
1291fn test_add_result_independent_of_repr() {
1292 let rns_base = zn_rns::Zn::new(vec![zn_64::Zn::new(17), zn_64::Zn::new(97)], BigIntRing::RING);
1293 let ring = ManagedDoubleRNSRingBase::new(Pow2CyclotomicNumberRing::new(4), rns_base);
1294 let base = &ring.get_ring().base;
1295 let reprs_of_11: [Box<dyn Fn() -> ManagedDoubleRNSEl<_, _>>; 4] = [
1296 Box::new(|| ring.get_ring().from_small_basis_repr(base.from_non_fft(base.base_ring().int_hom().map(11)))),
1297 Box::new(|| ring.get_ring().from_double_rns_repr(base.from(base.base_ring().int_hom().map(11)))),
1298 Box::new(|| ring.get_ring().new_element_sum(base.from_non_fft(base.base_ring().int_hom().map(10)), base.from(base.base_ring().int_hom().map(1)))),
1299 Box::new(|| ring.get_ring().new_element_both(base.from_non_fft(base.base_ring().int_hom().map(11)), base.from(base.base_ring().int_hom().map(11))))
1300 ];
1301 let reprs_of_102: [Box<dyn Fn() -> ManagedDoubleRNSEl<_, _>>; 4] = [
1302 Box::new(|| ring.get_ring().from_small_basis_repr(base.from_non_fft(base.base_ring().int_hom().map(102)))),
1303 Box::new(|| ring.get_ring().from_double_rns_repr(base.from(base.base_ring().int_hom().map(102)))),
1304 Box::new(|| ring.get_ring().new_element_sum(base.from_non_fft(base.base_ring().int_hom().map(100)), base.from(base.base_ring().int_hom().map(2)))),
1305 Box::new(|| ring.get_ring().new_element_both(base.from_non_fft(base.base_ring().int_hom().map(102)), base.from(base.base_ring().int_hom().map(102))))
1306 ];
1307 for a in &reprs_of_11 {
1308 for b in &reprs_of_102 {
1309 let x = a();
1310 assert_el_eq!(RingRef::new(base), base.from_int(22), ring.get_ring().to_doublerns(&ring.add_ref(&x, &x)).unwrap());
1311
1312 let x = a();
1313 let y = b();
1314 assert_el_eq!(RingRef::new(base), base.from_int(113), ring.get_ring().to_doublerns(&ring.add_ref(&x, &y)).unwrap());
1315
1316 let x = a();
1317 let y = b();
1318 assert!(base.eq_el_non_fft(&base.from_non_fft(base.base_ring().int_hom().map(113)), &*ring.get_ring().to_small_basis(&ring.add_ref(&x, &y)).unwrap()));
1319
1320 let x = a();
1321 let y = b();
1322 assert_el_eq!(RingRef::new(base), base.from_int(-91), ring.get_ring().to_doublerns(&ring.sub_ref(&x, &y)).unwrap());
1323
1324 let x = a();
1325 let y = b();
1326 assert!(base.eq_el_non_fft(&base.from_non_fft(base.base_ring().int_hom().map(-91)), &*ring.get_ring().to_small_basis(&ring.sub_ref(&x, &y)).unwrap()));
1327
1328 let x = a();
1329 assert_el_eq!(RingRef::new(base), base.from_int(121), ring.get_ring().to_doublerns(&ring.mul_ref(&x, &x)).unwrap());
1330
1331 let x = a();
1332 let y = b();
1333 assert_el_eq!(RingRef::new(base), base.from_int(1122), ring.get_ring().to_doublerns(&ring.mul_ref(&x, &y)).unwrap());
1334
1335 let x = a();
1336 let y = b();
1337 assert!(base.eq_el_non_fft(&base.from_non_fft(base.base_ring().int_hom().map(1122)), &*ring.get_ring().to_small_basis(&ring.mul_ref(&x, &y)).unwrap()));
1338 }
1339 }
1340}
1341
1342#[test]
1343fn test_serialization() {
1344 let (ring, elements) = ring_and_elements();
1345 feanor_math::serialization::generic_tests::test_serialization(&ring, elements.iter().map(|x| ring.clone_el(x)));
1346
1347 for a in &elements {
1348 if ring.is_zero(a) {
1349 continue;
1350 }
1351 let a_small_basis = ring.get_ring().from_small_basis_repr(ring.get_ring().unmanaged_ring().get_ring().clone_el_non_fft(ring.get_ring().to_small_basis(a).unwrap()));
1352 let serializer = serde_assert::Serializer::builder().is_human_readable(true).build();
1353 let tokens = ring.get_ring().serialize(&a_small_basis, &serializer).unwrap();
1354 let mut deserializer = serde_assert::Deserializer::builder(tokens).is_human_readable(true).build();
1355 let result = ring.get_ring().deserialize(&mut deserializer).unwrap();
1356 assert_el_eq!(ring, &a_small_basis, &result);
1357 match result.internal.get_repr() {
1358 ManagedDoubleRNSElRepresentation::SmallBasis(_) => {},
1359 _ => panic!("wrong representation")
1360 };
1361
1362 let a_small_basis = ring.get_ring().from_small_basis_repr(ring.get_ring().unmanaged_ring().get_ring().clone_el_non_fft(ring.get_ring().to_small_basis(a).unwrap()));
1363 let serializer = serde_assert::Serializer::builder().is_human_readable(false).build();
1364 let tokens = ring.get_ring().serialize(&a_small_basis, &serializer).unwrap();
1365 let mut deserializer = serde_assert::Deserializer::builder(tokens).is_human_readable(false).build();
1366 let result = ring.get_ring().deserialize(&mut deserializer).unwrap();
1367 assert_el_eq!(ring, &a_small_basis, &result);
1368 match result.internal.get_repr() {
1369 ManagedDoubleRNSElRepresentation::SmallBasis(_) => {},
1370 _ => panic!("wrong representation")
1371 };
1372
1373 let a_doublerns = ring.get_ring().from_double_rns_repr(ring.get_ring().unmanaged_ring().clone_el(ring.get_ring().to_doublerns(a).unwrap()));
1374 let serializer = serde_assert::Serializer::builder().is_human_readable(true).build();
1375 let tokens = ring.get_ring().serialize(&a_doublerns, &serializer).unwrap();
1376 let mut deserializer = serde_assert::Deserializer::builder(tokens).is_human_readable(true).build();
1377 let result = ring.get_ring().deserialize(&mut deserializer).unwrap();
1378 assert_el_eq!(ring, &a_doublerns, &result);
1379 match result.internal.get_repr() {
1380 ManagedDoubleRNSElRepresentation::SmallBasis(_) => {},
1381 _ => panic!("wrong representation")
1382 };
1383
1384 let a_doublerns = ring.get_ring().from_double_rns_repr(ring.get_ring().unmanaged_ring().clone_el(ring.get_ring().to_doublerns(a).unwrap()));
1385 let serializer = serde_assert::Serializer::builder().is_human_readable(false).build();
1386 let tokens = ring.get_ring().serialize(&a_doublerns, &serializer).unwrap();
1387 let mut deserializer = serde_assert::Deserializer::builder(tokens).is_human_readable(false).build();
1388 let result = ring.get_ring().deserialize(&mut deserializer).unwrap();
1389 assert_el_eq!(ring, &a_doublerns, &result);
1390 match result.internal.get_repr() {
1391 ManagedDoubleRNSElRepresentation::DoubleRNS(_) => {},
1392 _ => panic!("wrong representation")
1393 };
1394 }
1395}