1use singe_cuda::{data_type::DataTypeLike, types::DevicePtr};
2
3use singe_cusparse_sys as sys;
4
5use crate::{
6 context::Context,
7 error::Result,
8 matrix::{DenseMatrixDescriptor, SparseMatrixDescriptor},
9 operation::SpSmDescriptor,
10 scalar::Scalar,
11 try_ffi,
12 types::{Operation, SpSMAlgorithm, SpSmUpdate},
13 utility::to_usize,
14};
15
16pub fn spsm_buffer_size<Compute: DataTypeLike>(
17 ctx: &Context,
18 op_a: Operation,
19 op_b: Operation,
20 alpha: Scalar<'_, Compute>,
21 matrix_a: &SparseMatrixDescriptor,
22 matrix_b: &DenseMatrixDescriptor,
23 matrix_c: &mut DenseMatrixDescriptor,
24 algorithm: SpSMAlgorithm,
25 descriptor: &SpSmDescriptor,
26) -> Result<usize> {
27 descriptor.ensure_context(ctx)?;
28 matrix_a.ensure_context(ctx)?;
29 matrix_b.ensure_context(ctx)?;
30 matrix_c.ensure_context(ctx)?;
31 ctx.bind()?;
32 if ctx.scalar_pointer_mode()? != alpha.pointer_mode() {
33 ctx.set_scalar_pointer_mode(alpha.pointer_mode())?;
34 }
35
36 let mut size = 0;
37 unsafe {
38 try_ffi!(sys::cusparseSpSM_bufferSize(
39 ctx.as_raw(),
40 op_a.into(),
41 op_b.into(),
42 alpha.ptr().cast(),
43 matrix_a.as_raw_const(),
44 matrix_b.as_raw_const(),
45 matrix_c.as_raw(),
46 Compute::data_type().into(),
47 algorithm.into(),
48 descriptor.as_raw(),
49 &raw mut size,
50 ))?;
51 }
52 to_usize(size, "spsm buffer size")
53}
54
55pub fn spsm_analysis<Compute: DataTypeLike>(
56 ctx: &Context,
57 op_a: Operation,
58 op_b: Operation,
59 alpha: Scalar<'_, Compute>,
60 matrix_a: &SparseMatrixDescriptor,
61 matrix_b: &DenseMatrixDescriptor,
62 matrix_c: &mut DenseMatrixDescriptor,
63 algorithm: SpSMAlgorithm,
64 descriptor: &SpSmDescriptor,
65 external_buffer: Option<DevicePtr>,
66) -> Result<()> {
67 descriptor.ensure_context(ctx)?;
68 matrix_a.ensure_context(ctx)?;
69 matrix_b.ensure_context(ctx)?;
70 matrix_c.ensure_context(ctx)?;
71 ctx.bind()?;
72 if ctx.scalar_pointer_mode()? != alpha.pointer_mode() {
73 ctx.set_scalar_pointer_mode(alpha.pointer_mode())?;
74 }
75
76 unsafe {
77 try_ffi!(sys::cusparseSpSM_analysis(
78 ctx.as_raw(),
79 op_a.into(),
80 op_b.into(),
81 alpha.ptr().cast(),
82 matrix_a.as_raw_const(),
83 matrix_b.as_raw_const(),
84 matrix_c.as_raw(),
85 Compute::data_type().into(),
86 algorithm.into(),
87 descriptor.as_raw(),
88 external_buffer.unwrap_or(DevicePtr::null()).as_ptr() as _,
89 ))?;
90 }
91 Ok(())
92}
93
94pub fn spsm_solve<Compute: DataTypeLike>(
95 ctx: &Context,
96 op_a: Operation,
97 op_b: Operation,
98 alpha: Scalar<'_, Compute>,
99 matrix_a: &SparseMatrixDescriptor,
100 matrix_b: &DenseMatrixDescriptor,
101 matrix_c: &mut DenseMatrixDescriptor,
102 algorithm: SpSMAlgorithm,
103 descriptor: &SpSmDescriptor,
104) -> Result<()> {
105 descriptor.ensure_context(ctx)?;
106 matrix_a.ensure_context(ctx)?;
107 matrix_b.ensure_context(ctx)?;
108 matrix_c.ensure_context(ctx)?;
109 ctx.bind()?;
110 if ctx.scalar_pointer_mode()? != alpha.pointer_mode() {
111 ctx.set_scalar_pointer_mode(alpha.pointer_mode())?;
112 }
113
114 unsafe {
115 try_ffi!(sys::cusparseSpSM_solve(
116 ctx.as_raw(),
117 op_a.into(),
118 op_b.into(),
119 alpha.ptr().cast(),
120 matrix_a.as_raw_const(),
121 matrix_b.as_raw_const(),
122 matrix_c.as_raw(),
123 Compute::data_type().into(),
124 algorithm.into(),
125 descriptor.as_raw(),
126 ))?;
127 }
128 Ok(())
129}
130
131pub fn spsm_update_matrix(
132 ctx: &Context,
133 descriptor: &SpSmDescriptor,
134 new_values: DevicePtr,
135 update: SpSmUpdate,
136) -> Result<()> {
137 descriptor.ensure_context(ctx)?;
138 ctx.bind()?;
139 unsafe {
140 try_ffi!(sys::cusparseSpSM_updateMatrix(
141 ctx.as_raw(),
142 descriptor.as_raw(),
143 new_values.as_ptr() as _,
144 update.into(),
145 ))?;
146 }
147 Ok(())
148}