1 //------------------------------------------------------------------------------
2 // GrB_Matrix_apply: apply a unary or binary operator to a matrix
3 //------------------------------------------------------------------------------
4
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7
8 //------------------------------------------------------------------------------
9
10 #include "GB_apply.h"
11 #include "GB_scalar.h"
12
13 //------------------------------------------------------------------------------
14 // GrB_Matrix_apply: apply a unary operator to a matrix
15 //------------------------------------------------------------------------------
16
17 // C<M> = accum(C,op(A)) or accum(C,op(A'))
18
GrB_Matrix_apply(GrB_Matrix C,const GrB_Matrix M,const GrB_BinaryOp accum,const GrB_UnaryOp op,const GrB_Matrix A,const GrB_Descriptor desc)19 GrB_Info GrB_Matrix_apply // C<M> = accum (C, op(A)) or op(A')
20 (
21 GrB_Matrix C, // input/output matrix for results
22 const GrB_Matrix M, // optional mask for C, unused if NULL
23 const GrB_BinaryOp accum, // optional accum for Z=accum(C,T)
24 const GrB_UnaryOp op, // operator to apply to the entries
25 const GrB_Matrix A, // first input: matrix A
26 const GrB_Descriptor desc // descriptor for C, M, and A
27 )
28 {
29
30 //--------------------------------------------------------------------------
31 // check inputs
32 //--------------------------------------------------------------------------
33
34 GB_WHERE (C, "GrB_Matrix_apply (C, M, accum, op, A, desc)") ;
35 GB_BURBLE_START ("GrB_apply") ;
36 GB_RETURN_IF_NULL_OR_FAULTY (C) ;
37 GB_RETURN_IF_FAULTY (M) ;
38 GB_RETURN_IF_NULL_OR_FAULTY (A) ;
39
40 // get the descriptor
41 GB_GET_DESCRIPTOR (info, desc, C_replace, Mask_comp, Mask_struct,
42 A_transpose, xx1, xx2, xx7) ;
43 // printf ("unop A_transpose (GrB_INP0): %d\n", A_transpose) ;
44
45 //--------------------------------------------------------------------------
46 // apply the operator and optionally transpose
47 //--------------------------------------------------------------------------
48
49 info = GB_apply (
50 C, C_replace, // C and its descriptor
51 M, Mask_comp, Mask_struct, // mask and its descriptor
52 accum, // optional accum for Z=accum(C,T)
53 op, // operator op(.) to apply to the entries
54 NULL, NULL, false, // no binary operator
55 A, A_transpose, // A and its descriptor
56 Context) ;
57
58 GB_BURBLE_END ;
59 return (info) ;
60 }
61
62 //------------------------------------------------------------------------------
63 // GB_1st: apply a binary operator: op(x,A)
64 //------------------------------------------------------------------------------
65
GB_1st(GrB_Matrix C,const GrB_Matrix M,const GrB_BinaryOp accum,const GrB_BinaryOp op,const GxB_Scalar x,const GrB_Matrix A,const GrB_Descriptor desc,GB_Context Context)66 static inline GrB_Info GB_1st // C<M>=accum(C,op(x,A))
67 (
68 GrB_Matrix C, // input/output matrix for results
69 const GrB_Matrix M, // optional mask for C, unused if NULL
70 const GrB_BinaryOp accum, // optional accum for Z=accum(C,T)
71 const GrB_BinaryOp op, // operator to apply to the entries
72 const GxB_Scalar x, // first input: scalar x
73 const GrB_Matrix A, // second input: matrix A
74 const GrB_Descriptor desc, // descriptor for C, M, and A
75 GB_Context Context
76 )
77 {
78
79 //--------------------------------------------------------------------------
80 // check inputs
81 //--------------------------------------------------------------------------
82
83 GB_BURBLE_START ("GrB_apply") ;
84 GB_RETURN_IF_NULL_OR_FAULTY (C) ;
85 GB_RETURN_IF_FAULTY (M) ;
86 GB_RETURN_IF_NULL_OR_FAULTY (x) ;
87 GB_RETURN_IF_NULL_OR_FAULTY (A) ;
88
89 // get the descriptor, using GrB_INP1 to transpose the matrix
90 GB_GET_DESCRIPTOR (info, desc, C_replace, Mask_comp, Mask_struct,
91 xx1, A_transpose, xx2, xx7) ;
92 // printf ("bind1 A_transpose (GrB_INP1): %d\n", A_transpose) ;
93
94 //--------------------------------------------------------------------------
95 // apply the operator and optionally transpose
96 //--------------------------------------------------------------------------
97
98 info = GB_apply (
99 C, C_replace, // C and its descriptor
100 M, Mask_comp, Mask_struct, // mask and its descriptor
101 accum, // optional accum for Z=accum(C,T)
102 NULL, // no unary operator
103 op, x, true, // operator op(x,.) to apply to the entries
104 A, A_transpose, // A and its descriptor
105 Context) ;
106
107 GB_BURBLE_END ;
108 return (info) ;
109 }
110
111 //------------------------------------------------------------------------------
112 // GB_2nd: apply a binary operator: op(A,y)
113 //------------------------------------------------------------------------------
114
115 // C<M> = accum(C,op(A,y)) or accum(C,op(A,y'))
116
GB_2nd(GrB_Matrix C,const GrB_Matrix M,const GrB_BinaryOp accum,const GrB_BinaryOp op,const GrB_Matrix A,const GxB_Scalar y,const GrB_Descriptor desc,GB_Context Context)117 static inline GrB_Info GB_2nd // C<M>=accum(C,op(A,y))
118 (
119 GrB_Matrix C, // input/output matrix for results
120 const GrB_Matrix M, // optional mask for C, unused if NULL
121 const GrB_BinaryOp accum, // optional accum for Z=accum(C,T)
122 const GrB_BinaryOp op, // operator to apply to the entries
123 const GrB_Matrix A, // first input: matrix A
124 const GxB_Scalar y, // second input: scalar y
125 const GrB_Descriptor desc, // descriptor for C, M, and A
126 GB_Context Context
127 )
128 {
129
130 //--------------------------------------------------------------------------
131 // check inputs
132 //--------------------------------------------------------------------------
133
134 GB_BURBLE_START ("GrB_apply") ;
135 GB_RETURN_IF_NULL_OR_FAULTY (C) ;
136 GB_RETURN_IF_FAULTY (M) ;
137 GB_RETURN_IF_NULL_OR_FAULTY (A) ;
138 GB_RETURN_IF_NULL_OR_FAULTY (y) ;
139
140 // get the descriptor, using GrB_INP0 to transpose the matrix
141 GB_GET_DESCRIPTOR (info, desc, C_replace, Mask_comp, Mask_struct,
142 A_transpose, xx1, xx2, xx7) ;
143 // printf ("bind2 A_transpose (GrB_INP0): %d\n", A_transpose) ;
144
145 //--------------------------------------------------------------------------
146 // apply the operator and optionally transpose
147 //--------------------------------------------------------------------------
148
149 info = GB_apply (
150 C, C_replace, // C and its descriptor
151 M, Mask_comp, Mask_struct, // mask and its descriptor
152 accum, // optional accum for Z=accum(C,T)
153 NULL, // no unary operator
154 op, y, false, // operator op(.,y) to apply to the entries
155 A, A_transpose, // A and its descriptor
156 Context) ;
157
158 GB_BURBLE_END ;
159 return (info) ;
160 }
161
162 //------------------------------------------------------------------------------
163 // GxB_Matrix_apply_BinaryOp1st: apply a binary operator: op(x,A)
164 //------------------------------------------------------------------------------
165
166 // C<M> = accum(C,op(x,A)) or accum(C,op(x,A'))
167
GxB_Matrix_apply_BinaryOp1st(GrB_Matrix C,const GrB_Matrix M,const GrB_BinaryOp accum,const GrB_BinaryOp op,const GxB_Scalar x,const GrB_Matrix A,const GrB_Descriptor desc)168 GrB_Info GxB_Matrix_apply_BinaryOp1st // C<M>=accum(C,op(x,A))
169 (
170 GrB_Matrix C, // input/output matrix for results
171 const GrB_Matrix M, // optional mask for C, unused if NULL
172 const GrB_BinaryOp accum, // optional accum for Z=accum(C,T)
173 const GrB_BinaryOp op, // operator to apply to the entries
174 const GxB_Scalar x, // first input: scalar x
175 const GrB_Matrix A, // second input: matrix A
176 const GrB_Descriptor desc // descriptor for C, M, and A
177 )
178 {
179 GB_WHERE (C, "GxB_Matrix_apply_BinaryOp1st (C, M, accum, op, x, A, desc)") ;
180 return (GB_1st (C, M, accum, op, x, A, desc, Context)) ;
181 }
182
183 //------------------------------------------------------------------------------
184 // GxB_Matrix_apply_BinaryOp2nd: apply a binary operator: op(A,y)
185 //------------------------------------------------------------------------------
186
187 // C<M> = accum(C,op(A,y)) or accum(C,op(A,y'))
188
GxB_Matrix_apply_BinaryOp2nd(GrB_Matrix C,const GrB_Matrix M,const GrB_BinaryOp accum,const GrB_BinaryOp op,const GrB_Matrix A,const GxB_Scalar y,const GrB_Descriptor desc)189 GrB_Info GxB_Matrix_apply_BinaryOp2nd // C<M>=accum(C,op(A,y))
190 (
191 GrB_Matrix C, // input/output matrix for results
192 const GrB_Matrix M, // optional mask for C, unused if NULL
193 const GrB_BinaryOp accum, // optional accum for Z=accum(C,T)
194 const GrB_BinaryOp op, // operator to apply to the entries
195 const GrB_Matrix A, // first input: matrix A
196 const GxB_Scalar y, // second input: scalar y
197 const GrB_Descriptor desc // descriptor for C, M, and A
198 )
199 {
200 GB_WHERE (C, "GxB_Matrix_apply_BinaryOp2nd (C, M, accum, op, A, y, desc)") ;
201 return (GB_2nd (C, M, accum, op, A, y, desc, Context)) ;
202 }
203
204 //------------------------------------------------------------------------------
205 // GrB_Matrix_apply_BinaryOp1st_TYPE: apply a binary operator: op(x,A)
206 //------------------------------------------------------------------------------
207
208 #define GB_BIND1ST(prefix,type,T,ampersand,stype) \
209 GrB_Info GB_EVAL3 (prefix, _Matrix_apply_BinaryOp1st_, T) \
210 ( \
211 GrB_Matrix C, /* input/output matrix for results */ \
212 const GrB_Matrix M, /* optional mask for C*/ \
213 const GrB_BinaryOp accum, /* optional accum for Z=accum(C,T) */ \
214 const GrB_BinaryOp op, /* operator to apply to the entries */ \
215 const type x, /* first input: scalar x */ \
216 const GrB_Matrix A, /* second input: matrix A */ \
217 const GrB_Descriptor desc /* descriptor for C, M, and A */ \
218 ) \
219 { \
220 GB_WHERE (C, "GrB_Matrix_apply_BinaryOp1st_" GB_STR(T) \
221 "(C, M, accum, op, x, A, desc)") ; \
222 GB_SCALAR_WRAP (scalar, T, ampersand, x, stype) ; \
223 ASSERT_SCALAR_OK (scalar, "scalar for matrix_apply_bind1st", GB0) ; \
224 return (GB_1st (C, M, accum, op, scalar, A, desc, Context)) ; \
225 }
226
227 GB_BIND1ST (GrB, bool , BOOL , &, GrB_BOOL )
228 GB_BIND1ST (GrB, int8_t , INT8 , &, GrB_INT8 )
229 GB_BIND1ST (GrB, int16_t , INT16 , &, GrB_INT16 )
230 GB_BIND1ST (GrB, int32_t , INT32 , &, GrB_INT32 )
231 GB_BIND1ST (GrB, int64_t , INT64 , &, GrB_INT64 )
232 GB_BIND1ST (GrB, uint8_t , UINT8 , &, GrB_UINT8 )
233 GB_BIND1ST (GrB, uint16_t , UINT16 , &, GrB_UINT16)
234 GB_BIND1ST (GrB, uint32_t , UINT32 , &, GrB_UINT32)
235 GB_BIND1ST (GrB, uint64_t , UINT64 , &, GrB_UINT64)
236 GB_BIND1ST (GrB, float , FP32 , &, GrB_FP32 )
237 GB_BIND1ST (GrB, double , FP64 , &, GrB_FP64 )
238 GB_BIND1ST (GxB, GxB_FC32_t, FC32 , &, GxB_FC32 )
239 GB_BIND1ST (GxB, GxB_FC64_t, FC64 , &, GxB_FC64 )
240 GB_BIND1ST (GrB, void * , UDT , , op->xtype )
241
242 //------------------------------------------------------------------------------
243 // GrB_Matrix_apply_BinaryOp2nd_TYPE: apply a binary operator: op(A,y)
244 //------------------------------------------------------------------------------
245
246 #define GB_BIND2ND(prefix,type,T,ampersand,stype) \
247 GrB_Info GB_EVAL3 (prefix, _Matrix_apply_BinaryOp2nd_, T) \
248 ( \
249 GrB_Matrix C, /* input/output matrix for results */ \
250 const GrB_Matrix M, /* optional mask for C*/ \
251 const GrB_BinaryOp accum, /* optional accum for Z=accum(C,T) */ \
252 const GrB_BinaryOp op, /* operator to apply to the entries */ \
253 const GrB_Matrix A, /* first input: matrix A */ \
254 const type y, /* second input: scalar y */ \
255 const GrB_Descriptor desc /* descriptor for C, M, and A */ \
256 ) \
257 { \
258 GB_WHERE (C, "GrB_Matrix_apply_BinaryOp2nd_" GB_STR(T) \
259 "(C, M, accum, op, A, y, desc)") ; \
260 GB_SCALAR_WRAP (scalar, T, ampersand, y, stype) ; \
261 ASSERT_SCALAR_OK (scalar, "scalar for matrix_apply_bind2nd", GB0) ; \
262 return (GB_2nd (C, M, accum, op, A, scalar, desc, Context)) ; \
263 }
264
265 GB_BIND2ND (GrB, bool , BOOL , &, GrB_BOOL )
266 GB_BIND2ND (GrB, int8_t , INT8 , &, GrB_INT8 )
267 GB_BIND2ND (GrB, int16_t , INT16 , &, GrB_INT16 )
268 GB_BIND2ND (GrB, int32_t , INT32 , &, GrB_INT32 )
269 GB_BIND2ND (GrB, int64_t , INT64 , &, GrB_INT64 )
270 GB_BIND2ND (GrB, uint8_t , UINT8 , &, GrB_UINT8 )
271 GB_BIND2ND (GrB, uint16_t , UINT16 , &, GrB_UINT16)
272 GB_BIND2ND (GrB, uint32_t , UINT32 , &, GrB_UINT32)
273 GB_BIND2ND (GrB, uint64_t , UINT64 , &, GrB_UINT64)
274 GB_BIND2ND (GrB, float , FP32 , &, GrB_FP32 )
275 GB_BIND2ND (GrB, double , FP64 , &, GrB_FP64 )
276 GB_BIND2ND (GxB, GxB_FC32_t, FC32 , &, GxB_FC32 )
277 GB_BIND2ND (GxB, GxB_FC64_t, FC64 , &, GxB_FC64 )
278 GB_BIND2ND (GrB, void * , UDT , , op->ytype )
279
280