1use poulpy_hal::{
2 layouts::{
3 Backend, Data, FillUniform, HostDataMut, HostDataRef, MatZnx, MatZnxAtBackendMut, MatZnxAtBackendRef, MatZnxToBackendMut,
4 MatZnxToBackendRef, Module, ReaderFrom, TransferFrom, WriterTo,
5 },
6 source::Source,
7};
8use std::{
9 fmt,
10 ops::{Deref, DerefMut},
11};
12
13use crate::api::ModuleTransfer;
14use crate::layouts::{Base2K, Degree, Dnum, Dsize, GLWE, GLWEInfos, GLWEViewMut, GLWEViewRef, LWEInfos, Rank, TorusPrecision};
15
16pub trait GGSWInfos
23where
24 Self: GLWEInfos,
25{
26 fn dnum(&self) -> Dnum;
28 fn dsize(&self) -> Dsize;
30 fn ggsw_layout(&self) -> GGSWLayout {
32 GGSWLayout {
33 n: self.n(),
34 base2k: self.base2k(),
35 k: self.max_k(),
36 rank: self.rank(),
37 dnum: self.dnum(),
38 dsize: self.dsize(),
39 }
40 }
41}
42
43#[derive(PartialEq, Eq, Copy, Clone, Debug)]
45pub struct GGSWLayout {
46 pub n: Degree,
48 pub base2k: Base2K,
50 pub k: TorusPrecision,
52 pub rank: Rank,
54 pub dnum: Dnum,
56 pub dsize: Dsize,
58}
59
60impl LWEInfos for GGSWLayout {
61 fn base2k(&self) -> Base2K {
62 self.base2k
63 }
64
65 fn n(&self) -> Degree {
66 self.n
67 }
68
69 fn size(&self) -> usize {
70 self.k.as_usize().div_ceil(self.base2k.as_usize())
71 }
72}
73impl GLWEInfos for GGSWLayout {
74 fn rank(&self) -> Rank {
75 self.rank
76 }
77}
78
79impl GGSWInfos for GGSWLayout {
80 fn dsize(&self) -> Dsize {
81 self.dsize
82 }
83
84 fn dnum(&self) -> Dnum {
85 self.dnum
86 }
87}
88
89#[derive(PartialEq, Eq, Clone)]
97pub struct GGSW<D: Data> {
98 pub(crate) data: MatZnx<D>,
99 pub(crate) base2k: Base2K,
100 pub(crate) dsize: Dsize,
101}
102
103pub struct GGSWBackendRef<'a, BE: Backend + 'a> {
104 inner: GGSW<BE::BufRef<'a>>,
105}
106
107impl<'a, BE: Backend + 'a> GGSWBackendRef<'a, BE> {
108 pub fn from_inner(inner: GGSW<BE::BufRef<'a>>) -> Self {
109 Self { inner }
110 }
111
112 pub fn into_inner(self) -> GGSW<BE::BufRef<'a>> {
113 self.inner
114 }
115
116 pub fn at_view(&self, row: usize, col: usize) -> GLWEViewRef<'_, BE> {
117 GLWEViewRef::from_inner(ggsw_at_backend_ref_from_ref::<BE>(&self.inner, row, col))
118 }
119}
120
121impl<'a, BE: Backend + 'a> Deref for GGSWBackendRef<'a, BE> {
122 type Target = GGSW<BE::BufRef<'a>>;
123
124 fn deref(&self) -> &Self::Target {
125 &self.inner
126 }
127}
128
129pub struct GGSWBackendMut<'a, BE: Backend + 'a> {
130 inner: GGSW<BE::BufMut<'a>>,
131}
132
133impl<'a, BE: Backend + 'a> GGSWBackendMut<'a, BE> {
134 pub fn from_inner(inner: GGSW<BE::BufMut<'a>>) -> Self {
135 Self { inner }
136 }
137
138 pub fn into_inner(self) -> GGSW<BE::BufMut<'a>> {
139 self.inner
140 }
141
142 pub fn at_view(&self, row: usize, col: usize) -> GLWEViewRef<'_, BE> {
143 GLWEViewRef::from_inner(ggsw_at_backend_ref_from_mut::<BE>(&self.inner, row, col))
144 }
145
146 pub fn at_view_mut(&mut self, row: usize, col: usize) -> GLWEViewMut<'_, BE> {
147 GLWEViewMut::from_inner(ggsw_at_backend_mut_from_mut::<BE>(&mut self.inner, row, col))
148 }
149}
150
151impl<'a, BE: Backend + 'a> Deref for GGSWBackendMut<'a, BE> {
152 type Target = GGSW<BE::BufMut<'a>>;
153
154 fn deref(&self) -> &Self::Target {
155 &self.inner
156 }
157}
158
159impl<'a, BE: Backend + 'a> DerefMut for GGSWBackendMut<'a, BE> {
160 fn deref_mut(&mut self) -> &mut Self::Target {
161 &mut self.inner
162 }
163}
164
165impl<'a, BE: Backend + 'a> LWEInfos for GGSWBackendRef<'a, BE> {
166 fn base2k(&self) -> Base2K {
167 self.inner.base2k()
168 }
169
170 fn n(&self) -> Degree {
171 self.inner.n()
172 }
173
174 fn size(&self) -> usize {
175 self.inner.size()
176 }
177}
178
179impl<'a, BE: Backend + 'a> GLWEInfos for GGSWBackendRef<'a, BE> {
180 fn rank(&self) -> Rank {
181 self.inner.rank()
182 }
183}
184
185impl<'a, BE: Backend + 'a> GGSWInfos for GGSWBackendRef<'a, BE> {
186 fn dnum(&self) -> Dnum {
187 self.inner.dnum()
188 }
189
190 fn dsize(&self) -> Dsize {
191 self.inner.dsize()
192 }
193}
194
195impl<'a, BE: Backend + 'a> LWEInfos for GGSWBackendMut<'a, BE> {
196 fn base2k(&self) -> Base2K {
197 self.inner.base2k()
198 }
199
200 fn n(&self) -> Degree {
201 self.inner.n()
202 }
203
204 fn size(&self) -> usize {
205 self.inner.size()
206 }
207}
208
209impl<'a, BE: Backend + 'a> GLWEInfos for GGSWBackendMut<'a, BE> {
210 fn rank(&self) -> Rank {
211 self.inner.rank()
212 }
213}
214
215impl<'a, BE: Backend + 'a> GGSWInfos for GGSWBackendMut<'a, BE> {
216 fn dnum(&self) -> Dnum {
217 self.inner.dnum()
218 }
219
220 fn dsize(&self) -> Dsize {
221 self.inner.dsize()
222 }
223}
224
225impl<'a, BE: Backend + 'a> GGSWToBackendRef<BE> for GGSWBackendRef<'a, BE> {
226 fn to_backend_ref(&self) -> GGSWBackendRef<'_, BE> {
227 GGSWBackendRef::from_inner(GGSW {
228 dsize: self.inner.dsize,
229 base2k: self.inner.base2k,
230 data: poulpy_hal::layouts::mat_znx_backend_ref_from_ref::<BE>(&self.inner.data),
231 })
232 }
233}
234
235impl<'a, BE: Backend + 'a> GGSWToBackendRef<BE> for GGSWBackendMut<'a, BE> {
236 fn to_backend_ref(&self) -> GGSWBackendRef<'_, BE> {
237 GGSWBackendRef::from_inner(GGSW {
238 dsize: self.inner.dsize,
239 base2k: self.inner.base2k,
240 data: poulpy_hal::layouts::mat_znx_backend_ref_from_mut::<BE>(&self.inner.data),
241 })
242 }
243}
244
245impl<'a, BE: Backend + 'a> GGSWToBackendMut<BE> for GGSWBackendMut<'a, BE> {
246 fn to_backend_mut(&mut self) -> GGSWBackendMut<'_, BE> {
247 GGSWBackendMut::from_inner(GGSW {
248 dsize: self.inner.dsize,
249 base2k: self.inner.base2k,
250 data: poulpy_hal::layouts::mat_znx_backend_mut_from_mut::<BE>(&mut self.inner.data),
251 })
252 }
253}
254
255impl<'a, BE: Backend + 'a> GGSWAtViewRef<BE> for GGSWBackendRef<'a, BE> {
256 fn at_view(&self, row: usize, col: usize) -> GLWEViewRef<'_, BE> {
257 GGSWBackendRef::at_view(self, row, col)
258 }
259}
260
261impl<'a, BE: Backend + 'a> GGSWAtViewRef<BE> for GGSWBackendMut<'a, BE> {
262 fn at_view(&self, row: usize, col: usize) -> GLWEViewRef<'_, BE> {
263 GGSWBackendMut::at_view(self, row, col)
264 }
265}
266
267impl<'a, BE: Backend + 'a> GGSWAtViewRef<BE> for &GGSWBackendRef<'a, BE> {
268 fn at_view(&self, row: usize, col: usize) -> GLWEViewRef<'_, BE> {
269 GGSWBackendRef::at_view(self, row, col)
270 }
271}
272
273impl<D: Data> LWEInfos for GGSW<D> {
274 fn n(&self) -> Degree {
275 Degree(self.data.n() as u32)
276 }
277
278 fn base2k(&self) -> Base2K {
279 self.base2k
280 }
281
282 fn size(&self) -> usize {
283 self.data.size()
284 }
285}
286
287impl<D: Data> LWEInfos for &GGSW<D> {
288 fn n(&self) -> Degree {
289 Degree(self.data.n() as u32)
290 }
291
292 fn base2k(&self) -> Base2K {
293 self.base2k
294 }
295
296 fn size(&self) -> usize {
297 self.data.size()
298 }
299}
300
301impl<D: Data> GLWEInfos for GGSW<D> {
302 fn rank(&self) -> Rank {
303 Rank(self.data.cols_out() as u32 - 1)
304 }
305}
306
307impl<D: Data> GLWEInfos for &GGSW<D> {
308 fn rank(&self) -> Rank {
309 Rank(self.data.cols_out() as u32 - 1)
310 }
311}
312
313impl<D: Data> GGSWInfos for GGSW<D> {
314 fn dsize(&self) -> Dsize {
315 self.dsize
316 }
317
318 fn dnum(&self) -> Dnum {
319 Dnum(self.data.rows() as u32)
320 }
321}
322
323impl<D: Data> GGSWInfos for &GGSW<D> {
324 fn dsize(&self) -> Dsize {
325 self.dsize
326 }
327
328 fn dnum(&self) -> Dnum {
329 Dnum(self.data.rows() as u32)
330 }
331}
332
333impl<D: HostDataRef> fmt::Debug for GGSW<D> {
334 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
335 write!(f, "{}", self.data)
336 }
337}
338
339impl<D: HostDataRef> fmt::Display for GGSW<D> {
340 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341 write!(
342 f,
343 "(GGSW: k: {} base2k: {} dsize: {}) {}",
344 self.max_k().0,
345 self.base2k().0,
346 self.dsize().0,
347 self.data
348 )
349 }
350}
351
352impl<D: HostDataMut> FillUniform for GGSW<D> {
353 fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
354 self.data.fill_uniform(log_bound, source);
355 }
356}
357
358impl<D: HostDataRef> GGSW<D> {
359 pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> {
360 let data = self.data.at(row, col);
361 GLWE {
362 base2k: self.base2k,
363 data,
364 }
365 }
366}
367
368pub(crate) trait GGSWAtBackendRef<BE: Backend> {
369 fn at_backend(&self, row: usize, col: usize) -> GLWE<BE::BufRef<'_>>;
370}
371
372impl<BE: Backend> GGSWAtBackendRef<BE> for GGSW<BE::OwnedBuf> {
373 fn at_backend(&self, row: usize, col: usize) -> GLWE<BE::BufRef<'_>> {
374 let data = <MatZnx<BE::OwnedBuf> as MatZnxAtBackendRef<BE>>::at_backend(&self.data, row, col);
375 GLWE {
376 base2k: self.base2k,
377 data,
378 }
379 }
380}
381
382pub(crate) fn ggsw_at_backend_ref_from_ref<'a, 'b, BE: Backend>(
383 ggsw: &'a GGSW<BE::BufRef<'b>>,
384 row: usize,
385 col: usize,
386) -> GLWE<BE::BufRef<'a>> {
387 let data = poulpy_hal::layouts::mat_znx_at_backend_ref_from_ref::<BE>(&ggsw.data, row, col);
388 GLWE {
389 base2k: ggsw.base2k,
390 data,
391 }
392}
393
394pub trait GGSWAtViewRef<BE: Backend> {
395 fn at_view(&self, row: usize, col: usize) -> GLWEViewRef<'_, BE>;
396}
397
398impl<BE: Backend> GGSWAtViewRef<BE> for GGSW<BE::OwnedBuf> {
399 fn at_view(&self, row: usize, col: usize) -> GLWEViewRef<'_, BE> {
400 GLWEViewRef::from_inner(<GGSW<BE::OwnedBuf> as GGSWAtBackendRef<BE>>::at_backend(self, row, col))
401 }
402}
403
404impl<'b, BE: Backend + 'b> GGSWAtViewRef<BE> for &GGSW<BE::BufRef<'b>> {
405 fn at_view(&self, row: usize, col: usize) -> GLWEViewRef<'_, BE> {
406 GLWEViewRef::from_inner(ggsw_at_backend_ref_from_ref::<BE>(self, row, col))
407 }
408}
409
410pub(crate) fn ggsw_at_backend_ref_from_mut<'a, 'b, BE: Backend>(
411 ggsw: &'a GGSW<BE::BufMut<'b>>,
412 row: usize,
413 col: usize,
414) -> GLWE<BE::BufRef<'a>> {
415 let data = poulpy_hal::layouts::mat_znx_at_backend_ref_from_mut::<BE>(&ggsw.data, row, col);
416 GLWE {
417 base2k: ggsw.base2k,
418 data,
419 }
420}
421
422impl<D: HostDataMut> GGSW<D> {
423 pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> {
424 let base2k = self.base2k;
425 let data = self.data.at_mut(row, col);
426 GLWE { base2k, data }
427 }
428}
429
430pub(crate) trait GGSWAtBackendMut<BE: Backend> {
431 fn at_backend_mut(&mut self, row: usize, col: usize) -> GLWE<BE::BufMut<'_>>;
432}
433
434impl<BE: Backend> GGSWAtBackendMut<BE> for GGSW<BE::OwnedBuf> {
435 fn at_backend_mut(&mut self, row: usize, col: usize) -> GLWE<BE::BufMut<'_>> {
436 let base2k = self.base2k;
437 let data = <MatZnx<BE::OwnedBuf> as MatZnxAtBackendMut<BE>>::at_backend_mut(&mut self.data, row, col);
438 GLWE { base2k, data }
439 }
440}
441
442pub(crate) fn ggsw_at_backend_mut_from_mut<'a, 'b, BE: Backend>(
443 ggsw: &'a mut GGSW<BE::BufMut<'b>>,
444 row: usize,
445 col: usize,
446) -> GLWE<BE::BufMut<'a>> {
447 let base2k = ggsw.base2k;
448 let data = poulpy_hal::layouts::mat_znx_at_backend_mut_from_mut::<BE>(&mut ggsw.data, row, col);
449 GLWE { base2k, data }
450}
451
452pub trait GGSWAtViewMut<BE: Backend> {
453 fn at_view_mut(&mut self, row: usize, col: usize) -> GLWEViewMut<'_, BE>;
454}
455
456impl<BE: Backend> GGSWAtViewMut<BE> for GGSW<BE::OwnedBuf> {
457 fn at_view_mut(&mut self, row: usize, col: usize) -> GLWEViewMut<'_, BE> {
458 GLWEViewMut::from_inner(<GGSW<BE::OwnedBuf> as GGSWAtBackendMut<BE>>::at_backend_mut(self, row, col))
459 }
460}
461
462impl<'b, BE: Backend + 'b> GGSWAtViewMut<BE> for &mut GGSW<BE::BufMut<'b>> {
463 fn at_view_mut(&mut self, row: usize, col: usize) -> GLWEViewMut<'_, BE> {
464 GLWEViewMut::from_inner(ggsw_at_backend_mut_from_mut::<BE>(*self, row, col))
465 }
466}
467
468impl<'a, BE: Backend + 'a> GGSWAtViewMut<BE> for GGSWBackendMut<'a, BE> {
469 fn at_view_mut(&mut self, row: usize, col: usize) -> GLWEViewMut<'_, BE> {
470 GGSWBackendMut::at_view_mut(self, row, col)
471 }
472}
473
474impl<D: HostDataRef> GGSW<D> {
475 pub fn to_backend<BE, To>(&self, dst: &Module<To>) -> GGSW<To::OwnedBuf>
478 where
479 BE: Backend<OwnedBuf = D>,
480 To: Backend,
481 To: TransferFrom<BE>,
482 {
483 dst.upload_ggsw(self)
484 }
485}
486
487impl<D: Data> GGSW<D> {
488 pub fn reinterpret<To>(self) -> GGSW<To::OwnedBuf>
490 where
491 To: Backend<OwnedBuf = D>,
492 {
493 let (n, rows, cols_in, cols_out, size) = (
494 self.data.n(),
495 self.data.rows(),
496 self.data.cols_in(),
497 self.data.cols_out(),
498 self.data.size(),
499 );
500 GGSW {
501 data: MatZnx::from_data(self.data.into_data(), n, rows, cols_in, cols_out, size),
502 base2k: self.base2k,
503 dsize: self.dsize,
504 }
505 }
506}
507
508#[expect(
509 dead_code,
510 reason = "host-owned constructors are kept for serialization and host-only staging"
511)]
512impl GGSW<Vec<u8>> {
513 pub(crate) fn alloc_from_infos<A>(infos: &A) -> Self
514 where
515 A: GGSWInfos,
516 {
517 Self::alloc(
518 infos.n(),
519 infos.base2k(),
520 infos.max_k(),
521 infos.rank(),
522 infos.dnum(),
523 infos.dsize(),
524 )
525 }
526
527 pub(crate) fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
528 let size: usize = k.0.div_ceil(base2k.0) as usize;
529 assert!(
530 size as u32 > dsize.0,
531 "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
532 dsize.0
533 );
534
535 assert!(
536 dnum.0 * dsize.0 <= size as u32,
537 "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
538 dnum.0,
539 dsize.0,
540 );
541
542 GGSW {
543 data: MatZnx::from_data(
544 poulpy_hal::layouts::HostBytesBackend::alloc_bytes(MatZnx::<Vec<u8>>::bytes_of(
545 n.into(),
546 dnum.into(),
547 (rank + 1).into(),
548 (rank + 1).into(),
549 size,
550 )),
551 n.into(),
552 dnum.into(),
553 (rank + 1).into(),
554 (rank + 1).into(),
555 size,
556 ),
557 base2k,
558 dsize,
559 }
560 }
561
562 pub fn bytes_of_from_infos<A>(infos: &A) -> usize
563 where
564 A: GGSWInfos,
565 {
566 Self::bytes_of(
567 infos.n(),
568 infos.base2k(),
569 infos.max_k(),
570 infos.rank(),
571 infos.dnum(),
572 infos.dsize(),
573 )
574 }
575
576 pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
577 let size: usize = k.0.div_ceil(base2k.0) as usize;
578 assert!(
579 size as u32 > dsize.0,
580 "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
581 dsize.0
582 );
583
584 assert!(
585 dnum.0 * dsize.0 <= size as u32,
586 "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
587 dnum.0,
588 dsize.0,
589 );
590
591 MatZnx::bytes_of(
592 n.into(),
593 dnum.into(),
594 (rank + 1).into(),
595 (rank + 1).into(),
596 k.0.div_ceil(base2k.0) as usize,
597 )
598 }
599}
600
601use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
602
603impl<D: HostDataMut> ReaderFrom for GGSW<D> {
604 fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
605 self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
606 self.dsize = Dsize(reader.read_u32::<LittleEndian>()?);
607 self.data.read_from(reader)
608 }
609}
610
611impl<D: HostDataRef> WriterTo for GGSW<D> {
612 fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
613 writer.write_u32::<LittleEndian>(self.base2k.into())?;
614 writer.write_u32::<LittleEndian>(self.dsize.into())?;
615 self.data.write_to(writer)
616 }
617}
618
619pub trait GGSWToBackendMut<BE: Backend>: GGSWToBackendRef<BE> {
620 fn to_backend_mut(&mut self) -> GGSWBackendMut<'_, BE>;
621}
622
623impl<BE: Backend, D: Data> GGSWToBackendMut<BE> for GGSW<D>
624where
625 MatZnx<D>: MatZnxToBackendRef<BE> + MatZnxToBackendMut<BE>,
626{
627 fn to_backend_mut(&mut self) -> GGSWBackendMut<'_, BE> {
628 GGSWBackendMut::from_inner(GGSW {
629 dsize: self.dsize,
630 base2k: self.base2k,
631 data: self.data.to_backend_mut(),
632 })
633 }
634}
635
636impl<'b, BE: Backend + 'b> GGSWToBackendRef<BE> for &mut GGSW<BE::BufMut<'b>> {
637 fn to_backend_ref(&self) -> GGSWBackendRef<'_, BE> {
638 GGSWBackendRef::from_inner(GGSW {
639 dsize: self.dsize,
640 base2k: self.base2k,
641 data: poulpy_hal::layouts::mat_znx_backend_ref_from_mut::<BE>(&self.data),
642 })
643 }
644}
645
646impl<'b, BE: Backend + 'b> GGSWToBackendMut<BE> for &mut GGSW<BE::BufMut<'b>> {
647 fn to_backend_mut(&mut self) -> GGSWBackendMut<'_, BE> {
648 ggsw_backend_mut_from_mut::<BE>(self)
649 }
650}
651
652pub fn ggsw_backend_mut_from_mut<'a, 'b, BE: Backend>(ggsw: &'a mut GGSW<BE::BufMut<'b>>) -> GGSWBackendMut<'a, BE> {
653 GGSWBackendMut::from_inner(GGSW {
654 dsize: ggsw.dsize,
655 base2k: ggsw.base2k,
656 data: poulpy_hal::layouts::mat_znx_backend_mut_from_mut::<BE>(&mut ggsw.data),
657 })
658}
659
660pub struct GGSWBackendRowViewMut<'a, BE: Backend + 'a> {
664 inner: GGSWBackendMut<'a, BE>,
665}
666
667impl<'a, BE: Backend + 'a> GGSWBackendRowViewMut<'a, BE> {
668 pub fn from_inner(inner: GGSWBackendMut<'a, BE>) -> Self {
669 Self { inner }
670 }
671}
672
673impl<'a, BE: Backend + 'a> LWEInfos for GGSWBackendRowViewMut<'a, BE> {
674 fn base2k(&self) -> Base2K {
675 self.inner.base2k()
676 }
677 fn n(&self) -> Degree {
678 self.inner.n()
679 }
680 fn size(&self) -> usize {
681 self.inner.size()
682 }
683}
684
685impl<'a, BE: Backend + 'a> GLWEInfos for GGSWBackendRowViewMut<'a, BE> {
686 fn rank(&self) -> Rank {
687 self.inner.rank()
688 }
689}
690
691impl<'a, BE: Backend + 'a> GGSWInfos for GGSWBackendRowViewMut<'a, BE> {
692 fn dnum(&self) -> Dnum {
693 self.inner.dnum()
694 }
695 fn dsize(&self) -> Dsize {
696 self.inner.dsize()
697 }
698}
699
700impl<'a, BE: Backend + 'a> GGSWToBackendRef<BE> for GGSWBackendRowViewMut<'a, BE> {
701 fn to_backend_ref(&self) -> GGSWBackendRef<'_, BE> {
702 self.inner.to_backend_ref()
703 }
704}
705
706impl<'a, BE: Backend + 'a> GGSWToBackendMut<BE> for GGSWBackendRowViewMut<'a, BE> {
707 fn to_backend_mut(&mut self) -> GGSWBackendMut<'_, BE> {
708 GGSWBackendMut::from_inner(GGSW {
709 dsize: self.inner.inner.dsize,
710 base2k: self.inner.inner.base2k,
711 data: poulpy_hal::layouts::mat_znx_backend_mut_from_mut::<BE>(&mut self.inner.inner.data),
712 })
713 }
714}
715
716impl<'a, BE: Backend + 'a> GGSWAtViewRef<BE> for GGSWBackendRowViewMut<'a, BE> {
717 fn at_view(&self, row: usize, col: usize) -> GLWEViewRef<'_, BE> {
718 self.inner.at_view(row, col)
719 }
720}
721
722impl<'a, BE: Backend + 'a> GGSWAtViewMut<BE> for GGSWBackendRowViewMut<'a, BE> {
723 fn at_view_mut(&mut self, row: usize, col: usize) -> GLWEViewMut<'_, BE> {
724 self.inner.at_view_mut(row, col)
725 }
726}
727
728pub trait GGSWToBackendRef<BE: Backend> {
729 fn to_backend_ref(&self) -> GGSWBackendRef<'_, BE>;
730}
731
732impl<BE: Backend, D: Data> GGSWToBackendRef<BE> for GGSW<D>
733where
734 MatZnx<D>: MatZnxToBackendRef<BE>,
735{
736 fn to_backend_ref(&self) -> GGSWBackendRef<'_, BE> {
737 GGSWBackendRef::from_inner(GGSW {
738 dsize: self.dsize,
739 base2k: self.base2k,
740 data: self.data.to_backend_ref(),
741 })
742 }
743}