Skip to main content

singe_cusolver/eigen/
mod.rs

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::{ByteWorkspaceMut, MatrixMut, MatrixRef, SelectionWorkspaceSizes, WorkspaceSizes},
15    params::Params,
16    types::{EigenMode, EigenType, FillMode},
17};
18
19use raw::*;
20
21pub use info::SyevjInfo;
22
23#[derive(Debug, Clone, Copy, PartialEq)]
24#[non_exhaustive]
25pub enum EigenSelection<T> {
26    All,
27    ByValue { lower: T, upper: T },
28    ByIndex { start: usize, end: usize },
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub struct Syevd {
33    pub mode: EigenMode,
34    pub fill_mode: FillMode,
35    pub n: usize,
36    pub leading_dimension: usize,
37}
38
39impl Syevd {
40    pub fn new(mode: EigenMode, fill_mode: FillMode, n: usize, leading_dimension: usize) -> Self {
41        Self {
42            mode,
43            fill_mode,
44            n,
45            leading_dimension,
46        }
47    }
48
49    pub fn workspace_size<TA: DataTypeLike, TW: DataTypeLike>(
50        self,
51        ctx: &Context,
52        params: &Params,
53        input: SyevdInput<'_, TA, TW>,
54    ) -> Result<WorkspaceSizes> {
55        xsyevd_buffer_size(
56            ctx,
57            params,
58            self.mode,
59            self.fill_mode,
60            self.n,
61            input.a,
62            self.leading_dimension,
63            input.eigenvalues,
64        )
65    }
66
67    pub fn execute<TA: DataTypeLike, TW: DataTypeLike>(
68        self,
69        ctx: &Context,
70        params: &Params,
71        bindings: SyevdBindings<'_, TA, TW>,
72    ) -> Result<()> {
73        xsyevd(
74            ctx,
75            params,
76            self.mode,
77            self.fill_mode,
78            self.n,
79            bindings.a,
80            self.leading_dimension,
81            bindings.eigenvalues,
82            bindings.workspace,
83            bindings.dev_info,
84        )
85    }
86}
87
88#[derive(Debug, Clone, Copy)]
89pub struct SyevdInput<'a, TA, TW> {
90    pub a: &'a DeviceMemory<TA>,
91    pub eigenvalues: &'a DeviceMemory<TW>,
92}
93
94#[derive(Debug)]
95pub struct SyevdBindings<'a, TA, TW> {
96    pub a: &'a mut DeviceMemory<TA>,
97    pub eigenvalues: &'a mut DeviceMemory<TW>,
98    pub workspace: ByteWorkspaceMut<'a>,
99    pub dev_info: &'a mut DeviceMemory<i32>,
100}
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
103pub struct Geev {
104    pub n: usize,
105    pub leading_dimension: usize,
106}
107
108impl Geev {
109    pub fn new(n: usize, leading_dimension: usize) -> Self {
110        Self {
111            n,
112            leading_dimension,
113        }
114    }
115
116    pub fn workspace_size<TA: DataTypeLike, TW: DataTypeLike, TV: DataTypeLike>(
117        self,
118        ctx: &Context,
119        params: &Params,
120        input: GeevInput<'_, TA, TW, TV>,
121    ) -> Result<WorkspaceSizes> {
122        xgeev_buffer_size(
123            ctx,
124            params,
125            self.n,
126            MatrixRef::new(input.a, self.leading_dimension),
127            input.eigenvalues,
128            input.right_vectors,
129        )
130    }
131
132    pub fn execute<TA: DataTypeLike, TW: DataTypeLike, TV: DataTypeLike>(
133        self,
134        ctx: &Context,
135        params: &Params,
136        bindings: GeevBindings<'_, TA, TW, TV>,
137    ) -> Result<()> {
138        xgeev(
139            ctx,
140            params,
141            self.n,
142            MatrixMut::new(bindings.a, self.leading_dimension),
143            bindings.eigenvalues,
144            bindings.right_vectors,
145            bindings.workspace,
146            bindings.dev_info,
147        )
148    }
149}
150
151#[derive(Debug, Clone, Copy)]
152pub struct GeevInput<'a, TA, TW, TV> {
153    pub a: &'a DeviceMemory<TA>,
154    pub eigenvalues: &'a DeviceMemory<TW>,
155    pub right_vectors: Option<MatrixRef<'a, TV>>,
156}
157
158#[derive(Debug)]
159pub struct GeevBindings<'a, TA, TW, TV> {
160    pub a: &'a mut DeviceMemory<TA>,
161    pub eigenvalues: &'a mut DeviceMemory<TW>,
162    pub right_vectors: Option<MatrixMut<'a, TV>>,
163    pub workspace: ByteWorkspaceMut<'a>,
164    pub dev_info: &'a mut DeviceMemory<i32>,
165}
166
167#[derive(Debug, Clone, Copy, PartialEq, Eq)]
168pub struct SyevBatched {
169    pub mode: EigenMode,
170    pub fill_mode: FillMode,
171    pub n: usize,
172    pub leading_dimension: usize,
173    pub batch_count: usize,
174}
175
176impl SyevBatched {
177    pub fn new(
178        mode: EigenMode,
179        fill_mode: FillMode,
180        n: usize,
181        leading_dimension: usize,
182        batch_count: usize,
183    ) -> Self {
184        Self {
185            mode,
186            fill_mode,
187            n,
188            leading_dimension,
189            batch_count,
190        }
191    }
192
193    pub fn workspace_size<TA: DataTypeLike, TW: DataTypeLike>(
194        self,
195        ctx: &Context,
196        params: &Params,
197        input: SyevdInput<'_, TA, TW>,
198    ) -> Result<WorkspaceSizes> {
199        xsyev_batched_buffer_size(
200            ctx,
201            params,
202            self.mode,
203            self.fill_mode,
204            self.n,
205            MatrixRef::new(input.a, self.leading_dimension),
206            input.eigenvalues,
207            self.batch_count,
208        )
209    }
210
211    pub fn execute<TA: DataTypeLike, TW: DataTypeLike>(
212        self,
213        ctx: &Context,
214        params: &Params,
215        bindings: SyevdBindings<'_, TA, TW>,
216    ) -> Result<()> {
217        xsyev_batched(
218            ctx,
219            params,
220            self.mode,
221            self.fill_mode,
222            self.n,
223            MatrixMut::new(bindings.a, self.leading_dimension),
224            bindings.eigenvalues,
225            self.batch_count,
226            bindings.workspace,
227            bindings.dev_info,
228        )
229    }
230}
231
232#[derive(Debug, Clone, Copy, PartialEq)]
233pub struct Syevdx<T> {
234    pub mode: EigenMode,
235    pub fill_mode: FillMode,
236    pub selection: EigenSelection<T>,
237    pub n: usize,
238    pub leading_dimension: usize,
239}
240
241impl<T> Syevdx<T> {
242    pub fn new(
243        mode: EigenMode,
244        fill_mode: FillMode,
245        selection: EigenSelection<T>,
246        n: usize,
247        leading_dimension: usize,
248    ) -> Self {
249        Self {
250            mode,
251            fill_mode,
252            selection,
253            n,
254            leading_dimension,
255        }
256    }
257}
258
259impl<T: Copy + Default> Syevdx<T> {
260    pub fn workspace_size<TA: DataTypeLike, TW: DataTypeLike>(
261        self,
262        ctx: &Context,
263        params: &Params,
264        input: SyevdInput<'_, TA, TW>,
265    ) -> Result<SelectionWorkspaceSizes> {
266        xsyevdx_buffer_size(
267            ctx,
268            params,
269            self.mode,
270            self.fill_mode,
271            self.selection,
272            self.n,
273            input.a,
274            self.leading_dimension,
275            input.eigenvalues,
276        )
277    }
278
279    pub fn execute<TA: DataTypeLike, TW: DataTypeLike>(
280        self,
281        ctx: &Context,
282        params: &Params,
283        bindings: SyevdBindings<'_, TA, TW>,
284    ) -> Result<usize> {
285        xsyevdx(
286            ctx,
287            params,
288            self.mode,
289            self.fill_mode,
290            self.selection,
291            self.n,
292            bindings.a,
293            self.leading_dimension,
294            bindings.eigenvalues,
295            bindings.workspace,
296            bindings.dev_info,
297        )
298    }
299}
300
301#[derive(Debug, Clone, Copy, PartialEq, Eq)]
302pub struct Syevj {
303    pub mode: EigenMode,
304    pub fill_mode: FillMode,
305    pub n: usize,
306    pub leading_dimension: usize,
307}
308
309impl Syevj {
310    pub fn new(mode: EigenMode, fill_mode: FillMode, n: usize, leading_dimension: usize) -> Self {
311        Self {
312            mode,
313            fill_mode,
314            n,
315            leading_dimension,
316        }
317    }
318
319    pub fn workspace_size_f32(
320        self,
321        ctx: &Context,
322        input: SyevjInput<'_, f32, f32>,
323        params: &SyevjInfo,
324    ) -> Result<usize> {
325        ssyevj_buffer_size(
326            ctx,
327            self.mode,
328            self.fill_mode,
329            self.n,
330            input.a,
331            self.leading_dimension,
332            input.eigenvalues,
333            params,
334        )
335    }
336
337    pub fn execute_f32(
338        self,
339        ctx: &Context,
340        bindings: SyevjBindings<'_, f32, f32>,
341        params: &SyevjInfo,
342    ) -> Result<()> {
343        ssyevj(
344            ctx,
345            self.mode,
346            self.fill_mode,
347            self.n,
348            bindings.a,
349            self.leading_dimension,
350            bindings.eigenvalues,
351            bindings.workspace,
352            bindings.dev_info,
353            params,
354        )
355    }
356
357    pub fn workspace_size_f64(
358        self,
359        ctx: &Context,
360        input: SyevjInput<'_, f64, f64>,
361        params: &SyevjInfo,
362    ) -> Result<usize> {
363        dsyevj_buffer_size(
364            ctx,
365            self.mode,
366            self.fill_mode,
367            self.n,
368            input.a,
369            self.leading_dimension,
370            input.eigenvalues,
371            params,
372        )
373    }
374
375    pub fn execute_f64(
376        self,
377        ctx: &Context,
378        bindings: SyevjBindings<'_, f64, f64>,
379        params: &SyevjInfo,
380    ) -> Result<()> {
381        dsyevj(
382            ctx,
383            self.mode,
384            self.fill_mode,
385            self.n,
386            bindings.a,
387            self.leading_dimension,
388            bindings.eigenvalues,
389            bindings.workspace,
390            bindings.dev_info,
391            params,
392        )
393    }
394
395    pub fn workspace_size_complex_f32(
396        self,
397        ctx: &Context,
398        input: SyevjInput<'_, Complex32, f32>,
399        params: &SyevjInfo,
400    ) -> Result<usize> {
401        cheevj_buffer_size(
402            ctx,
403            self.mode,
404            self.fill_mode,
405            self.n,
406            input.a,
407            self.leading_dimension,
408            input.eigenvalues,
409            params,
410        )
411    }
412
413    pub fn execute_complex_f32(
414        self,
415        ctx: &Context,
416        bindings: SyevjBindings<'_, Complex32, f32>,
417        params: &SyevjInfo,
418    ) -> Result<()> {
419        cheevj(
420            ctx,
421            self.mode,
422            self.fill_mode,
423            self.n,
424            bindings.a,
425            self.leading_dimension,
426            bindings.eigenvalues,
427            bindings.workspace,
428            bindings.dev_info,
429            params,
430        )
431    }
432
433    pub fn workspace_size_complex_f64(
434        self,
435        ctx: &Context,
436        input: SyevjInput<'_, Complex64, f64>,
437        params: &SyevjInfo,
438    ) -> Result<usize> {
439        zheevj_buffer_size(
440            ctx,
441            self.mode,
442            self.fill_mode,
443            self.n,
444            input.a,
445            self.leading_dimension,
446            input.eigenvalues,
447            params,
448        )
449    }
450
451    pub fn execute_complex_f64(
452        self,
453        ctx: &Context,
454        bindings: SyevjBindings<'_, Complex64, f64>,
455        params: &SyevjInfo,
456    ) -> Result<()> {
457        zheevj(
458            ctx,
459            self.mode,
460            self.fill_mode,
461            self.n,
462            bindings.a,
463            self.leading_dimension,
464            bindings.eigenvalues,
465            bindings.workspace,
466            bindings.dev_info,
467            params,
468        )
469    }
470}
471
472#[derive(Debug, Clone, Copy, PartialEq, Eq)]
473pub struct SyevjBatched {
474    pub mode: EigenMode,
475    pub fill_mode: FillMode,
476    pub n: usize,
477    pub leading_dimension: usize,
478    pub batch_count: usize,
479}
480
481impl SyevjBatched {
482    pub fn new(
483        mode: EigenMode,
484        fill_mode: FillMode,
485        n: usize,
486        leading_dimension: usize,
487        batch_count: usize,
488    ) -> Self {
489        Self {
490            mode,
491            fill_mode,
492            n,
493            leading_dimension,
494            batch_count,
495        }
496    }
497
498    pub fn workspace_size_f32(
499        self,
500        ctx: &Context,
501        input: SyevjInput<'_, f32, f32>,
502        params: &SyevjInfo,
503    ) -> Result<usize> {
504        ssyevj_batched_buffer_size(
505            ctx,
506            self.mode,
507            self.fill_mode,
508            self.n,
509            input.a,
510            self.leading_dimension,
511            input.eigenvalues,
512            params,
513            self.batch_count,
514        )
515    }
516
517    pub fn execute_f32(
518        self,
519        ctx: &Context,
520        bindings: SyevjBindings<'_, f32, f32>,
521        params: &SyevjInfo,
522    ) -> Result<()> {
523        ssyevj_batched(
524            ctx,
525            self.mode,
526            self.fill_mode,
527            self.n,
528            bindings.a,
529            self.leading_dimension,
530            bindings.eigenvalues,
531            bindings.workspace,
532            bindings.dev_info,
533            params,
534            self.batch_count,
535        )
536    }
537
538    pub fn workspace_size_f64(
539        self,
540        ctx: &Context,
541        input: SyevjInput<'_, f64, f64>,
542        params: &SyevjInfo,
543    ) -> Result<usize> {
544        dsyevj_batched_buffer_size(
545            ctx,
546            self.mode,
547            self.fill_mode,
548            self.n,
549            input.a,
550            self.leading_dimension,
551            input.eigenvalues,
552            params,
553            self.batch_count,
554        )
555    }
556
557    pub fn execute_f64(
558        self,
559        ctx: &Context,
560        bindings: SyevjBindings<'_, f64, f64>,
561        params: &SyevjInfo,
562    ) -> Result<()> {
563        dsyevj_batched(
564            ctx,
565            self.mode,
566            self.fill_mode,
567            self.n,
568            bindings.a,
569            self.leading_dimension,
570            bindings.eigenvalues,
571            bindings.workspace,
572            bindings.dev_info,
573            params,
574            self.batch_count,
575        )
576    }
577
578    pub fn workspace_size_complex_f32(
579        self,
580        ctx: &Context,
581        input: SyevjInput<'_, Complex32, f32>,
582        params: &SyevjInfo,
583    ) -> Result<usize> {
584        cheevj_batched_buffer_size(
585            ctx,
586            self.mode,
587            self.fill_mode,
588            self.n,
589            input.a,
590            self.leading_dimension,
591            input.eigenvalues,
592            params,
593            self.batch_count,
594        )
595    }
596
597    pub fn execute_complex_f32(
598        self,
599        ctx: &Context,
600        bindings: SyevjBindings<'_, Complex32, f32>,
601        params: &SyevjInfo,
602    ) -> Result<()> {
603        cheevj_batched(
604            ctx,
605            self.mode,
606            self.fill_mode,
607            self.n,
608            bindings.a,
609            self.leading_dimension,
610            bindings.eigenvalues,
611            bindings.workspace,
612            bindings.dev_info,
613            params,
614            self.batch_count,
615        )
616    }
617
618    pub fn workspace_size_complex_f64(
619        self,
620        ctx: &Context,
621        input: SyevjInput<'_, Complex64, f64>,
622        params: &SyevjInfo,
623    ) -> Result<usize> {
624        zheevj_batched_buffer_size(
625            ctx,
626            self.mode,
627            self.fill_mode,
628            self.n,
629            input.a,
630            self.leading_dimension,
631            input.eigenvalues,
632            params,
633            self.batch_count,
634        )
635    }
636
637    pub fn execute_complex_f64(
638        self,
639        ctx: &Context,
640        bindings: SyevjBindings<'_, Complex64, f64>,
641        params: &SyevjInfo,
642    ) -> Result<()> {
643        zheevj_batched(
644            ctx,
645            self.mode,
646            self.fill_mode,
647            self.n,
648            bindings.a,
649            self.leading_dimension,
650            bindings.eigenvalues,
651            bindings.workspace,
652            bindings.dev_info,
653            params,
654            self.batch_count,
655        )
656    }
657}
658
659#[derive(Debug, Clone, Copy)]
660pub struct SyevjInput<'a, TA, TW> {
661    pub a: &'a DeviceMemory<TA>,
662    pub eigenvalues: &'a DeviceMemory<TW>,
663}
664
665#[derive(Debug)]
666pub struct SyevjBindings<'a, TA, TW> {
667    pub a: &'a mut DeviceMemory<TA>,
668    pub eigenvalues: &'a mut DeviceMemory<TW>,
669    pub workspace: &'a mut DeviceMemory<TA>,
670    pub dev_info: &'a mut DeviceMemory<i32>,
671}
672
673#[derive(Debug, Clone, Copy, PartialEq, Eq)]
674pub struct Sygvj {
675    pub eig_type: EigenType,
676    pub mode: EigenMode,
677    pub fill_mode: FillMode,
678    pub n: usize,
679    pub leading_dimension_a: usize,
680    pub leading_dimension_b: usize,
681}
682
683impl Sygvj {
684    pub fn new(
685        eig_type: EigenType,
686        mode: EigenMode,
687        fill_mode: FillMode,
688        n: usize,
689        leading_dimension_a: usize,
690        leading_dimension_b: usize,
691    ) -> Self {
692        Self {
693            eig_type,
694            mode,
695            fill_mode,
696            n,
697            leading_dimension_a,
698            leading_dimension_b,
699        }
700    }
701
702    pub fn workspace_size_f32(
703        self,
704        ctx: &Context,
705        input: SygvInput<'_, f32, f32>,
706        params: &SyevjInfo,
707    ) -> Result<usize> {
708        ssygvj_buffer_size(
709            ctx,
710            self.eig_type,
711            self.mode,
712            self.fill_mode,
713            self.n,
714            input.a,
715            self.leading_dimension_a,
716            input.b,
717            self.leading_dimension_b,
718            input.eigenvalues,
719            params,
720        )
721    }
722
723    pub fn execute_f32(
724        self,
725        ctx: &Context,
726        bindings: SygvBindings<'_, f32, f32>,
727        params: &SyevjInfo,
728    ) -> Result<()> {
729        ssygvj(
730            ctx,
731            self.eig_type,
732            self.mode,
733            self.fill_mode,
734            self.n,
735            bindings.a,
736            self.leading_dimension_a,
737            bindings.b,
738            self.leading_dimension_b,
739            bindings.eigenvalues,
740            bindings.workspace,
741            bindings.dev_info,
742            params,
743        )
744    }
745
746    pub fn workspace_size_f64(
747        self,
748        ctx: &Context,
749        input: SygvInput<'_, f64, f64>,
750        params: &SyevjInfo,
751    ) -> Result<usize> {
752        dsygvj_buffer_size(
753            ctx,
754            self.eig_type,
755            self.mode,
756            self.fill_mode,
757            self.n,
758            input.a,
759            self.leading_dimension_a,
760            input.b,
761            self.leading_dimension_b,
762            input.eigenvalues,
763            params,
764        )
765    }
766
767    pub fn execute_f64(
768        self,
769        ctx: &Context,
770        bindings: SygvBindings<'_, f64, f64>,
771        params: &SyevjInfo,
772    ) -> Result<()> {
773        dsygvj(
774            ctx,
775            self.eig_type,
776            self.mode,
777            self.fill_mode,
778            self.n,
779            bindings.a,
780            self.leading_dimension_a,
781            bindings.b,
782            self.leading_dimension_b,
783            bindings.eigenvalues,
784            bindings.workspace,
785            bindings.dev_info,
786            params,
787        )
788    }
789
790    pub fn workspace_size_complex_f32(
791        self,
792        ctx: &Context,
793        input: SygvInput<'_, Complex32, f32>,
794        params: &SyevjInfo,
795    ) -> Result<usize> {
796        chegvj_buffer_size(
797            ctx,
798            self.eig_type,
799            self.mode,
800            self.fill_mode,
801            self.n,
802            input.a,
803            self.leading_dimension_a,
804            input.b,
805            self.leading_dimension_b,
806            input.eigenvalues,
807            params,
808        )
809    }
810
811    pub fn execute_complex_f32(
812        self,
813        ctx: &Context,
814        bindings: SygvBindings<'_, Complex32, f32>,
815        params: &SyevjInfo,
816    ) -> Result<()> {
817        chegvj(
818            ctx,
819            self.eig_type,
820            self.mode,
821            self.fill_mode,
822            self.n,
823            bindings.a,
824            self.leading_dimension_a,
825            bindings.b,
826            self.leading_dimension_b,
827            bindings.eigenvalues,
828            bindings.workspace,
829            bindings.dev_info,
830            params,
831        )
832    }
833
834    pub fn workspace_size_complex_f64(
835        self,
836        ctx: &Context,
837        input: SygvInput<'_, Complex64, f64>,
838        params: &SyevjInfo,
839    ) -> Result<usize> {
840        zhegvj_buffer_size(
841            ctx,
842            self.eig_type,
843            self.mode,
844            self.fill_mode,
845            self.n,
846            input.a,
847            self.leading_dimension_a,
848            input.b,
849            self.leading_dimension_b,
850            input.eigenvalues,
851            params,
852        )
853    }
854
855    pub fn execute_complex_f64(
856        self,
857        ctx: &Context,
858        bindings: SygvBindings<'_, Complex64, f64>,
859        params: &SyevjInfo,
860    ) -> Result<()> {
861        zhegvj(
862            ctx,
863            self.eig_type,
864            self.mode,
865            self.fill_mode,
866            self.n,
867            bindings.a,
868            self.leading_dimension_a,
869            bindings.b,
870            self.leading_dimension_b,
871            bindings.eigenvalues,
872            bindings.workspace,
873            bindings.dev_info,
874            params,
875        )
876    }
877}
878
879#[derive(Debug, Clone, Copy, PartialEq, Eq)]
880pub struct Sygvd {
881    pub eig_type: EigenType,
882    pub mode: EigenMode,
883    pub fill_mode: FillMode,
884    pub n: usize,
885    pub leading_dimension_a: usize,
886    pub leading_dimension_b: usize,
887}
888
889impl Sygvd {
890    pub fn new(
891        eig_type: EigenType,
892        mode: EigenMode,
893        fill_mode: FillMode,
894        n: usize,
895        leading_dimension_a: usize,
896        leading_dimension_b: usize,
897    ) -> Self {
898        Self {
899            eig_type,
900            mode,
901            fill_mode,
902            n,
903            leading_dimension_a,
904            leading_dimension_b,
905        }
906    }
907
908    pub fn workspace_size_f32(
909        self,
910        ctx: &Context,
911        input: SygvInput<'_, f32, f32>,
912    ) -> Result<usize> {
913        ssygvd_buffer_size(
914            ctx,
915            self.eig_type,
916            self.mode,
917            self.fill_mode,
918            self.n,
919            input.a,
920            self.leading_dimension_a,
921            input.b,
922            self.leading_dimension_b,
923            input.eigenvalues,
924        )
925    }
926
927    pub fn execute_f32(self, ctx: &Context, bindings: SygvBindings<'_, f32, f32>) -> Result<()> {
928        ssygvd(
929            ctx,
930            self.eig_type,
931            self.mode,
932            self.fill_mode,
933            self.n,
934            bindings.a,
935            self.leading_dimension_a,
936            bindings.b,
937            self.leading_dimension_b,
938            bindings.eigenvalues,
939            bindings.workspace,
940            bindings.dev_info,
941        )
942    }
943
944    pub fn workspace_size_f64(
945        self,
946        ctx: &Context,
947        input: SygvInput<'_, f64, f64>,
948    ) -> Result<usize> {
949        dsygvd_buffer_size(
950            ctx,
951            self.eig_type,
952            self.mode,
953            self.fill_mode,
954            self.n,
955            input.a,
956            self.leading_dimension_a,
957            input.b,
958            self.leading_dimension_b,
959            input.eigenvalues,
960        )
961    }
962
963    pub fn execute_f64(self, ctx: &Context, bindings: SygvBindings<'_, f64, f64>) -> Result<()> {
964        dsygvd(
965            ctx,
966            self.eig_type,
967            self.mode,
968            self.fill_mode,
969            self.n,
970            bindings.a,
971            self.leading_dimension_a,
972            bindings.b,
973            self.leading_dimension_b,
974            bindings.eigenvalues,
975            bindings.workspace,
976            bindings.dev_info,
977        )
978    }
979
980    pub fn workspace_size_complex_f32(
981        self,
982        ctx: &Context,
983        input: SygvInput<'_, Complex32, f32>,
984    ) -> Result<usize> {
985        chegvd_buffer_size(
986            ctx,
987            self.eig_type,
988            self.mode,
989            self.fill_mode,
990            self.n,
991            input.a,
992            self.leading_dimension_a,
993            input.b,
994            self.leading_dimension_b,
995            input.eigenvalues,
996        )
997    }
998
999    pub fn execute_complex_f32(
1000        self,
1001        ctx: &Context,
1002        bindings: SygvBindings<'_, Complex32, f32>,
1003    ) -> Result<()> {
1004        chegvd(
1005            ctx,
1006            self.eig_type,
1007            self.mode,
1008            self.fill_mode,
1009            self.n,
1010            bindings.a,
1011            self.leading_dimension_a,
1012            bindings.b,
1013            self.leading_dimension_b,
1014            bindings.eigenvalues,
1015            bindings.workspace,
1016            bindings.dev_info,
1017        )
1018    }
1019
1020    pub fn workspace_size_complex_f64(
1021        self,
1022        ctx: &Context,
1023        input: SygvInput<'_, Complex64, f64>,
1024    ) -> Result<usize> {
1025        zhegvd_buffer_size(
1026            ctx,
1027            self.eig_type,
1028            self.mode,
1029            self.fill_mode,
1030            self.n,
1031            input.a,
1032            self.leading_dimension_a,
1033            input.b,
1034            self.leading_dimension_b,
1035            input.eigenvalues,
1036        )
1037    }
1038
1039    pub fn execute_complex_f64(
1040        self,
1041        ctx: &Context,
1042        bindings: SygvBindings<'_, Complex64, f64>,
1043    ) -> Result<()> {
1044        zhegvd(
1045            ctx,
1046            self.eig_type,
1047            self.mode,
1048            self.fill_mode,
1049            self.n,
1050            bindings.a,
1051            self.leading_dimension_a,
1052            bindings.b,
1053            self.leading_dimension_b,
1054            bindings.eigenvalues,
1055            bindings.workspace,
1056            bindings.dev_info,
1057        )
1058    }
1059}
1060
1061#[derive(Debug, Clone, Copy, PartialEq)]
1062pub struct Sygvdx<T> {
1063    pub eig_type: EigenType,
1064    pub mode: EigenMode,
1065    pub fill_mode: FillMode,
1066    pub selection: EigenSelection<T>,
1067    pub n: usize,
1068    pub leading_dimension_a: usize,
1069    pub leading_dimension_b: usize,
1070}
1071
1072impl<T> Sygvdx<T> {
1073    pub fn new(
1074        eig_type: EigenType,
1075        mode: EigenMode,
1076        fill_mode: FillMode,
1077        selection: EigenSelection<T>,
1078        n: usize,
1079        leading_dimension_a: usize,
1080        leading_dimension_b: usize,
1081    ) -> Self {
1082        Self {
1083            eig_type,
1084            mode,
1085            fill_mode,
1086            selection,
1087            n,
1088            leading_dimension_a,
1089            leading_dimension_b,
1090        }
1091    }
1092}
1093
1094impl Sygvdx<f32> {
1095    pub fn workspace_size_f32(
1096        self,
1097        ctx: &Context,
1098        input: SygvInput<'_, f32, f32>,
1099    ) -> Result<(usize, usize)> {
1100        ssygvdx_selected_buffer_size(
1101            ctx,
1102            self.eig_type,
1103            self.mode,
1104            self.fill_mode,
1105            self.selection,
1106            self.n,
1107            input.a,
1108            self.leading_dimension_a,
1109            input.b,
1110            self.leading_dimension_b,
1111            input.eigenvalues,
1112        )
1113    }
1114
1115    pub fn execute_f32(self, ctx: &Context, bindings: SygvBindings<'_, f32, f32>) -> Result<usize> {
1116        ssygvdx_selected(
1117            ctx,
1118            self.eig_type,
1119            self.mode,
1120            self.fill_mode,
1121            self.selection,
1122            self.n,
1123            bindings.a,
1124            self.leading_dimension_a,
1125            bindings.b,
1126            self.leading_dimension_b,
1127            bindings.eigenvalues,
1128            bindings.workspace,
1129            bindings.dev_info,
1130        )
1131    }
1132
1133    pub fn workspace_size_complex_f32(
1134        self,
1135        ctx: &Context,
1136        input: SygvInput<'_, Complex32, f32>,
1137    ) -> Result<(usize, usize)> {
1138        chegvdx_selected_buffer_size(
1139            ctx,
1140            self.eig_type,
1141            self.mode,
1142            self.fill_mode,
1143            self.selection,
1144            self.n,
1145            input.a,
1146            self.leading_dimension_a,
1147            input.b,
1148            self.leading_dimension_b,
1149            input.eigenvalues,
1150        )
1151    }
1152
1153    pub fn execute_complex_f32(
1154        self,
1155        ctx: &Context,
1156        bindings: SygvBindings<'_, Complex32, f32>,
1157    ) -> Result<usize> {
1158        chegvdx_selected(
1159            ctx,
1160            self.eig_type,
1161            self.mode,
1162            self.fill_mode,
1163            self.selection,
1164            self.n,
1165            bindings.a,
1166            self.leading_dimension_a,
1167            bindings.b,
1168            self.leading_dimension_b,
1169            bindings.eigenvalues,
1170            bindings.workspace,
1171            bindings.dev_info,
1172        )
1173    }
1174}
1175
1176impl Sygvdx<f64> {
1177    pub fn workspace_size_f64(
1178        self,
1179        ctx: &Context,
1180        input: SygvInput<'_, f64, f64>,
1181    ) -> Result<(usize, usize)> {
1182        dsygvdx_selected_buffer_size(
1183            ctx,
1184            self.eig_type,
1185            self.mode,
1186            self.fill_mode,
1187            self.selection,
1188            self.n,
1189            input.a,
1190            self.leading_dimension_a,
1191            input.b,
1192            self.leading_dimension_b,
1193            input.eigenvalues,
1194        )
1195    }
1196
1197    pub fn execute_f64(self, ctx: &Context, bindings: SygvBindings<'_, f64, f64>) -> Result<usize> {
1198        dsygvdx_selected(
1199            ctx,
1200            self.eig_type,
1201            self.mode,
1202            self.fill_mode,
1203            self.selection,
1204            self.n,
1205            bindings.a,
1206            self.leading_dimension_a,
1207            bindings.b,
1208            self.leading_dimension_b,
1209            bindings.eigenvalues,
1210            bindings.workspace,
1211            bindings.dev_info,
1212        )
1213    }
1214
1215    pub fn workspace_size_complex_f64(
1216        self,
1217        ctx: &Context,
1218        input: SygvInput<'_, Complex64, f64>,
1219    ) -> Result<(usize, usize)> {
1220        zhegvdx_selected_buffer_size(
1221            ctx,
1222            self.eig_type,
1223            self.mode,
1224            self.fill_mode,
1225            self.selection,
1226            self.n,
1227            input.a,
1228            self.leading_dimension_a,
1229            input.b,
1230            self.leading_dimension_b,
1231            input.eigenvalues,
1232        )
1233    }
1234
1235    pub fn execute_complex_f64(
1236        self,
1237        ctx: &Context,
1238        bindings: SygvBindings<'_, Complex64, f64>,
1239    ) -> Result<usize> {
1240        zhegvdx_selected(
1241            ctx,
1242            self.eig_type,
1243            self.mode,
1244            self.fill_mode,
1245            self.selection,
1246            self.n,
1247            bindings.a,
1248            self.leading_dimension_a,
1249            bindings.b,
1250            self.leading_dimension_b,
1251            bindings.eigenvalues,
1252            bindings.workspace,
1253            bindings.dev_info,
1254        )
1255    }
1256}
1257
1258#[derive(Debug, Clone, Copy)]
1259pub struct SygvInput<'a, TA, TW> {
1260    pub a: &'a DeviceMemory<TA>,
1261    pub b: &'a DeviceMemory<TA>,
1262    pub eigenvalues: &'a DeviceMemory<TW>,
1263}
1264
1265#[derive(Debug)]
1266pub struct SygvBindings<'a, TA, TW> {
1267    pub a: &'a mut DeviceMemory<TA>,
1268    pub b: &'a mut DeviceMemory<TA>,
1269    pub eigenvalues: &'a mut DeviceMemory<TW>,
1270    pub workspace: &'a mut DeviceMemory<TA>,
1271    pub dev_info: &'a mut DeviceMemory<i32>,
1272}
1273
1274#[cfg(test)]
1275mod tests {
1276    use super::{EigenSelection, Geev, SyevBatched};
1277    use crate::{
1278        eigen::validation::selection_parts,
1279        types::{EigenMode, EigenRange, FillMode},
1280    };
1281
1282    #[test]
1283    fn eigen_selection_all_maps_cleanly() {
1284        let (range, values, indices) = selection_parts::<f32>(EigenSelection::All);
1285        assert_eq!(range, EigenRange::All);
1286        assert_eq!(values, None);
1287        assert_eq!(indices, None);
1288    }
1289
1290    #[test]
1291    fn eigen_selection_index_maps_cleanly() {
1292        let (range, values, indices) =
1293            selection_parts::<f64>(EigenSelection::ByIndex { start: 2, end: 5 });
1294        assert_eq!(range, EigenRange::Index);
1295        assert_eq!(values, None);
1296        assert_eq!(indices, Some((2, 5)));
1297    }
1298
1299    #[test]
1300    fn syev_batched_descriptor_preserves_operation_shape() {
1301        let op = SyevBatched::new(EigenMode::Vector, FillMode::Lower, 16, 20, 7);
1302
1303        assert_eq!(op.mode, EigenMode::Vector);
1304        assert_eq!(op.fill_mode, FillMode::Lower);
1305        assert_eq!(op.n, 16);
1306        assert_eq!(op.leading_dimension, 20);
1307        assert_eq!(op.batch_count, 7);
1308    }
1309
1310    #[test]
1311    fn geev_descriptor_preserves_operation_shape() {
1312        let op = Geev::new(12, 16);
1313
1314        assert_eq!(op.n, 12);
1315        assert_eq!(op.leading_dimension, 16);
1316    }
1317}