1use std::ffi::CString;
11use std::marker::PhantomData;
12
13use aocl_sparse_sys as sys;
14use aocl_types::{sealed::Sealed, Complex32, Complex64};
15
16use crate::{check_status, trans_raw, Error, IndexBase, MatDescr, Order, Result, SorType, Trans};
17
18pub trait ComplexScalar: Copy + Sized + Sealed {
20 fn axpyi(alpha: Self, x: &[Self], indx: &[sys::aoclsparse_int], y: &mut [Self]) -> Result<()>;
22
23 fn gthr(y: &[Self], indx: &[sys::aoclsparse_int], x: &mut [Self]) -> Result<()>;
25
26 fn sctr(x: &[Self], indx: &[sys::aoclsparse_int], y: &mut [Self]) -> Result<()>;
28
29 #[allow(clippy::too_many_arguments)]
31 fn create_csr(
32 base: IndexBase,
33 m: usize,
34 n: usize,
35 nnz: usize,
36 row_ptr: *mut sys::aoclsparse_int,
37 col_idx: *mut sys::aoclsparse_int,
38 val: *mut Self,
39 ) -> Result<sys::aoclsparse_matrix>;
40
41 fn export_csr(
43 mat: sys::aoclsparse_matrix,
44 ) -> Result<(
45 IndexBase,
46 usize,
47 usize,
48 usize,
49 *mut sys::aoclsparse_int,
50 *mut sys::aoclsparse_int,
51 *mut Self,
52 )>;
53
54 #[allow(clippy::too_many_arguments)]
56 fn mv(
57 op: Trans,
58 alpha: Self,
59 mat: sys::aoclsparse_matrix,
60 descr: &MatDescr,
61 x: &[Self],
62 beta: Self,
63 y: &mut [Self],
64 ) -> Result<()>;
65
66 #[allow(clippy::too_many_arguments)]
68 fn trsv(
69 op: Trans,
70 alpha: Self,
71 mat: sys::aoclsparse_matrix,
72 descr: &MatDescr,
73 b: &[Self],
74 x: &mut [Self],
75 ) -> Result<()>;
76
77 fn ilu_smoother(
79 op: Trans,
80 a: sys::aoclsparse_matrix,
81 descr: &MatDescr,
82 x: &mut [Self],
83 b: &[Self],
84 ) -> Result<()>;
85
86 fn itsol_init(handle: &mut sys::aoclsparse_itsol_handle) -> Result<()>;
88
89 #[allow(clippy::too_many_arguments)]
91 fn itsol_solve(
92 handle: sys::aoclsparse_itsol_handle,
93 n: usize,
94 mat: sys::aoclsparse_matrix,
95 descr: &MatDescr,
96 b: &[Self],
97 x: &mut [Self],
98 rinfo: &mut [Self::Real; 100],
99 ) -> Result<()>;
100
101 #[allow(clippy::too_many_arguments)]
104 fn csrmm(
105 op: Trans,
106 alpha: Self,
107 a: sys::aoclsparse_matrix,
108 descr: &MatDescr,
109 order: Order,
110 b: &[Self],
111 n: usize,
112 ldb: usize,
113 beta: Self,
114 c: &mut [Self],
115 ldc: usize,
116 ) -> Result<()>;
117
118 #[allow(clippy::too_many_arguments)]
120 fn spmmd(
121 op: Trans,
122 a: sys::aoclsparse_matrix,
123 b: sys::aoclsparse_matrix,
124 layout: Order,
125 c: &mut [Self],
126 ldc: usize,
127 ) -> Result<()>;
128
129 #[allow(clippy::too_many_arguments)]
131 fn sp2md(
132 op_a: Trans,
133 descr_a: &MatDescr,
134 a: sys::aoclsparse_matrix,
135 op_b: Trans,
136 descr_b: &MatDescr,
137 b: sys::aoclsparse_matrix,
138 alpha: Self,
139 beta: Self,
140 c: &mut [Self],
141 layout: Order,
142 ldc: usize,
143 ) -> Result<()>;
144
145 unsafe fn add_ffi(
151 op: sys::aoclsparse_operation,
152 a: sys::aoclsparse_matrix,
153 alpha: Self,
154 b: sys::aoclsparse_matrix,
155 out: *mut sys::aoclsparse_matrix,
156 ) -> sys::aoclsparse_status;
157
158 #[allow(clippy::too_many_arguments)]
160 fn sorv(
161 sor_type: SorType,
162 descr: &MatDescr,
163 a: sys::aoclsparse_matrix,
164 omega: Self,
165 alpha: Self,
166 x: &mut [Self],
167 b: &[Self],
168 ) -> Result<()>;
169
170 type Real: Copy + Default;
174}
175
176impl ComplexScalar for Complex32 {
181 type Real = f32;
182
183 fn axpyi(alpha: Self, x: &[Self], indx: &[sys::aoclsparse_int], y: &mut [Self]) -> Result<()> {
184 let status = unsafe {
185 sys::aoclsparse_caxpyi(
186 x.len() as sys::aoclsparse_int,
187 &alpha as *const _ as *const std::os::raw::c_void,
188 x.as_ptr() as *const std::os::raw::c_void,
189 indx.as_ptr(),
190 y.as_mut_ptr() as *mut std::os::raw::c_void,
191 )
192 };
193 check_status("sparse", status)
194 }
195
196 fn gthr(y: &[Self], indx: &[sys::aoclsparse_int], x: &mut [Self]) -> Result<()> {
197 let status = unsafe {
198 sys::aoclsparse_cgthr(
199 x.len() as sys::aoclsparse_int,
200 y.as_ptr() as *const std::os::raw::c_void,
201 x.as_mut_ptr() as *mut std::os::raw::c_void,
202 indx.as_ptr(),
203 )
204 };
205 check_status("sparse", status)
206 }
207
208 fn sctr(x: &[Self], indx: &[sys::aoclsparse_int], y: &mut [Self]) -> Result<()> {
209 let status = unsafe {
210 sys::aoclsparse_csctr(
211 x.len() as sys::aoclsparse_int,
212 x.as_ptr() as *const std::os::raw::c_void,
213 indx.as_ptr(),
214 y.as_mut_ptr() as *mut std::os::raw::c_void,
215 )
216 };
217 check_status("sparse", status)
218 }
219
220 fn create_csr(
221 base: IndexBase,
222 m: usize,
223 n: usize,
224 nnz: usize,
225 row_ptr: *mut sys::aoclsparse_int,
226 col_idx: *mut sys::aoclsparse_int,
227 val: *mut Self,
228 ) -> Result<sys::aoclsparse_matrix> {
229 let mut raw: sys::aoclsparse_matrix = std::ptr::null_mut();
230 let status = unsafe {
231 sys::aoclsparse_create_ccsr(
232 &mut raw,
233 base.raw_for_complex(),
234 m as sys::aoclsparse_int,
235 n as sys::aoclsparse_int,
236 nnz as sys::aoclsparse_int,
237 row_ptr,
238 col_idx,
239 val as *mut sys::aoclsparse_float_complex,
240 )
241 };
242 check_status("sparse", status)?;
243 if raw.is_null() {
244 return Err(Error::AllocationFailed("sparse"));
245 }
246 Ok(raw)
247 }
248
249 fn export_csr(
250 mat: sys::aoclsparse_matrix,
251 ) -> Result<(
252 IndexBase,
253 usize,
254 usize,
255 usize,
256 *mut sys::aoclsparse_int,
257 *mut sys::aoclsparse_int,
258 *mut Self,
259 )> {
260 let mut base: sys::aoclsparse_index_base = 0;
261 let mut m: sys::aoclsparse_int = 0;
262 let mut n: sys::aoclsparse_int = 0;
263 let mut nnz: sys::aoclsparse_int = 0;
264 let mut row_ptr: *mut sys::aoclsparse_int = std::ptr::null_mut();
265 let mut col_ind: *mut sys::aoclsparse_int = std::ptr::null_mut();
266 let mut val: *mut sys::aoclsparse_float_complex = std::ptr::null_mut();
267 let status = unsafe {
268 sys::aoclsparse_export_ccsr(
269 mat,
270 &mut base,
271 &mut m,
272 &mut n,
273 &mut nnz,
274 &mut row_ptr,
275 &mut col_ind,
276 &mut val,
277 )
278 };
279 check_status("sparse", status)?;
280 let base_e = if base == sys::aoclsparse_index_base__aoclsparse_index_base_one {
281 IndexBase::One
282 } else {
283 IndexBase::Zero
284 };
285 Ok((
286 base_e,
287 m as usize,
288 n as usize,
289 nnz as usize,
290 row_ptr,
291 col_ind,
292 val as *mut Self,
293 ))
294 }
295
296 fn mv(
297 op: Trans,
298 alpha: Self,
299 mat: sys::aoclsparse_matrix,
300 descr: &MatDescr,
301 x: &[Self],
302 beta: Self,
303 y: &mut [Self],
304 ) -> Result<()> {
305 let status = unsafe {
306 sys::aoclsparse_cmv(
307 trans_raw(op),
308 &alpha as *const _ as *const sys::aoclsparse_float_complex,
309 mat,
310 descr.as_raw(),
311 x.as_ptr() as *const sys::aoclsparse_float_complex,
312 &beta as *const _ as *const sys::aoclsparse_float_complex,
313 y.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
314 )
315 };
316 check_status("sparse", status)
317 }
318
319 fn trsv(
320 op: Trans,
321 alpha: Self,
322 mat: sys::aoclsparse_matrix,
323 descr: &MatDescr,
324 b: &[Self],
325 x: &mut [Self],
326 ) -> Result<()> {
327 let alpha_raw = sys::aoclsparse_float_complex {
329 real: alpha.re,
330 imag: alpha.im,
331 };
332 let status = unsafe {
333 sys::aoclsparse_ctrsv(
334 trans_raw(op),
335 alpha_raw,
336 mat,
337 descr.as_raw(),
338 b.as_ptr() as *const sys::aoclsparse_float_complex,
339 x.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
340 )
341 };
342 check_status("sparse", status)
343 }
344
345 fn ilu_smoother(
346 op: Trans,
347 a: sys::aoclsparse_matrix,
348 descr: &MatDescr,
349 x: &mut [Self],
350 b: &[Self],
351 ) -> Result<()> {
352 let mut precond_csr_val: *mut sys::aoclsparse_float_complex = std::ptr::null_mut();
353 let status = unsafe {
354 sys::aoclsparse_cilu_smoother(
355 trans_raw(op),
356 a,
357 descr.as_raw(),
358 &mut precond_csr_val,
359 std::ptr::null(),
360 x.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
361 b.as_ptr() as *const sys::aoclsparse_float_complex,
362 )
363 };
364 check_status("sparse", status)
365 }
366
367 fn itsol_init(handle: &mut sys::aoclsparse_itsol_handle) -> Result<()> {
368 let status = unsafe { sys::aoclsparse_itsol_c_init(handle) };
369 check_status("sparse", status)
370 }
371
372 fn itsol_solve(
373 handle: sys::aoclsparse_itsol_handle,
374 n: usize,
375 mat: sys::aoclsparse_matrix,
376 descr: &MatDescr,
377 b: &[Self],
378 x: &mut [Self],
379 rinfo: &mut [f32; 100],
380 ) -> Result<()> {
381 if b.len() < n || x.len() < n {
382 return Err(Error::InvalidArgument(format!(
383 "itsol_solve: b.len()={}, x.len()={}, n={n}",
384 b.len(),
385 x.len()
386 )));
387 }
388 let status = unsafe {
389 sys::aoclsparse_itsol_c_solve(
390 handle,
391 n as sys::aoclsparse_int,
392 mat,
393 descr.as_raw(),
394 b.as_ptr() as *const sys::aoclsparse_float_complex,
395 x.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
396 rinfo.as_mut_ptr(),
397 None,
398 None,
399 std::ptr::null_mut(),
400 )
401 };
402 check_status("sparse", status)
403 }
404
405 fn csrmm(
406 op: Trans,
407 alpha: Self,
408 a: sys::aoclsparse_matrix,
409 descr: &MatDescr,
410 order: Order,
411 b: &[Self],
412 n: usize,
413 ldb: usize,
414 beta: Self,
415 c: &mut [Self],
416 ldc: usize,
417 ) -> Result<()> {
418 let alpha_raw = sys::aoclsparse_float_complex {
419 real: alpha.re,
420 imag: alpha.im,
421 };
422 let beta_raw = sys::aoclsparse_float_complex {
423 real: beta.re,
424 imag: beta.im,
425 };
426 let status = unsafe {
427 sys::aoclsparse_ccsrmm(
428 trans_raw(op),
429 alpha_raw,
430 a,
431 descr.as_raw(),
432 order.raw(),
433 b.as_ptr() as *const sys::aoclsparse_float_complex,
434 n as sys::aoclsparse_int,
435 ldb as sys::aoclsparse_int,
436 beta_raw,
437 c.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
438 ldc as sys::aoclsparse_int,
439 )
440 };
441 check_status("sparse", status)
442 }
443
444 fn spmmd(
445 op: Trans,
446 a: sys::aoclsparse_matrix,
447 b: sys::aoclsparse_matrix,
448 layout: Order,
449 c: &mut [Self],
450 ldc: usize,
451 ) -> Result<()> {
452 let status = unsafe {
453 sys::aoclsparse_cspmmd(
454 trans_raw(op),
455 a,
456 b,
457 layout.raw(),
458 c.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
459 ldc as sys::aoclsparse_int,
460 )
461 };
462 check_status("sparse", status)
463 }
464
465 fn sp2md(
466 op_a: Trans,
467 descr_a: &MatDescr,
468 a: sys::aoclsparse_matrix,
469 op_b: Trans,
470 descr_b: &MatDescr,
471 b: sys::aoclsparse_matrix,
472 alpha: Self,
473 beta: Self,
474 c: &mut [Self],
475 layout: Order,
476 ldc: usize,
477 ) -> Result<()> {
478 let alpha_raw = sys::aoclsparse_float_complex {
479 real: alpha.re,
480 imag: alpha.im,
481 };
482 let beta_raw = sys::aoclsparse_float_complex {
483 real: beta.re,
484 imag: beta.im,
485 };
486 let status = unsafe {
487 sys::aoclsparse_csp2md(
488 trans_raw(op_a),
489 descr_a.as_raw(),
490 a,
491 trans_raw(op_b),
492 descr_b.as_raw(),
493 b,
494 alpha_raw,
495 beta_raw,
496 c.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
497 layout.raw(),
498 ldc as sys::aoclsparse_int,
499 )
500 };
501 check_status("sparse", status)
502 }
503
504 unsafe fn add_ffi(
505 op: sys::aoclsparse_operation,
506 a: sys::aoclsparse_matrix,
507 alpha: Self,
508 b: sys::aoclsparse_matrix,
509 out: *mut sys::aoclsparse_matrix,
510 ) -> sys::aoclsparse_status {
511 let alpha_raw = sys::aoclsparse_float_complex {
512 real: alpha.re,
513 imag: alpha.im,
514 };
515 sys::aoclsparse_cadd(op, a, alpha_raw, b, out)
516 }
517
518 fn sorv(
519 sor_type: SorType,
520 descr: &MatDescr,
521 a: sys::aoclsparse_matrix,
522 omega: Self,
523 alpha: Self,
524 x: &mut [Self],
525 b: &[Self],
526 ) -> Result<()> {
527 let omega_raw = sys::aoclsparse_float_complex {
528 real: omega.re,
529 imag: omega.im,
530 };
531 let alpha_raw = sys::aoclsparse_float_complex {
532 real: alpha.re,
533 imag: alpha.im,
534 };
535 let status = unsafe {
536 sys::aoclsparse_csorv(
537 sor_type.raw(),
538 descr.as_raw(),
539 a,
540 omega_raw,
541 alpha_raw,
542 x.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
543 b.as_ptr() as *const sys::aoclsparse_float_complex,
544 )
545 };
546 check_status("sparse", status)
547 }
548}
549
550impl ComplexScalar for Complex64 {
555 type Real = f64;
556
557 fn axpyi(alpha: Self, x: &[Self], indx: &[sys::aoclsparse_int], y: &mut [Self]) -> Result<()> {
558 let status = unsafe {
559 sys::aoclsparse_zaxpyi(
560 x.len() as sys::aoclsparse_int,
561 &alpha as *const _ as *const std::os::raw::c_void,
562 x.as_ptr() as *const std::os::raw::c_void,
563 indx.as_ptr(),
564 y.as_mut_ptr() as *mut std::os::raw::c_void,
565 )
566 };
567 check_status("sparse", status)
568 }
569
570 fn gthr(y: &[Self], indx: &[sys::aoclsparse_int], x: &mut [Self]) -> Result<()> {
571 let status = unsafe {
572 sys::aoclsparse_zgthr(
573 x.len() as sys::aoclsparse_int,
574 y.as_ptr() as *const std::os::raw::c_void,
575 x.as_mut_ptr() as *mut std::os::raw::c_void,
576 indx.as_ptr(),
577 )
578 };
579 check_status("sparse", status)
580 }
581
582 fn sctr(x: &[Self], indx: &[sys::aoclsparse_int], y: &mut [Self]) -> Result<()> {
583 let status = unsafe {
584 sys::aoclsparse_zsctr(
585 x.len() as sys::aoclsparse_int,
586 x.as_ptr() as *const std::os::raw::c_void,
587 indx.as_ptr(),
588 y.as_mut_ptr() as *mut std::os::raw::c_void,
589 )
590 };
591 check_status("sparse", status)
592 }
593
594 fn create_csr(
595 base: IndexBase,
596 m: usize,
597 n: usize,
598 nnz: usize,
599 row_ptr: *mut sys::aoclsparse_int,
600 col_idx: *mut sys::aoclsparse_int,
601 val: *mut Self,
602 ) -> Result<sys::aoclsparse_matrix> {
603 let mut raw: sys::aoclsparse_matrix = std::ptr::null_mut();
604 let status = unsafe {
605 sys::aoclsparse_create_zcsr(
606 &mut raw,
607 base.raw_for_complex(),
608 m as sys::aoclsparse_int,
609 n as sys::aoclsparse_int,
610 nnz as sys::aoclsparse_int,
611 row_ptr,
612 col_idx,
613 val as *mut sys::aoclsparse_double_complex,
614 )
615 };
616 check_status("sparse", status)?;
617 if raw.is_null() {
618 return Err(Error::AllocationFailed("sparse"));
619 }
620 Ok(raw)
621 }
622
623 fn export_csr(
624 mat: sys::aoclsparse_matrix,
625 ) -> Result<(
626 IndexBase,
627 usize,
628 usize,
629 usize,
630 *mut sys::aoclsparse_int,
631 *mut sys::aoclsparse_int,
632 *mut Self,
633 )> {
634 let mut base: sys::aoclsparse_index_base = 0;
635 let mut m: sys::aoclsparse_int = 0;
636 let mut n: sys::aoclsparse_int = 0;
637 let mut nnz: sys::aoclsparse_int = 0;
638 let mut row_ptr: *mut sys::aoclsparse_int = std::ptr::null_mut();
639 let mut col_ind: *mut sys::aoclsparse_int = std::ptr::null_mut();
640 let mut val: *mut sys::aoclsparse_double_complex = std::ptr::null_mut();
641 let status = unsafe {
642 sys::aoclsparse_export_zcsr(
643 mat,
644 &mut base,
645 &mut m,
646 &mut n,
647 &mut nnz,
648 &mut row_ptr,
649 &mut col_ind,
650 &mut val,
651 )
652 };
653 check_status("sparse", status)?;
654 let base_e = if base == sys::aoclsparse_index_base__aoclsparse_index_base_one {
655 IndexBase::One
656 } else {
657 IndexBase::Zero
658 };
659 Ok((
660 base_e,
661 m as usize,
662 n as usize,
663 nnz as usize,
664 row_ptr,
665 col_ind,
666 val as *mut Self,
667 ))
668 }
669
670 fn mv(
671 op: Trans,
672 alpha: Self,
673 mat: sys::aoclsparse_matrix,
674 descr: &MatDescr,
675 x: &[Self],
676 beta: Self,
677 y: &mut [Self],
678 ) -> Result<()> {
679 let status = unsafe {
680 sys::aoclsparse_zmv(
681 trans_raw(op),
682 &alpha as *const _ as *const sys::aoclsparse_double_complex,
683 mat,
684 descr.as_raw(),
685 x.as_ptr() as *const sys::aoclsparse_double_complex,
686 &beta as *const _ as *const sys::aoclsparse_double_complex,
687 y.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
688 )
689 };
690 check_status("sparse", status)
691 }
692
693 fn trsv(
694 op: Trans,
695 alpha: Self,
696 mat: sys::aoclsparse_matrix,
697 descr: &MatDescr,
698 b: &[Self],
699 x: &mut [Self],
700 ) -> Result<()> {
701 let alpha_raw = sys::aoclsparse_double_complex_ {
702 real: alpha.re,
703 imag: alpha.im,
704 };
705 let status = unsafe {
706 sys::aoclsparse_ztrsv(
707 trans_raw(op),
708 alpha_raw,
709 mat,
710 descr.as_raw(),
711 b.as_ptr() as *const sys::aoclsparse_double_complex,
712 x.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
713 )
714 };
715 check_status("sparse", status)
716 }
717
718 fn ilu_smoother(
719 op: Trans,
720 a: sys::aoclsparse_matrix,
721 descr: &MatDescr,
722 x: &mut [Self],
723 b: &[Self],
724 ) -> Result<()> {
725 let mut precond_csr_val: *mut sys::aoclsparse_double_complex = std::ptr::null_mut();
726 let status = unsafe {
727 sys::aoclsparse_zilu_smoother(
728 trans_raw(op),
729 a,
730 descr.as_raw(),
731 &mut precond_csr_val,
732 std::ptr::null(),
733 x.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
734 b.as_ptr() as *const sys::aoclsparse_double_complex,
735 )
736 };
737 check_status("sparse", status)
738 }
739
740 fn itsol_init(handle: &mut sys::aoclsparse_itsol_handle) -> Result<()> {
741 let status = unsafe { sys::aoclsparse_itsol_z_init(handle) };
742 check_status("sparse", status)
743 }
744
745 fn itsol_solve(
746 handle: sys::aoclsparse_itsol_handle,
747 n: usize,
748 mat: sys::aoclsparse_matrix,
749 descr: &MatDescr,
750 b: &[Self],
751 x: &mut [Self],
752 rinfo: &mut [f64; 100],
753 ) -> Result<()> {
754 if b.len() < n || x.len() < n {
755 return Err(Error::InvalidArgument(format!(
756 "itsol_solve: b.len()={}, x.len()={}, n={n}",
757 b.len(),
758 x.len()
759 )));
760 }
761 let status = unsafe {
762 sys::aoclsparse_itsol_z_solve(
763 handle,
764 n as sys::aoclsparse_int,
765 mat,
766 descr.as_raw(),
767 b.as_ptr() as *const sys::aoclsparse_double_complex,
768 x.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
769 rinfo.as_mut_ptr(),
770 None,
771 None,
772 std::ptr::null_mut(),
773 )
774 };
775 check_status("sparse", status)
776 }
777
778 fn csrmm(
779 op: Trans,
780 alpha: Self,
781 a: sys::aoclsparse_matrix,
782 descr: &MatDescr,
783 order: Order,
784 b: &[Self],
785 n: usize,
786 ldb: usize,
787 beta: Self,
788 c: &mut [Self],
789 ldc: usize,
790 ) -> Result<()> {
791 let alpha_raw = sys::aoclsparse_double_complex_ {
792 real: alpha.re,
793 imag: alpha.im,
794 };
795 let beta_raw = sys::aoclsparse_double_complex_ {
796 real: beta.re,
797 imag: beta.im,
798 };
799 let status = unsafe {
800 sys::aoclsparse_zcsrmm(
801 trans_raw(op),
802 alpha_raw,
803 a,
804 descr.as_raw(),
805 order.raw(),
806 b.as_ptr() as *const sys::aoclsparse_double_complex,
807 n as sys::aoclsparse_int,
808 ldb as sys::aoclsparse_int,
809 beta_raw,
810 c.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
811 ldc as sys::aoclsparse_int,
812 )
813 };
814 check_status("sparse", status)
815 }
816
817 fn spmmd(
818 op: Trans,
819 a: sys::aoclsparse_matrix,
820 b: sys::aoclsparse_matrix,
821 layout: Order,
822 c: &mut [Self],
823 ldc: usize,
824 ) -> Result<()> {
825 let status = unsafe {
826 sys::aoclsparse_zspmmd(
827 trans_raw(op),
828 a,
829 b,
830 layout.raw(),
831 c.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
832 ldc as sys::aoclsparse_int,
833 )
834 };
835 check_status("sparse", status)
836 }
837
838 fn sp2md(
839 op_a: Trans,
840 descr_a: &MatDescr,
841 a: sys::aoclsparse_matrix,
842 op_b: Trans,
843 descr_b: &MatDescr,
844 b: sys::aoclsparse_matrix,
845 alpha: Self,
846 beta: Self,
847 c: &mut [Self],
848 layout: Order,
849 ldc: usize,
850 ) -> Result<()> {
851 let alpha_raw = sys::aoclsparse_double_complex_ {
852 real: alpha.re,
853 imag: alpha.im,
854 };
855 let beta_raw = sys::aoclsparse_double_complex_ {
856 real: beta.re,
857 imag: beta.im,
858 };
859 let status = unsafe {
860 sys::aoclsparse_zsp2md(
861 trans_raw(op_a),
862 descr_a.as_raw(),
863 a,
864 trans_raw(op_b),
865 descr_b.as_raw(),
866 b,
867 alpha_raw,
868 beta_raw,
869 c.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
870 layout.raw(),
871 ldc as sys::aoclsparse_int,
872 )
873 };
874 check_status("sparse", status)
875 }
876
877 unsafe fn add_ffi(
878 op: sys::aoclsparse_operation,
879 a: sys::aoclsparse_matrix,
880 alpha: Self,
881 b: sys::aoclsparse_matrix,
882 out: *mut sys::aoclsparse_matrix,
883 ) -> sys::aoclsparse_status {
884 let alpha_raw = sys::aoclsparse_double_complex_ {
885 real: alpha.re,
886 imag: alpha.im,
887 };
888 sys::aoclsparse_zadd(op, a, alpha_raw, b, out)
889 }
890
891 fn sorv(
892 sor_type: SorType,
893 descr: &MatDescr,
894 a: sys::aoclsparse_matrix,
895 omega: Self,
896 alpha: Self,
897 x: &mut [Self],
898 b: &[Self],
899 ) -> Result<()> {
900 let omega_raw = sys::aoclsparse_double_complex_ {
901 real: omega.re,
902 imag: omega.im,
903 };
904 let alpha_raw = sys::aoclsparse_double_complex_ {
905 real: alpha.re,
906 imag: alpha.im,
907 };
908 let status = unsafe {
909 sys::aoclsparse_zsorv(
910 sor_type.raw(),
911 descr.as_raw(),
912 a,
913 omega_raw,
914 alpha_raw,
915 x.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
916 b.as_ptr() as *const sys::aoclsparse_double_complex,
917 )
918 };
919 check_status("sparse", status)
920 }
921}
922
923enum CsrStorage<T: ComplexScalar> {
928 Owned {
929 _row_ptr: Vec<sys::aoclsparse_int>,
930 _col_ind: Vec<sys::aoclsparse_int>,
931 _val: Vec<T>,
932 },
933 LibraryOwned,
934}
935
936pub struct ComplexSparseMatrix<T: ComplexScalar> {
938 raw: sys::aoclsparse_matrix,
939 #[allow(dead_code)]
940 storage: CsrStorage<T>,
941 base: IndexBase,
942 m: usize,
943 n: usize,
944 nnz: usize,
945}
946
947impl<T: ComplexScalar> ComplexSparseMatrix<T> {
948 pub fn from_csr(
950 base: IndexBase,
951 m: usize,
952 n: usize,
953 row_ptr: &[sys::aoclsparse_int],
954 col_ind: &[sys::aoclsparse_int],
955 val: &[T],
956 ) -> Result<Self> {
957 if row_ptr.len() != m + 1 {
958 return Err(Error::InvalidArgument(format!(
959 "complex from_csr: row_ptr length {} != m+1 = {}",
960 row_ptr.len(),
961 m + 1
962 )));
963 }
964 let nnz = val.len();
965 if col_ind.len() != nnz {
966 return Err(Error::InvalidArgument(format!(
967 "complex from_csr: col_ind length {} != val length {nnz}",
968 col_ind.len()
969 )));
970 }
971 let mut row_ptr = row_ptr.to_vec();
972 let mut col_ind = col_ind.to_vec();
973 let mut val = val.to_vec();
974 let raw = T::create_csr(
975 base,
976 m,
977 n,
978 nnz,
979 row_ptr.as_mut_ptr(),
980 col_ind.as_mut_ptr(),
981 val.as_mut_ptr(),
982 )?;
983 Ok(Self {
984 raw,
985 storage: CsrStorage::Owned {
986 _row_ptr: row_ptr,
987 _col_ind: col_ind,
988 _val: val,
989 },
990 base,
991 m,
992 n,
993 nnz,
994 })
995 }
996
997 pub unsafe fn from_library_owned(raw: sys::aoclsparse_matrix) -> Result<Self> {
1004 if raw.is_null() {
1005 return Err(Error::AllocationFailed("sparse"));
1006 }
1007 let (base, m, n, nnz, _, _, _) = T::export_csr(raw)?;
1008 Ok(Self {
1009 raw,
1010 storage: CsrStorage::LibraryOwned,
1011 base,
1012 m,
1013 n,
1014 nnz,
1015 })
1016 }
1017
1018 pub fn dims(&self) -> (usize, usize) {
1020 (self.m, self.n)
1021 }
1022 pub fn nnz(&self) -> usize {
1024 self.nnz
1025 }
1026 pub fn base(&self) -> IndexBase {
1028 self.base
1029 }
1030
1031 pub fn as_raw(&self) -> sys::aoclsparse_matrix {
1034 self.raw
1035 }
1036
1037 pub fn export_csr(
1039 &self,
1040 ) -> Result<(
1041 IndexBase,
1042 Vec<sys::aoclsparse_int>,
1043 Vec<sys::aoclsparse_int>,
1044 Vec<T>,
1045 )> {
1046 let (base, m, _, nnz, row_ptr, col_ind, val) = T::export_csr(self.raw)?;
1047 let row_ptr = unsafe { std::slice::from_raw_parts(row_ptr, m + 1).to_vec() };
1048 let col_ind = unsafe { std::slice::from_raw_parts(col_ind, nnz).to_vec() };
1049 let val = unsafe { std::slice::from_raw_parts(val, nnz).to_vec() };
1050 Ok((base, row_ptr, col_ind, val))
1051 }
1052}
1053
1054impl<T: ComplexScalar> Drop for ComplexSparseMatrix<T> {
1055 fn drop(&mut self) {
1056 if !self.raw.is_null() {
1057 unsafe {
1058 let _ = sys::aoclsparse_destroy(&mut self.raw);
1059 }
1060 self.raw = std::ptr::null_mut();
1061 }
1062 }
1063}
1064
1065impl<T: ComplexScalar> std::fmt::Debug for ComplexSparseMatrix<T> {
1066 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1067 f.debug_struct("ComplexSparseMatrix")
1068 .field("m", &self.m)
1069 .field("n", &self.n)
1070 .field("nnz", &self.nnz)
1071 .field("base", &self.base)
1072 .finish()
1073 }
1074}
1075
1076pub fn axpyi<T: ComplexScalar>(
1082 alpha: T,
1083 x: &[T],
1084 indx: &[sys::aoclsparse_int],
1085 y: &mut [T],
1086) -> Result<()> {
1087 if x.len() != indx.len() {
1088 return Err(Error::InvalidArgument(format!(
1089 "axpyi: x.len()={}, indx.len()={}",
1090 x.len(),
1091 indx.len()
1092 )));
1093 }
1094 T::axpyi(alpha, x, indx, y)
1095}
1096
1097pub fn gthr<T: ComplexScalar>(y: &[T], indx: &[sys::aoclsparse_int], x: &mut [T]) -> Result<()> {
1099 if x.len() != indx.len() {
1100 return Err(Error::InvalidArgument(format!(
1101 "gthr: x.len()={}, indx.len()={}",
1102 x.len(),
1103 indx.len()
1104 )));
1105 }
1106 T::gthr(y, indx, x)
1107}
1108
1109pub fn sctr<T: ComplexScalar>(x: &[T], indx: &[sys::aoclsparse_int], y: &mut [T]) -> Result<()> {
1111 if x.len() != indx.len() {
1112 return Err(Error::InvalidArgument(format!(
1113 "sctr: x.len()={}, indx.len()={}",
1114 x.len(),
1115 indx.len()
1116 )));
1117 }
1118 T::sctr(x, indx, y)
1119}
1120
1121#[allow(clippy::too_many_arguments)]
1123pub fn mv<T: ComplexScalar>(
1124 op: Trans,
1125 alpha: T,
1126 a: &ComplexSparseMatrix<T>,
1127 descr: &MatDescr,
1128 x: &[T],
1129 beta: T,
1130 y: &mut [T],
1131) -> Result<()> {
1132 let (x_len, y_len) = match op {
1133 Trans::No => (a.n, a.m),
1134 Trans::T | Trans::C => (a.m, a.n),
1135 };
1136 if x.len() < x_len || y.len() < y_len {
1137 return Err(Error::InvalidArgument(format!(
1138 "mv: x.len()={}, y.len()={}, expected ({x_len}, {y_len})",
1139 x.len(),
1140 y.len()
1141 )));
1142 }
1143 T::mv(op, alpha, a.raw, descr, x, beta, y)
1144}
1145
1146#[allow(clippy::too_many_arguments)]
1148pub fn trsv<T: ComplexScalar>(
1149 op: Trans,
1150 alpha: T,
1151 a: &ComplexSparseMatrix<T>,
1152 descr: &MatDescr,
1153 b: &[T],
1154 x: &mut [T],
1155) -> Result<()> {
1156 if b.len() < a.m || x.len() < a.m {
1157 return Err(Error::InvalidArgument(format!(
1158 "trsv: b.len()={}, x.len()={}, m={}",
1159 b.len(),
1160 x.len(),
1161 a.m
1162 )));
1163 }
1164 T::trsv(op, alpha, a.raw, descr, b, x)
1165}
1166
1167#[allow(clippy::too_many_arguments)]
1170pub fn csrmm<T: ComplexScalar>(
1171 op: Trans,
1172 alpha: T,
1173 a: &ComplexSparseMatrix<T>,
1174 descr: &MatDescr,
1175 order: Order,
1176 b: &[T],
1177 n: usize,
1178 ldb: usize,
1179 beta: T,
1180 c: &mut [T],
1181 ldc: usize,
1182) -> Result<()> {
1183 T::csrmm(op, alpha, a.as_raw(), descr, order, b, n, ldb, beta, c, ldc)
1184}
1185
1186pub fn spmmd<T: ComplexScalar>(
1189 op: Trans,
1190 a: &ComplexSparseMatrix<T>,
1191 b: &ComplexSparseMatrix<T>,
1192 layout: Order,
1193 c: &mut [T],
1194 ldc: usize,
1195) -> Result<()> {
1196 T::spmmd(op, a.as_raw(), b.as_raw(), layout, c, ldc)
1197}
1198
1199#[allow(clippy::too_many_arguments)]
1202pub fn sp2md<T: ComplexScalar>(
1203 op_a: Trans,
1204 descr_a: &MatDescr,
1205 a: &ComplexSparseMatrix<T>,
1206 op_b: Trans,
1207 descr_b: &MatDescr,
1208 b: &ComplexSparseMatrix<T>,
1209 alpha: T,
1210 beta: T,
1211 c: &mut [T],
1212 layout: Order,
1213 ldc: usize,
1214) -> Result<()> {
1215 T::sp2md(
1216 op_a,
1217 descr_a,
1218 a.as_raw(),
1219 op_b,
1220 descr_b,
1221 b.as_raw(),
1222 alpha,
1223 beta,
1224 c,
1225 layout,
1226 ldc,
1227 )
1228}
1229
1230pub fn add<T: ComplexScalar>(
1232 op: Trans,
1233 a: &ComplexSparseMatrix<T>,
1234 alpha: T,
1235 b: &ComplexSparseMatrix<T>,
1236) -> Result<ComplexSparseMatrix<T>> {
1237 let mut c_raw: sys::aoclsparse_matrix = std::ptr::null_mut();
1238 let status = unsafe { T::add_ffi(trans_raw(op), a.as_raw(), alpha, b.as_raw(), &mut c_raw) };
1239 check_status("sparse", status)?;
1240 unsafe { ComplexSparseMatrix::from_library_owned(c_raw) }
1241}
1242
1243pub fn sorv<T: ComplexScalar>(
1246 sor_type: SorType,
1247 descr: &MatDescr,
1248 a: &ComplexSparseMatrix<T>,
1249 omega: T,
1250 alpha: T,
1251 x: &mut [T],
1252 b: &[T],
1253) -> Result<()> {
1254 if x.len() < a.dims().1 || b.len() < a.dims().0 {
1255 return Err(Error::InvalidArgument(format!(
1256 "sorv: x.len()={}, b.len()={}, dims=({}, {})",
1257 x.len(),
1258 b.len(),
1259 a.dims().0,
1260 a.dims().1
1261 )));
1262 }
1263 T::sorv(sor_type, descr, a.as_raw(), omega, alpha, x, b)
1264}
1265
1266pub fn ilu_smoother<T: ComplexScalar>(
1268 op: Trans,
1269 a: &ComplexSparseMatrix<T>,
1270 descr: &MatDescr,
1271 x: &mut [T],
1272 b: &[T],
1273) -> Result<()> {
1274 if x.len() < a.n || b.len() < a.m {
1275 return Err(Error::InvalidArgument(format!(
1276 "ilu_smoother: x.len()={}, b.len()={}, dims=({}, {})",
1277 x.len(),
1278 b.len(),
1279 a.m,
1280 a.n
1281 )));
1282 }
1283 T::ilu_smoother(op, a.raw, descr, x, b)
1284}
1285
1286pub struct ComplexIterSolver<T: ComplexScalar> {
1292 handle: sys::aoclsparse_itsol_handle,
1293 _marker: PhantomData<T>,
1294}
1295
1296impl<T: ComplexScalar> ComplexIterSolver<T> {
1297 pub fn new() -> Result<Self> {
1299 let mut handle: sys::aoclsparse_itsol_handle = std::ptr::null_mut();
1300 T::itsol_init(&mut handle)?;
1301 if handle.is_null() {
1302 return Err(Error::AllocationFailed("sparse"));
1303 }
1304 Ok(Self {
1305 handle,
1306 _marker: PhantomData,
1307 })
1308 }
1309
1310 pub fn set_option(&mut self, name: &str, value: &str) -> Result<()> {
1312 let c_name = CString::new(name)
1313 .map_err(|_| Error::InvalidArgument("set_option: name has interior NUL".into()))?;
1314 let c_value = CString::new(value)
1315 .map_err(|_| Error::InvalidArgument("set_option: value has interior NUL".into()))?;
1316 let status = unsafe {
1317 sys::aoclsparse_itsol_option_set(self.handle, c_name.as_ptr(), c_value.as_ptr())
1318 };
1319 check_status("sparse", status)
1320 }
1321
1322 pub fn solve(
1324 &mut self,
1325 mat: &ComplexSparseMatrix<T>,
1326 descr: &MatDescr,
1327 b: &[T],
1328 x: &mut [T],
1329 ) -> Result<Box<[T::Real; 100]>> {
1330 let n = mat.n;
1331 if mat.m != mat.n {
1332 return Err(Error::InvalidArgument(format!(
1333 "iterative solve requires square matrix; got ({}, {})",
1334 mat.m, mat.n
1335 )));
1336 }
1337 let mut rinfo: Box<[T::Real; 100]> = Box::new([T::Real::default(); 100]);
1338 T::itsol_solve(self.handle, n, mat.raw, descr, b, x, &mut rinfo)?;
1339 Ok(rinfo)
1340 }
1341}
1342
1343impl<T: ComplexScalar> Drop for ComplexIterSolver<T> {
1344 fn drop(&mut self) {
1345 if !self.handle.is_null() {
1346 unsafe {
1347 sys::aoclsparse_itsol_destroy(&mut self.handle);
1348 }
1349 self.handle = std::ptr::null_mut();
1350 }
1351 }
1352}
1353
1354impl<T: ComplexScalar> std::fmt::Debug for ComplexIterSolver<T> {
1355 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1356 f.debug_struct("ComplexIterSolver").finish_non_exhaustive()
1357 }
1358}
1359
1360pub fn symgs_c64(
1370 op: Trans,
1371 a: &ComplexSparseMatrix<Complex64>,
1372 descr: &MatDescr,
1373 alpha: Complex64,
1374 b: &[Complex64],
1375 x: &mut [Complex64],
1376) -> Result<()> {
1377 let alpha_raw = sys::aoclsparse_double_complex_ {
1378 real: alpha.re,
1379 imag: alpha.im,
1380 };
1381 let status = unsafe {
1382 sys::aoclsparse_zsymgs(
1383 trans_raw(op),
1384 a.as_raw(),
1385 descr.as_raw(),
1386 alpha_raw,
1387 b.as_ptr() as *const sys::aoclsparse_double_complex,
1388 x.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
1389 )
1390 };
1391 check_status("sparse", status)
1392}
1393
1394pub fn symgs_c32(
1396 op: Trans,
1397 a: &ComplexSparseMatrix<Complex32>,
1398 descr: &MatDescr,
1399 alpha: Complex32,
1400 b: &[Complex32],
1401 x: &mut [Complex32],
1402) -> Result<()> {
1403 let alpha_raw = sys::aoclsparse_float_complex {
1404 real: alpha.re,
1405 imag: alpha.im,
1406 };
1407 let status = unsafe {
1408 sys::aoclsparse_csymgs(
1409 trans_raw(op),
1410 a.as_raw(),
1411 descr.as_raw(),
1412 alpha_raw,
1413 b.as_ptr() as *const sys::aoclsparse_float_complex,
1414 x.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
1415 )
1416 };
1417 check_status("sparse", status)
1418}
1419
1420#[allow(clippy::too_many_arguments)]
1422pub fn symgs_mv_c64(
1423 op: Trans,
1424 a: &ComplexSparseMatrix<Complex64>,
1425 descr: &MatDescr,
1426 alpha: Complex64,
1427 b: &[Complex64],
1428 x: &mut [Complex64],
1429 y: &mut [Complex64],
1430) -> Result<()> {
1431 let alpha_raw = sys::aoclsparse_double_complex_ {
1432 real: alpha.re,
1433 imag: alpha.im,
1434 };
1435 let status = unsafe {
1436 sys::aoclsparse_zsymgs_mv(
1437 trans_raw(op),
1438 a.as_raw(),
1439 descr.as_raw(),
1440 alpha_raw,
1441 b.as_ptr() as *const sys::aoclsparse_double_complex,
1442 x.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
1443 y.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
1444 )
1445 };
1446 check_status("sparse", status)
1447}
1448
1449#[allow(clippy::too_many_arguments)]
1451pub fn symgs_mv_c32(
1452 op: Trans,
1453 a: &ComplexSparseMatrix<Complex32>,
1454 descr: &MatDescr,
1455 alpha: Complex32,
1456 b: &[Complex32],
1457 x: &mut [Complex32],
1458 y: &mut [Complex32],
1459) -> Result<()> {
1460 let alpha_raw = sys::aoclsparse_float_complex {
1461 real: alpha.re,
1462 imag: alpha.im,
1463 };
1464 let status = unsafe {
1465 sys::aoclsparse_csymgs_mv(
1466 trans_raw(op),
1467 a.as_raw(),
1468 descr.as_raw(),
1469 alpha_raw,
1470 b.as_ptr() as *const sys::aoclsparse_float_complex,
1471 x.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
1472 y.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
1473 )
1474 };
1475 check_status("sparse", status)
1476}
1477
1478pub fn set_value_c64(
1482 a: &mut ComplexSparseMatrix<Complex64>,
1483 row_idx: i32,
1484 col_idx: i32,
1485 val: Complex64,
1486) -> Result<()> {
1487 let val_raw = sys::aoclsparse_double_complex_ {
1488 real: val.re,
1489 imag: val.im,
1490 };
1491 let status = unsafe {
1492 sys::aoclsparse_zset_value(
1493 a.as_raw(),
1494 row_idx as sys::aoclsparse_int,
1495 col_idx as sys::aoclsparse_int,
1496 val_raw,
1497 )
1498 };
1499 check_status("sparse", status)
1500}
1501pub fn set_value_c32(
1503 a: &mut ComplexSparseMatrix<Complex32>,
1504 row_idx: i32,
1505 col_idx: i32,
1506 val: Complex32,
1507) -> Result<()> {
1508 let val_raw = sys::aoclsparse_float_complex {
1509 real: val.re,
1510 imag: val.im,
1511 };
1512 let status = unsafe {
1513 sys::aoclsparse_cset_value(
1514 a.as_raw(),
1515 row_idx as sys::aoclsparse_int,
1516 col_idx as sys::aoclsparse_int,
1517 val_raw,
1518 )
1519 };
1520 check_status("sparse", status)
1521}
1522
1523pub fn update_values_c64(
1525 a: &mut ComplexSparseMatrix<Complex64>,
1526 val: &mut [Complex64],
1527) -> Result<()> {
1528 let status = unsafe {
1529 sys::aoclsparse_zupdate_values(
1530 a.as_raw(),
1531 val.len() as sys::aoclsparse_int,
1532 val.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
1533 )
1534 };
1535 check_status("sparse", status)
1536}
1537pub fn update_values_c32(
1539 a: &mut ComplexSparseMatrix<Complex32>,
1540 val: &mut [Complex32],
1541) -> Result<()> {
1542 let status = unsafe {
1543 sys::aoclsparse_cupdate_values(
1544 a.as_raw(),
1545 val.len() as sys::aoclsparse_int,
1546 val.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
1547 )
1548 };
1549 check_status("sparse", status)
1550}
1551
1552#[allow(clippy::too_many_arguments)]
1557pub fn trsm_c64(
1558 op: Trans,
1559 alpha: Complex64,
1560 a: &ComplexSparseMatrix<Complex64>,
1561 descr: &MatDescr,
1562 b: &[Complex64],
1563 n_rhs: usize,
1564 ldb: usize,
1565 x: &mut [Complex64],
1566 ldx: usize,
1567) -> Result<()> {
1568 let alpha_raw = sys::aoclsparse_double_complex_ {
1569 real: alpha.re,
1570 imag: alpha.im,
1571 };
1572 let status = unsafe {
1573 sys::aoclsparse_ztrsm(
1574 trans_raw(op),
1575 alpha_raw,
1576 a.as_raw(),
1577 descr.as_raw(),
1578 sys::aoclsparse_order__aoclsparse_order_row,
1579 b.as_ptr() as *const sys::aoclsparse_double_complex,
1580 n_rhs as sys::aoclsparse_int,
1581 ldb as sys::aoclsparse_int,
1582 x.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
1583 ldx as sys::aoclsparse_int,
1584 )
1585 };
1586 check_status("sparse", status)
1587}
1588
1589#[allow(clippy::too_many_arguments)]
1591pub fn trsm_c32(
1592 op: Trans,
1593 alpha: Complex32,
1594 a: &ComplexSparseMatrix<Complex32>,
1595 descr: &MatDescr,
1596 b: &[Complex32],
1597 n_rhs: usize,
1598 ldb: usize,
1599 x: &mut [Complex32],
1600 ldx: usize,
1601) -> Result<()> {
1602 let alpha_raw = sys::aoclsparse_float_complex {
1603 real: alpha.re,
1604 imag: alpha.im,
1605 };
1606 let status = unsafe {
1607 sys::aoclsparse_ctrsm(
1608 trans_raw(op),
1609 alpha_raw,
1610 a.as_raw(),
1611 descr.as_raw(),
1612 sys::aoclsparse_order__aoclsparse_order_row,
1613 b.as_ptr() as *const sys::aoclsparse_float_complex,
1614 n_rhs as sys::aoclsparse_int,
1615 ldb as sys::aoclsparse_int,
1616 x.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
1617 ldx as sys::aoclsparse_int,
1618 )
1619 };
1620 check_status("sparse", status)
1621}
1622
1623#[allow(clippy::too_many_arguments)]
1627pub fn dotmv_c64(
1628 op: Trans,
1629 alpha: Complex64,
1630 a: &ComplexSparseMatrix<Complex64>,
1631 descr: &MatDescr,
1632 x: &[Complex64],
1633 beta: Complex64,
1634 y: &mut [Complex64],
1635 d: &mut Complex64,
1636) -> Result<()> {
1637 let alpha_raw = sys::aoclsparse_double_complex_ {
1638 real: alpha.re,
1639 imag: alpha.im,
1640 };
1641 let beta_raw = sys::aoclsparse_double_complex_ {
1642 real: beta.re,
1643 imag: beta.im,
1644 };
1645 let status = unsafe {
1646 sys::aoclsparse_zdotmv(
1647 trans_raw(op),
1648 alpha_raw,
1649 a.as_raw(),
1650 descr.as_raw(),
1651 x.as_ptr() as *const sys::aoclsparse_double_complex,
1652 beta_raw,
1653 y.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
1654 d as *mut _ as *mut sys::aoclsparse_double_complex,
1655 )
1656 };
1657 check_status("sparse", status)
1658}
1659
1660#[allow(clippy::too_many_arguments)]
1662pub fn dotmv_c32(
1663 op: Trans,
1664 alpha: Complex32,
1665 a: &ComplexSparseMatrix<Complex32>,
1666 descr: &MatDescr,
1667 x: &[Complex32],
1668 beta: Complex32,
1669 y: &mut [Complex32],
1670 d: &mut Complex32,
1671) -> Result<()> {
1672 let alpha_raw = sys::aoclsparse_float_complex {
1673 real: alpha.re,
1674 imag: alpha.im,
1675 };
1676 let beta_raw = sys::aoclsparse_float_complex {
1677 real: beta.re,
1678 imag: beta.im,
1679 };
1680 let status = unsafe {
1681 sys::aoclsparse_cdotmv(
1682 trans_raw(op),
1683 alpha_raw,
1684 a.as_raw(),
1685 descr.as_raw(),
1686 x.as_ptr() as *const sys::aoclsparse_float_complex,
1687 beta_raw,
1688 y.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
1689 d as *mut _ as *mut sys::aoclsparse_float_complex,
1690 )
1691 };
1692 check_status("sparse", status)
1693}
1694
1695pub fn dotui_c64(
1697 x: &[Complex64],
1698 indx: &[sys::aoclsparse_int],
1699 y: &[Complex64],
1700) -> Result<Complex64> {
1701 let mut out = Complex64::new(0.0, 0.0);
1702 let status = unsafe {
1703 sys::aoclsparse_zdotui(
1704 x.len() as sys::aoclsparse_int,
1705 x.as_ptr() as *const std::os::raw::c_void,
1706 indx.as_ptr(),
1707 y.as_ptr() as *const std::os::raw::c_void,
1708 &mut out as *mut _ as *mut std::os::raw::c_void,
1709 )
1710 };
1711 check_status("sparse", status)?;
1712 Ok(out)
1713}
1714pub fn dotui_c32(
1716 x: &[Complex32],
1717 indx: &[sys::aoclsparse_int],
1718 y: &[Complex32],
1719) -> Result<Complex32> {
1720 let mut out = Complex32::new(0.0, 0.0);
1721 let status = unsafe {
1722 sys::aoclsparse_cdotui(
1723 x.len() as sys::aoclsparse_int,
1724 x.as_ptr() as *const std::os::raw::c_void,
1725 indx.as_ptr(),
1726 y.as_ptr() as *const std::os::raw::c_void,
1727 &mut out as *mut _ as *mut std::os::raw::c_void,
1728 )
1729 };
1730 check_status("sparse", status)?;
1731 Ok(out)
1732}
1733
1734pub fn dotci_c64(
1736 x: &[Complex64],
1737 indx: &[sys::aoclsparse_int],
1738 y: &[Complex64],
1739) -> Result<Complex64> {
1740 let mut out = Complex64::new(0.0, 0.0);
1741 let status = unsafe {
1742 sys::aoclsparse_zdotci(
1743 x.len() as sys::aoclsparse_int,
1744 x.as_ptr() as *const std::os::raw::c_void,
1745 indx.as_ptr(),
1746 y.as_ptr() as *const std::os::raw::c_void,
1747 &mut out as *mut _ as *mut std::os::raw::c_void,
1748 )
1749 };
1750 check_status("sparse", status)?;
1751 Ok(out)
1752}
1753pub fn dotci_c32(
1755 x: &[Complex32],
1756 indx: &[sys::aoclsparse_int],
1757 y: &[Complex32],
1758) -> Result<Complex32> {
1759 let mut out = Complex32::new(0.0, 0.0);
1760 let status = unsafe {
1761 sys::aoclsparse_cdotci(
1762 x.len() as sys::aoclsparse_int,
1763 x.as_ptr() as *const std::os::raw::c_void,
1764 indx.as_ptr(),
1765 y.as_ptr() as *const std::os::raw::c_void,
1766 &mut out as *mut _ as *mut std::os::raw::c_void,
1767 )
1768 };
1769 check_status("sparse", status)?;
1770 Ok(out)
1771}
1772
1773pub fn gthrs_c64(y: &[Complex64], x: &mut [Complex64], stride: i32) -> Result<()> {
1777 let status = unsafe {
1778 sys::aoclsparse_zgthrs(
1779 x.len() as sys::aoclsparse_int,
1780 y.as_ptr() as *const std::os::raw::c_void,
1781 x.as_mut_ptr() as *mut std::os::raw::c_void,
1782 stride as sys::aoclsparse_int,
1783 )
1784 };
1785 check_status("sparse", status)
1786}
1787pub fn gthrs_c32(y: &[Complex32], x: &mut [Complex32], stride: i32) -> Result<()> {
1789 let status = unsafe {
1790 sys::aoclsparse_cgthrs(
1791 x.len() as sys::aoclsparse_int,
1792 y.as_ptr() as *const std::os::raw::c_void,
1793 x.as_mut_ptr() as *mut std::os::raw::c_void,
1794 stride as sys::aoclsparse_int,
1795 )
1796 };
1797 check_status("sparse", status)
1798}
1799
1800pub fn gthrz_c64(
1802 y: &mut [Complex64],
1803 indx: &[sys::aoclsparse_int],
1804 x: &mut [Complex64],
1805) -> Result<()> {
1806 let status = unsafe {
1807 sys::aoclsparse_zgthrz(
1808 x.len() as sys::aoclsparse_int,
1809 y.as_mut_ptr() as *mut std::os::raw::c_void,
1810 x.as_mut_ptr() as *mut std::os::raw::c_void,
1811 indx.as_ptr(),
1812 )
1813 };
1814 check_status("sparse", status)
1815}
1816pub fn gthrz_c32(
1818 y: &mut [Complex32],
1819 indx: &[sys::aoclsparse_int],
1820 x: &mut [Complex32],
1821) -> Result<()> {
1822 let status = unsafe {
1823 sys::aoclsparse_cgthrz(
1824 x.len() as sys::aoclsparse_int,
1825 y.as_mut_ptr() as *mut std::os::raw::c_void,
1826 x.as_mut_ptr() as *mut std::os::raw::c_void,
1827 indx.as_ptr(),
1828 )
1829 };
1830 check_status("sparse", status)
1831}
1832
1833pub fn sctrs_c64(x: &[Complex64], y: &mut [Complex64], stride: i32) -> Result<()> {
1835 let status = unsafe {
1836 sys::aoclsparse_zsctrs(
1837 x.len() as sys::aoclsparse_int,
1838 x.as_ptr() as *const std::os::raw::c_void,
1839 stride as sys::aoclsparse_int,
1840 y.as_mut_ptr() as *mut std::os::raw::c_void,
1841 )
1842 };
1843 check_status("sparse", status)
1844}
1845pub fn sctrs_c32(x: &[Complex32], y: &mut [Complex32], stride: i32) -> Result<()> {
1847 let status = unsafe {
1848 sys::aoclsparse_csctrs(
1849 x.len() as sys::aoclsparse_int,
1850 x.as_ptr() as *const std::os::raw::c_void,
1851 stride as sys::aoclsparse_int,
1852 y.as_mut_ptr() as *mut std::os::raw::c_void,
1853 )
1854 };
1855 check_status("sparse", status)
1856}
1857
1858#[allow(clippy::too_many_arguments)]
1862pub fn syrkd_c64(
1863 op_a: Trans,
1864 a: &ComplexSparseMatrix<Complex64>,
1865 alpha: Complex64,
1866 beta: Complex64,
1867 c: &mut [Complex64],
1868 order_c: Order,
1869 ldc: usize,
1870) -> Result<()> {
1871 let alpha_raw = sys::aoclsparse_double_complex_ {
1872 real: alpha.re,
1873 imag: alpha.im,
1874 };
1875 let beta_raw = sys::aoclsparse_double_complex_ {
1876 real: beta.re,
1877 imag: beta.im,
1878 };
1879 let status = unsafe {
1880 sys::aoclsparse_zsyrkd(
1881 trans_raw(op_a),
1882 a.as_raw(),
1883 alpha_raw,
1884 beta_raw,
1885 c.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
1886 order_c.raw(),
1887 ldc as sys::aoclsparse_int,
1888 )
1889 };
1890 check_status("sparse", status)
1891}
1892#[allow(clippy::too_many_arguments)]
1894pub fn syrkd_c32(
1895 op_a: Trans,
1896 a: &ComplexSparseMatrix<Complex32>,
1897 alpha: Complex32,
1898 beta: Complex32,
1899 c: &mut [Complex32],
1900 order_c: Order,
1901 ldc: usize,
1902) -> Result<()> {
1903 let alpha_raw = sys::aoclsparse_float_complex {
1904 real: alpha.re,
1905 imag: alpha.im,
1906 };
1907 let beta_raw = sys::aoclsparse_float_complex {
1908 real: beta.re,
1909 imag: beta.im,
1910 };
1911 let status = unsafe {
1912 sys::aoclsparse_csyrkd(
1913 trans_raw(op_a),
1914 a.as_raw(),
1915 alpha_raw,
1916 beta_raw,
1917 c.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
1918 order_c.raw(),
1919 ldc as sys::aoclsparse_int,
1920 )
1921 };
1922 check_status("sparse", status)
1923}
1924
1925#[allow(clippy::too_many_arguments)]
1928pub fn syprd_c64(
1929 op_a: Trans,
1930 a: &ComplexSparseMatrix<Complex64>,
1931 b: &[Complex64],
1932 order_b: Order,
1933 ldb: usize,
1934 alpha: Complex64,
1935 beta: Complex64,
1936 c: &mut [Complex64],
1937 order_c: Order,
1938 ldc: usize,
1939) -> Result<()> {
1940 let alpha_raw = sys::aoclsparse_double_complex_ {
1941 real: alpha.re,
1942 imag: alpha.im,
1943 };
1944 let beta_raw = sys::aoclsparse_double_complex_ {
1945 real: beta.re,
1946 imag: beta.im,
1947 };
1948 let status = unsafe {
1949 sys::aoclsparse_zsyprd(
1950 trans_raw(op_a),
1951 a.as_raw(),
1952 b.as_ptr() as *const sys::aoclsparse_double_complex,
1953 order_b.raw(),
1954 ldb as sys::aoclsparse_int,
1955 alpha_raw,
1956 beta_raw,
1957 c.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
1958 order_c.raw(),
1959 ldc as sys::aoclsparse_int,
1960 )
1961 };
1962 check_status("sparse", status)
1963}
1964#[allow(clippy::too_many_arguments)]
1966pub fn syprd_c32(
1967 op_a: Trans,
1968 a: &ComplexSparseMatrix<Complex32>,
1969 b: &[Complex32],
1970 order_b: Order,
1971 ldb: usize,
1972 alpha: Complex32,
1973 beta: Complex32,
1974 c: &mut [Complex32],
1975 order_c: Order,
1976 ldc: usize,
1977) -> Result<()> {
1978 let alpha_raw = sys::aoclsparse_float_complex {
1979 real: alpha.re,
1980 imag: alpha.im,
1981 };
1982 let beta_raw = sys::aoclsparse_float_complex {
1983 real: beta.re,
1984 imag: beta.im,
1985 };
1986 let status = unsafe {
1987 sys::aoclsparse_csyprd(
1988 trans_raw(op_a),
1989 a.as_raw(),
1990 b.as_ptr() as *const sys::aoclsparse_float_complex,
1991 order_b.raw(),
1992 ldb as sys::aoclsparse_int,
1993 alpha_raw,
1994 beta_raw,
1995 c.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
1996 order_c.raw(),
1997 ldc as sys::aoclsparse_int,
1998 )
1999 };
2000 check_status("sparse", status)
2001}
2002
2003#[allow(clippy::too_many_arguments)]
2007pub fn create_csc_c64(
2008 base: IndexBase,
2009 m: usize,
2010 n: usize,
2011 nnz: usize,
2012 col_ptr: &mut [sys::aoclsparse_int],
2013 row_idx: &mut [sys::aoclsparse_int],
2014 val: &mut [Complex64],
2015) -> Result<sys::aoclsparse_matrix> {
2016 let mut raw: sys::aoclsparse_matrix = std::ptr::null_mut();
2017 let status = unsafe {
2018 sys::aoclsparse_create_zcsc(
2019 &mut raw,
2020 base.raw_for_complex(),
2021 m as sys::aoclsparse_int,
2022 n as sys::aoclsparse_int,
2023 nnz as sys::aoclsparse_int,
2024 col_ptr.as_mut_ptr(),
2025 row_idx.as_mut_ptr(),
2026 val.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
2027 )
2028 };
2029 check_status("sparse", status)?;
2030 if raw.is_null() {
2031 return Err(Error::AllocationFailed("sparse"));
2032 }
2033 Ok(raw)
2034}
2035#[allow(clippy::too_many_arguments)]
2037pub fn create_csc_c32(
2038 base: IndexBase,
2039 m: usize,
2040 n: usize,
2041 nnz: usize,
2042 col_ptr: &mut [sys::aoclsparse_int],
2043 row_idx: &mut [sys::aoclsparse_int],
2044 val: &mut [Complex32],
2045) -> Result<sys::aoclsparse_matrix> {
2046 let mut raw: sys::aoclsparse_matrix = std::ptr::null_mut();
2047 let status = unsafe {
2048 sys::aoclsparse_create_ccsc(
2049 &mut raw,
2050 base.raw_for_complex(),
2051 m as sys::aoclsparse_int,
2052 n as sys::aoclsparse_int,
2053 nnz as sys::aoclsparse_int,
2054 col_ptr.as_mut_ptr(),
2055 row_idx.as_mut_ptr(),
2056 val.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
2057 )
2058 };
2059 check_status("sparse", status)?;
2060 if raw.is_null() {
2061 return Err(Error::AllocationFailed("sparse"));
2062 }
2063 Ok(raw)
2064}
2065
2066#[allow(clippy::too_many_arguments)]
2069pub fn create_tcsr_c64(
2070 base: IndexBase,
2071 m: usize,
2072 n: usize,
2073 nnz: usize,
2074 row_ptr_l: &mut [sys::aoclsparse_int],
2075 row_ptr_u: &mut [sys::aoclsparse_int],
2076 col_idx_l: &mut [sys::aoclsparse_int],
2077 col_idx_u: &mut [sys::aoclsparse_int],
2078 val_l: &mut [Complex64],
2079 val_u: &mut [Complex64],
2080) -> Result<sys::aoclsparse_matrix> {
2081 let mut raw: sys::aoclsparse_matrix = std::ptr::null_mut();
2082 let status = unsafe {
2083 sys::aoclsparse_create_ztcsr(
2084 &mut raw,
2085 base.raw_for_complex(),
2086 m as sys::aoclsparse_int,
2087 n as sys::aoclsparse_int,
2088 nnz as sys::aoclsparse_int,
2089 row_ptr_l.as_mut_ptr(),
2090 row_ptr_u.as_mut_ptr(),
2091 col_idx_l.as_mut_ptr(),
2092 col_idx_u.as_mut_ptr(),
2093 val_l.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
2094 val_u.as_mut_ptr() as *mut sys::aoclsparse_double_complex,
2095 )
2096 };
2097 check_status("sparse", status)?;
2098 if raw.is_null() {
2099 return Err(Error::AllocationFailed("sparse"));
2100 }
2101 Ok(raw)
2102}
2103#[allow(clippy::too_many_arguments)]
2105pub fn create_tcsr_c32(
2106 base: IndexBase,
2107 m: usize,
2108 n: usize,
2109 nnz: usize,
2110 row_ptr_l: &mut [sys::aoclsparse_int],
2111 row_ptr_u: &mut [sys::aoclsparse_int],
2112 col_idx_l: &mut [sys::aoclsparse_int],
2113 col_idx_u: &mut [sys::aoclsparse_int],
2114 val_l: &mut [Complex32],
2115 val_u: &mut [Complex32],
2116) -> Result<sys::aoclsparse_matrix> {
2117 let mut raw: sys::aoclsparse_matrix = std::ptr::null_mut();
2118 let status = unsafe {
2119 sys::aoclsparse_create_ctcsr(
2120 &mut raw,
2121 base.raw_for_complex(),
2122 m as sys::aoclsparse_int,
2123 n as sys::aoclsparse_int,
2124 nnz as sys::aoclsparse_int,
2125 row_ptr_l.as_mut_ptr(),
2126 row_ptr_u.as_mut_ptr(),
2127 col_idx_l.as_mut_ptr(),
2128 col_idx_u.as_mut_ptr(),
2129 val_l.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
2130 val_u.as_mut_ptr() as *mut sys::aoclsparse_float_complex,
2131 )
2132 };
2133 check_status("sparse", status)?;
2134 if raw.is_null() {
2135 return Err(Error::AllocationFailed("sparse"));
2136 }
2137 Ok(raw)
2138}
2139
2140impl IndexBase {
2143 pub(crate) fn raw_for_complex(self) -> sys::aoclsparse_index_base {
2144 match self {
2145 IndexBase::Zero => sys::aoclsparse_index_base__aoclsparse_index_base_zero,
2146 IndexBase::One => sys::aoclsparse_index_base__aoclsparse_index_base_one,
2147 }
2148 }
2149}
2150
2151#[cfg(test)]
2152mod tests {
2153 use super::*;
2154
2155 #[test]
2156 fn axpyi_c64_round_trip() {
2157 let mut y = [
2160 Complex64::new(1.0, 0.0),
2161 Complex64::new(2.0, 0.0),
2162 Complex64::new(3.0, 0.0),
2163 Complex64::new(4.0, 0.0),
2164 ];
2165 let x = [Complex64::new(10.0, 1.0), Complex64::new(20.0, 2.0)];
2166 let indx: [sys::aoclsparse_int; 2] = [0, 2];
2167 axpyi(Complex64::new(3.0, 0.0), &x, &indx, &mut y).unwrap();
2168 assert!((y[0].re - 31.0).abs() < 1e-12);
2169 assert!((y[0].im - 3.0).abs() < 1e-12);
2170 assert!((y[2].re - 63.0).abs() < 1e-12);
2171 assert!((y[2].im - 6.0).abs() < 1e-12);
2172 assert!((y[1].re - 2.0).abs() < 1e-12);
2173 assert!((y[3].re - 4.0).abs() < 1e-12);
2174 }
2175
2176 #[test]
2177 fn complex_sparse_matrix_round_trip_c64() {
2178 let val = [Complex64::new(1.0, 0.0), Complex64::new(1.0, 0.0)];
2180 let col: [sys::aoclsparse_int; 2] = [0, 1];
2181 let rp: [sys::aoclsparse_int; 3] = [0, 1, 2];
2182 let mat =
2183 ComplexSparseMatrix::<Complex64>::from_csr(IndexBase::Zero, 2, 2, &rp, &col, &val)
2184 .unwrap();
2185 assert_eq!(mat.dims(), (2, 2));
2186 assert_eq!(mat.nnz(), 2);
2187 let (base, rp2, col2, val2) = mat.export_csr().unwrap();
2188 assert_eq!(base, IndexBase::Zero);
2189 assert_eq!(rp2, [0, 1, 2]);
2190 assert_eq!(col2, [0, 1]);
2191 assert!((val2[0].re - 1.0).abs() < 1e-12);
2192 }
2193
2194 #[test]
2195 fn complex_mv_identity_c64() {
2196 let val = [Complex64::new(1.0, 0.0), Complex64::new(1.0, 0.0)];
2198 let col: [sys::aoclsparse_int; 2] = [0, 1];
2199 let rp: [sys::aoclsparse_int; 3] = [0, 1, 2];
2200 let mat =
2201 ComplexSparseMatrix::<Complex64>::from_csr(IndexBase::Zero, 2, 2, &rp, &col, &val)
2202 .unwrap();
2203 let descr = MatDescr::new().unwrap();
2204 let x = [Complex64::new(3.0, 1.0), Complex64::new(4.0, -2.0)];
2205 let mut y = [Complex64::new(0.0, 0.0); 2];
2206 mv(
2207 Trans::No,
2208 Complex64::new(1.0, 0.0),
2209 &mat,
2210 &descr,
2211 &x,
2212 Complex64::new(0.0, 0.0),
2213 &mut y,
2214 )
2215 .unwrap();
2216 assert!((y[0].re - 3.0).abs() < 1e-12);
2217 assert!((y[0].im - 1.0).abs() < 1e-12);
2218 assert!((y[1].re - 4.0).abs() < 1e-12);
2219 assert!((y[1].im + 2.0).abs() < 1e-12);
2220 }
2221
2222 #[test]
2223 fn complex_mv_identity_c32() {
2224 let val = [Complex32::new(1.0, 0.0), Complex32::new(1.0, 0.0)];
2225 let col: [sys::aoclsparse_int; 2] = [0, 1];
2226 let rp: [sys::aoclsparse_int; 3] = [0, 1, 2];
2227 let mat =
2228 ComplexSparseMatrix::<Complex32>::from_csr(IndexBase::Zero, 2, 2, &rp, &col, &val)
2229 .unwrap();
2230 let descr = MatDescr::new().unwrap();
2231 let x = [Complex32::new(3.0, 1.0), Complex32::new(4.0, -2.0)];
2232 let mut y = [Complex32::new(0.0, 0.0); 2];
2233 mv(
2234 Trans::No,
2235 Complex32::new(1.0, 0.0),
2236 &mat,
2237 &descr,
2238 &x,
2239 Complex32::new(0.0, 0.0),
2240 &mut y,
2241 )
2242 .unwrap();
2243 assert!((y[0].re - 3.0).abs() < 1e-6);
2244 assert!((y[0].im - 1.0).abs() < 1e-6);
2245 assert!((y[1].re - 4.0).abs() < 1e-6);
2246 assert!((y[1].im + 2.0).abs() < 1e-6);
2247 }
2248
2249 #[test]
2250 fn complex_csrmm_identity_c64() {
2251 let val = [Complex64::new(1.0, 0.0), Complex64::new(1.0, 0.0)];
2253 let col: [sys::aoclsparse_int; 2] = [0, 1];
2254 let rp: [sys::aoclsparse_int; 3] = [0, 1, 2];
2255 let a = ComplexSparseMatrix::<Complex64>::from_csr(IndexBase::Zero, 2, 2, &rp, &col, &val)
2256 .unwrap();
2257 let descr = MatDescr::new().unwrap();
2258 let b = [
2262 Complex64::new(1.0, 1.0),
2263 Complex64::new(2.0, -1.0),
2264 Complex64::new(3.0, 0.0),
2265 Complex64::new(4.0, 2.0),
2266 ];
2267 let mut c = [Complex64::new(0.0, 0.0); 4];
2268 crate::complex::csrmm(
2269 Trans::No,
2270 Complex64::new(1.0, 0.0),
2271 &a,
2272 &descr,
2273 Order::RowMajor,
2274 &b,
2275 2,
2276 2,
2277 Complex64::new(0.0, 0.0),
2278 &mut c,
2279 2,
2280 )
2281 .unwrap();
2282 for (got, want) in c.iter().zip(b.iter()) {
2283 assert!((got.re - want.re).abs() < 1e-12);
2284 assert!((got.im - want.im).abs() < 1e-12);
2285 }
2286 }
2287
2288 #[test]
2289 fn complex_add_identity_plus_identity_c64() {
2290 let val = [Complex64::new(1.0, 0.0), Complex64::new(1.0, 0.0)];
2291 let col: [sys::aoclsparse_int; 2] = [0, 1];
2292 let rp: [sys::aoclsparse_int; 3] = [0, 1, 2];
2293 let a = ComplexSparseMatrix::<Complex64>::from_csr(IndexBase::Zero, 2, 2, &rp, &col, &val)
2294 .unwrap();
2295 let b = ComplexSparseMatrix::<Complex64>::from_csr(IndexBase::Zero, 2, 2, &rp, &col, &val)
2296 .unwrap();
2297 let c = crate::complex::add(Trans::No, &a, Complex64::new(1.0, 0.0), &b).unwrap();
2298 let (_, _, _, val_c) = c.export_csr().unwrap();
2299 assert_eq!(val_c.len(), 2);
2300 for v in &val_c {
2301 assert!((v.re - 2.0).abs() < 1e-12);
2302 assert!(v.im.abs() < 1e-12);
2303 }
2304 }
2305}