1mod info;
2mod raw;
3mod validation;
4
5use singe_cuda::{
6 data_type::DataTypeLike,
7 memory::DeviceMemory,
8 types::{Complex32, Complex64},
9};
10
11use crate::{
12 context::Context,
13 error::Result,
14 layout::{
15 ByteWorkspaceMut, MatrixMut, MatrixRef, StridedBatchedMatrixMut, StridedBatchedMatrixRef,
16 StridedBatchedVectorMut, StridedBatchedVectorRef, WorkspaceSizes,
17 },
18 params::Params,
19 types::{EigenMode, SvdMode, TruncatedSvdMode},
20};
21
22use raw::*;
23
24pub use info::GesvdjInfo;
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct Gesvd {
28 pub job_u: SvdMode,
29 pub job_vt: SvdMode,
30 pub rows: usize,
31 pub columns: usize,
32}
33
34impl Gesvd {
35 pub fn new(job_u: SvdMode, job_vt: SvdMode, rows: usize, columns: usize) -> Self {
36 Self {
37 job_u,
38 job_vt,
39 rows,
40 columns,
41 }
42 }
43
44 pub fn workspace_size<
45 TA: DataTypeLike,
46 TS: DataTypeLike,
47 TU: DataTypeLike,
48 TVT: DataTypeLike,
49 >(
50 self,
51 ctx: &Context,
52 params: &Params,
53 input: GesvdInput<'_, TA, TS, TU, TVT>,
54 ) -> Result<WorkspaceSizes> {
55 xgesvd_buffer_size(
56 ctx,
57 params,
58 self.job_u,
59 self.job_vt,
60 self.rows,
61 self.columns,
62 input.a,
63 input.singular_values,
64 input.left_vectors,
65 input.right_vectors_transposed,
66 )
67 }
68
69 pub fn execute<TA: DataTypeLike, TS: DataTypeLike, TU: DataTypeLike, TVT: DataTypeLike>(
70 self,
71 ctx: &Context,
72 params: &Params,
73 bindings: GesvdBindings<'_, TA, TS, TU, TVT>,
74 ) -> Result<()> {
75 xgesvd(
76 ctx,
77 params,
78 self.job_u,
79 self.job_vt,
80 self.rows,
81 self.columns,
82 bindings.a,
83 bindings.singular_values,
84 bindings.left_vectors,
85 bindings.right_vectors_transposed,
86 bindings.workspace,
87 bindings.dev_info,
88 )
89 }
90}
91
92#[derive(Debug, Clone, Copy)]
93pub struct GesvdInput<'a, TA, TS, TU, TVT> {
94 pub a: MatrixRef<'a, TA>,
95 pub singular_values: &'a DeviceMemory<TS>,
96 pub left_vectors: Option<MatrixRef<'a, TU>>,
97 pub right_vectors_transposed: Option<MatrixRef<'a, TVT>>,
98}
99
100#[derive(Debug)]
101pub struct GesvdBindings<'a, TA, TS, TU, TVT> {
102 pub a: MatrixMut<'a, TA>,
103 pub singular_values: &'a mut DeviceMemory<TS>,
104 pub left_vectors: Option<MatrixMut<'a, TU>>,
105 pub right_vectors_transposed: Option<MatrixMut<'a, TVT>>,
106 pub workspace: ByteWorkspaceMut<'a>,
107 pub dev_info: &'a mut DeviceMemory<i32>,
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub struct Gesvdp {
112 pub mode: EigenMode,
113 pub economy: bool,
114 pub rows: usize,
115 pub columns: usize,
116}
117
118impl Gesvdp {
119 pub fn new(mode: EigenMode, economy: bool, rows: usize, columns: usize) -> Self {
120 Self {
121 mode,
122 economy,
123 rows,
124 columns,
125 }
126 }
127
128 pub fn workspace_size<
129 TA: DataTypeLike,
130 TS: DataTypeLike,
131 TU: DataTypeLike,
132 TV: DataTypeLike,
133 >(
134 self,
135 ctx: &Context,
136 params: &Params,
137 input: GesvdpInput<'_, TA, TS, TU, TV>,
138 ) -> Result<WorkspaceSizes> {
139 xgesvdp_buffer_size(
140 ctx,
141 params,
142 self.mode,
143 self.economy,
144 self.rows,
145 self.columns,
146 input.a,
147 input.singular_values,
148 input.left_vectors,
149 input.right_vectors,
150 )
151 }
152
153 pub fn execute<TA: DataTypeLike, TS: DataTypeLike, TU: DataTypeLike, TV: DataTypeLike>(
154 self,
155 ctx: &Context,
156 params: &Params,
157 bindings: GesvdpBindings<'_, TA, TS, TU, TV>,
158 ) -> Result<()> {
159 xgesvdp(
160 ctx,
161 params,
162 self.mode,
163 self.economy,
164 self.rows,
165 self.columns,
166 bindings.a,
167 bindings.singular_values,
168 bindings.left_vectors,
169 bindings.right_vectors,
170 bindings.workspace,
171 bindings.dev_info,
172 bindings.residual,
173 )
174 }
175}
176
177#[derive(Debug, Clone, Copy)]
178pub struct GesvdpInput<'a, TA, TS, TU, TV> {
179 pub a: MatrixRef<'a, TA>,
180 pub singular_values: &'a DeviceMemory<TS>,
181 pub left_vectors: Option<MatrixRef<'a, TU>>,
182 pub right_vectors: Option<MatrixRef<'a, TV>>,
183}
184
185#[derive(Debug)]
186pub struct GesvdpBindings<'a, TA, TS, TU, TV> {
187 pub a: MatrixMut<'a, TA>,
188 pub singular_values: &'a mut DeviceMemory<TS>,
189 pub left_vectors: Option<MatrixMut<'a, TU>>,
190 pub right_vectors: Option<MatrixMut<'a, TV>>,
191 pub workspace: ByteWorkspaceMut<'a>,
192 pub dev_info: &'a mut DeviceMemory<i32>,
193 pub residual: Option<&'a mut f64>,
194}
195
196#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197pub struct Gesvdr {
198 pub left_vectors: TruncatedSvdMode,
199 pub right_vectors: TruncatedSvdMode,
200 pub rows: usize,
201 pub columns: usize,
202 pub rank: usize,
203 pub oversamples: usize,
204 pub iterations: usize,
205}
206
207impl Gesvdr {
208 pub fn new(
209 left_vectors: TruncatedSvdMode,
210 right_vectors: TruncatedSvdMode,
211 rows: usize,
212 columns: usize,
213 rank: usize,
214 oversamples: usize,
215 iterations: usize,
216 ) -> Self {
217 Self {
218 left_vectors,
219 right_vectors,
220 rows,
221 columns,
222 rank,
223 oversamples,
224 iterations,
225 }
226 }
227
228 pub fn workspace_size<
229 TA: DataTypeLike,
230 TS: DataTypeLike,
231 TU: DataTypeLike,
232 TV: DataTypeLike,
233 >(
234 self,
235 ctx: &Context,
236 params: &Params,
237 input: GesvdrInput<'_, TA, TS, TU, TV>,
238 ) -> Result<WorkspaceSizes> {
239 xgesvdr_buffer_size(
240 ctx,
241 params,
242 self.left_vectors,
243 self.right_vectors,
244 self.rows,
245 self.columns,
246 self.rank,
247 self.oversamples,
248 self.iterations,
249 input.a,
250 input.singular_values,
251 input.left_vectors,
252 input.right_vectors,
253 )
254 }
255
256 pub fn execute<TA: DataTypeLike, TS: DataTypeLike, TU: DataTypeLike, TV: DataTypeLike>(
257 self,
258 ctx: &Context,
259 params: &Params,
260 bindings: GesvdrBindings<'_, TA, TS, TU, TV>,
261 ) -> Result<()> {
262 xgesvdr(
263 ctx,
264 params,
265 self.left_vectors,
266 self.right_vectors,
267 self.rows,
268 self.columns,
269 self.rank,
270 self.oversamples,
271 self.iterations,
272 bindings.a,
273 bindings.singular_values,
274 bindings.left_vectors,
275 bindings.right_vectors,
276 bindings.workspace,
277 bindings.dev_info,
278 )
279 }
280}
281
282#[derive(Debug, Clone, Copy)]
283pub struct GesvdrInput<'a, TA, TS, TU, TV> {
284 pub a: MatrixRef<'a, TA>,
285 pub singular_values: &'a DeviceMemory<TS>,
286 pub left_vectors: Option<MatrixRef<'a, TU>>,
287 pub right_vectors: Option<MatrixRef<'a, TV>>,
288}
289
290#[derive(Debug)]
291pub struct GesvdrBindings<'a, TA, TS, TU, TV> {
292 pub a: MatrixMut<'a, TA>,
293 pub singular_values: &'a mut DeviceMemory<TS>,
294 pub left_vectors: Option<MatrixMut<'a, TU>>,
295 pub right_vectors: Option<MatrixMut<'a, TV>>,
296 pub workspace: ByteWorkspaceMut<'a>,
297 pub dev_info: &'a mut DeviceMemory<i32>,
298}
299
300#[derive(Debug, Clone, Copy, PartialEq, Eq)]
301pub struct Gesvdj {
302 pub mode: EigenMode,
303 pub economy: bool,
304 pub rows: usize,
305 pub columns: usize,
306}
307
308impl Gesvdj {
309 pub fn new(mode: EigenMode, economy: bool, rows: usize, columns: usize) -> Self {
310 Self {
311 mode,
312 economy,
313 rows,
314 columns,
315 }
316 }
317
318 pub fn workspace_size_f32(
319 self,
320 ctx: &Context,
321 input: GesvdjInput<'_, f32, f32>,
322 params: &GesvdjInfo,
323 ) -> Result<usize> {
324 sgesvdj_buffer_size(
325 ctx,
326 self.mode,
327 self.economy,
328 self.rows,
329 self.columns,
330 input.a,
331 input.singular_values,
332 input.left_vectors,
333 input.right_vectors,
334 params,
335 )
336 }
337
338 pub fn execute_f32(
339 self,
340 ctx: &Context,
341 bindings: GesvdjBindings<'_, f32, f32>,
342 params: &GesvdjInfo,
343 ) -> Result<()> {
344 sgesvdj(
345 ctx,
346 self.mode,
347 self.economy,
348 self.rows,
349 self.columns,
350 bindings.a,
351 bindings.singular_values,
352 bindings.left_vectors,
353 bindings.right_vectors,
354 bindings.workspace,
355 bindings.dev_info,
356 params,
357 )
358 }
359
360 pub fn workspace_size_f64(
361 self,
362 ctx: &Context,
363 input: GesvdjInput<'_, f64, f64>,
364 params: &GesvdjInfo,
365 ) -> Result<usize> {
366 dgesvdj_buffer_size(
367 ctx,
368 self.mode,
369 self.economy,
370 self.rows,
371 self.columns,
372 input.a,
373 input.singular_values,
374 input.left_vectors,
375 input.right_vectors,
376 params,
377 )
378 }
379
380 pub fn execute_f64(
381 self,
382 ctx: &Context,
383 bindings: GesvdjBindings<'_, f64, f64>,
384 params: &GesvdjInfo,
385 ) -> Result<()> {
386 dgesvdj(
387 ctx,
388 self.mode,
389 self.economy,
390 self.rows,
391 self.columns,
392 bindings.a,
393 bindings.singular_values,
394 bindings.left_vectors,
395 bindings.right_vectors,
396 bindings.workspace,
397 bindings.dev_info,
398 params,
399 )
400 }
401
402 pub fn workspace_size_complex_f32(
403 self,
404 ctx: &Context,
405 input: GesvdjInput<'_, Complex32, f32>,
406 params: &GesvdjInfo,
407 ) -> Result<usize> {
408 cgesvdj_buffer_size(
409 ctx,
410 self.mode,
411 self.economy,
412 self.rows,
413 self.columns,
414 input.a,
415 input.singular_values,
416 input.left_vectors,
417 input.right_vectors,
418 params,
419 )
420 }
421
422 pub fn execute_complex_f32(
423 self,
424 ctx: &Context,
425 bindings: GesvdjBindings<'_, Complex32, f32>,
426 params: &GesvdjInfo,
427 ) -> Result<()> {
428 cgesvdj(
429 ctx,
430 self.mode,
431 self.economy,
432 self.rows,
433 self.columns,
434 bindings.a,
435 bindings.singular_values,
436 bindings.left_vectors,
437 bindings.right_vectors,
438 bindings.workspace,
439 bindings.dev_info,
440 params,
441 )
442 }
443
444 pub fn workspace_size_complex_f64(
445 self,
446 ctx: &Context,
447 input: GesvdjInput<'_, Complex64, f64>,
448 params: &GesvdjInfo,
449 ) -> Result<usize> {
450 zgesvdj_buffer_size(
451 ctx,
452 self.mode,
453 self.economy,
454 self.rows,
455 self.columns,
456 input.a,
457 input.singular_values,
458 input.left_vectors,
459 input.right_vectors,
460 params,
461 )
462 }
463
464 pub fn execute_complex_f64(
465 self,
466 ctx: &Context,
467 bindings: GesvdjBindings<'_, Complex64, f64>,
468 params: &GesvdjInfo,
469 ) -> Result<()> {
470 zgesvdj(
471 ctx,
472 self.mode,
473 self.economy,
474 self.rows,
475 self.columns,
476 bindings.a,
477 bindings.singular_values,
478 bindings.left_vectors,
479 bindings.right_vectors,
480 bindings.workspace,
481 bindings.dev_info,
482 params,
483 )
484 }
485}
486
487#[derive(Debug, Clone, Copy)]
488pub struct GesvdjInput<'a, TA, TS> {
489 pub a: MatrixRef<'a, TA>,
490 pub singular_values: &'a DeviceMemory<TS>,
491 pub left_vectors: Option<MatrixRef<'a, TA>>,
492 pub right_vectors: Option<MatrixRef<'a, TA>>,
493}
494
495#[derive(Debug)]
496pub struct GesvdjBindings<'a, TA, TS> {
497 pub a: MatrixMut<'a, TA>,
498 pub singular_values: &'a mut DeviceMemory<TS>,
499 pub left_vectors: Option<MatrixMut<'a, TA>>,
500 pub right_vectors: Option<MatrixMut<'a, TA>>,
501 pub workspace: &'a mut DeviceMemory<TA>,
502 pub dev_info: &'a mut DeviceMemory<i32>,
503}
504
505#[derive(Debug, Clone, Copy, PartialEq, Eq)]
506pub struct GesvdjBatched {
507 pub mode: EigenMode,
508 pub rows: usize,
509 pub columns: usize,
510 pub batch_size: usize,
511}
512
513impl GesvdjBatched {
514 pub fn new(mode: EigenMode, rows: usize, columns: usize, batch_size: usize) -> Self {
515 Self {
516 mode,
517 rows,
518 columns,
519 batch_size,
520 }
521 }
522
523 pub fn workspace_size_f32(
524 self,
525 ctx: &Context,
526 input: GesvdjInput<'_, f32, f32>,
527 params: &GesvdjInfo,
528 ) -> Result<usize> {
529 sgesvdj_batched_buffer_size(
530 ctx,
531 self.mode,
532 self.rows,
533 self.columns,
534 input.a,
535 input.singular_values,
536 input.left_vectors,
537 input.right_vectors,
538 params,
539 self.batch_size,
540 )
541 }
542
543 pub fn execute_f32(
544 self,
545 ctx: &Context,
546 bindings: GesvdjBindings<'_, f32, f32>,
547 params: &GesvdjInfo,
548 ) -> Result<()> {
549 sgesvdj_batched(
550 ctx,
551 self.mode,
552 self.rows,
553 self.columns,
554 bindings.a,
555 bindings.singular_values,
556 bindings.left_vectors,
557 bindings.right_vectors,
558 bindings.workspace,
559 bindings.dev_info,
560 params,
561 self.batch_size,
562 )
563 }
564
565 pub fn workspace_size_f64(
566 self,
567 ctx: &Context,
568 input: GesvdjInput<'_, f64, f64>,
569 params: &GesvdjInfo,
570 ) -> Result<usize> {
571 dgesvdj_batched_buffer_size(
572 ctx,
573 self.mode,
574 self.rows,
575 self.columns,
576 input.a,
577 input.singular_values,
578 input.left_vectors,
579 input.right_vectors,
580 params,
581 self.batch_size,
582 )
583 }
584
585 pub fn execute_f64(
586 self,
587 ctx: &Context,
588 bindings: GesvdjBindings<'_, f64, f64>,
589 params: &GesvdjInfo,
590 ) -> Result<()> {
591 dgesvdj_batched(
592 ctx,
593 self.mode,
594 self.rows,
595 self.columns,
596 bindings.a,
597 bindings.singular_values,
598 bindings.left_vectors,
599 bindings.right_vectors,
600 bindings.workspace,
601 bindings.dev_info,
602 params,
603 self.batch_size,
604 )
605 }
606
607 pub fn workspace_size_complex_f32(
608 self,
609 ctx: &Context,
610 input: GesvdjInput<'_, Complex32, f32>,
611 params: &GesvdjInfo,
612 ) -> Result<usize> {
613 cgesvdj_batched_buffer_size(
614 ctx,
615 self.mode,
616 self.rows,
617 self.columns,
618 input.a,
619 input.singular_values,
620 input.left_vectors,
621 input.right_vectors,
622 params,
623 self.batch_size,
624 )
625 }
626
627 pub fn execute_complex_f32(
628 self,
629 ctx: &Context,
630 bindings: GesvdjBindings<'_, Complex32, f32>,
631 params: &GesvdjInfo,
632 ) -> Result<()> {
633 cgesvdj_batched(
634 ctx,
635 self.mode,
636 self.rows,
637 self.columns,
638 bindings.a,
639 bindings.singular_values,
640 bindings.left_vectors,
641 bindings.right_vectors,
642 bindings.workspace,
643 bindings.dev_info,
644 params,
645 self.batch_size,
646 )
647 }
648
649 pub fn workspace_size_complex_f64(
650 self,
651 ctx: &Context,
652 input: GesvdjInput<'_, Complex64, f64>,
653 params: &GesvdjInfo,
654 ) -> Result<usize> {
655 zgesvdj_batched_buffer_size(
656 ctx,
657 self.mode,
658 self.rows,
659 self.columns,
660 input.a,
661 input.singular_values,
662 input.left_vectors,
663 input.right_vectors,
664 params,
665 self.batch_size,
666 )
667 }
668
669 pub fn execute_complex_f64(
670 self,
671 ctx: &Context,
672 bindings: GesvdjBindings<'_, Complex64, f64>,
673 params: &GesvdjInfo,
674 ) -> Result<()> {
675 zgesvdj_batched(
676 ctx,
677 self.mode,
678 self.rows,
679 self.columns,
680 bindings.a,
681 bindings.singular_values,
682 bindings.left_vectors,
683 bindings.right_vectors,
684 bindings.workspace,
685 bindings.dev_info,
686 params,
687 self.batch_size,
688 )
689 }
690}
691
692#[derive(Debug, Clone, Copy, PartialEq, Eq)]
693pub struct GesvdaStridedBatched {
694 pub mode: EigenMode,
695 pub rank: usize,
696 pub rows: usize,
697 pub columns: usize,
698 pub batch_size: usize,
699}
700
701impl GesvdaStridedBatched {
702 pub fn new(
703 mode: EigenMode,
704 rank: usize,
705 rows: usize,
706 columns: usize,
707 batch_size: usize,
708 ) -> Self {
709 Self {
710 mode,
711 rank,
712 rows,
713 columns,
714 batch_size,
715 }
716 }
717
718 pub fn workspace_size_f32(
719 self,
720 ctx: &Context,
721 input: GesvdaStridedBatchedInput<'_, f32, f32>,
722 ) -> Result<usize> {
723 sgesvda_strided_batched_buffer_size(
724 ctx,
725 self.mode,
726 self.rank,
727 self.rows,
728 self.columns,
729 input.a,
730 input.singular_values,
731 input.left_vectors,
732 input.right_vectors,
733 self.batch_size,
734 )
735 }
736
737 pub fn execute_f32(
738 self,
739 ctx: &Context,
740 bindings: GesvdaStridedBatchedBindings<'_, f32, f32>,
741 ) -> Result<()> {
742 sgesvda_strided_batched(
743 ctx,
744 self.mode,
745 self.rank,
746 self.rows,
747 self.columns,
748 bindings.a,
749 bindings.singular_values,
750 bindings.left_vectors,
751 bindings.right_vectors,
752 bindings.workspace,
753 bindings.dev_info,
754 bindings.residual,
755 self.batch_size,
756 )
757 }
758
759 pub fn workspace_size_f64(
760 self,
761 ctx: &Context,
762 input: GesvdaStridedBatchedInput<'_, f64, f64>,
763 ) -> Result<usize> {
764 dgesvda_strided_batched_buffer_size(
765 ctx,
766 self.mode,
767 self.rank,
768 self.rows,
769 self.columns,
770 input.a,
771 input.singular_values,
772 input.left_vectors,
773 input.right_vectors,
774 self.batch_size,
775 )
776 }
777
778 pub fn execute_f64(
779 self,
780 ctx: &Context,
781 bindings: GesvdaStridedBatchedBindings<'_, f64, f64>,
782 ) -> Result<()> {
783 dgesvda_strided_batched(
784 ctx,
785 self.mode,
786 self.rank,
787 self.rows,
788 self.columns,
789 bindings.a,
790 bindings.singular_values,
791 bindings.left_vectors,
792 bindings.right_vectors,
793 bindings.workspace,
794 bindings.dev_info,
795 bindings.residual,
796 self.batch_size,
797 )
798 }
799
800 pub fn workspace_size_complex_f32(
801 self,
802 ctx: &Context,
803 input: GesvdaStridedBatchedInput<'_, Complex32, f32>,
804 ) -> Result<usize> {
805 cgesvda_strided_batched_buffer_size(
806 ctx,
807 self.mode,
808 self.rank,
809 self.rows,
810 self.columns,
811 input.a,
812 input.singular_values,
813 input.left_vectors,
814 input.right_vectors,
815 self.batch_size,
816 )
817 }
818
819 pub fn execute_complex_f32(
820 self,
821 ctx: &Context,
822 bindings: GesvdaStridedBatchedBindings<'_, Complex32, f32>,
823 ) -> Result<()> {
824 cgesvda_strided_batched(
825 ctx,
826 self.mode,
827 self.rank,
828 self.rows,
829 self.columns,
830 bindings.a,
831 bindings.singular_values,
832 bindings.left_vectors,
833 bindings.right_vectors,
834 bindings.workspace,
835 bindings.dev_info,
836 bindings.residual,
837 self.batch_size,
838 )
839 }
840
841 pub fn workspace_size_complex_f64(
842 self,
843 ctx: &Context,
844 input: GesvdaStridedBatchedInput<'_, Complex64, f64>,
845 ) -> Result<usize> {
846 zgesvda_strided_batched_buffer_size(
847 ctx,
848 self.mode,
849 self.rank,
850 self.rows,
851 self.columns,
852 input.a,
853 input.singular_values,
854 input.left_vectors,
855 input.right_vectors,
856 self.batch_size,
857 )
858 }
859
860 pub fn execute_complex_f64(
861 self,
862 ctx: &Context,
863 bindings: GesvdaStridedBatchedBindings<'_, Complex64, f64>,
864 ) -> Result<()> {
865 zgesvda_strided_batched(
866 ctx,
867 self.mode,
868 self.rank,
869 self.rows,
870 self.columns,
871 bindings.a,
872 bindings.singular_values,
873 bindings.left_vectors,
874 bindings.right_vectors,
875 bindings.workspace,
876 bindings.dev_info,
877 bindings.residual,
878 self.batch_size,
879 )
880 }
881}
882
883#[derive(Debug, Clone, Copy)]
884pub struct GesvdaStridedBatchedInput<'a, TA, TS> {
885 pub a: StridedBatchedMatrixRef<'a, TA>,
886 pub singular_values: StridedBatchedVectorRef<'a, TS>,
887 pub left_vectors: Option<StridedBatchedMatrixRef<'a, TA>>,
888 pub right_vectors: Option<StridedBatchedMatrixRef<'a, TA>>,
889}
890
891#[derive(Debug)]
892pub struct GesvdaStridedBatchedBindings<'a, TA, TS> {
893 pub a: StridedBatchedMatrixRef<'a, TA>,
894 pub singular_values: StridedBatchedVectorMut<'a, TS>,
895 pub left_vectors: Option<StridedBatchedMatrixMut<'a, TA>>,
896 pub right_vectors: Option<StridedBatchedMatrixMut<'a, TA>>,
897 pub workspace: &'a mut DeviceMemory<TA>,
898 pub dev_info: &'a mut DeviceMemory<i32>,
899 pub residual: Option<&'a mut f64>,
900}
901
902#[cfg(all(test, feature = "testing"))]
903mod tests {
904 use singe_core::assert_close;
905 use singe_cuda::memory::DeviceMemory;
906
907 use super::*;
908 use crate::{params::Params, testing::setup_context_if_available};
909
910 #[test]
911 fn gesvd_descriptor_returns_expected_singular_values() -> Result<()> {
912 let Some(ctx) = setup_context_if_available()? else {
913 return Ok(());
914 };
915 let params = Params::create()?;
916
917 let mut a = DeviceMemory::from_slice(&[
918 3.0_f32, 0.0, 0.0, 2.0,
920 ])?;
921 let mut s = DeviceMemory::<f32>::create(2)?;
922 let operation = Gesvd::new(SvdMode::None, SvdMode::None, 2, 2);
923 let workspace_sizes = operation.workspace_size(
924 &ctx,
925 ¶ms,
926 GesvdInput {
927 a: MatrixRef::new(&a, 2),
928 singular_values: &s,
929 left_vectors: None::<MatrixRef<'_, f32>>,
930 right_vectors_transposed: None::<MatrixRef<'_, f32>>,
931 },
932 )?;
933 let mut workspace = DeviceMemory::<u8>::create(workspace_sizes.device_bytes)?;
934 let mut host_workspace = vec![0_u8; workspace_sizes.host_bytes];
935 let mut dev_info = DeviceMemory::create(1)?;
936
937 operation.execute(
938 &ctx,
939 ¶ms,
940 GesvdBindings {
941 a: MatrixMut::new(&mut a, 2),
942 singular_values: &mut s,
943 left_vectors: None::<MatrixMut<'_, f32>>,
944 right_vectors_transposed: None::<MatrixMut<'_, f32>>,
945 workspace: ByteWorkspaceMut::new(&mut workspace, &mut host_workspace),
946 dev_info: &mut dev_info,
947 },
948 )?;
949
950 let singular_values = s.copy_to_host_vec()?;
951 let info = dev_info.copy_to_host_vec()?;
952
953 assert_eq!(info, vec![0]);
954 assert_close!(&singular_values, &[3.0, 2.0], 1.0e-5);
955 Ok(())
956 }
957
958 #[test]
959 fn gesvdp_descriptor_preserves_operation_shape() {
960 let operation = Gesvdp::new(EigenMode::Vector, true, 32, 16);
961
962 assert_eq!(operation.mode, EigenMode::Vector);
963 assert!(operation.economy);
964 assert_eq!(operation.rows, 32);
965 assert_eq!(operation.columns, 16);
966 }
967
968 #[test]
969 fn gesvdr_descriptor_preserves_operation_shape() {
970 let operation = Gesvdr::new(
971 TruncatedSvdMode::Some,
972 TruncatedSvdMode::None,
973 128,
974 64,
975 12,
976 24,
977 3,
978 );
979
980 assert_eq!(operation.left_vectors, TruncatedSvdMode::Some);
981 assert_eq!(operation.right_vectors, TruncatedSvdMode::None);
982 assert_eq!(operation.rows, 128);
983 assert_eq!(operation.columns, 64);
984 assert_eq!(operation.rank, 12);
985 assert_eq!(operation.oversamples, 24);
986 assert_eq!(operation.iterations, 3);
987 }
988
989 #[test]
990 fn test_xgesvd_returns_expected_singular_values() -> Result<()> {
991 let Some(ctx) = setup_context_if_available()? else {
992 return Ok(());
993 };
994 let params = Params::create()?;
995
996 let mut a = DeviceMemory::from_slice(&[
997 3.0_f32, 0.0, 0.0, 2.0,
999 ])?;
1000 let mut s = DeviceMemory::create(2)?;
1001 let workspace_sizes = xgesvd_buffer_size::<f32, f32, f32, f32>(
1002 &ctx,
1003 ¶ms,
1004 SvdMode::None,
1005 SvdMode::None,
1006 2,
1007 2,
1008 MatrixRef::new(&a, 2),
1009 &s,
1010 None,
1011 None,
1012 )?;
1013 let mut device_workspace = DeviceMemory::create(workspace_sizes.device_bytes.max(1))?;
1014 let mut host_workspace = vec![0_u8; workspace_sizes.host_bytes.max(1)];
1015 let mut dev_info = DeviceMemory::create(1)?;
1016
1017 xgesvd::<f32, f32, f32, f32>(
1018 &ctx,
1019 ¶ms,
1020 SvdMode::None,
1021 SvdMode::None,
1022 2,
1023 2,
1024 MatrixMut::new(&mut a, 2),
1025 &mut s,
1026 None,
1027 None,
1028 ByteWorkspaceMut::new(&mut device_workspace, &mut host_workspace),
1029 &mut dev_info,
1030 )?;
1031
1032 let singular_values = s.copy_to_host_vec()?;
1033 let info = dev_info.copy_to_host_vec()?;
1034
1035 assert_eq!(info, vec![0]);
1036 assert_close!(&singular_values, &[3.0, 2.0], 1.0e-5);
1037 Ok(())
1038 }
1039}