singe_cusolver/dense/legacy/bidiagonal.rs
1use singe_cuda::{
2 memory::DeviceMemory,
3 types::{Complex32, Complex64},
4};
5
6use crate::{
7 context::Context,
8 dense::validation::{
9 require_info_buffer, require_workspace, validate_bidiagonal_buffers,
10 validate_bidiagonal_dims, validate_orgbr_inputs,
11 },
12 error::Result,
13 sys, try_ffi,
14 types::SideMode,
15 utility::{to_i32, to_usize},
16};
17
18pub fn sgebrd_buffer_size(ctx: &Context, m: usize, n: usize) -> Result<usize> {
19 ctx.bind()?;
20 validate_bidiagonal_dims(m, n)?;
21 let mut lwork = 0;
22 unsafe {
23 try_ffi!(sys::cusolverDnSgebrd_bufferSize(
24 ctx.as_raw(),
25 to_i32(m, "m")?,
26 to_i32(n, "n")?,
27 &raw mut lwork,
28 ))?;
29 }
30 to_usize(lwork, "lwork")
31}
32
33pub fn dgebrd_buffer_size(ctx: &Context, m: usize, n: usize) -> Result<usize> {
34 ctx.bind()?;
35 validate_bidiagonal_dims(m, n)?;
36 let mut lwork = 0;
37 unsafe {
38 try_ffi!(sys::cusolverDnDgebrd_bufferSize(
39 ctx.as_raw(),
40 to_i32(m, "m")?,
41 to_i32(n, "n")?,
42 &raw mut lwork,
43 ))?;
44 }
45 to_usize(lwork, "lwork")
46}
47
48pub fn cgebrd_buffer_size(ctx: &Context, m: usize, n: usize) -> Result<usize> {
49 ctx.bind()?;
50 validate_bidiagonal_dims(m, n)?;
51 let mut lwork = 0;
52 unsafe {
53 try_ffi!(sys::cusolverDnCgebrd_bufferSize(
54 ctx.as_raw(),
55 to_i32(m, "m")?,
56 to_i32(n, "n")?,
57 &raw mut lwork,
58 ))?;
59 }
60 to_usize(lwork, "lwork")
61}
62
63pub fn zgebrd_buffer_size(ctx: &Context, m: usize, n: usize) -> Result<usize> {
64 ctx.bind()?;
65 validate_bidiagonal_dims(m, n)?;
66 let mut lwork = 0;
67 unsafe {
68 try_ffi!(sys::cusolverDnZgebrd_bufferSize(
69 ctx.as_raw(),
70 to_i32(m, "m")?,
71 to_i32(n, "n")?,
72 &raw mut lwork,
73 ))?;
74 }
75 to_usize(lwork, "lwork")
76}
77
78/// Use the matching buffer-size helper to calculate the required workspace size.
79///
80/// The S and D data types are real valued single and double precision, respectively.
81///
82/// The C and Z data types are complex valued single and double precision, respectively.
83///
84/// Reduces a general $m \times n$ matrix `A` to a real upper or lower
85/// bidiagonal form `B` by an orthogonal transformation:
86/// $Q^{H}\cdot A\cdot P = B$.
87///
88/// If `m >= n`, `B` is upper bidiagonal; if `m < n`, `B` is lower
89/// bidiagonal.
90///
91/// The matrix `Q` and `P` are overwritten into matrix `A` in the following sense:
92///
93/// - If `m >= n`, the diagonal and first superdiagonal are overwritten with
94/// the upper bidiagonal matrix `B`. Elements below the diagonal, together
95/// with `tauq`, represent `Q`; elements above the first superdiagonal,
96/// together with `taup`, represent `P`.
97/// - If `m < n`, the diagonal and first subdiagonal are overwritten with the
98/// lower bidiagonal matrix `B`. Elements below the first subdiagonal,
99/// together with `tauq`, represent `Q`; elements above the diagonal,
100/// together with `taup`, represent `P`.
101///
102/// Provide workspace through `workspace`.
103/// Use the corresponding `*_buffer_size` helper to query the required workspace length.
104///
105/// If the reported `dev_info` value is `-i`, the `i`th parameter is invalid.
106///
107/// `gebrd` only supports `m >= n`.
108///
109/// # Errors
110///
111/// Returns an error if cuSOLVER has not been initialized, if the
112/// matrix dimensions or leading dimension are invalid, if the current GPU
113/// architecture is unsupported, or if cuSOLVER reports an internal failure.
114pub fn sgebrd(
115 ctx: &Context,
116 m: usize,
117 n: usize,
118 a: &mut DeviceMemory<f32>,
119 lda: usize,
120 d: &mut DeviceMemory<f32>,
121 e: &mut DeviceMemory<f32>,
122 tauq: &mut DeviceMemory<f32>,
123 taup: &mut DeviceMemory<f32>,
124 workspace: &mut DeviceMemory<f32>,
125 dev_info: &mut DeviceMemory<i32>,
126) -> Result<()> {
127 ctx.bind()?;
128 validate_bidiagonal_buffers(m, n, a.len(), lda, d.len(), e.len(), tauq.len(), taup.len())?;
129 require_info_buffer(dev_info)?;
130 let lwork = sgebrd_buffer_size(ctx, m, n)?;
131 require_workspace(workspace.len(), lwork)?;
132 unsafe {
133 try_ffi!(sys::cusolverDnSgebrd(
134 ctx.as_raw(),
135 to_i32(m, "m")?,
136 to_i32(n, "n")?,
137 a.as_mut_ptr().cast(),
138 to_i32(lda, "lda")?,
139 d.as_mut_ptr().cast(),
140 e.as_mut_ptr().cast(),
141 tauq.as_mut_ptr().cast(),
142 taup.as_mut_ptr().cast(),
143 workspace.as_mut_ptr().cast(),
144 to_i32(lwork, "lwork")?,
145 dev_info.as_mut_ptr().cast(),
146 ))?;
147 }
148 Ok(())
149}
150
151/// Use the matching buffer-size helper to calculate the required workspace size.
152///
153/// The S and D data types are real valued single and double precision, respectively.
154///
155/// The C and Z data types are complex valued single and double precision, respectively.
156///
157/// Reduces a general $m \times n$ matrix `A` to a real upper or lower
158/// bidiagonal form `B` by an orthogonal transformation:
159/// $Q^{H}\cdot A\cdot P = B$.
160///
161/// If `m >= n`, `B` is upper bidiagonal; if `m < n`, `B` is lower
162/// bidiagonal.
163///
164/// The matrix `Q` and `P` are overwritten into matrix `A` in the following sense:
165///
166/// - If `m >= n`, the diagonal and first superdiagonal are overwritten with
167/// the upper bidiagonal matrix `B`. Elements below the diagonal, together
168/// with `tauq`, represent `Q`; elements above the first superdiagonal,
169/// together with `taup`, represent `P`.
170/// - If `m < n`, the diagonal and first subdiagonal are overwritten with the
171/// lower bidiagonal matrix `B`. Elements below the first subdiagonal,
172/// together with `tauq`, represent `Q`; elements above the diagonal,
173/// together with `taup`, represent `P`.
174///
175/// Provide workspace through `workspace`.
176/// Use the corresponding `*_buffer_size` helper to query the required workspace length.
177///
178/// If the reported `dev_info` value is `-i`, the `i`th parameter is invalid.
179///
180/// `gebrd` only supports `m >= n`.
181///
182/// # Errors
183///
184/// Returns an error if cuSOLVER has not been initialized, if the
185/// matrix dimensions or leading dimension are invalid, if the current GPU
186/// architecture is unsupported, or if cuSOLVER reports an internal failure.
187pub fn dgebrd(
188 ctx: &Context,
189 m: usize,
190 n: usize,
191 a: &mut DeviceMemory<f64>,
192 lda: usize,
193 d: &mut DeviceMemory<f64>,
194 e: &mut DeviceMemory<f64>,
195 tauq: &mut DeviceMemory<f64>,
196 taup: &mut DeviceMemory<f64>,
197 workspace: &mut DeviceMemory<f64>,
198 dev_info: &mut DeviceMemory<i32>,
199) -> Result<()> {
200 ctx.bind()?;
201 validate_bidiagonal_buffers(m, n, a.len(), lda, d.len(), e.len(), tauq.len(), taup.len())?;
202 require_info_buffer(dev_info)?;
203 let lwork = dgebrd_buffer_size(ctx, m, n)?;
204 require_workspace(workspace.len(), lwork)?;
205 unsafe {
206 try_ffi!(sys::cusolverDnDgebrd(
207 ctx.as_raw(),
208 to_i32(m, "m")?,
209 to_i32(n, "n")?,
210 a.as_mut_ptr().cast(),
211 to_i32(lda, "lda")?,
212 d.as_mut_ptr().cast(),
213 e.as_mut_ptr().cast(),
214 tauq.as_mut_ptr().cast(),
215 taup.as_mut_ptr().cast(),
216 workspace.as_mut_ptr().cast(),
217 to_i32(lwork, "lwork")?,
218 dev_info.as_mut_ptr().cast(),
219 ))?;
220 }
221 Ok(())
222}
223
224/// Use the matching buffer-size helper to calculate the required workspace size.
225///
226/// The S and D data types are real valued single and double precision, respectively.
227///
228/// The C and Z data types are complex valued single and double precision, respectively.
229///
230/// Reduces a general $m \times n$ matrix `A` to a real upper or lower
231/// bidiagonal form `B` by an orthogonal transformation:
232/// $Q^{H}\cdot A\cdot P = B$.
233///
234/// If `m >= n`, `B` is upper bidiagonal; if `m < n`, `B` is lower
235/// bidiagonal.
236///
237/// The matrix `Q` and `P` are overwritten into matrix `A` in the following sense:
238///
239/// - If `m >= n`, the diagonal and first superdiagonal are overwritten with
240/// the upper bidiagonal matrix `B`. Elements below the diagonal, together
241/// with `tauq`, represent `Q`; elements above the first superdiagonal,
242/// together with `taup`, represent `P`.
243/// - If `m < n`, the diagonal and first subdiagonal are overwritten with the
244/// lower bidiagonal matrix `B`. Elements below the first subdiagonal,
245/// together with `tauq`, represent `Q`; elements above the diagonal,
246/// together with `taup`, represent `P`.
247///
248/// Provide workspace through `workspace`.
249/// Use the corresponding `*_buffer_size` helper to query the required workspace length.
250///
251/// If the reported `dev_info` value is `-i`, the `i`th parameter is invalid.
252///
253/// `gebrd` only supports `m >= n`.
254///
255/// # Errors
256///
257/// Returns an error if cuSOLVER has not been initialized, if the
258/// matrix dimensions or leading dimension are invalid, if the current GPU
259/// architecture is unsupported, or if cuSOLVER reports an internal failure.
260pub fn cgebrd(
261 ctx: &Context,
262 m: usize,
263 n: usize,
264 a: &mut DeviceMemory<Complex32>,
265 lda: usize,
266 d: &mut DeviceMemory<f32>,
267 e: &mut DeviceMemory<f32>,
268 tauq: &mut DeviceMemory<Complex32>,
269 taup: &mut DeviceMemory<Complex32>,
270 workspace: &mut DeviceMemory<Complex32>,
271 dev_info: &mut DeviceMemory<i32>,
272) -> Result<()> {
273 ctx.bind()?;
274 validate_bidiagonal_buffers(m, n, a.len(), lda, d.len(), e.len(), tauq.len(), taup.len())?;
275 require_info_buffer(dev_info)?;
276 let lwork = cgebrd_buffer_size(ctx, m, n)?;
277 require_workspace(workspace.len(), lwork)?;
278 unsafe {
279 try_ffi!(sys::cusolverDnCgebrd(
280 ctx.as_raw(),
281 to_i32(m, "m")?,
282 to_i32(n, "n")?,
283 a.as_mut_ptr().cast(),
284 to_i32(lda, "lda")?,
285 d.as_mut_ptr().cast(),
286 e.as_mut_ptr().cast(),
287 tauq.as_mut_ptr().cast(),
288 taup.as_mut_ptr().cast(),
289 workspace.as_mut_ptr().cast(),
290 to_i32(lwork, "lwork")?,
291 dev_info.as_mut_ptr().cast(),
292 ))?;
293 }
294 Ok(())
295}
296
297/// Use the matching buffer-size helper to calculate the required workspace size.
298///
299/// The S and D data types are real valued single and double precision, respectively.
300///
301/// The C and Z data types are complex valued single and double precision, respectively.
302///
303/// Reduces a general $m \times n$ matrix `A` to a real upper or lower
304/// bidiagonal form `B` by an orthogonal transformation:
305/// $Q^{H}\cdot A\cdot P = B$.
306///
307/// If `m >= n`, `B` is upper bidiagonal; if `m < n`, `B` is lower
308/// bidiagonal.
309///
310/// The matrix `Q` and `P` are overwritten into matrix `A` in the following sense:
311///
312/// - If `m >= n`, the diagonal and first superdiagonal are overwritten with
313/// the upper bidiagonal matrix `B`. Elements below the diagonal, together
314/// with `tauq`, represent `Q`; elements above the first superdiagonal,
315/// together with `taup`, represent `P`.
316/// - If `m < n`, the diagonal and first subdiagonal are overwritten with the
317/// lower bidiagonal matrix `B`. Elements below the first subdiagonal,
318/// together with `tauq`, represent `Q`; elements above the diagonal,
319/// together with `taup`, represent `P`.
320///
321/// Provide workspace through `workspace`.
322/// Use the corresponding `*_buffer_size` helper to query the required workspace length.
323///
324/// If the reported `dev_info` value is `-i`, the `i`th parameter is invalid.
325///
326/// `gebrd` only supports `m >= n`.
327///
328/// # Errors
329///
330/// Returns an error if cuSOLVER has not been initialized, if the
331/// matrix dimensions or leading dimension are invalid, if the current GPU
332/// architecture is unsupported, or if cuSOLVER reports an internal failure.
333pub fn zgebrd(
334 ctx: &Context,
335 m: usize,
336 n: usize,
337 a: &mut DeviceMemory<Complex64>,
338 lda: usize,
339 d: &mut DeviceMemory<f64>,
340 e: &mut DeviceMemory<f64>,
341 tauq: &mut DeviceMemory<Complex64>,
342 taup: &mut DeviceMemory<Complex64>,
343 workspace: &mut DeviceMemory<Complex64>,
344 dev_info: &mut DeviceMemory<i32>,
345) -> Result<()> {
346 ctx.bind()?;
347 validate_bidiagonal_buffers(m, n, a.len(), lda, d.len(), e.len(), tauq.len(), taup.len())?;
348 require_info_buffer(dev_info)?;
349 let lwork = zgebrd_buffer_size(ctx, m, n)?;
350 require_workspace(workspace.len(), lwork)?;
351 unsafe {
352 try_ffi!(sys::cusolverDnZgebrd(
353 ctx.as_raw(),
354 to_i32(m, "m")?,
355 to_i32(n, "n")?,
356 a.as_mut_ptr().cast(),
357 to_i32(lda, "lda")?,
358 d.as_mut_ptr().cast(),
359 e.as_mut_ptr().cast(),
360 tauq.as_mut_ptr().cast(),
361 taup.as_mut_ptr().cast(),
362 workspace.as_mut_ptr().cast(),
363 to_i32(lwork, "lwork")?,
364 dev_info.as_mut_ptr().cast(),
365 ))?;
366 }
367 Ok(())
368}
369
370pub fn sorgbr_buffer_size(
371 ctx: &Context,
372 side: SideMode,
373 m: usize,
374 n: usize,
375 k: usize,
376 a: &DeviceMemory<f32>,
377 lda: usize,
378 tau: &DeviceMemory<f32>,
379) -> Result<usize> {
380 ctx.bind()?;
381 validate_orgbr_inputs(side, m, n, k, a.len(), lda, tau.len())?;
382 let mut lwork = 0;
383 unsafe {
384 try_ffi!(sys::cusolverDnSorgbr_bufferSize(
385 ctx.as_raw(),
386 side.into(),
387 to_i32(m, "m")?,
388 to_i32(n, "n")?,
389 to_i32(k, "k")?,
390 a.as_ptr().cast(),
391 to_i32(lda, "lda")?,
392 tau.as_ptr().cast(),
393 &raw mut lwork,
394 ))?;
395 }
396 to_usize(lwork, "lwork")
397}
398
399pub fn dorgbr_buffer_size(
400 ctx: &Context,
401 side: SideMode,
402 m: usize,
403 n: usize,
404 k: usize,
405 a: &DeviceMemory<f64>,
406 lda: usize,
407 tau: &DeviceMemory<f64>,
408) -> Result<usize> {
409 ctx.bind()?;
410 validate_orgbr_inputs(side, m, n, k, a.len(), lda, tau.len())?;
411 let mut lwork = 0;
412 unsafe {
413 try_ffi!(sys::cusolverDnDorgbr_bufferSize(
414 ctx.as_raw(),
415 side.into(),
416 to_i32(m, "m")?,
417 to_i32(n, "n")?,
418 to_i32(k, "k")?,
419 a.as_ptr().cast(),
420 to_i32(lda, "lda")?,
421 tau.as_ptr().cast(),
422 &raw mut lwork,
423 ))?;
424 }
425 to_usize(lwork, "lwork")
426}
427
428pub fn cungbr_buffer_size(
429 ctx: &Context,
430 side: SideMode,
431 m: usize,
432 n: usize,
433 k: usize,
434 a: &DeviceMemory<Complex32>,
435 lda: usize,
436 tau: &DeviceMemory<Complex32>,
437) -> Result<usize> {
438 ctx.bind()?;
439 validate_orgbr_inputs(side, m, n, k, a.len(), lda, tau.len())?;
440 let mut lwork = 0;
441 unsafe {
442 try_ffi!(sys::cusolverDnCungbr_bufferSize(
443 ctx.as_raw(),
444 side.into(),
445 to_i32(m, "m")?,
446 to_i32(n, "n")?,
447 to_i32(k, "k")?,
448 a.as_ptr().cast(),
449 to_i32(lda, "lda")?,
450 tau.as_ptr().cast(),
451 &raw mut lwork,
452 ))?;
453 }
454 to_usize(lwork, "lwork")
455}
456
457pub fn zungbr_buffer_size(
458 ctx: &Context,
459 side: SideMode,
460 m: usize,
461 n: usize,
462 k: usize,
463 a: &DeviceMemory<Complex64>,
464 lda: usize,
465 tau: &DeviceMemory<Complex64>,
466) -> Result<usize> {
467 ctx.bind()?;
468 validate_orgbr_inputs(side, m, n, k, a.len(), lda, tau.len())?;
469 let mut lwork = 0;
470 unsafe {
471 try_ffi!(sys::cusolverDnZungbr_bufferSize(
472 ctx.as_raw(),
473 side.into(),
474 to_i32(m, "m")?,
475 to_i32(n, "n")?,
476 to_i32(k, "k")?,
477 a.as_ptr().cast(),
478 to_i32(lda, "lda")?,
479 tau.as_ptr().cast(),
480 &raw mut lwork,
481 ))?;
482 }
483 to_usize(lwork, "lwork")
484}
485
486/// Use the matching buffer-size helper to calculate the required workspace size.
487///
488/// The S and D data types are real valued single and double precision, respectively.
489///
490/// The C and Z data types are complex valued single and double precision, respectively.
491///
492/// Generates one of the unitary matrices `Q` or $P^{H}$ determined by `gebrd`
493/// when reducing matrix `A` to bidiagonal form:
494/// $Q^{H}\cdot A\cdot P = B$.
495///
496/// `Q` and $P^{H}$ are defined as products of elementary reflectors `H(i)`
497/// or `G(i)`, respectively.
498///
499/// Provide workspace through `workspace`.
500/// Use the corresponding `*_buffer_size` helper to query the required workspace length.
501/// The workspace size in bytes is `size_of::<T>() * lwork`.
502///
503/// If the reported `dev_info` value is `-i`, the `i`th parameter is invalid.
504///
505/// # Errors
506///
507/// Returns an error if cuSOLVER has not been initialized, if the
508/// matrix dimensions or leading dimension are invalid, if the current GPU
509/// architecture is unsupported, or if cuSOLVER reports an internal failure.
510pub fn sorgbr(
511 ctx: &Context,
512 side: SideMode,
513 m: usize,
514 n: usize,
515 k: usize,
516 a: &mut DeviceMemory<f32>,
517 lda: usize,
518 tau: &DeviceMemory<f32>,
519 workspace: &mut DeviceMemory<f32>,
520 dev_info: &mut DeviceMemory<i32>,
521) -> Result<()> {
522 ctx.bind()?;
523 validate_orgbr_inputs(side, m, n, k, a.len(), lda, tau.len())?;
524 require_info_buffer(dev_info)?;
525 let lwork = sorgbr_buffer_size(ctx, side, m, n, k, a, lda, tau)?;
526 require_workspace(workspace.len(), lwork)?;
527 unsafe {
528 try_ffi!(sys::cusolverDnSorgbr(
529 ctx.as_raw(),
530 side.into(),
531 to_i32(m, "m")?,
532 to_i32(n, "n")?,
533 to_i32(k, "k")?,
534 a.as_mut_ptr().cast(),
535 to_i32(lda, "lda")?,
536 tau.as_ptr().cast(),
537 workspace.as_mut_ptr().cast(),
538 to_i32(lwork, "lwork")?,
539 dev_info.as_mut_ptr().cast(),
540 ))?;
541 }
542 Ok(())
543}
544
545/// Use the matching buffer-size helper to calculate the required workspace size.
546///
547/// The S and D data types are real valued single and double precision, respectively.
548///
549/// The C and Z data types are complex valued single and double precision, respectively.
550///
551/// Generates one of the unitary matrices `Q` or $P^{H}$ determined by `gebrd`
552/// when reducing matrix `A` to bidiagonal form:
553/// $Q^{H}\cdot A\cdot P = B$.
554///
555/// `Q` and $P^{H}$ are defined as products of elementary reflectors `H(i)`
556/// or `G(i)`, respectively.
557///
558/// Provide workspace through `workspace`.
559/// Use the corresponding `*_buffer_size` helper to query the required workspace length.
560/// The workspace size in bytes is `size_of::<T>() * lwork`.
561///
562/// If the reported `dev_info` value is `-i`, the `i`th parameter is invalid.
563///
564/// # Errors
565///
566/// Returns an error if cuSOLVER has not been initialized, if the
567/// matrix dimensions or leading dimension are invalid, if the current GPU
568/// architecture is unsupported, or if cuSOLVER reports an internal failure.
569pub fn dorgbr(
570 ctx: &Context,
571 side: SideMode,
572 m: usize,
573 n: usize,
574 k: usize,
575 a: &mut DeviceMemory<f64>,
576 lda: usize,
577 tau: &DeviceMemory<f64>,
578 workspace: &mut DeviceMemory<f64>,
579 dev_info: &mut DeviceMemory<i32>,
580) -> Result<()> {
581 ctx.bind()?;
582 validate_orgbr_inputs(side, m, n, k, a.len(), lda, tau.len())?;
583 require_info_buffer(dev_info)?;
584 let lwork = dorgbr_buffer_size(ctx, side, m, n, k, a, lda, tau)?;
585 require_workspace(workspace.len(), lwork)?;
586 unsafe {
587 try_ffi!(sys::cusolverDnDorgbr(
588 ctx.as_raw(),
589 side.into(),
590 to_i32(m, "m")?,
591 to_i32(n, "n")?,
592 to_i32(k, "k")?,
593 a.as_mut_ptr().cast(),
594 to_i32(lda, "lda")?,
595 tau.as_ptr().cast(),
596 workspace.as_mut_ptr().cast(),
597 to_i32(lwork, "lwork")?,
598 dev_info.as_mut_ptr().cast(),
599 ))?;
600 }
601 Ok(())
602}
603
604pub fn cungbr(
605 ctx: &Context,
606 side: SideMode,
607 m: usize,
608 n: usize,
609 k: usize,
610 a: &mut DeviceMemory<Complex32>,
611 lda: usize,
612 tau: &DeviceMemory<Complex32>,
613 workspace: &mut DeviceMemory<Complex32>,
614 dev_info: &mut DeviceMemory<i32>,
615) -> Result<()> {
616 ctx.bind()?;
617 validate_orgbr_inputs(side, m, n, k, a.len(), lda, tau.len())?;
618 require_info_buffer(dev_info)?;
619 let lwork = cungbr_buffer_size(ctx, side, m, n, k, a, lda, tau)?;
620 require_workspace(workspace.len(), lwork)?;
621 unsafe {
622 try_ffi!(sys::cusolverDnCungbr(
623 ctx.as_raw(),
624 side.into(),
625 to_i32(m, "m")?,
626 to_i32(n, "n")?,
627 to_i32(k, "k")?,
628 a.as_mut_ptr().cast(),
629 to_i32(lda, "lda")?,
630 tau.as_ptr().cast(),
631 workspace.as_mut_ptr().cast(),
632 to_i32(lwork, "lwork")?,
633 dev_info.as_mut_ptr().cast(),
634 ))?;
635 }
636 Ok(())
637}
638
639pub fn zungbr(
640 ctx: &Context,
641 side: SideMode,
642 m: usize,
643 n: usize,
644 k: usize,
645 a: &mut DeviceMemory<Complex64>,
646 lda: usize,
647 tau: &DeviceMemory<Complex64>,
648 workspace: &mut DeviceMemory<Complex64>,
649 dev_info: &mut DeviceMemory<i32>,
650) -> Result<()> {
651 ctx.bind()?;
652 validate_orgbr_inputs(side, m, n, k, a.len(), lda, tau.len())?;
653 require_info_buffer(dev_info)?;
654 let lwork = zungbr_buffer_size(ctx, side, m, n, k, a, lda, tau)?;
655 require_workspace(workspace.len(), lwork)?;
656 unsafe {
657 try_ffi!(sys::cusolverDnZungbr(
658 ctx.as_raw(),
659 side.into(),
660 to_i32(m, "m")?,
661 to_i32(n, "n")?,
662 to_i32(k, "k")?,
663 a.as_mut_ptr().cast(),
664 to_i32(lda, "lda")?,
665 tau.as_ptr().cast(),
666 workspace.as_mut_ptr().cast(),
667 to_i32(lwork, "lwork")?,
668 dev_info.as_mut_ptr().cast(),
669 ))?;
670 }
671 Ok(())
672}