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