1#[allow(unused_imports)]
2use crate::error::Status;
3
4use std::{mem::size_of, ptr};
5
6use singe_cuda::{
7 data_type::{DataType, DataTypeLike},
8 memory::DeviceMemory,
9 types::{Complex32, Complex64},
10};
11
12use crate::{
13 context::Context,
14 error::{Error, Result},
15 layout::{ByteWorkspaceMut, MatrixMut, MatrixRef, SelectionWorkspaceSizes, WorkspaceSizes},
16 params::Params,
17 sys, try_ffi,
18 types::{EigenMode, EigenRange, EigenType, FillMode},
19 utility::{to_i32, to_i64, to_usize},
20};
21
22#[derive(Debug, Clone, Copy, PartialEq)]
23pub enum EigenSelection<T> {
24 All,
25 ByValue { lower: T, upper: T },
26 ByIndex { start: usize, end: usize },
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub struct Syevd {
31 pub mode: EigenMode,
32 pub fill_mode: FillMode,
33 pub n: usize,
34 pub leading_dimension: usize,
35}
36
37impl Syevd {
38 pub fn new(mode: EigenMode, fill_mode: FillMode, n: usize, leading_dimension: usize) -> Self {
39 Self {
40 mode,
41 fill_mode,
42 n,
43 leading_dimension,
44 }
45 }
46
47 pub fn workspace_size<TA: DataTypeLike, TW: DataTypeLike>(
48 self,
49 ctx: &Context,
50 params: &Params,
51 input: SyevdInput<'_, TA, TW>,
52 ) -> Result<WorkspaceSizes> {
53 xsyevd_buffer_size(
54 ctx,
55 params,
56 self.mode,
57 self.fill_mode,
58 self.n,
59 input.a,
60 self.leading_dimension,
61 input.eigenvalues,
62 )
63 }
64
65 pub fn execute<TA: DataTypeLike, TW: DataTypeLike>(
66 self,
67 ctx: &Context,
68 params: &Params,
69 bindings: SyevdBindings<'_, TA, TW>,
70 ) -> Result<()> {
71 xsyevd(
72 ctx,
73 params,
74 self.mode,
75 self.fill_mode,
76 self.n,
77 bindings.a,
78 self.leading_dimension,
79 bindings.eigenvalues,
80 bindings.workspace,
81 bindings.dev_info,
82 )
83 }
84}
85
86#[derive(Debug, Clone, Copy)]
87pub struct SyevdInput<'a, TA, TW> {
88 pub a: &'a DeviceMemory<TA>,
89 pub eigenvalues: &'a DeviceMemory<TW>,
90}
91
92#[derive(Debug)]
93pub struct SyevdBindings<'a, TA, TW> {
94 pub a: &'a mut DeviceMemory<TA>,
95 pub eigenvalues: &'a mut DeviceMemory<TW>,
96 pub workspace: ByteWorkspaceMut<'a>,
97 pub dev_info: &'a mut DeviceMemory<i32>,
98}
99
100#[derive(Debug, Clone, Copy, PartialEq)]
101pub struct Syevdx<T> {
102 pub mode: EigenMode,
103 pub fill_mode: FillMode,
104 pub selection: EigenSelection<T>,
105 pub n: usize,
106 pub leading_dimension: usize,
107}
108
109impl<T> Syevdx<T> {
110 pub fn new(
111 mode: EigenMode,
112 fill_mode: FillMode,
113 selection: EigenSelection<T>,
114 n: usize,
115 leading_dimension: usize,
116 ) -> Self {
117 Self {
118 mode,
119 fill_mode,
120 selection,
121 n,
122 leading_dimension,
123 }
124 }
125}
126
127impl<T: Copy + Default> Syevdx<T> {
128 pub fn workspace_size<TA: DataTypeLike, TW: DataTypeLike>(
129 self,
130 ctx: &Context,
131 params: &Params,
132 input: SyevdInput<'_, TA, TW>,
133 ) -> Result<SelectionWorkspaceSizes> {
134 xsyevdx_buffer_size(
135 ctx,
136 params,
137 self.mode,
138 self.fill_mode,
139 self.selection,
140 self.n,
141 input.a,
142 self.leading_dimension,
143 input.eigenvalues,
144 )
145 }
146
147 pub fn execute<TA: DataTypeLike, TW: DataTypeLike>(
148 self,
149 ctx: &Context,
150 params: &Params,
151 bindings: SyevdBindings<'_, TA, TW>,
152 ) -> Result<usize> {
153 xsyevdx(
154 ctx,
155 params,
156 self.mode,
157 self.fill_mode,
158 self.selection,
159 self.n,
160 bindings.a,
161 self.leading_dimension,
162 bindings.eigenvalues,
163 bindings.workspace,
164 bindings.dev_info,
165 )
166 }
167}
168
169#[derive(Debug)]
170pub struct SyevjInfo {
171 handle: sys::syevjInfo_t,
172}
173
174unsafe impl Send for SyevjInfo {}
177unsafe impl Sync for SyevjInfo {}
178
179impl SyevjInfo {
180 pub fn create() -> Result<Self> {
190 let mut handle = ptr::null_mut();
191 unsafe {
192 try_ffi!(sys::cusolverDnCreateSyevjInfo(&raw mut handle))?;
193 }
194
195 if handle.is_null() {
196 return Err(Error::NullHandle);
197 }
198
199 Ok(Self { handle })
200 }
201
202 pub fn set_tolerance(&mut self, tolerance: f64) -> Result<()> {
208 unsafe {
209 try_ffi!(sys::cusolverDnXsyevjSetTolerance(self.as_raw(), tolerance,))?;
210 }
211 Ok(())
212 }
213
214 pub fn set_max_sweeps(&mut self, max_sweeps: i32) -> Result<()> {
221 unsafe {
222 try_ffi!(sys::cusolverDnXsyevjSetMaxSweeps(self.as_raw(), max_sweeps,))?;
223 }
224 Ok(())
225 }
226
227 pub fn set_sort_eigenvalues(&mut self, sort_eigenvalues: bool) -> Result<()> {
236 unsafe {
237 try_ffi!(sys::cusolverDnXsyevjSetSortEig(
238 self.as_raw(),
239 i32::from(sort_eigenvalues),
240 ))?;
241 }
242 Ok(())
243 }
244
245 pub fn residual(&self, ctx: &Context) -> Result<f64> {
254 ctx.bind()?;
255
256 let mut residual = 0.0;
257 unsafe {
258 try_ffi!(sys::cusolverDnXsyevjGetResidual(
259 ctx.as_raw(),
260 self.as_raw(),
261 &raw mut residual,
262 ))?;
263 }
264 Ok(residual)
265 }
266
267 pub fn executed_sweeps(&self, ctx: &Context) -> Result<i32> {
276 ctx.bind()?;
277
278 let mut sweeps = 0;
279 unsafe {
280 try_ffi!(sys::cusolverDnXsyevjGetSweeps(
281 ctx.as_raw(),
282 self.as_raw(),
283 &raw mut sweeps,
284 ))?;
285 }
286 Ok(sweeps)
287 }
288
289 pub fn as_raw(&self) -> sys::syevjInfo_t {
290 self.handle
291 }
292}
293
294impl Drop for SyevjInfo {
295 fn drop(&mut self) {
296 unsafe {
297 if let Err(err) = try_ffi!(sys::cusolverDnDestroySyevjInfo(self.handle)) {
298 #[cfg(debug_assertions)]
299 eprintln!("failed to destroy cusolver syevj info: {err}");
300 }
301 }
302 }
303}
304
305pub fn xsyevd_buffer_size<TA: DataTypeLike, TW: DataTypeLike>(
306 ctx: &Context,
307 params: &Params,
308 mode: EigenMode,
309 fill_mode: FillMode,
310 n: usize,
311 a: &DeviceMemory<TA>,
312 lda: usize,
313 w: &DeviceMemory<TW>,
314) -> Result<WorkspaceSizes> {
315 xsyevd_raw_buffer_size(
316 ctx,
317 params,
318 mode,
319 fill_mode,
320 n,
321 TA::data_type(),
322 a,
323 lda,
324 TW::data_type(),
325 w,
326 TA::data_type(),
327 )
328}
329
330pub fn xsyevd<TA: DataTypeLike, TW: DataTypeLike>(
331 ctx: &Context,
332 params: &Params,
333 mode: EigenMode,
334 fill_mode: FillMode,
335 n: usize,
336 a: &mut DeviceMemory<TA>,
337 lda: usize,
338 w: &mut DeviceMemory<TW>,
339 workspace: ByteWorkspaceMut<'_>,
340 dev_info: &mut DeviceMemory<i32>,
341) -> Result<()> {
342 xsyevd_raw(
343 ctx,
344 params,
345 mode,
346 fill_mode,
347 n,
348 TA::data_type(),
349 a,
350 lda,
351 TW::data_type(),
352 w,
353 TA::data_type(),
354 workspace,
355 dev_info,
356 )
357}
358
359pub fn xsyevdx_buffer_size<TA: DataTypeLike, TR: Copy + Default, TW: DataTypeLike>(
360 ctx: &Context,
361 params: &Params,
362 mode: EigenMode,
363 fill_mode: FillMode,
364 selection: EigenSelection<TR>,
365 n: usize,
366 a: &DeviceMemory<TA>,
367 lda: usize,
368 w: &DeviceMemory<TW>,
369) -> Result<SelectionWorkspaceSizes> {
370 let (range, value_range, index_range) = selection_parts(selection);
371 xsyevdx_raw_buffer_size(
372 ctx,
373 params,
374 mode,
375 range,
376 fill_mode,
377 n,
378 TA::data_type(),
379 a,
380 lda,
381 value_range,
382 index_range,
383 TW::data_type(),
384 w,
385 TA::data_type(),
386 )
387}
388
389pub fn xsyevdx<TA: DataTypeLike, TR: Copy + Default, TW: DataTypeLike>(
390 ctx: &Context,
391 params: &Params,
392 mode: EigenMode,
393 fill_mode: FillMode,
394 selection: EigenSelection<TR>,
395 n: usize,
396 a: &mut DeviceMemory<TA>,
397 lda: usize,
398 w: &mut DeviceMemory<TW>,
399 workspace: ByteWorkspaceMut<'_>,
400 dev_info: &mut DeviceMemory<i32>,
401) -> Result<usize> {
402 let (range, value_range, index_range) = selection_parts(selection);
403 xsyevdx_raw(
404 ctx,
405 params,
406 mode,
407 range,
408 fill_mode,
409 n,
410 TA::data_type(),
411 a,
412 lda,
413 value_range,
414 index_range,
415 TW::data_type(),
416 w,
417 TA::data_type(),
418 workspace,
419 dev_info,
420 )
421}
422
423pub fn xsyev_batched_buffer_size<TA: DataTypeLike, TW: DataTypeLike>(
424 ctx: &Context,
425 params: &Params,
426 mode: EigenMode,
427 fill_mode: FillMode,
428 n: usize,
429 a: MatrixRef<'_, TA>,
430 w: &DeviceMemory<TW>,
431 batch_count: usize,
432) -> Result<WorkspaceSizes> {
433 ctx.bind()?;
434 validate_xsyev_batched_buffers(
435 n,
436 a.data.byte_len(),
437 a.leading_dimension,
438 TA::data_type(),
439 w.byte_len(),
440 TW::data_type(),
441 batch_count,
442 )?;
443 let mut device_bytes = 0;
444 let mut host_bytes = 0;
445 unsafe {
446 try_ffi!(sys::cusolverDnXsyevBatched_bufferSize(
447 ctx.as_raw(),
448 params.as_raw(),
449 mode.into(),
450 fill_mode.into(),
451 to_i64(n, "n")?,
452 TA::data_type().into(),
453 a.data.as_ptr().cast(),
454 to_i64(a.leading_dimension, "lda")?,
455 TW::data_type().into(),
456 w.as_ptr().cast(),
457 TA::data_type().into(),
458 &raw mut device_bytes,
459 &raw mut host_bytes,
460 to_i64(batch_count, "batch_count")?,
461 ))?;
462 }
463 Ok(WorkspaceSizes::new(
464 device_bytes as usize,
465 host_bytes as usize,
466 ))
467}
468
469pub fn xsyev_batched<TA: DataTypeLike, TW: DataTypeLike>(
527 ctx: &Context,
528 params: &Params,
529 mode: EigenMode,
530 fill_mode: FillMode,
531 n: usize,
532 a: MatrixMut<'_, TA>,
533 w: &mut DeviceMemory<TW>,
534 batch_count: usize,
535 workspace: ByteWorkspaceMut<'_>,
536 dev_info: &mut DeviceMemory<i32>,
537) -> Result<()> {
538 ctx.bind()?;
539 validate_xsyev_batched_buffers(
540 n,
541 a.data.byte_len(),
542 a.leading_dimension,
543 TA::data_type(),
544 w.byte_len(),
545 TW::data_type(),
546 batch_count,
547 )?;
548 require_info_buffer_len(dev_info, batch_count)?;
549 let workspace_sizes =
550 xsyev_batched_buffer_size(ctx, params, mode, fill_mode, n, a.as_ref(), w, batch_count)?;
551 require_workspace_bytes(workspace.device.byte_len(), workspace_sizes.device_bytes)?;
552 require_host_workspace(workspace.host.len(), workspace_sizes.host_bytes)?;
553 unsafe {
554 try_ffi!(sys::cusolverDnXsyevBatched(
555 ctx.as_raw(),
556 params.as_raw(),
557 mode.into(),
558 fill_mode.into(),
559 to_i64(n, "n")?,
560 TA::data_type().into(),
561 a.data.as_mut_ptr().cast(),
562 to_i64(a.leading_dimension, "lda")?,
563 TW::data_type().into(),
564 w.as_mut_ptr().cast(),
565 TA::data_type().into(),
566 workspace.device.as_mut_ptr().cast(),
567 workspace_sizes.device_bytes as _,
568 workspace.host.as_mut_ptr().cast(),
569 workspace_sizes.host_bytes as _,
570 dev_info.as_mut_ptr().cast(),
571 to_i64(batch_count, "batch_count")?,
572 ))?;
573 }
574 Ok(())
575}
576
577pub fn xgeev_buffer_size<TA: DataTypeLike, TW: DataTypeLike, TV: DataTypeLike>(
578 ctx: &Context,
579 params: &Params,
580 n: usize,
581 a: MatrixRef<'_, TA>,
582 eigenvalues: &DeviceMemory<TW>,
583 right_vectors: Option<MatrixRef<'_, TV>>,
584) -> Result<WorkspaceSizes> {
585 ctx.bind()?;
586 validate_xgeev_inputs(
587 n,
588 a.data.byte_len(),
589 a.leading_dimension,
590 TA::data_type(),
591 eigenvalues.byte_len(),
592 TW::data_type(),
593 matrix_ref_parts(right_vectors),
594 TV::data_type(),
595 )?;
596 let (vr_ptr, ldvr) = optional_xgeev_matrix_ptr(matrix_ref_parts(right_vectors))?;
597 let mut device_bytes = 0;
598 let mut host_bytes = 0;
599 unsafe {
600 try_ffi!(sys::cusolverDnXgeev_bufferSize(
601 ctx.as_raw(),
602 params.as_raw(),
603 EigenMode::NoVector.into(),
604 if right_vectors.is_some() {
605 EigenMode::Vector
606 } else {
607 EigenMode::NoVector
608 }
609 .into(),
610 to_i64(n, "n")?,
611 TA::data_type().into(),
612 a.data.as_ptr().cast(),
613 to_i64(a.leading_dimension, "lda")?,
614 TW::data_type().into(),
615 eigenvalues.as_ptr().cast(),
616 TA::data_type().into(),
617 ptr::null(),
618 1,
619 TV::data_type().into(),
620 vr_ptr.cast(),
621 ldvr,
622 TA::data_type().into(),
623 &raw mut device_bytes,
624 &raw mut host_bytes,
625 ))?;
626 }
627 Ok(WorkspaceSizes::new(
628 device_bytes as usize,
629 host_bytes as usize,
630 ))
631}
632
633pub fn xgeev<TA: DataTypeLike, TW: DataTypeLike, TV: DataTypeLike>(
705 ctx: &Context,
706 params: &Params,
707 n: usize,
708 a: MatrixMut<'_, TA>,
709 eigenvalues: &mut DeviceMemory<TW>,
710 right_vectors: Option<MatrixMut<'_, TV>>,
711 workspace: ByteWorkspaceMut<'_>,
712 dev_info: &mut DeviceMemory<i32>,
713) -> Result<()> {
714 ctx.bind()?;
715 validate_xgeev_inputs(
716 n,
717 a.data.byte_len(),
718 a.leading_dimension,
719 TA::data_type(),
720 eigenvalues.byte_len(),
721 TW::data_type(),
722 matrix_mut_ref_parts(right_vectors.as_ref()),
723 TV::data_type(),
724 )?;
725 require_info_buffer(dev_info)?;
726 let workspace_sizes = xgeev_buffer_size(
727 ctx,
728 params,
729 n,
730 a.as_ref(),
731 eigenvalues,
732 matrix_mut_ref_option(right_vectors.as_ref()),
733 )?;
734 require_workspace_bytes(workspace.device.byte_len(), workspace_sizes.device_bytes)?;
735 require_host_workspace(workspace.host.len(), workspace_sizes.host_bytes)?;
736 let (vr_ptr, ldvr) = optional_xgeev_matrix_mut_ptr(matrix_mut_parts(right_vectors))?;
737 unsafe {
738 try_ffi!(sys::cusolverDnXgeev(
739 ctx.as_raw(),
740 params.as_raw(),
741 EigenMode::NoVector.into(),
742 if vr_ptr.is_null() {
743 EigenMode::NoVector
744 } else {
745 EigenMode::Vector
746 }
747 .into(),
748 to_i64(n, "n")?,
749 TA::data_type().into(),
750 a.data.as_mut_ptr().cast(),
751 to_i64(a.leading_dimension, "lda")?,
752 TW::data_type().into(),
753 eigenvalues.as_mut_ptr().cast(),
754 TA::data_type().into(),
755 ptr::null_mut(),
756 1,
757 TV::data_type().into(),
758 vr_ptr.cast(),
759 ldvr,
760 TA::data_type().into(),
761 workspace.device.as_mut_ptr().cast(),
762 workspace_sizes.device_bytes as _,
763 workspace.host.as_mut_ptr().cast(),
764 workspace_sizes.host_bytes as _,
765 dev_info.as_mut_ptr().cast(),
766 ))?;
767 }
768 Ok(())
769}
770
771fn xsyevd_raw_buffer_size<TA, TW>(
772 ctx: &Context,
773 params: &Params,
774 mode: EigenMode,
775 fill_mode: FillMode,
776 n: usize,
777 a_type: DataType,
778 a: &DeviceMemory<TA>,
779 lda: usize,
780 w_type: DataType,
781 w: &DeviceMemory<TW>,
782 compute_type: DataType,
783) -> Result<WorkspaceSizes> {
784 ctx.bind()?;
785 validate_xsyevd_buffers(n, a.byte_len(), lda, a_type, w.byte_len(), w_type)?;
786 let mut device_bytes = 0;
787 let mut host_bytes = 0;
788 unsafe {
789 try_ffi!(sys::cusolverDnXsyevd_bufferSize(
790 ctx.as_raw(),
791 params.as_raw(),
792 mode.into(),
793 fill_mode.into(),
794 to_i64(n, "n")?,
795 a_type.into(),
796 a.as_ptr().cast(),
797 to_i64(lda, "lda")?,
798 w_type.into(),
799 w.as_ptr().cast(),
800 compute_type.into(),
801 &raw mut device_bytes,
802 &raw mut host_bytes,
803 ))?;
804 }
805 Ok(WorkspaceSizes::new(
806 device_bytes as usize,
807 host_bytes as usize,
808 ))
809}
810
811fn xsyevd_raw<TA, TW>(
812 ctx: &Context,
813 params: &Params,
814 mode: EigenMode,
815 fill_mode: FillMode,
816 n: usize,
817 a_type: DataType,
818 a: &mut DeviceMemory<TA>,
819 lda: usize,
820 w_type: DataType,
821 w: &mut DeviceMemory<TW>,
822 compute_type: DataType,
823 workspace: ByteWorkspaceMut<'_>,
824 dev_info: &mut DeviceMemory<i32>,
825) -> Result<()> {
826 ctx.bind()?;
827 validate_xsyevd_buffers(n, a.byte_len(), lda, a_type, w.byte_len(), w_type)?;
828 require_info_buffer(dev_info)?;
829 let workspace_sizes = xsyevd_raw_buffer_size(
830 ctx,
831 params,
832 mode,
833 fill_mode,
834 n,
835 a_type,
836 a,
837 lda,
838 w_type,
839 w,
840 compute_type,
841 )?;
842 require_workspace_bytes(workspace.device.byte_len(), workspace_sizes.device_bytes)?;
843 require_host_workspace(workspace.host.len(), workspace_sizes.host_bytes)?;
844 unsafe {
845 try_ffi!(sys::cusolverDnXsyevd(
846 ctx.as_raw(),
847 params.as_raw(),
848 mode.into(),
849 fill_mode.into(),
850 to_i64(n, "n")?,
851 a_type.into(),
852 a.as_mut_ptr().cast(),
853 to_i64(lda, "lda")?,
854 w_type.into(),
855 w.as_mut_ptr().cast(),
856 compute_type.into(),
857 workspace.device.as_mut_ptr().cast(),
858 workspace_sizes.device_bytes as _,
859 workspace.host.as_mut_ptr().cast(),
860 workspace_sizes.host_bytes as _,
861 dev_info.as_mut_ptr().cast(),
862 ))?;
863 }
864 Ok(())
865}
866
867fn xsyevdx_raw_buffer_size<TA, TR, TW>(
868 ctx: &Context,
869 params: &Params,
870 mode: EigenMode,
871 range: EigenRange,
872 fill_mode: FillMode,
873 n: usize,
874 a_type: DataType,
875 a: &DeviceMemory<TA>,
876 lda: usize,
877 value_range: Option<(TR, TR)>,
878 index_range: Option<(usize, usize)>,
879 w_type: DataType,
880 w: &DeviceMemory<TW>,
881 compute_type: DataType,
882) -> Result<SelectionWorkspaceSizes>
883where
884 TR: Copy + Default,
885{
886 ctx.bind()?;
887 validate_xsyevd_buffers(n, a.byte_len(), lda, a_type, w.byte_len(), w_type)?;
888 validate_xsyevdx_value_type::<TR>(w_type)?;
889 let (mut vl, mut vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
890 let mut meig = 0;
891 let mut device_bytes = 0;
892 let mut host_bytes = 0;
893 unsafe {
894 try_ffi!(sys::cusolverDnXsyevdx_bufferSize(
895 ctx.as_raw(),
896 params.as_raw(),
897 mode.into(),
898 range.into(),
899 fill_mode.into(),
900 to_i64(n, "n")?,
901 a_type.into(),
902 a.as_ptr().cast(),
903 to_i64(lda, "lda")?,
904 (&raw mut vl).cast(),
905 (&raw mut vu).cast(),
906 to_i64(il, "il")?,
907 to_i64(iu, "iu")?,
908 &raw mut meig,
909 w_type.into(),
910 w.as_ptr().cast(),
911 compute_type.into(),
912 &raw mut device_bytes,
913 &raw mut host_bytes,
914 ))?;
915 }
916 Ok(SelectionWorkspaceSizes::new(
917 to_usize(meig, "meig")?,
918 device_bytes as usize,
919 host_bytes as usize,
920 ))
921}
922
923fn xsyevdx_raw<TA, TR, TW>(
924 ctx: &Context,
925 params: &Params,
926 mode: EigenMode,
927 range: EigenRange,
928 fill_mode: FillMode,
929 n: usize,
930 a_type: DataType,
931 a: &mut DeviceMemory<TA>,
932 lda: usize,
933 value_range: Option<(TR, TR)>,
934 index_range: Option<(usize, usize)>,
935 w_type: DataType,
936 w: &mut DeviceMemory<TW>,
937 compute_type: DataType,
938 workspace: ByteWorkspaceMut<'_>,
939 dev_info: &mut DeviceMemory<i32>,
940) -> Result<usize>
941where
942 TR: Copy + Default,
943{
944 ctx.bind()?;
945 validate_xsyevd_buffers(n, a.byte_len(), lda, a_type, w.byte_len(), w_type)?;
946 validate_xsyevdx_value_type::<TR>(w_type)?;
947 require_info_buffer(dev_info)?;
948 let workspace_sizes = xsyevdx_raw_buffer_size(
949 ctx,
950 params,
951 mode,
952 range,
953 fill_mode,
954 n,
955 a_type,
956 a,
957 lda,
958 value_range,
959 index_range,
960 w_type,
961 w,
962 compute_type,
963 )?;
964 require_workspace_bytes(
965 workspace.device.byte_len(),
966 workspace_sizes.workspace.device_bytes,
967 )?;
968 require_host_workspace(workspace.host.len(), workspace_sizes.workspace.host_bytes)?;
969 let (mut vl, mut vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
970 let mut meig_raw = 0;
971 unsafe {
972 try_ffi!(sys::cusolverDnXsyevdx(
973 ctx.as_raw(),
974 params.as_raw(),
975 mode.into(),
976 range.into(),
977 fill_mode.into(),
978 to_i64(n, "n")?,
979 a_type.into(),
980 a.as_mut_ptr().cast(),
981 to_i64(lda, "lda")?,
982 (&raw mut vl).cast(),
983 (&raw mut vu).cast(),
984 to_i64(il, "il")?,
985 to_i64(iu, "iu")?,
986 &raw mut meig_raw,
987 w_type.into(),
988 w.as_mut_ptr().cast(),
989 compute_type.into(),
990 workspace.device.as_mut_ptr().cast(),
991 workspace_sizes.workspace.device_bytes as _,
992 workspace.host.as_mut_ptr().cast(),
993 workspace_sizes.workspace.host_bytes as _,
994 dev_info.as_mut_ptr().cast(),
995 ))?;
996 }
997 debug_assert_eq!(workspace_sizes.selection_size, to_usize(meig_raw, "meig")?);
998 Ok(workspace_sizes.selection_size)
999}
1000
1001pub fn ssyevd_buffer_size(
1002 ctx: &Context,
1003 mode: EigenMode,
1004 fill_mode: FillMode,
1005 n: usize,
1006 a: &DeviceMemory<f32>,
1007 lda: usize,
1008 w: &DeviceMemory<f32>,
1009) -> Result<usize> {
1010 ctx.bind()?;
1011 validate_syev_buffers(n, a.len(), lda, w.len())?;
1012 let mut lwork = 0;
1013 unsafe {
1014 try_ffi!(sys::cusolverDnSsyevd_bufferSize(
1015 ctx.as_raw(),
1016 mode.into(),
1017 fill_mode.into(),
1018 to_i32(n, "n")?,
1019 a.as_ptr().cast(),
1020 to_i32(lda, "lda")?,
1021 w.as_ptr().cast(),
1022 &raw mut lwork,
1023 ))?;
1024 }
1025 to_usize(lwork, "lwork")
1026}
1027
1028pub fn dsyevd_buffer_size(
1029 ctx: &Context,
1030 mode: EigenMode,
1031 fill_mode: FillMode,
1032 n: usize,
1033 a: &DeviceMemory<f64>,
1034 lda: usize,
1035 w: &DeviceMemory<f64>,
1036) -> Result<usize> {
1037 ctx.bind()?;
1038 validate_syev_buffers(n, a.len(), lda, w.len())?;
1039 let mut lwork = 0;
1040 unsafe {
1041 try_ffi!(sys::cusolverDnDsyevd_bufferSize(
1042 ctx.as_raw(),
1043 mode.into(),
1044 fill_mode.into(),
1045 to_i32(n, "n")?,
1046 a.as_ptr().cast(),
1047 to_i32(lda, "lda")?,
1048 w.as_ptr().cast(),
1049 &raw mut lwork,
1050 ))?;
1051 }
1052 to_usize(lwork, "lwork")
1053}
1054
1055pub fn cheevd_buffer_size(
1056 ctx: &Context,
1057 mode: EigenMode,
1058 fill_mode: FillMode,
1059 n: usize,
1060 a: &DeviceMemory<Complex32>,
1061 lda: usize,
1062 w: &DeviceMemory<f32>,
1063) -> Result<usize> {
1064 ctx.bind()?;
1065 validate_syev_buffers(n, a.len(), lda, w.len())?;
1066 let mut lwork = 0;
1067 unsafe {
1068 try_ffi!(sys::cusolverDnCheevd_bufferSize(
1069 ctx.as_raw(),
1070 mode.into(),
1071 fill_mode.into(),
1072 to_i32(n, "n")?,
1073 a.as_ptr().cast(),
1074 to_i32(lda, "lda")?,
1075 w.as_ptr().cast(),
1076 &raw mut lwork,
1077 ))?;
1078 }
1079 to_usize(lwork, "lwork")
1080}
1081
1082pub fn zheevd_buffer_size(
1083 ctx: &Context,
1084 mode: EigenMode,
1085 fill_mode: FillMode,
1086 n: usize,
1087 a: &DeviceMemory<Complex64>,
1088 lda: usize,
1089 w: &DeviceMemory<f64>,
1090) -> Result<usize> {
1091 ctx.bind()?;
1092 validate_syev_buffers(n, a.len(), lda, w.len())?;
1093 let mut lwork = 0;
1094 unsafe {
1095 try_ffi!(sys::cusolverDnZheevd_bufferSize(
1096 ctx.as_raw(),
1097 mode.into(),
1098 fill_mode.into(),
1099 to_i32(n, "n")?,
1100 a.as_ptr().cast(),
1101 to_i32(lda, "lda")?,
1102 w.as_ptr().cast(),
1103 &raw mut lwork,
1104 ))?;
1105 }
1106 to_usize(lwork, "lwork")
1107}
1108
1109pub fn ssyevd(
1139 ctx: &Context,
1140 mode: EigenMode,
1141 fill_mode: FillMode,
1142 n: usize,
1143 a: &mut DeviceMemory<f32>,
1144 lda: usize,
1145 w: &mut DeviceMemory<f32>,
1146 workspace: &mut DeviceMemory<f32>,
1147 dev_info: &mut DeviceMemory<i32>,
1148) -> Result<()> {
1149 ctx.bind()?;
1150 validate_syev_buffers(n, a.len(), lda, w.len())?;
1151 require_info_buffer(dev_info)?;
1152 let lwork = ssyevd_buffer_size(ctx, mode, fill_mode, n, a, lda, w)?;
1153 require_workspace(workspace.len(), lwork)?;
1154 unsafe {
1155 try_ffi!(sys::cusolverDnSsyevd(
1156 ctx.as_raw(),
1157 mode.into(),
1158 fill_mode.into(),
1159 to_i32(n, "n")?,
1160 a.as_mut_ptr().cast(),
1161 to_i32(lda, "lda")?,
1162 w.as_mut_ptr().cast(),
1163 workspace.as_mut_ptr().cast(),
1164 to_i32(lwork, "lwork")?,
1165 dev_info.as_mut_ptr().cast(),
1166 ))?;
1167 }
1168 Ok(())
1169}
1170
1171pub fn dsyevd(
1201 ctx: &Context,
1202 mode: EigenMode,
1203 fill_mode: FillMode,
1204 n: usize,
1205 a: &mut DeviceMemory<f64>,
1206 lda: usize,
1207 w: &mut DeviceMemory<f64>,
1208 workspace: &mut DeviceMemory<f64>,
1209 dev_info: &mut DeviceMemory<i32>,
1210) -> Result<()> {
1211 ctx.bind()?;
1212 validate_syev_buffers(n, a.len(), lda, w.len())?;
1213 require_info_buffer(dev_info)?;
1214 let lwork = dsyevd_buffer_size(ctx, mode, fill_mode, n, a, lda, w)?;
1215 require_workspace(workspace.len(), lwork)?;
1216 unsafe {
1217 try_ffi!(sys::cusolverDnDsyevd(
1218 ctx.as_raw(),
1219 mode.into(),
1220 fill_mode.into(),
1221 to_i32(n, "n")?,
1222 a.as_mut_ptr().cast(),
1223 to_i32(lda, "lda")?,
1224 w.as_mut_ptr().cast(),
1225 workspace.as_mut_ptr().cast(),
1226 to_i32(lwork, "lwork")?,
1227 dev_info.as_mut_ptr().cast(),
1228 ))?;
1229 }
1230 Ok(())
1231}
1232
1233pub fn cheevd(
1234 ctx: &Context,
1235 mode: EigenMode,
1236 fill_mode: FillMode,
1237 n: usize,
1238 a: &mut DeviceMemory<Complex32>,
1239 lda: usize,
1240 w: &mut DeviceMemory<f32>,
1241 workspace: &mut DeviceMemory<Complex32>,
1242 dev_info: &mut DeviceMemory<i32>,
1243) -> Result<()> {
1244 ctx.bind()?;
1245 validate_syev_buffers(n, a.len(), lda, w.len())?;
1246 require_info_buffer(dev_info)?;
1247 let lwork = cheevd_buffer_size(ctx, mode, fill_mode, n, a, lda, w)?;
1248 require_workspace(workspace.len(), lwork)?;
1249 unsafe {
1250 try_ffi!(sys::cusolverDnCheevd(
1251 ctx.as_raw(),
1252 mode.into(),
1253 fill_mode.into(),
1254 to_i32(n, "n")?,
1255 a.as_mut_ptr().cast(),
1256 to_i32(lda, "lda")?,
1257 w.as_mut_ptr().cast(),
1258 workspace.as_mut_ptr().cast(),
1259 to_i32(lwork, "lwork")?,
1260 dev_info.as_mut_ptr().cast(),
1261 ))?;
1262 }
1263 Ok(())
1264}
1265
1266pub fn zheevd(
1267 ctx: &Context,
1268 mode: EigenMode,
1269 fill_mode: FillMode,
1270 n: usize,
1271 a: &mut DeviceMemory<Complex64>,
1272 lda: usize,
1273 w: &mut DeviceMemory<f64>,
1274 workspace: &mut DeviceMemory<Complex64>,
1275 dev_info: &mut DeviceMemory<i32>,
1276) -> Result<()> {
1277 ctx.bind()?;
1278 validate_syev_buffers(n, a.len(), lda, w.len())?;
1279 require_info_buffer(dev_info)?;
1280 let lwork = zheevd_buffer_size(ctx, mode, fill_mode, n, a, lda, w)?;
1281 require_workspace(workspace.len(), lwork)?;
1282 unsafe {
1283 try_ffi!(sys::cusolverDnZheevd(
1284 ctx.as_raw(),
1285 mode.into(),
1286 fill_mode.into(),
1287 to_i32(n, "n")?,
1288 a.as_mut_ptr().cast(),
1289 to_i32(lda, "lda")?,
1290 w.as_mut_ptr().cast(),
1291 workspace.as_mut_ptr().cast(),
1292 to_i32(lwork, "lwork")?,
1293 dev_info.as_mut_ptr().cast(),
1294 ))?;
1295 }
1296 Ok(())
1297}
1298
1299pub fn ssyevj_buffer_size(
1300 ctx: &Context,
1301 mode: EigenMode,
1302 fill_mode: FillMode,
1303 n: usize,
1304 a: &DeviceMemory<f32>,
1305 lda: usize,
1306 w: &DeviceMemory<f32>,
1307 params: &SyevjInfo,
1308) -> Result<usize> {
1309 ctx.bind()?;
1310 validate_syev_buffers(n, a.len(), lda, w.len())?;
1311 let mut lwork = 0;
1312 unsafe {
1313 try_ffi!(sys::cusolverDnSsyevj_bufferSize(
1314 ctx.as_raw(),
1315 mode.into(),
1316 fill_mode.into(),
1317 to_i32(n, "n")?,
1318 a.as_ptr().cast(),
1319 to_i32(lda, "lda")?,
1320 w.as_ptr().cast(),
1321 &raw mut lwork,
1322 params.as_raw(),
1323 ))?;
1324 }
1325 to_usize(lwork, "lwork")
1326}
1327
1328pub fn dsyevj_buffer_size(
1329 ctx: &Context,
1330 mode: EigenMode,
1331 fill_mode: FillMode,
1332 n: usize,
1333 a: &DeviceMemory<f64>,
1334 lda: usize,
1335 w: &DeviceMemory<f64>,
1336 params: &SyevjInfo,
1337) -> Result<usize> {
1338 ctx.bind()?;
1339 validate_syev_buffers(n, a.len(), lda, w.len())?;
1340 let mut lwork = 0;
1341 unsafe {
1342 try_ffi!(sys::cusolverDnDsyevj_bufferSize(
1343 ctx.as_raw(),
1344 mode.into(),
1345 fill_mode.into(),
1346 to_i32(n, "n")?,
1347 a.as_ptr().cast(),
1348 to_i32(lda, "lda")?,
1349 w.as_ptr().cast(),
1350 &raw mut lwork,
1351 params.as_raw(),
1352 ))?;
1353 }
1354 to_usize(lwork, "lwork")
1355}
1356
1357pub fn cheevj_buffer_size(
1358 ctx: &Context,
1359 mode: EigenMode,
1360 fill_mode: FillMode,
1361 n: usize,
1362 a: &DeviceMemory<Complex32>,
1363 lda: usize,
1364 w: &DeviceMemory<f32>,
1365 params: &SyevjInfo,
1366) -> Result<usize> {
1367 ctx.bind()?;
1368 validate_syev_buffers(n, a.len(), lda, w.len())?;
1369 let mut lwork = 0;
1370 unsafe {
1371 try_ffi!(sys::cusolverDnCheevj_bufferSize(
1372 ctx.as_raw(),
1373 mode.into(),
1374 fill_mode.into(),
1375 to_i32(n, "n")?,
1376 a.as_ptr().cast(),
1377 to_i32(lda, "lda")?,
1378 w.as_ptr().cast(),
1379 &raw mut lwork,
1380 params.as_raw(),
1381 ))?;
1382 }
1383 to_usize(lwork, "lwork")
1384}
1385
1386pub fn zheevj_buffer_size(
1387 ctx: &Context,
1388 mode: EigenMode,
1389 fill_mode: FillMode,
1390 n: usize,
1391 a: &DeviceMemory<Complex64>,
1392 lda: usize,
1393 w: &DeviceMemory<f64>,
1394 params: &SyevjInfo,
1395) -> Result<usize> {
1396 ctx.bind()?;
1397 validate_syev_buffers(n, a.len(), lda, w.len())?;
1398 let mut lwork = 0;
1399 unsafe {
1400 try_ffi!(sys::cusolverDnZheevj_bufferSize(
1401 ctx.as_raw(),
1402 mode.into(),
1403 fill_mode.into(),
1404 to_i32(n, "n")?,
1405 a.as_ptr().cast(),
1406 to_i32(lda, "lda")?,
1407 w.as_ptr().cast(),
1408 &raw mut lwork,
1409 params.as_raw(),
1410 ))?;
1411 }
1412 to_usize(lwork, "lwork")
1413}
1414
1415pub fn ssyevj(
1477 ctx: &Context,
1478 mode: EigenMode,
1479 fill_mode: FillMode,
1480 n: usize,
1481 a: &mut DeviceMemory<f32>,
1482 lda: usize,
1483 w: &mut DeviceMemory<f32>,
1484 workspace: &mut DeviceMemory<f32>,
1485 dev_info: &mut DeviceMemory<i32>,
1486 params: &SyevjInfo,
1487) -> Result<()> {
1488 ctx.bind()?;
1489 validate_syev_buffers(n, a.len(), lda, w.len())?;
1490 require_info_buffer(dev_info)?;
1491 let lwork = ssyevj_buffer_size(ctx, mode, fill_mode, n, a, lda, w, params)?;
1492 require_workspace(workspace.len(), lwork)?;
1493 unsafe {
1494 try_ffi!(sys::cusolverDnSsyevj(
1495 ctx.as_raw(),
1496 mode.into(),
1497 fill_mode.into(),
1498 to_i32(n, "n")?,
1499 a.as_mut_ptr().cast(),
1500 to_i32(lda, "lda")?,
1501 w.as_mut_ptr().cast(),
1502 workspace.as_mut_ptr().cast(),
1503 to_i32(lwork, "lwork")?,
1504 dev_info.as_mut_ptr().cast(),
1505 params.as_raw(),
1506 ))?;
1507 }
1508 Ok(())
1509}
1510
1511pub fn dsyevj(
1565 ctx: &Context,
1566 mode: EigenMode,
1567 fill_mode: FillMode,
1568 n: usize,
1569 a: &mut DeviceMemory<f64>,
1570 lda: usize,
1571 w: &mut DeviceMemory<f64>,
1572 workspace: &mut DeviceMemory<f64>,
1573 dev_info: &mut DeviceMemory<i32>,
1574 params: &SyevjInfo,
1575) -> Result<()> {
1576 ctx.bind()?;
1577 validate_syev_buffers(n, a.len(), lda, w.len())?;
1578 require_info_buffer(dev_info)?;
1579 let lwork = dsyevj_buffer_size(ctx, mode, fill_mode, n, a, lda, w, params)?;
1580 require_workspace(workspace.len(), lwork)?;
1581 unsafe {
1582 try_ffi!(sys::cusolverDnDsyevj(
1583 ctx.as_raw(),
1584 mode.into(),
1585 fill_mode.into(),
1586 to_i32(n, "n")?,
1587 a.as_mut_ptr().cast(),
1588 to_i32(lda, "lda")?,
1589 w.as_mut_ptr().cast(),
1590 workspace.as_mut_ptr().cast(),
1591 to_i32(lwork, "lwork")?,
1592 dev_info.as_mut_ptr().cast(),
1593 params.as_raw(),
1594 ))?;
1595 }
1596 Ok(())
1597}
1598
1599pub fn cheevj(
1600 ctx: &Context,
1601 mode: EigenMode,
1602 fill_mode: FillMode,
1603 n: usize,
1604 a: &mut DeviceMemory<Complex32>,
1605 lda: usize,
1606 w: &mut DeviceMemory<f32>,
1607 workspace: &mut DeviceMemory<Complex32>,
1608 dev_info: &mut DeviceMemory<i32>,
1609 params: &SyevjInfo,
1610) -> Result<()> {
1611 ctx.bind()?;
1612 validate_syev_buffers(n, a.len(), lda, w.len())?;
1613 require_info_buffer(dev_info)?;
1614 let lwork = cheevj_buffer_size(ctx, mode, fill_mode, n, a, lda, w, params)?;
1615 require_workspace(workspace.len(), lwork)?;
1616 unsafe {
1617 try_ffi!(sys::cusolverDnCheevj(
1618 ctx.as_raw(),
1619 mode.into(),
1620 fill_mode.into(),
1621 to_i32(n, "n")?,
1622 a.as_mut_ptr().cast(),
1623 to_i32(lda, "lda")?,
1624 w.as_mut_ptr().cast(),
1625 workspace.as_mut_ptr().cast(),
1626 to_i32(lwork, "lwork")?,
1627 dev_info.as_mut_ptr().cast(),
1628 params.as_raw(),
1629 ))?;
1630 }
1631 Ok(())
1632}
1633
1634pub fn zheevj(
1635 ctx: &Context,
1636 mode: EigenMode,
1637 fill_mode: FillMode,
1638 n: usize,
1639 a: &mut DeviceMemory<Complex64>,
1640 lda: usize,
1641 w: &mut DeviceMemory<f64>,
1642 workspace: &mut DeviceMemory<Complex64>,
1643 dev_info: &mut DeviceMemory<i32>,
1644 params: &SyevjInfo,
1645) -> Result<()> {
1646 ctx.bind()?;
1647 validate_syev_buffers(n, a.len(), lda, w.len())?;
1648 require_info_buffer(dev_info)?;
1649 let lwork = zheevj_buffer_size(ctx, mode, fill_mode, n, a, lda, w, params)?;
1650 require_workspace(workspace.len(), lwork)?;
1651 unsafe {
1652 try_ffi!(sys::cusolverDnZheevj(
1653 ctx.as_raw(),
1654 mode.into(),
1655 fill_mode.into(),
1656 to_i32(n, "n")?,
1657 a.as_mut_ptr().cast(),
1658 to_i32(lda, "lda")?,
1659 w.as_mut_ptr().cast(),
1660 workspace.as_mut_ptr().cast(),
1661 to_i32(lwork, "lwork")?,
1662 dev_info.as_mut_ptr().cast(),
1663 params.as_raw(),
1664 ))?;
1665 }
1666 Ok(())
1667}
1668
1669pub fn ssyevj_batched_buffer_size(
1670 ctx: &Context,
1671 mode: EigenMode,
1672 fill_mode: FillMode,
1673 n: usize,
1674 a: &DeviceMemory<f32>,
1675 lda: usize,
1676 w: &DeviceMemory<f32>,
1677 params: &SyevjInfo,
1678 batch_count: usize,
1679) -> Result<usize> {
1680 ctx.bind()?;
1681 validate_syevj_batched_buffers(n, a.len(), lda, w.len(), batch_count)?;
1682 let mut lwork = 0;
1683 unsafe {
1684 try_ffi!(sys::cusolverDnSsyevjBatched_bufferSize(
1685 ctx.as_raw(),
1686 mode.into(),
1687 fill_mode.into(),
1688 to_i32(n, "n")?,
1689 a.as_ptr().cast(),
1690 to_i32(lda, "lda")?,
1691 w.as_ptr().cast(),
1692 &raw mut lwork,
1693 params.as_raw(),
1694 to_i32(batch_count, "batch_count")?,
1695 ))?;
1696 }
1697 to_usize(lwork, "lwork")
1698}
1699
1700pub fn dsyevj_batched_buffer_size(
1701 ctx: &Context,
1702 mode: EigenMode,
1703 fill_mode: FillMode,
1704 n: usize,
1705 a: &DeviceMemory<f64>,
1706 lda: usize,
1707 w: &DeviceMemory<f64>,
1708 params: &SyevjInfo,
1709 batch_count: usize,
1710) -> Result<usize> {
1711 ctx.bind()?;
1712 validate_syevj_batched_buffers(n, a.len(), lda, w.len(), batch_count)?;
1713 let mut lwork = 0;
1714 unsafe {
1715 try_ffi!(sys::cusolverDnDsyevjBatched_bufferSize(
1716 ctx.as_raw(),
1717 mode.into(),
1718 fill_mode.into(),
1719 to_i32(n, "n")?,
1720 a.as_ptr().cast(),
1721 to_i32(lda, "lda")?,
1722 w.as_ptr().cast(),
1723 &raw mut lwork,
1724 params.as_raw(),
1725 to_i32(batch_count, "batch_count")?,
1726 ))?;
1727 }
1728 to_usize(lwork, "lwork")
1729}
1730
1731pub fn cheevj_batched_buffer_size(
1732 ctx: &Context,
1733 mode: EigenMode,
1734 fill_mode: FillMode,
1735 n: usize,
1736 a: &DeviceMemory<Complex32>,
1737 lda: usize,
1738 w: &DeviceMemory<f32>,
1739 params: &SyevjInfo,
1740 batch_count: usize,
1741) -> Result<usize> {
1742 ctx.bind()?;
1743 validate_syevj_batched_buffers(n, a.len(), lda, w.len(), batch_count)?;
1744 let mut lwork = 0;
1745 unsafe {
1746 try_ffi!(sys::cusolverDnCheevjBatched_bufferSize(
1747 ctx.as_raw(),
1748 mode.into(),
1749 fill_mode.into(),
1750 to_i32(n, "n")?,
1751 a.as_ptr().cast(),
1752 to_i32(lda, "lda")?,
1753 w.as_ptr().cast(),
1754 &raw mut lwork,
1755 params.as_raw(),
1756 to_i32(batch_count, "batch_count")?,
1757 ))?;
1758 }
1759 to_usize(lwork, "lwork")
1760}
1761
1762pub fn zheevj_batched_buffer_size(
1763 ctx: &Context,
1764 mode: EigenMode,
1765 fill_mode: FillMode,
1766 n: usize,
1767 a: &DeviceMemory<Complex64>,
1768 lda: usize,
1769 w: &DeviceMemory<f64>,
1770 params: &SyevjInfo,
1771 batch_count: usize,
1772) -> Result<usize> {
1773 ctx.bind()?;
1774 validate_syevj_batched_buffers(n, a.len(), lda, w.len(), batch_count)?;
1775 let mut lwork = 0;
1776 unsafe {
1777 try_ffi!(sys::cusolverDnZheevjBatched_bufferSize(
1778 ctx.as_raw(),
1779 mode.into(),
1780 fill_mode.into(),
1781 to_i32(n, "n")?,
1782 a.as_ptr().cast(),
1783 to_i32(lda, "lda")?,
1784 w.as_ptr().cast(),
1785 &raw mut lwork,
1786 params.as_raw(),
1787 to_i32(batch_count, "batch_count")?,
1788 ))?;
1789 }
1790 to_usize(lwork, "lwork")
1791}
1792
1793pub fn ssyevj_batched(
1836 ctx: &Context,
1837 mode: EigenMode,
1838 fill_mode: FillMode,
1839 n: usize,
1840 a: &mut DeviceMemory<f32>,
1841 lda: usize,
1842 w: &mut DeviceMemory<f32>,
1843 workspace: &mut DeviceMemory<f32>,
1844 dev_info: &mut DeviceMemory<i32>,
1845 params: &SyevjInfo,
1846 batch_count: usize,
1847) -> Result<()> {
1848 ctx.bind()?;
1849 validate_syevj_batched_buffers(n, a.len(), lda, w.len(), batch_count)?;
1850 require_info_buffer_len(dev_info, batch_count)?;
1851 let lwork =
1852 ssyevj_batched_buffer_size(ctx, mode, fill_mode, n, a, lda, w, params, batch_count)?;
1853 require_workspace(workspace.len(), lwork)?;
1854 unsafe {
1855 try_ffi!(sys::cusolverDnSsyevjBatched(
1856 ctx.as_raw(),
1857 mode.into(),
1858 fill_mode.into(),
1859 to_i32(n, "n")?,
1860 a.as_mut_ptr().cast(),
1861 to_i32(lda, "lda")?,
1862 w.as_mut_ptr().cast(),
1863 workspace.as_mut_ptr().cast(),
1864 to_i32(lwork, "lwork")?,
1865 dev_info.as_mut_ptr().cast(),
1866 params.as_raw(),
1867 to_i32(batch_count, "batch_count")?,
1868 ))?;
1869 }
1870 Ok(())
1871}
1872
1873pub fn dsyevj_batched(
1916 ctx: &Context,
1917 mode: EigenMode,
1918 fill_mode: FillMode,
1919 n: usize,
1920 a: &mut DeviceMemory<f64>,
1921 lda: usize,
1922 w: &mut DeviceMemory<f64>,
1923 workspace: &mut DeviceMemory<f64>,
1924 dev_info: &mut DeviceMemory<i32>,
1925 params: &SyevjInfo,
1926 batch_count: usize,
1927) -> Result<()> {
1928 ctx.bind()?;
1929 validate_syevj_batched_buffers(n, a.len(), lda, w.len(), batch_count)?;
1930 require_info_buffer_len(dev_info, batch_count)?;
1931 let lwork =
1932 dsyevj_batched_buffer_size(ctx, mode, fill_mode, n, a, lda, w, params, batch_count)?;
1933 require_workspace(workspace.len(), lwork)?;
1934 unsafe {
1935 try_ffi!(sys::cusolverDnDsyevjBatched(
1936 ctx.as_raw(),
1937 mode.into(),
1938 fill_mode.into(),
1939 to_i32(n, "n")?,
1940 a.as_mut_ptr().cast(),
1941 to_i32(lda, "lda")?,
1942 w.as_mut_ptr().cast(),
1943 workspace.as_mut_ptr().cast(),
1944 to_i32(lwork, "lwork")?,
1945 dev_info.as_mut_ptr().cast(),
1946 params.as_raw(),
1947 to_i32(batch_count, "batch_count")?,
1948 ))?;
1949 }
1950 Ok(())
1951}
1952
1953pub fn cheevj_batched(
1954 ctx: &Context,
1955 mode: EigenMode,
1956 fill_mode: FillMode,
1957 n: usize,
1958 a: &mut DeviceMemory<Complex32>,
1959 lda: usize,
1960 w: &mut DeviceMemory<f32>,
1961 workspace: &mut DeviceMemory<Complex32>,
1962 dev_info: &mut DeviceMemory<i32>,
1963 params: &SyevjInfo,
1964 batch_count: usize,
1965) -> Result<()> {
1966 ctx.bind()?;
1967 validate_syevj_batched_buffers(n, a.len(), lda, w.len(), batch_count)?;
1968 require_info_buffer_len(dev_info, batch_count)?;
1969 let lwork =
1970 cheevj_batched_buffer_size(ctx, mode, fill_mode, n, a, lda, w, params, batch_count)?;
1971 require_workspace(workspace.len(), lwork)?;
1972 unsafe {
1973 try_ffi!(sys::cusolverDnCheevjBatched(
1974 ctx.as_raw(),
1975 mode.into(),
1976 fill_mode.into(),
1977 to_i32(n, "n")?,
1978 a.as_mut_ptr().cast(),
1979 to_i32(lda, "lda")?,
1980 w.as_mut_ptr().cast(),
1981 workspace.as_mut_ptr().cast(),
1982 to_i32(lwork, "lwork")?,
1983 dev_info.as_mut_ptr().cast(),
1984 params.as_raw(),
1985 to_i32(batch_count, "batch_count")?,
1986 ))?;
1987 }
1988 Ok(())
1989}
1990
1991pub fn zheevj_batched(
1992 ctx: &Context,
1993 mode: EigenMode,
1994 fill_mode: FillMode,
1995 n: usize,
1996 a: &mut DeviceMemory<Complex64>,
1997 lda: usize,
1998 w: &mut DeviceMemory<f64>,
1999 workspace: &mut DeviceMemory<Complex64>,
2000 dev_info: &mut DeviceMemory<i32>,
2001 params: &SyevjInfo,
2002 batch_count: usize,
2003) -> Result<()> {
2004 ctx.bind()?;
2005 validate_syevj_batched_buffers(n, a.len(), lda, w.len(), batch_count)?;
2006 require_info_buffer_len(dev_info, batch_count)?;
2007 let lwork =
2008 zheevj_batched_buffer_size(ctx, mode, fill_mode, n, a, lda, w, params, batch_count)?;
2009 require_workspace(workspace.len(), lwork)?;
2010 unsafe {
2011 try_ffi!(sys::cusolverDnZheevjBatched(
2012 ctx.as_raw(),
2013 mode.into(),
2014 fill_mode.into(),
2015 to_i32(n, "n")?,
2016 a.as_mut_ptr().cast(),
2017 to_i32(lda, "lda")?,
2018 w.as_mut_ptr().cast(),
2019 workspace.as_mut_ptr().cast(),
2020 to_i32(lwork, "lwork")?,
2021 dev_info.as_mut_ptr().cast(),
2022 params.as_raw(),
2023 to_i32(batch_count, "batch_count")?,
2024 ))?;
2025 }
2026 Ok(())
2027}
2028
2029pub fn ssygvj_buffer_size(
2030 ctx: &Context,
2031 eig_type: EigenType,
2032 mode: EigenMode,
2033 fill_mode: FillMode,
2034 n: usize,
2035 a: &DeviceMemory<f32>,
2036 lda: usize,
2037 b: &DeviceMemory<f32>,
2038 ldb: usize,
2039 w: &DeviceMemory<f32>,
2040 params: &SyevjInfo,
2041) -> Result<usize> {
2042 ctx.bind()?;
2043 validate_sygvj_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2044 let mut lwork = 0;
2045 unsafe {
2046 try_ffi!(sys::cusolverDnSsygvj_bufferSize(
2047 ctx.as_raw(),
2048 eig_type.into(),
2049 mode.into(),
2050 fill_mode.into(),
2051 to_i32(n, "n")?,
2052 a.as_ptr().cast(),
2053 to_i32(lda, "lda")?,
2054 b.as_ptr().cast(),
2055 to_i32(ldb, "ldb")?,
2056 w.as_ptr().cast(),
2057 &raw mut lwork,
2058 params.as_raw(),
2059 ))?;
2060 }
2061 to_usize(lwork, "lwork")
2062}
2063
2064pub fn dsygvj_buffer_size(
2065 ctx: &Context,
2066 eig_type: EigenType,
2067 mode: EigenMode,
2068 fill_mode: FillMode,
2069 n: usize,
2070 a: &DeviceMemory<f64>,
2071 lda: usize,
2072 b: &DeviceMemory<f64>,
2073 ldb: usize,
2074 w: &DeviceMemory<f64>,
2075 params: &SyevjInfo,
2076) -> Result<usize> {
2077 ctx.bind()?;
2078 validate_sygvj_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2079 let mut lwork = 0;
2080 unsafe {
2081 try_ffi!(sys::cusolverDnDsygvj_bufferSize(
2082 ctx.as_raw(),
2083 eig_type.into(),
2084 mode.into(),
2085 fill_mode.into(),
2086 to_i32(n, "n")?,
2087 a.as_ptr().cast(),
2088 to_i32(lda, "lda")?,
2089 b.as_ptr().cast(),
2090 to_i32(ldb, "ldb")?,
2091 w.as_ptr().cast(),
2092 &raw mut lwork,
2093 params.as_raw(),
2094 ))?;
2095 }
2096 to_usize(lwork, "lwork")
2097}
2098
2099pub fn chegvj_buffer_size(
2100 ctx: &Context,
2101 eig_type: EigenType,
2102 mode: EigenMode,
2103 fill_mode: FillMode,
2104 n: usize,
2105 a: &DeviceMemory<Complex32>,
2106 lda: usize,
2107 b: &DeviceMemory<Complex32>,
2108 ldb: usize,
2109 w: &DeviceMemory<f32>,
2110 params: &SyevjInfo,
2111) -> Result<usize> {
2112 ctx.bind()?;
2113 validate_sygvj_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2114 let mut lwork = 0;
2115 unsafe {
2116 try_ffi!(sys::cusolverDnChegvj_bufferSize(
2117 ctx.as_raw(),
2118 eig_type.into(),
2119 mode.into(),
2120 fill_mode.into(),
2121 to_i32(n, "n")?,
2122 a.as_ptr().cast(),
2123 to_i32(lda, "lda")?,
2124 b.as_ptr().cast(),
2125 to_i32(ldb, "ldb")?,
2126 w.as_ptr().cast(),
2127 &raw mut lwork,
2128 params.as_raw(),
2129 ))?;
2130 }
2131 to_usize(lwork, "lwork")
2132}
2133
2134pub fn zhegvj_buffer_size(
2135 ctx: &Context,
2136 eig_type: EigenType,
2137 mode: EigenMode,
2138 fill_mode: FillMode,
2139 n: usize,
2140 a: &DeviceMemory<Complex64>,
2141 lda: usize,
2142 b: &DeviceMemory<Complex64>,
2143 ldb: usize,
2144 w: &DeviceMemory<f64>,
2145 params: &SyevjInfo,
2146) -> Result<usize> {
2147 ctx.bind()?;
2148 validate_sygvj_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2149 let mut lwork = 0;
2150 unsafe {
2151 try_ffi!(sys::cusolverDnZhegvj_bufferSize(
2152 ctx.as_raw(),
2153 eig_type.into(),
2154 mode.into(),
2155 fill_mode.into(),
2156 to_i32(n, "n")?,
2157 a.as_ptr().cast(),
2158 to_i32(lda, "lda")?,
2159 b.as_ptr().cast(),
2160 to_i32(ldb, "ldb")?,
2161 w.as_ptr().cast(),
2162 &raw mut lwork,
2163 params.as_raw(),
2164 ))?;
2165 }
2166 to_usize(lwork, "lwork")
2167}
2168
2169pub fn ssygvj(
2217 ctx: &Context,
2218 eig_type: EigenType,
2219 mode: EigenMode,
2220 fill_mode: FillMode,
2221 n: usize,
2222 a: &mut DeviceMemory<f32>,
2223 lda: usize,
2224 b: &mut DeviceMemory<f32>,
2225 ldb: usize,
2226 w: &mut DeviceMemory<f32>,
2227 workspace: &mut DeviceMemory<f32>,
2228 dev_info: &mut DeviceMemory<i32>,
2229 params: &SyevjInfo,
2230) -> Result<()> {
2231 ctx.bind()?;
2232 validate_sygvj_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2233 require_info_buffer(dev_info)?;
2234 let lwork = ssygvj_buffer_size(ctx, eig_type, mode, fill_mode, n, a, lda, b, ldb, w, params)?;
2235 require_workspace(workspace.len(), lwork)?;
2236 unsafe {
2237 try_ffi!(sys::cusolverDnSsygvj(
2238 ctx.as_raw(),
2239 eig_type.into(),
2240 mode.into(),
2241 fill_mode.into(),
2242 to_i32(n, "n")?,
2243 a.as_mut_ptr().cast(),
2244 to_i32(lda, "lda")?,
2245 b.as_mut_ptr().cast(),
2246 to_i32(ldb, "ldb")?,
2247 w.as_mut_ptr().cast(),
2248 workspace.as_mut_ptr().cast(),
2249 to_i32(lwork, "lwork")?,
2250 dev_info.as_mut_ptr().cast(),
2251 params.as_raw(),
2252 ))?;
2253 }
2254 Ok(())
2255}
2256
2257pub fn dsygvj(
2305 ctx: &Context,
2306 eig_type: EigenType,
2307 mode: EigenMode,
2308 fill_mode: FillMode,
2309 n: usize,
2310 a: &mut DeviceMemory<f64>,
2311 lda: usize,
2312 b: &mut DeviceMemory<f64>,
2313 ldb: usize,
2314 w: &mut DeviceMemory<f64>,
2315 workspace: &mut DeviceMemory<f64>,
2316 dev_info: &mut DeviceMemory<i32>,
2317 params: &SyevjInfo,
2318) -> Result<()> {
2319 ctx.bind()?;
2320 validate_sygvj_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2321 require_info_buffer(dev_info)?;
2322 let lwork = dsygvj_buffer_size(ctx, eig_type, mode, fill_mode, n, a, lda, b, ldb, w, params)?;
2323 require_workspace(workspace.len(), lwork)?;
2324 unsafe {
2325 try_ffi!(sys::cusolverDnDsygvj(
2326 ctx.as_raw(),
2327 eig_type.into(),
2328 mode.into(),
2329 fill_mode.into(),
2330 to_i32(n, "n")?,
2331 a.as_mut_ptr().cast(),
2332 to_i32(lda, "lda")?,
2333 b.as_mut_ptr().cast(),
2334 to_i32(ldb, "ldb")?,
2335 w.as_mut_ptr().cast(),
2336 workspace.as_mut_ptr().cast(),
2337 to_i32(lwork, "lwork")?,
2338 dev_info.as_mut_ptr().cast(),
2339 params.as_raw(),
2340 ))?;
2341 }
2342 Ok(())
2343}
2344
2345pub fn chegvj(
2346 ctx: &Context,
2347 eig_type: EigenType,
2348 mode: EigenMode,
2349 fill_mode: FillMode,
2350 n: usize,
2351 a: &mut DeviceMemory<Complex32>,
2352 lda: usize,
2353 b: &mut DeviceMemory<Complex32>,
2354 ldb: usize,
2355 w: &mut DeviceMemory<f32>,
2356 workspace: &mut DeviceMemory<Complex32>,
2357 dev_info: &mut DeviceMemory<i32>,
2358 params: &SyevjInfo,
2359) -> Result<()> {
2360 ctx.bind()?;
2361 validate_sygvj_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2362 require_info_buffer(dev_info)?;
2363 let lwork = chegvj_buffer_size(ctx, eig_type, mode, fill_mode, n, a, lda, b, ldb, w, params)?;
2364 require_workspace(workspace.len(), lwork)?;
2365 unsafe {
2366 try_ffi!(sys::cusolverDnChegvj(
2367 ctx.as_raw(),
2368 eig_type.into(),
2369 mode.into(),
2370 fill_mode.into(),
2371 to_i32(n, "n")?,
2372 a.as_mut_ptr().cast(),
2373 to_i32(lda, "lda")?,
2374 b.as_mut_ptr().cast(),
2375 to_i32(ldb, "ldb")?,
2376 w.as_mut_ptr().cast(),
2377 workspace.as_mut_ptr().cast(),
2378 to_i32(lwork, "lwork")?,
2379 dev_info.as_mut_ptr().cast(),
2380 params.as_raw(),
2381 ))?;
2382 }
2383 Ok(())
2384}
2385
2386pub fn zhegvj(
2387 ctx: &Context,
2388 eig_type: EigenType,
2389 mode: EigenMode,
2390 fill_mode: FillMode,
2391 n: usize,
2392 a: &mut DeviceMemory<Complex64>,
2393 lda: usize,
2394 b: &mut DeviceMemory<Complex64>,
2395 ldb: usize,
2396 w: &mut DeviceMemory<f64>,
2397 workspace: &mut DeviceMemory<Complex64>,
2398 dev_info: &mut DeviceMemory<i32>,
2399 params: &SyevjInfo,
2400) -> Result<()> {
2401 ctx.bind()?;
2402 validate_sygvj_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2403 require_info_buffer(dev_info)?;
2404 let lwork = zhegvj_buffer_size(ctx, eig_type, mode, fill_mode, n, a, lda, b, ldb, w, params)?;
2405 require_workspace(workspace.len(), lwork)?;
2406 unsafe {
2407 try_ffi!(sys::cusolverDnZhegvj(
2408 ctx.as_raw(),
2409 eig_type.into(),
2410 mode.into(),
2411 fill_mode.into(),
2412 to_i32(n, "n")?,
2413 a.as_mut_ptr().cast(),
2414 to_i32(lda, "lda")?,
2415 b.as_mut_ptr().cast(),
2416 to_i32(ldb, "ldb")?,
2417 w.as_mut_ptr().cast(),
2418 workspace.as_mut_ptr().cast(),
2419 to_i32(lwork, "lwork")?,
2420 dev_info.as_mut_ptr().cast(),
2421 params.as_raw(),
2422 ))?;
2423 }
2424 Ok(())
2425}
2426
2427pub fn ssygvd_buffer_size(
2428 ctx: &Context,
2429 eig_type: EigenType,
2430 mode: EigenMode,
2431 fill_mode: FillMode,
2432 n: usize,
2433 a: &DeviceMemory<f32>,
2434 lda: usize,
2435 b: &DeviceMemory<f32>,
2436 ldb: usize,
2437 w: &DeviceMemory<f32>,
2438) -> Result<usize> {
2439 ctx.bind()?;
2440 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2441 let mut lwork = 0;
2442 unsafe {
2443 try_ffi!(sys::cusolverDnSsygvd_bufferSize(
2444 ctx.as_raw(),
2445 eig_type.into(),
2446 mode.into(),
2447 fill_mode.into(),
2448 to_i32(n, "n")?,
2449 a.as_ptr().cast(),
2450 to_i32(lda, "lda")?,
2451 b.as_ptr().cast(),
2452 to_i32(ldb, "ldb")?,
2453 w.as_ptr().cast(),
2454 &raw mut lwork,
2455 ))?;
2456 }
2457 to_usize(lwork, "lwork")
2458}
2459
2460pub fn dsygvd_buffer_size(
2461 ctx: &Context,
2462 eig_type: EigenType,
2463 mode: EigenMode,
2464 fill_mode: FillMode,
2465 n: usize,
2466 a: &DeviceMemory<f64>,
2467 lda: usize,
2468 b: &DeviceMemory<f64>,
2469 ldb: usize,
2470 w: &DeviceMemory<f64>,
2471) -> Result<usize> {
2472 ctx.bind()?;
2473 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2474 let mut lwork = 0;
2475 unsafe {
2476 try_ffi!(sys::cusolverDnDsygvd_bufferSize(
2477 ctx.as_raw(),
2478 eig_type.into(),
2479 mode.into(),
2480 fill_mode.into(),
2481 to_i32(n, "n")?,
2482 a.as_ptr().cast(),
2483 to_i32(lda, "lda")?,
2484 b.as_ptr().cast(),
2485 to_i32(ldb, "ldb")?,
2486 w.as_ptr().cast(),
2487 &raw mut lwork,
2488 ))?;
2489 }
2490 to_usize(lwork, "lwork")
2491}
2492
2493pub fn chegvd_buffer_size(
2494 ctx: &Context,
2495 eig_type: EigenType,
2496 mode: EigenMode,
2497 fill_mode: FillMode,
2498 n: usize,
2499 a: &DeviceMemory<Complex32>,
2500 lda: usize,
2501 b: &DeviceMemory<Complex32>,
2502 ldb: usize,
2503 w: &DeviceMemory<f32>,
2504) -> Result<usize> {
2505 ctx.bind()?;
2506 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2507 let mut lwork = 0;
2508 unsafe {
2509 try_ffi!(sys::cusolverDnChegvd_bufferSize(
2510 ctx.as_raw(),
2511 eig_type.into(),
2512 mode.into(),
2513 fill_mode.into(),
2514 to_i32(n, "n")?,
2515 a.as_ptr().cast(),
2516 to_i32(lda, "lda")?,
2517 b.as_ptr().cast(),
2518 to_i32(ldb, "ldb")?,
2519 w.as_ptr().cast(),
2520 &raw mut lwork,
2521 ))?;
2522 }
2523 to_usize(lwork, "lwork")
2524}
2525
2526pub fn zhegvd_buffer_size(
2527 ctx: &Context,
2528 eig_type: EigenType,
2529 mode: EigenMode,
2530 fill_mode: FillMode,
2531 n: usize,
2532 a: &DeviceMemory<Complex64>,
2533 lda: usize,
2534 b: &DeviceMemory<Complex64>,
2535 ldb: usize,
2536 w: &DeviceMemory<f64>,
2537) -> Result<usize> {
2538 ctx.bind()?;
2539 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2540 let mut lwork = 0;
2541 unsafe {
2542 try_ffi!(sys::cusolverDnZhegvd_bufferSize(
2543 ctx.as_raw(),
2544 eig_type.into(),
2545 mode.into(),
2546 fill_mode.into(),
2547 to_i32(n, "n")?,
2548 a.as_ptr().cast(),
2549 to_i32(lda, "lda")?,
2550 b.as_ptr().cast(),
2551 to_i32(ldb, "ldb")?,
2552 w.as_ptr().cast(),
2553 &raw mut lwork,
2554 ))?;
2555 }
2556 to_usize(lwork, "lwork")
2557}
2558
2559pub fn ssygvd(
2598 ctx: &Context,
2599 eig_type: EigenType,
2600 mode: EigenMode,
2601 fill_mode: FillMode,
2602 n: usize,
2603 a: &mut DeviceMemory<f32>,
2604 lda: usize,
2605 b: &mut DeviceMemory<f32>,
2606 ldb: usize,
2607 w: &mut DeviceMemory<f32>,
2608 workspace: &mut DeviceMemory<f32>,
2609 dev_info: &mut DeviceMemory<i32>,
2610) -> Result<()> {
2611 ctx.bind()?;
2612 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2613 require_info_buffer(dev_info)?;
2614 let lwork = ssygvd_buffer_size(ctx, eig_type, mode, fill_mode, n, a, lda, b, ldb, w)?;
2615 require_workspace(workspace.len(), lwork)?;
2616 unsafe {
2617 try_ffi!(sys::cusolverDnSsygvd(
2618 ctx.as_raw(),
2619 eig_type.into(),
2620 mode.into(),
2621 fill_mode.into(),
2622 to_i32(n, "n")?,
2623 a.as_mut_ptr().cast(),
2624 to_i32(lda, "lda")?,
2625 b.as_mut_ptr().cast(),
2626 to_i32(ldb, "ldb")?,
2627 w.as_mut_ptr().cast(),
2628 workspace.as_mut_ptr().cast(),
2629 to_i32(lwork, "lwork")?,
2630 dev_info.as_mut_ptr().cast(),
2631 ))?;
2632 }
2633 Ok(())
2634}
2635
2636pub fn dsygvd(
2675 ctx: &Context,
2676 eig_type: EigenType,
2677 mode: EigenMode,
2678 fill_mode: FillMode,
2679 n: usize,
2680 a: &mut DeviceMemory<f64>,
2681 lda: usize,
2682 b: &mut DeviceMemory<f64>,
2683 ldb: usize,
2684 w: &mut DeviceMemory<f64>,
2685 workspace: &mut DeviceMemory<f64>,
2686 dev_info: &mut DeviceMemory<i32>,
2687) -> Result<()> {
2688 ctx.bind()?;
2689 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2690 require_info_buffer(dev_info)?;
2691 let lwork = dsygvd_buffer_size(ctx, eig_type, mode, fill_mode, n, a, lda, b, ldb, w)?;
2692 require_workspace(workspace.len(), lwork)?;
2693 unsafe {
2694 try_ffi!(sys::cusolverDnDsygvd(
2695 ctx.as_raw(),
2696 eig_type.into(),
2697 mode.into(),
2698 fill_mode.into(),
2699 to_i32(n, "n")?,
2700 a.as_mut_ptr().cast(),
2701 to_i32(lda, "lda")?,
2702 b.as_mut_ptr().cast(),
2703 to_i32(ldb, "ldb")?,
2704 w.as_mut_ptr().cast(),
2705 workspace.as_mut_ptr().cast(),
2706 to_i32(lwork, "lwork")?,
2707 dev_info.as_mut_ptr().cast(),
2708 ))?;
2709 }
2710 Ok(())
2711}
2712
2713pub fn chegvd(
2714 ctx: &Context,
2715 eig_type: EigenType,
2716 mode: EigenMode,
2717 fill_mode: FillMode,
2718 n: usize,
2719 a: &mut DeviceMemory<Complex32>,
2720 lda: usize,
2721 b: &mut DeviceMemory<Complex32>,
2722 ldb: usize,
2723 w: &mut DeviceMemory<f32>,
2724 workspace: &mut DeviceMemory<Complex32>,
2725 dev_info: &mut DeviceMemory<i32>,
2726) -> Result<()> {
2727 ctx.bind()?;
2728 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2729 require_info_buffer(dev_info)?;
2730 let lwork = chegvd_buffer_size(ctx, eig_type, mode, fill_mode, n, a, lda, b, ldb, w)?;
2731 require_workspace(workspace.len(), lwork)?;
2732 unsafe {
2733 try_ffi!(sys::cusolverDnChegvd(
2734 ctx.as_raw(),
2735 eig_type.into(),
2736 mode.into(),
2737 fill_mode.into(),
2738 to_i32(n, "n")?,
2739 a.as_mut_ptr().cast(),
2740 to_i32(lda, "lda")?,
2741 b.as_mut_ptr().cast(),
2742 to_i32(ldb, "ldb")?,
2743 w.as_mut_ptr().cast(),
2744 workspace.as_mut_ptr().cast(),
2745 to_i32(lwork, "lwork")?,
2746 dev_info.as_mut_ptr().cast(),
2747 ))?;
2748 }
2749 Ok(())
2750}
2751
2752pub fn zhegvd(
2753 ctx: &Context,
2754 eig_type: EigenType,
2755 mode: EigenMode,
2756 fill_mode: FillMode,
2757 n: usize,
2758 a: &mut DeviceMemory<Complex64>,
2759 lda: usize,
2760 b: &mut DeviceMemory<Complex64>,
2761 ldb: usize,
2762 w: &mut DeviceMemory<f64>,
2763 workspace: &mut DeviceMemory<Complex64>,
2764 dev_info: &mut DeviceMemory<i32>,
2765) -> Result<()> {
2766 ctx.bind()?;
2767 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2768 require_info_buffer(dev_info)?;
2769 let lwork = zhegvd_buffer_size(ctx, eig_type, mode, fill_mode, n, a, lda, b, ldb, w)?;
2770 require_workspace(workspace.len(), lwork)?;
2771 unsafe {
2772 try_ffi!(sys::cusolverDnZhegvd(
2773 ctx.as_raw(),
2774 eig_type.into(),
2775 mode.into(),
2776 fill_mode.into(),
2777 to_i32(n, "n")?,
2778 a.as_mut_ptr().cast(),
2779 to_i32(lda, "lda")?,
2780 b.as_mut_ptr().cast(),
2781 to_i32(ldb, "ldb")?,
2782 w.as_mut_ptr().cast(),
2783 workspace.as_mut_ptr().cast(),
2784 to_i32(lwork, "lwork")?,
2785 dev_info.as_mut_ptr().cast(),
2786 ))?;
2787 }
2788 Ok(())
2789}
2790
2791pub fn ssygvdx_selected_buffer_size(
2792 ctx: &Context,
2793 eig_type: EigenType,
2794 mode: EigenMode,
2795 fill_mode: FillMode,
2796 selection: EigenSelection<f32>,
2797 n: usize,
2798 a: &DeviceMemory<f32>,
2799 lda: usize,
2800 b: &DeviceMemory<f32>,
2801 ldb: usize,
2802 w: &DeviceMemory<f32>,
2803) -> Result<(usize, usize)> {
2804 ctx.bind()?;
2805 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2806 let (range, value_range, index_range) = selection_parts(selection);
2807 let (vl, vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
2808 let mut meig = 0;
2809 let mut lwork = 0;
2810 unsafe {
2811 try_ffi!(sys::cusolverDnSsygvdx_bufferSize(
2812 ctx.as_raw(),
2813 eig_type.into(),
2814 mode.into(),
2815 range.into(),
2816 fill_mode.into(),
2817 to_i32(n, "n")?,
2818 a.as_ptr().cast(),
2819 to_i32(lda, "lda")?,
2820 b.as_ptr().cast(),
2821 to_i32(ldb, "ldb")?,
2822 vl,
2823 vu,
2824 to_i32(il, "il")?,
2825 to_i32(iu, "iu")?,
2826 &raw mut meig,
2827 w.as_ptr().cast(),
2828 &raw mut lwork,
2829 ))?;
2830 }
2831 Ok((to_usize(meig, "meig")?, to_usize(lwork, "lwork")?))
2832}
2833
2834pub fn dsygvdx_selected_buffer_size(
2835 ctx: &Context,
2836 eig_type: EigenType,
2837 mode: EigenMode,
2838 fill_mode: FillMode,
2839 selection: EigenSelection<f64>,
2840 n: usize,
2841 a: &DeviceMemory<f64>,
2842 lda: usize,
2843 b: &DeviceMemory<f64>,
2844 ldb: usize,
2845 w: &DeviceMemory<f64>,
2846) -> Result<(usize, usize)> {
2847 ctx.bind()?;
2848 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2849 let (range, value_range, index_range) = selection_parts(selection);
2850 let (vl, vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
2851 let mut meig = 0;
2852 let mut lwork = 0;
2853 unsafe {
2854 try_ffi!(sys::cusolverDnDsygvdx_bufferSize(
2855 ctx.as_raw(),
2856 eig_type.into(),
2857 mode.into(),
2858 range.into(),
2859 fill_mode.into(),
2860 to_i32(n, "n")?,
2861 a.as_ptr().cast(),
2862 to_i32(lda, "lda")?,
2863 b.as_ptr().cast(),
2864 to_i32(ldb, "ldb")?,
2865 vl,
2866 vu,
2867 to_i32(il, "il")?,
2868 to_i32(iu, "iu")?,
2869 &raw mut meig,
2870 w.as_ptr().cast(),
2871 &raw mut lwork,
2872 ))?;
2873 }
2874 Ok((to_usize(meig, "meig")?, to_usize(lwork, "lwork")?))
2875}
2876
2877pub fn chegvdx_selected_buffer_size(
2878 ctx: &Context,
2879 eig_type: EigenType,
2880 mode: EigenMode,
2881 fill_mode: FillMode,
2882 selection: EigenSelection<f32>,
2883 n: usize,
2884 a: &DeviceMemory<Complex32>,
2885 lda: usize,
2886 b: &DeviceMemory<Complex32>,
2887 ldb: usize,
2888 w: &DeviceMemory<f32>,
2889) -> Result<(usize, usize)> {
2890 ctx.bind()?;
2891 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2892 let (range, value_range, index_range) = selection_parts(selection);
2893 let (vl, vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
2894 let mut meig = 0;
2895 let mut lwork = 0;
2896 unsafe {
2897 try_ffi!(sys::cusolverDnChegvdx_bufferSize(
2898 ctx.as_raw(),
2899 eig_type.into(),
2900 mode.into(),
2901 range.into(),
2902 fill_mode.into(),
2903 to_i32(n, "n")?,
2904 a.as_ptr().cast(),
2905 to_i32(lda, "lda")?,
2906 b.as_ptr().cast(),
2907 to_i32(ldb, "ldb")?,
2908 vl,
2909 vu,
2910 to_i32(il, "il")?,
2911 to_i32(iu, "iu")?,
2912 &raw mut meig,
2913 w.as_ptr().cast(),
2914 &raw mut lwork,
2915 ))?;
2916 }
2917 Ok((to_usize(meig, "meig")?, to_usize(lwork, "lwork")?))
2918}
2919
2920pub fn zhegvdx_selected_buffer_size(
2921 ctx: &Context,
2922 eig_type: EigenType,
2923 mode: EigenMode,
2924 fill_mode: FillMode,
2925 selection: EigenSelection<f64>,
2926 n: usize,
2927 a: &DeviceMemory<Complex64>,
2928 lda: usize,
2929 b: &DeviceMemory<Complex64>,
2930 ldb: usize,
2931 w: &DeviceMemory<f64>,
2932) -> Result<(usize, usize)> {
2933 ctx.bind()?;
2934 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
2935 let (range, value_range, index_range) = selection_parts(selection);
2936 let (vl, vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
2937 let mut meig = 0;
2938 let mut lwork = 0;
2939 unsafe {
2940 try_ffi!(sys::cusolverDnZhegvdx_bufferSize(
2941 ctx.as_raw(),
2942 eig_type.into(),
2943 mode.into(),
2944 range.into(),
2945 fill_mode.into(),
2946 to_i32(n, "n")?,
2947 a.as_ptr().cast(),
2948 to_i32(lda, "lda")?,
2949 b.as_ptr().cast(),
2950 to_i32(ldb, "ldb")?,
2951 vl,
2952 vu,
2953 to_i32(il, "il")?,
2954 to_i32(iu, "iu")?,
2955 &raw mut meig,
2956 w.as_ptr().cast(),
2957 &raw mut lwork,
2958 ))?;
2959 }
2960 Ok((to_usize(meig, "meig")?, to_usize(lwork, "lwork")?))
2961}
2962
2963pub fn ssygvdx_selected(
3003 ctx: &Context,
3004 eig_type: EigenType,
3005 mode: EigenMode,
3006 fill_mode: FillMode,
3007 selection: EigenSelection<f32>,
3008 n: usize,
3009 a: &mut DeviceMemory<f32>,
3010 lda: usize,
3011 b: &mut DeviceMemory<f32>,
3012 ldb: usize,
3013 w: &mut DeviceMemory<f32>,
3014 workspace: &mut DeviceMemory<f32>,
3015 dev_info: &mut DeviceMemory<i32>,
3016) -> Result<usize> {
3017 ctx.bind()?;
3018 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
3019 require_info_buffer(dev_info)?;
3020 let (range, value_range, index_range) = selection_parts(selection);
3021 let (meig, lwork) = ssygvdx_selected_buffer_size(
3022 ctx, eig_type, mode, fill_mode, selection, n, a, lda, b, ldb, w,
3023 )?;
3024 require_workspace(workspace.len(), lwork)?;
3025 let (vl, vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
3026 let mut meig_raw = 0;
3027 unsafe {
3028 try_ffi!(sys::cusolverDnSsygvdx(
3029 ctx.as_raw(),
3030 eig_type.into(),
3031 mode.into(),
3032 range.into(),
3033 fill_mode.into(),
3034 to_i32(n, "n")?,
3035 a.as_mut_ptr().cast(),
3036 to_i32(lda, "lda")?,
3037 b.as_mut_ptr().cast(),
3038 to_i32(ldb, "ldb")?,
3039 vl,
3040 vu,
3041 to_i32(il, "il")?,
3042 to_i32(iu, "iu")?,
3043 &raw mut meig_raw,
3044 w.as_mut_ptr().cast(),
3045 workspace.as_mut_ptr().cast(),
3046 to_i32(lwork, "lwork")?,
3047 dev_info.as_mut_ptr().cast(),
3048 ))?;
3049 }
3050 debug_assert_eq!(meig, to_usize(meig_raw, "meig")?);
3051 Ok(meig)
3052}
3053
3054pub fn dsygvdx_selected(
3094 ctx: &Context,
3095 eig_type: EigenType,
3096 mode: EigenMode,
3097 fill_mode: FillMode,
3098 selection: EigenSelection<f64>,
3099 n: usize,
3100 a: &mut DeviceMemory<f64>,
3101 lda: usize,
3102 b: &mut DeviceMemory<f64>,
3103 ldb: usize,
3104 w: &mut DeviceMemory<f64>,
3105 workspace: &mut DeviceMemory<f64>,
3106 dev_info: &mut DeviceMemory<i32>,
3107) -> Result<usize> {
3108 ctx.bind()?;
3109 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
3110 require_info_buffer(dev_info)?;
3111 let (range, value_range, index_range) = selection_parts(selection);
3112 let (meig, lwork) = dsygvdx_selected_buffer_size(
3113 ctx, eig_type, mode, fill_mode, selection, n, a, lda, b, ldb, w,
3114 )?;
3115 require_workspace(workspace.len(), lwork)?;
3116 let (vl, vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
3117 let mut meig_raw = 0;
3118 unsafe {
3119 try_ffi!(sys::cusolverDnDsygvdx(
3120 ctx.as_raw(),
3121 eig_type.into(),
3122 mode.into(),
3123 range.into(),
3124 fill_mode.into(),
3125 to_i32(n, "n")?,
3126 a.as_mut_ptr().cast(),
3127 to_i32(lda, "lda")?,
3128 b.as_mut_ptr().cast(),
3129 to_i32(ldb, "ldb")?,
3130 vl,
3131 vu,
3132 to_i32(il, "il")?,
3133 to_i32(iu, "iu")?,
3134 &raw mut meig_raw,
3135 w.as_mut_ptr().cast(),
3136 workspace.as_mut_ptr().cast(),
3137 to_i32(lwork, "lwork")?,
3138 dev_info.as_mut_ptr().cast(),
3139 ))?;
3140 }
3141 debug_assert_eq!(meig, to_usize(meig_raw, "meig")?);
3142 Ok(meig)
3143}
3144
3145pub fn chegvdx_selected(
3146 ctx: &Context,
3147 eig_type: EigenType,
3148 mode: EigenMode,
3149 fill_mode: FillMode,
3150 selection: EigenSelection<f32>,
3151 n: usize,
3152 a: &mut DeviceMemory<Complex32>,
3153 lda: usize,
3154 b: &mut DeviceMemory<Complex32>,
3155 ldb: usize,
3156 w: &mut DeviceMemory<f32>,
3157 workspace: &mut DeviceMemory<Complex32>,
3158 dev_info: &mut DeviceMemory<i32>,
3159) -> Result<usize> {
3160 ctx.bind()?;
3161 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
3162 require_info_buffer(dev_info)?;
3163 let (range, value_range, index_range) = selection_parts(selection);
3164 let (meig, lwork) = chegvdx_selected_buffer_size(
3165 ctx, eig_type, mode, fill_mode, selection, n, a, lda, b, ldb, w,
3166 )?;
3167 require_workspace(workspace.len(), lwork)?;
3168 let (vl, vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
3169 let mut meig_raw = 0;
3170 unsafe {
3171 try_ffi!(sys::cusolverDnChegvdx(
3172 ctx.as_raw(),
3173 eig_type.into(),
3174 mode.into(),
3175 range.into(),
3176 fill_mode.into(),
3177 to_i32(n, "n")?,
3178 a.as_mut_ptr().cast(),
3179 to_i32(lda, "lda")?,
3180 b.as_mut_ptr().cast(),
3181 to_i32(ldb, "ldb")?,
3182 vl,
3183 vu,
3184 to_i32(il, "il")?,
3185 to_i32(iu, "iu")?,
3186 &raw mut meig_raw,
3187 w.as_mut_ptr().cast(),
3188 workspace.as_mut_ptr().cast(),
3189 to_i32(lwork, "lwork")?,
3190 dev_info.as_mut_ptr().cast(),
3191 ))?;
3192 }
3193 debug_assert_eq!(meig, to_usize(meig_raw, "meig")?);
3194 Ok(meig)
3195}
3196
3197pub fn zhegvdx_selected(
3198 ctx: &Context,
3199 eig_type: EigenType,
3200 mode: EigenMode,
3201 fill_mode: FillMode,
3202 selection: EigenSelection<f64>,
3203 n: usize,
3204 a: &mut DeviceMemory<Complex64>,
3205 lda: usize,
3206 b: &mut DeviceMemory<Complex64>,
3207 ldb: usize,
3208 w: &mut DeviceMemory<f64>,
3209 workspace: &mut DeviceMemory<Complex64>,
3210 dev_info: &mut DeviceMemory<i32>,
3211) -> Result<usize> {
3212 ctx.bind()?;
3213 validate_sygvd_buffers(n, a.len(), lda, b.len(), ldb, w.len())?;
3214 require_info_buffer(dev_info)?;
3215 let (range, value_range, index_range) = selection_parts(selection);
3216 let (meig, lwork) = zhegvdx_selected_buffer_size(
3217 ctx, eig_type, mode, fill_mode, selection, n, a, lda, b, ldb, w,
3218 )?;
3219 require_workspace(workspace.len(), lwork)?;
3220 let (vl, vu, il, iu) = validate_xsyevdx_range(range, n, value_range, index_range)?;
3221 let mut meig_raw = 0;
3222 unsafe {
3223 try_ffi!(sys::cusolverDnZhegvdx(
3224 ctx.as_raw(),
3225 eig_type.into(),
3226 mode.into(),
3227 range.into(),
3228 fill_mode.into(),
3229 to_i32(n, "n")?,
3230 a.as_mut_ptr().cast(),
3231 to_i32(lda, "lda")?,
3232 b.as_mut_ptr().cast(),
3233 to_i32(ldb, "ldb")?,
3234 vl,
3235 vu,
3236 to_i32(il, "il")?,
3237 to_i32(iu, "iu")?,
3238 &raw mut meig_raw,
3239 w.as_mut_ptr().cast(),
3240 workspace.as_mut_ptr().cast(),
3241 to_i32(lwork, "lwork")?,
3242 dev_info.as_mut_ptr().cast(),
3243 ))?;
3244 }
3245 debug_assert_eq!(meig, to_usize(meig_raw, "meig")?);
3246 Ok(meig)
3247}
3248
3249pub fn ssyevdx_buffer_size(
3250 ctx: &Context,
3251 mode: EigenMode,
3252 range: EigenRange,
3253 fill_mode: FillMode,
3254 n: usize,
3255 a: &DeviceMemory<f32>,
3256 lda: usize,
3257 value_range: (f32, f32),
3258 index_range: (usize, usize),
3259 w: &DeviceMemory<f32>,
3260) -> Result<(usize, usize)> {
3261 ctx.bind()?;
3262 validate_syev_buffers(n, a.len(), lda, w.len())?;
3263 let mut meig = 0;
3264 let mut lwork = 0;
3265 unsafe {
3266 try_ffi!(sys::cusolverDnSsyevdx_bufferSize(
3267 ctx.as_raw(),
3268 mode.into(),
3269 range.into(),
3270 fill_mode.into(),
3271 to_i32(n, "n")?,
3272 a.as_ptr().cast(),
3273 to_i32(lda, "lda")?,
3274 value_range.0,
3275 value_range.1,
3276 to_i32(index_range.0, "il")?,
3277 to_i32(index_range.1, "iu")?,
3278 &raw mut meig,
3279 w.as_ptr().cast(),
3280 &raw mut lwork,
3281 ))?;
3282 }
3283 Ok((to_usize(meig, "meig")?, to_usize(lwork, "lwork")?))
3284}
3285
3286pub fn dsyevdx_buffer_size(
3287 ctx: &Context,
3288 mode: EigenMode,
3289 range: EigenRange,
3290 fill_mode: FillMode,
3291 n: usize,
3292 a: &DeviceMemory<f64>,
3293 lda: usize,
3294 value_range: (f64, f64),
3295 index_range: (usize, usize),
3296 w: &DeviceMemory<f64>,
3297) -> Result<(usize, usize)> {
3298 ctx.bind()?;
3299 validate_syev_buffers(n, a.len(), lda, w.len())?;
3300 let mut meig = 0;
3301 let mut lwork = 0;
3302 unsafe {
3303 try_ffi!(sys::cusolverDnDsyevdx_bufferSize(
3304 ctx.as_raw(),
3305 mode.into(),
3306 range.into(),
3307 fill_mode.into(),
3308 to_i32(n, "n")?,
3309 a.as_ptr().cast(),
3310 to_i32(lda, "lda")?,
3311 value_range.0,
3312 value_range.1,
3313 to_i32(index_range.0, "il")?,
3314 to_i32(index_range.1, "iu")?,
3315 &raw mut meig,
3316 w.as_ptr().cast(),
3317 &raw mut lwork,
3318 ))?;
3319 }
3320 Ok((to_usize(meig, "meig")?, to_usize(lwork, "lwork")?))
3321}
3322
3323pub fn cheevdx_buffer_size(
3324 ctx: &Context,
3325 mode: EigenMode,
3326 range: EigenRange,
3327 fill_mode: FillMode,
3328 n: usize,
3329 a: &DeviceMemory<Complex32>,
3330 lda: usize,
3331 value_range: (f32, f32),
3332 index_range: (usize, usize),
3333 w: &DeviceMemory<f32>,
3334) -> Result<(usize, usize)> {
3335 ctx.bind()?;
3336 validate_syev_buffers(n, a.len(), lda, w.len())?;
3337 let mut meig = 0;
3338 let mut lwork = 0;
3339 unsafe {
3340 try_ffi!(sys::cusolverDnCheevdx_bufferSize(
3341 ctx.as_raw(),
3342 mode.into(),
3343 range.into(),
3344 fill_mode.into(),
3345 to_i32(n, "n")?,
3346 a.as_ptr().cast(),
3347 to_i32(lda, "lda")?,
3348 value_range.0,
3349 value_range.1,
3350 to_i32(index_range.0, "il")?,
3351 to_i32(index_range.1, "iu")?,
3352 &raw mut meig,
3353 w.as_ptr().cast(),
3354 &raw mut lwork,
3355 ))?;
3356 }
3357 Ok((to_usize(meig, "meig")?, to_usize(lwork, "lwork")?))
3358}
3359
3360pub fn zheevdx_buffer_size(
3361 ctx: &Context,
3362 mode: EigenMode,
3363 range: EigenRange,
3364 fill_mode: FillMode,
3365 n: usize,
3366 a: &DeviceMemory<Complex64>,
3367 lda: usize,
3368 value_range: (f64, f64),
3369 index_range: (usize, usize),
3370 w: &DeviceMemory<f64>,
3371) -> Result<(usize, usize)> {
3372 ctx.bind()?;
3373 validate_syev_buffers(n, a.len(), lda, w.len())?;
3374 let mut meig = 0;
3375 let mut lwork = 0;
3376 unsafe {
3377 try_ffi!(sys::cusolverDnZheevdx_bufferSize(
3378 ctx.as_raw(),
3379 mode.into(),
3380 range.into(),
3381 fill_mode.into(),
3382 to_i32(n, "n")?,
3383 a.as_ptr().cast(),
3384 to_i32(lda, "lda")?,
3385 value_range.0,
3386 value_range.1,
3387 to_i32(index_range.0, "il")?,
3388 to_i32(index_range.1, "iu")?,
3389 &raw mut meig,
3390 w.as_ptr().cast(),
3391 &raw mut lwork,
3392 ))?;
3393 }
3394 Ok((to_usize(meig, "meig")?, to_usize(lwork, "lwork")?))
3395}
3396
3397pub fn ssyevdx(
3428 ctx: &Context,
3429 mode: EigenMode,
3430 range: EigenRange,
3431 fill_mode: FillMode,
3432 n: usize,
3433 a: &mut DeviceMemory<f32>,
3434 lda: usize,
3435 value_range: (f32, f32),
3436 index_range: (usize, usize),
3437 w: &mut DeviceMemory<f32>,
3438 workspace: &mut DeviceMemory<f32>,
3439 dev_info: &mut DeviceMemory<i32>,
3440) -> Result<usize> {
3441 ctx.bind()?;
3442 validate_syev_buffers(n, a.len(), lda, w.len())?;
3443 require_info_buffer(dev_info)?;
3444 let (meig, lwork) = ssyevdx_buffer_size(
3445 ctx,
3446 mode,
3447 range,
3448 fill_mode,
3449 n,
3450 a,
3451 lda,
3452 value_range,
3453 index_range,
3454 w,
3455 )?;
3456 require_workspace(workspace.len(), lwork)?;
3457 let mut meig_raw = 0;
3458 unsafe {
3459 try_ffi!(sys::cusolverDnSsyevdx(
3460 ctx.as_raw(),
3461 mode.into(),
3462 range.into(),
3463 fill_mode.into(),
3464 to_i32(n, "n")?,
3465 a.as_mut_ptr().cast(),
3466 to_i32(lda, "lda")?,
3467 value_range.0,
3468 value_range.1,
3469 to_i32(index_range.0, "il")?,
3470 to_i32(index_range.1, "iu")?,
3471 &raw mut meig_raw,
3472 w.as_mut_ptr().cast(),
3473 workspace.as_mut_ptr().cast(),
3474 to_i32(lwork, "lwork")?,
3475 dev_info.as_mut_ptr().cast(),
3476 ))?;
3477 }
3478 debug_assert_eq!(meig, to_usize(meig_raw, "meig")?);
3479 Ok(meig)
3480}
3481
3482pub fn dsyevdx(
3513 ctx: &Context,
3514 mode: EigenMode,
3515 range: EigenRange,
3516 fill_mode: FillMode,
3517 n: usize,
3518 a: &mut DeviceMemory<f64>,
3519 lda: usize,
3520 value_range: (f64, f64),
3521 index_range: (usize, usize),
3522 w: &mut DeviceMemory<f64>,
3523 workspace: &mut DeviceMemory<f64>,
3524 dev_info: &mut DeviceMemory<i32>,
3525) -> Result<usize> {
3526 ctx.bind()?;
3527 validate_syev_buffers(n, a.len(), lda, w.len())?;
3528 require_info_buffer(dev_info)?;
3529 let (meig, lwork) = dsyevdx_buffer_size(
3530 ctx,
3531 mode,
3532 range,
3533 fill_mode,
3534 n,
3535 a,
3536 lda,
3537 value_range,
3538 index_range,
3539 w,
3540 )?;
3541 require_workspace(workspace.len(), lwork)?;
3542 let mut meig_raw = 0;
3543 unsafe {
3544 try_ffi!(sys::cusolverDnDsyevdx(
3545 ctx.as_raw(),
3546 mode.into(),
3547 range.into(),
3548 fill_mode.into(),
3549 to_i32(n, "n")?,
3550 a.as_mut_ptr().cast(),
3551 to_i32(lda, "lda")?,
3552 value_range.0,
3553 value_range.1,
3554 to_i32(index_range.0, "il")?,
3555 to_i32(index_range.1, "iu")?,
3556 &raw mut meig_raw,
3557 w.as_mut_ptr().cast(),
3558 workspace.as_mut_ptr().cast(),
3559 to_i32(lwork, "lwork")?,
3560 dev_info.as_mut_ptr().cast(),
3561 ))?;
3562 }
3563 debug_assert_eq!(meig, to_usize(meig_raw, "meig")?);
3564 Ok(meig)
3565}
3566
3567pub fn cheevdx(
3568 ctx: &Context,
3569 mode: EigenMode,
3570 range: EigenRange,
3571 fill_mode: FillMode,
3572 n: usize,
3573 a: &mut DeviceMemory<Complex32>,
3574 lda: usize,
3575 value_range: (f32, f32),
3576 index_range: (usize, usize),
3577 w: &mut DeviceMemory<f32>,
3578 workspace: &mut DeviceMemory<Complex32>,
3579 dev_info: &mut DeviceMemory<i32>,
3580) -> Result<usize> {
3581 ctx.bind()?;
3582 validate_syev_buffers(n, a.len(), lda, w.len())?;
3583 require_info_buffer(dev_info)?;
3584 let (meig, lwork) = cheevdx_buffer_size(
3585 ctx,
3586 mode,
3587 range,
3588 fill_mode,
3589 n,
3590 a,
3591 lda,
3592 value_range,
3593 index_range,
3594 w,
3595 )?;
3596 require_workspace(workspace.len(), lwork)?;
3597 let mut meig_raw = 0;
3598 unsafe {
3599 try_ffi!(sys::cusolverDnCheevdx(
3600 ctx.as_raw(),
3601 mode.into(),
3602 range.into(),
3603 fill_mode.into(),
3604 to_i32(n, "n")?,
3605 a.as_mut_ptr().cast(),
3606 to_i32(lda, "lda")?,
3607 value_range.0,
3608 value_range.1,
3609 to_i32(index_range.0, "il")?,
3610 to_i32(index_range.1, "iu")?,
3611 &raw mut meig_raw,
3612 w.as_mut_ptr().cast(),
3613 workspace.as_mut_ptr().cast(),
3614 to_i32(lwork, "lwork")?,
3615 dev_info.as_mut_ptr().cast(),
3616 ))?;
3617 }
3618 debug_assert_eq!(meig, to_usize(meig_raw, "meig")?);
3619 Ok(meig)
3620}
3621
3622pub fn zheevdx(
3623 ctx: &Context,
3624 mode: EigenMode,
3625 range: EigenRange,
3626 fill_mode: FillMode,
3627 n: usize,
3628 a: &mut DeviceMemory<Complex64>,
3629 lda: usize,
3630 value_range: (f64, f64),
3631 index_range: (usize, usize),
3632 w: &mut DeviceMemory<f64>,
3633 workspace: &mut DeviceMemory<Complex64>,
3634 dev_info: &mut DeviceMemory<i32>,
3635) -> Result<usize> {
3636 ctx.bind()?;
3637 validate_syev_buffers(n, a.len(), lda, w.len())?;
3638 require_info_buffer(dev_info)?;
3639 let (meig, lwork) = zheevdx_buffer_size(
3640 ctx,
3641 mode,
3642 range,
3643 fill_mode,
3644 n,
3645 a,
3646 lda,
3647 value_range,
3648 index_range,
3649 w,
3650 )?;
3651 require_workspace(workspace.len(), lwork)?;
3652 let mut meig_raw = 0;
3653 unsafe {
3654 try_ffi!(sys::cusolverDnZheevdx(
3655 ctx.as_raw(),
3656 mode.into(),
3657 range.into(),
3658 fill_mode.into(),
3659 to_i32(n, "n")?,
3660 a.as_mut_ptr().cast(),
3661 to_i32(lda, "lda")?,
3662 value_range.0,
3663 value_range.1,
3664 to_i32(index_range.0, "il")?,
3665 to_i32(index_range.1, "iu")?,
3666 &raw mut meig_raw,
3667 w.as_mut_ptr().cast(),
3668 workspace.as_mut_ptr().cast(),
3669 to_i32(lwork, "lwork")?,
3670 dev_info.as_mut_ptr().cast(),
3671 ))?;
3672 }
3673 debug_assert_eq!(meig, to_usize(meig_raw, "meig")?);
3674 Ok(meig)
3675}
3676
3677fn validate_syev_buffers(n: usize, a_len: usize, lda: usize, w_len: usize) -> Result<()> {
3678 validate_square_matrix(n, a_len, lda)?;
3679 if w_len < n {
3680 return Err(Error::InvalidVectorShape);
3681 }
3682 Ok(())
3683}
3684
3685fn validate_square_matrix(n: usize, len: usize, lda: usize) -> Result<()> {
3686 validate_matrix(n, n, len, lda)
3687}
3688
3689fn validate_matrix(rows: usize, cols: usize, len: usize, lda: usize) -> Result<()> {
3690 if rows == 0 || cols == 0 {
3691 return Err(Error::InvalidMatrixShape);
3692 }
3693 if lda < rows {
3694 return Err(Error::InvalidLeadingDimension);
3695 }
3696 let required = lda.checked_mul(cols).ok_or(Error::InvalidMatrixShape)?;
3697 if len < required {
3698 return Err(Error::InvalidMatrixShape);
3699 }
3700 Ok(())
3701}
3702
3703fn require_workspace(actual: usize, required: usize) -> Result<()> {
3704 if actual < required {
3705 return Err(Error::InsufficientWorkspaceSize { required, actual });
3706 }
3707 Ok(())
3708}
3709
3710fn require_workspace_bytes(actual: usize, required: usize) -> Result<()> {
3711 if actual < required {
3712 return Err(Error::InsufficientWorkspaceSize { required, actual });
3713 }
3714 Ok(())
3715}
3716
3717fn require_host_workspace(actual: usize, required: usize) -> Result<()> {
3718 if actual < required {
3719 return Err(Error::InsufficientWorkspaceSize { required, actual });
3720 }
3721 Ok(())
3722}
3723
3724fn require_info_buffer(dev_info: &DeviceMemory<i32>) -> Result<()> {
3725 if dev_info.is_empty() {
3726 return Err(Error::InvalidVectorShape);
3727 }
3728 Ok(())
3729}
3730
3731fn validate_xsyevd_buffers(
3732 n: usize,
3733 a_bytes: usize,
3734 lda: usize,
3735 a_type: DataType,
3736 w_bytes: usize,
3737 w_type: DataType,
3738) -> Result<()> {
3739 validate_x_matrix(n, n, a_bytes, lda, a_type)?;
3740 validate_x_vector(n, w_bytes, w_type)?;
3741 Ok(())
3742}
3743
3744fn validate_xsyev_batched_buffers(
3745 n: usize,
3746 a_bytes: usize,
3747 lda: usize,
3748 a_type: DataType,
3749 w_bytes: usize,
3750 w_type: DataType,
3751 batch_count: usize,
3752) -> Result<()> {
3753 if batch_count == 0 {
3754 return Err(Error::InvalidMatrixShape);
3755 }
3756 validate_x_matrix(
3757 n,
3758 n.checked_mul(batch_count)
3759 .ok_or(Error::InvalidMatrixShape)?,
3760 a_bytes,
3761 lda,
3762 a_type,
3763 )?;
3764 validate_x_vector(
3765 n.checked_mul(batch_count)
3766 .ok_or(Error::InvalidVectorShape)?,
3767 w_bytes,
3768 w_type,
3769 )?;
3770 let problem_size = n
3771 .checked_mul(lda)
3772 .and_then(|value| value.checked_mul(batch_count))
3773 .ok_or(Error::InvalidMatrixShape)?;
3774 if problem_size > i32::MAX as usize {
3775 return Err(Error::OutOfRange {
3776 name: "batched problem size".into(),
3777 });
3778 }
3779 Ok(())
3780}
3781
3782fn validate_syevj_batched_buffers(
3783 n: usize,
3784 a_len: usize,
3785 lda: usize,
3786 w_len: usize,
3787 batch_count: usize,
3788) -> Result<()> {
3789 if batch_count == 0 {
3790 return Err(Error::InvalidMatrixShape);
3791 }
3792 let matrix_cols = n
3793 .checked_mul(batch_count)
3794 .ok_or(Error::InvalidMatrixShape)?;
3795 validate_matrix(n, matrix_cols, a_len, lda)?;
3796 let eigenvalues = n
3797 .checked_mul(batch_count)
3798 .ok_or(Error::InvalidVectorShape)?;
3799 if w_len < eigenvalues {
3800 return Err(Error::InvalidVectorShape);
3801 }
3802 Ok(())
3803}
3804
3805fn validate_sygvj_buffers(
3806 n: usize,
3807 a_len: usize,
3808 lda: usize,
3809 b_len: usize,
3810 ldb: usize,
3811 w_len: usize,
3812) -> Result<()> {
3813 validate_square_matrix(n, a_len, lda)?;
3814 validate_square_matrix(n, b_len, ldb)?;
3815 if w_len < n {
3816 return Err(Error::InvalidVectorShape);
3817 }
3818 Ok(())
3819}
3820
3821fn validate_sygvd_buffers(
3822 n: usize,
3823 a_len: usize,
3824 lda: usize,
3825 b_len: usize,
3826 ldb: usize,
3827 w_len: usize,
3828) -> Result<()> {
3829 validate_square_matrix(n, a_len, lda)?;
3830 validate_square_matrix(n, b_len, ldb)?;
3831 if w_len < n {
3832 return Err(Error::InvalidVectorShape);
3833 }
3834 Ok(())
3835}
3836
3837fn validate_x_matrix(
3838 rows: usize,
3839 cols: usize,
3840 bytes: usize,
3841 lda: usize,
3842 data_type: DataType,
3843) -> Result<()> {
3844 if rows == 0 || cols == 0 {
3845 return Err(Error::InvalidMatrixShape);
3846 }
3847 if lda < rows {
3848 return Err(Error::InvalidLeadingDimension);
3849 }
3850 let required = lda
3851 .checked_mul(cols)
3852 .and_then(|count| count.checked_mul(data_type.size_in_bytes()))
3853 .ok_or(Error::InvalidMatrixShape)?;
3854 if bytes < required {
3855 return Err(Error::InvalidMatrixShape);
3856 }
3857 Ok(())
3858}
3859
3860fn validate_x_vector(len: usize, bytes: usize, data_type: DataType) -> Result<()> {
3861 let required = len
3862 .checked_mul(data_type.size_in_bytes())
3863 .ok_or(Error::InvalidVectorShape)?;
3864 if bytes < required {
3865 return Err(Error::InvalidVectorShape);
3866 }
3867 Ok(())
3868}
3869
3870fn validate_xsyevdx_value_type<T>(w_type: DataType) -> Result<()> {
3871 if size_of::<T>() != w_type.size_in_bytes() {
3872 return Err(Error::InvalidEigRange);
3873 }
3874 Ok(())
3875}
3876
3877type EigenSelectionParts<T> = (EigenRange, Option<(T, T)>, Option<(usize, usize)>);
3878
3879fn validate_xsyevdx_range<T>(
3880 range: EigenRange,
3881 n: usize,
3882 value_range: Option<(T, T)>,
3883 index_range: Option<(usize, usize)>,
3884) -> Result<(T, T, usize, usize)>
3885where
3886 T: Default,
3887{
3888 match range {
3889 EigenRange::All => {
3890 if value_range.is_some() || index_range.is_some() {
3891 return Err(Error::InvalidEigRange);
3892 }
3893 Ok((T::default(), T::default(), 0, 0))
3894 }
3895 EigenRange::Value => {
3896 if index_range.is_some() {
3897 return Err(Error::InvalidEigRange);
3898 }
3899 let Some((vl, vu)) = value_range else {
3900 return Err(Error::InvalidEigRange);
3901 };
3902 Ok((vl, vu, 0, 0))
3903 }
3904 EigenRange::Index => {
3905 if value_range.is_some() {
3906 return Err(Error::InvalidEigRange);
3907 }
3908 let Some((il, iu)) = index_range else {
3909 return Err(Error::InvalidEigRange);
3910 };
3911 if il == 0 || iu == 0 || il > iu || iu > n {
3912 return Err(Error::InvalidEigRange);
3913 }
3914 Ok((T::default(), T::default(), il, iu))
3915 }
3916 }
3917}
3918
3919fn selection_parts<T>(selection: EigenSelection<T>) -> EigenSelectionParts<T> {
3920 match selection {
3921 EigenSelection::All => (EigenRange::All, None, None),
3922 EigenSelection::ByValue { lower, upper } => (EigenRange::Value, Some((lower, upper)), None),
3923 EigenSelection::ByIndex { start, end } => (EigenRange::Index, None, Some((start, end))),
3924 }
3925}
3926
3927fn matrix_ref_parts<T>(matrix: Option<MatrixRef<'_, T>>) -> Option<(&DeviceMemory<T>, usize)> {
3928 matrix.map(|matrix| (matrix.data, matrix.leading_dimension))
3929}
3930
3931fn matrix_mut_parts<T>(matrix: Option<MatrixMut<'_, T>>) -> Option<(&mut DeviceMemory<T>, usize)> {
3932 matrix.map(|matrix| (matrix.data, matrix.leading_dimension))
3933}
3934
3935fn matrix_mut_ref_parts<'a, T>(
3936 matrix: Option<&'a MatrixMut<'a, T>>,
3937) -> Option<(&'a DeviceMemory<T>, usize)> {
3938 matrix.map(|matrix| (&*matrix.data, matrix.leading_dimension))
3939}
3940
3941fn matrix_mut_ref_option<'a, T>(matrix: Option<&'a MatrixMut<'a, T>>) -> Option<MatrixRef<'a, T>> {
3942 matrix.map(MatrixMut::as_ref)
3943}
3944
3945fn validate_xgeev_inputs<TV>(
3946 n: usize,
3947 a_bytes: usize,
3948 lda: usize,
3949 a_type: DataType,
3950 w_bytes: usize,
3951 w_type: DataType,
3952 right_vectors: Option<(&DeviceMemory<TV>, usize)>,
3953 vr_type: DataType,
3954) -> Result<()> {
3955 validate_x_matrix(n, n, a_bytes, lda, a_type)?;
3956 validate_xgeev_eigenvalues(n, w_bytes, a_type, w_type)?;
3957 if let Some((vr, ldvr)) = right_vectors {
3958 validate_x_matrix(n, n, vr.byte_len(), ldvr, vr_type)?;
3959 }
3960 Ok(())
3961}
3962
3963fn validate_xgeev_eigenvalues(
3964 n: usize,
3965 w_bytes: usize,
3966 a_type: DataType,
3967 w_type: DataType,
3968) -> Result<()> {
3969 let expected_len = match (a_type, w_type) {
3970 (DataType::F32, DataType::F32) | (DataType::F64, DataType::F64) => {
3971 n.checked_mul(2).ok_or(Error::InvalidVectorShape)?
3972 }
3973 (DataType::F32, DataType::ComplexF32)
3974 | (DataType::F64, DataType::ComplexF64)
3975 | (DataType::ComplexF32, DataType::ComplexF32)
3976 | (DataType::ComplexF64, DataType::ComplexF64) => n,
3977 _ => return Err(Error::InvalidVectorShape),
3978 };
3979 validate_x_vector(expected_len, w_bytes, w_type)
3980}
3981
3982fn optional_xgeev_matrix_ptr<T: DataTypeLike>(
3983 matrix: Option<(&DeviceMemory<T>, usize)>,
3984) -> Result<(*const T, i64)> {
3985 match matrix {
3986 Some((matrix, ld)) => Ok((matrix.as_ptr().cast(), to_i64(ld, "ldvr")?)),
3987 None => Ok((ptr::null(), 1)),
3988 }
3989}
3990
3991fn optional_xgeev_matrix_mut_ptr<T: DataTypeLike>(
3992 matrix: Option<(&mut DeviceMemory<T>, usize)>,
3993) -> Result<(*mut T, i64)> {
3994 match matrix {
3995 Some((matrix, ld)) => Ok((matrix.as_mut_ptr().cast(), to_i64(ld, "ldvr")?)),
3996 None => Ok((ptr::null_mut(), 1)),
3997 }
3998}
3999
4000fn require_info_buffer_len(dev_info: &DeviceMemory<i32>, required: usize) -> Result<()> {
4001 if dev_info.len() < required {
4002 return Err(Error::InvalidVectorShape);
4003 }
4004 Ok(())
4005}
4006
4007#[cfg(test)]
4008mod tests {
4009 use super::{EigenSelection, selection_parts};
4010 use crate::types::EigenRange;
4011
4012 #[test]
4013 fn eigen_selection_all_maps_cleanly() {
4014 let (range, values, indices) = selection_parts::<f32>(EigenSelection::All);
4015 assert_eq!(range, EigenRange::All);
4016 assert_eq!(values, None);
4017 assert_eq!(indices, None);
4018 }
4019
4020 #[test]
4021 fn eigen_selection_index_maps_cleanly() {
4022 let (range, values, indices) =
4023 selection_parts::<f64>(EigenSelection::ByIndex { start: 2, end: 5 });
4024 assert_eq!(range, EigenRange::Index);
4025 assert_eq!(values, None);
4026 assert_eq!(indices, Some((2, 5)));
4027 }
4028}