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