1 //------------------------------------------------------------------------------
2 // GB_binop:  hard-coded functions for each built-in binary operator
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 // If this file is in the Generated/ folder, do not edit it (auto-generated).
11 
12 #include "GB.h"
13 #ifndef GBCOMPACT
14 #include "GB_emult.h"
15 #include "GB_control.h"
16 #include "GB_ek_slice.h"
17 #include "GB_dense.h"
18 #include "GB_atomics.h"
19 #include "GB_bitmap_assign_methods.h"
20 #include "GB_binop__include.h"
21 
22 // C=binop(A,B) is defined by the following types and operators:
23 
24 // A+B function (eWiseAdd):         GB (_AaddB__div_fc64)
25 // A.*B function (eWiseMult):       GB (_AemultB)
26 // A.*B function (eWiseMult):       GB (_AemultB_02__div_fc64)
27 // A.*B function (eWiseMult):       GB (_AemultB_03__div_fc64)
28 // A.*B function (eWiseMult):       GB (_AemultB_bitmap__div_fc64)
29 // A*D function (colscale):         GB (_AxD__div_fc64)
30 // D*A function (rowscale):         GB (_DxB__div_fc64)
31 // C+=B function (dense accum):     GB (_Cdense_accumB__div_fc64)
32 // C+=b function (dense accum):     GB (_Cdense_accumb__div_fc64)
33 // C+=A+B function (dense ewise3):  GB (_Cdense_ewise3_accum__div_fc64)
34 // C=A+B function (dense ewise3):   GB (_Cdense_ewise3_noaccum__div_fc64)
35 // C=scalar+B                       GB (_bind1st__div_fc64)
36 // C=scalar+B'                      GB (_bind1st_tran__div_fc64)
37 // C=A+scalar                       GB (_bind2nd__div_fc64)
38 // C=A'+scalar                      GB (_bind2nd_tran__div_fc64)
39 
40 // C type:   GxB_FC64_t
41 // A type:   GxB_FC64_t
42 // B,b type: GxB_FC64_t
43 // BinaryOp: cij = GB_FC64_div (aij, bij)
44 
45 #define GB_ATYPE \
46     GxB_FC64_t
47 
48 #define GB_BTYPE \
49     GxB_FC64_t
50 
51 #define GB_CTYPE \
52     GxB_FC64_t
53 
54 // true if the types of A and B are identical
55 #define GB_ATYPE_IS_BTYPE \
56     1
57 
58 // true if the types of C and A are identical
59 #define GB_CTYPE_IS_ATYPE \
60     1
61 
62 // true if the types of C and B are identical
63 #define GB_CTYPE_IS_BTYPE \
64     1
65 
66 // aij = Ax [pA]
67 #define GB_GETA(aij,Ax,pA)  \
68     GxB_FC64_t aij = Ax [pA]
69 
70 // bij = Bx [pB]
71 #define GB_GETB(bij,Bx,pB)  \
72     GxB_FC64_t bij = Bx [pB]
73 
74 // declare scalar of the same type as C
75 #define GB_CTYPE_SCALAR(t)  \
76     GxB_FC64_t t
77 
78 // cij = Ax [pA]
79 #define GB_COPY_A_TO_C(cij,Ax,pA) \
80     cij = Ax [pA]
81 
82 // cij = Bx [pB]
83 #define GB_COPY_B_TO_C(cij,Bx,pB) \
84     cij = Bx [pB]
85 
86 #define GB_CX(p) Cx [p]
87 
88 // binary operator
89 #define GB_BINOP(z, x, y, i, j) \
90     z = GB_FC64_div (x, y) ;
91 
92 // true if the binop must be flipped
93 #define GB_BINOP_FLIP \
94     0
95 
96 // op is second
97 #define GB_OP_IS_SECOND \
98     0
99 
100 // do the numerical phases of GB_add and GB_emult
101 #define GB_PHASE_2_OF_2
102 
103 // hard-coded loops can be vectorized
104 #define GB_PRAGMA_SIMD_VECTORIZE GB_PRAGMA_SIMD
105 
106 // disable this operator and use the generic case if these conditions hold
107 #define GB_DISABLE \
108     (GxB_NO_DIV || GxB_NO_FC64 || GxB_NO_DIV_FC64)
109 
110 //------------------------------------------------------------------------------
111 // C += A+B, all 3 matrices dense
112 //------------------------------------------------------------------------------
113 
114 
115 
116 // The op must be MIN, MAX, PLUS, MINUS, RMINUS, TIMES, DIV, or RDIV.
117 
GB(_Cdense_ewise3_accum__div_fc64)118 void GB (_Cdense_ewise3_accum__div_fc64)
119 (
120     GrB_Matrix C,
121     const GrB_Matrix A,
122     const GrB_Matrix B,
123     const int nthreads
124 )
125 {
126     #include "GB_dense_ewise3_accum_template.c"
127 }
128 
129 
130 
131 //------------------------------------------------------------------------------
132 // C = A+B, all 3 matrices dense
133 //------------------------------------------------------------------------------
134 
GB(_Cdense_ewise3_noaccum__div_fc64)135 GrB_Info GB (_Cdense_ewise3_noaccum__div_fc64)
136 (
137     GrB_Matrix C,
138     const GrB_Matrix A,
139     const GrB_Matrix B,
140     const int nthreads
141 )
142 {
143     #if GB_DISABLE
144     return (GrB_NO_VALUE) ;
145     #else
146     #include "GB_dense_ewise3_noaccum_template.c"
147     return (GrB_SUCCESS) ;
148     #endif
149 }
150 
151 //------------------------------------------------------------------------------
152 // C += B, accumulate a sparse matrix into a dense matrix
153 //------------------------------------------------------------------------------
154 
GB(_Cdense_accumB__div_fc64)155 GrB_Info GB (_Cdense_accumB__div_fc64)
156 (
157     GrB_Matrix C,
158     const GrB_Matrix B,
159     const int64_t *B_ek_slicing, const int B_ntasks, const int B_nthreads
160 )
161 {
162     #if GB_DISABLE
163     return (GrB_NO_VALUE) ;
164     #else
165 
166     {
167         #include "GB_dense_subassign_23_template.c"
168     }
169 
170     return (GrB_SUCCESS) ;
171     #endif
172 }
173 
174 //------------------------------------------------------------------------------
175 // C += b, accumulate a scalar into a dense matrix
176 //------------------------------------------------------------------------------
177 
GB(_Cdense_accumb__div_fc64)178 GrB_Info GB (_Cdense_accumb__div_fc64)
179 (
180     GrB_Matrix C,
181     const GB_void *p_bwork,
182     const int nthreads
183 )
184 {
185     #if GB_DISABLE
186     return (GrB_NO_VALUE) ;
187     #else
188 
189     {
190         // get the scalar b for C += b, of type GxB_FC64_t
191         GxB_FC64_t bwork = (*((GxB_FC64_t *) p_bwork)) ;
192         #include "GB_dense_subassign_22_template.c"
193         return (GrB_SUCCESS) ;
194     }
195 
196     return (GrB_SUCCESS) ;
197     #endif
198 }
199 
200 //------------------------------------------------------------------------------
201 // C = A*D, column scale with diagonal D matrix
202 //------------------------------------------------------------------------------
203 
204 
205 
GB(_AxD__div_fc64)206 GrB_Info GB (_AxD__div_fc64)
207 (
208     GrB_Matrix C,
209     const GrB_Matrix A, bool A_is_pattern,
210     const GrB_Matrix D, bool D_is_pattern,
211     const int64_t *A_ek_slicing, const int A_ntasks, const int A_nthreads
212 )
213 {
214     #if GB_DISABLE
215     return (GrB_NO_VALUE) ;
216     #else
217     GxB_FC64_t *restrict Cx = (GxB_FC64_t *) C->x ;
218     #include "GB_AxB_colscale_meta.c"
219     return (GrB_SUCCESS) ;
220     #endif
221 }
222 
223 
224 
225 //------------------------------------------------------------------------------
226 // C = D*B, row scale with diagonal D matrix
227 //------------------------------------------------------------------------------
228 
229 
230 
GB(_DxB__div_fc64)231 GrB_Info GB (_DxB__div_fc64)
232 (
233     GrB_Matrix C,
234     const GrB_Matrix D, bool D_is_pattern,
235     const GrB_Matrix B, bool B_is_pattern,
236     int nthreads
237 )
238 {
239     #if GB_DISABLE
240     return (GrB_NO_VALUE) ;
241     #else
242     GxB_FC64_t *restrict Cx = (GxB_FC64_t *) C->x ;
243     #include "GB_AxB_rowscale_meta.c"
244     return (GrB_SUCCESS) ;
245     #endif
246 }
247 
248 
249 
250 //------------------------------------------------------------------------------
251 // eWiseAdd: C = A+B or C<M> = A+B
252 //------------------------------------------------------------------------------
253 
GB(_AaddB__div_fc64)254 GrB_Info GB (_AaddB__div_fc64)
255 (
256     GrB_Matrix C,
257     const int C_sparsity,
258     const GrB_Matrix M,
259     const bool Mask_struct,
260     const bool Mask_comp,
261     const GrB_Matrix A,
262     const GrB_Matrix B,
263     const bool Ch_is_Mh,
264     const int64_t *restrict C_to_M,
265     const int64_t *restrict C_to_A,
266     const int64_t *restrict C_to_B,
267     const GB_task_struct *restrict TaskList,
268     const int C_ntasks,
269     const int C_nthreads,
270     GB_Context Context
271 )
272 {
273     #if GB_DISABLE
274     return (GrB_NO_VALUE) ;
275     #else
276     GB_WERK_DECLARE (M_ek_slicing, int64_t) ;
277     GB_WERK_DECLARE (A_ek_slicing, int64_t) ;
278     GB_WERK_DECLARE (B_ek_slicing, int64_t) ;
279     #include "GB_add_template.c"
280     GB_FREE_WORK ;
281     return (GrB_SUCCESS) ;
282     #endif
283 }
284 
285 //------------------------------------------------------------------------------
286 // eWiseMult: C = A.*B or C<M> = A.*B
287 //------------------------------------------------------------------------------
288 
GB(_AemultB_01__div_fc64)289 GrB_Info GB (_AemultB_01__div_fc64)
290 (
291     GrB_Matrix C,
292     const int C_sparsity,
293     const int ewise_method,
294     const GrB_Matrix M,
295     const bool Mask_struct,
296     const bool Mask_comp,
297     const GrB_Matrix A,
298     const GrB_Matrix B,
299     const int64_t *restrict C_to_M,
300     const int64_t *restrict C_to_A,
301     const int64_t *restrict C_to_B,
302     const GB_task_struct *restrict TaskList,
303     const int C_ntasks,
304     const int C_nthreads,
305     GB_Context Context
306 )
307 {
308     #if GB_DISABLE
309     return (GrB_NO_VALUE) ;
310     #else
311     #include "GB_emult_01_meta.c"
312     return (GrB_SUCCESS) ;
313     #endif
314 }
315 
316 //------------------------------------------------------------------------------
317 // eWiseMult: C<#> = A.*B when A is sparse/hyper and B is bitmap/full
318 //------------------------------------------------------------------------------
319 
GB(_AemultB_02__div_fc64)320 GrB_Info GB (_AemultB_02__div_fc64)
321 (
322     GrB_Matrix C,
323     const GrB_Matrix M,
324     const bool Mask_struct,
325     const bool Mask_comp,
326     const GrB_Matrix A,
327     const GrB_Matrix B,
328     const bool flipxy,
329     const int64_t *restrict Cp_kfirst,
330     const int64_t *A_ek_slicing, const int A_ntasks, const int A_nthreads
331 )
332 {
333     #if GB_DISABLE
334     return (GrB_NO_VALUE) ;
335     #else
336     #if GB_BINOP_FLIP
337         // The operator is not commutative, and does not have a flipped
338         // variant.  For example z=atan2(y,x).
339         if (flipxy)
340         {
341             // use fmult(y,x)
342             #undef  GB_FLIPPED
343             #define GB_FLIPPED 1
344             #include "GB_emult_02_template.c"
345         }
346         else
347         {
348             // use fmult(x,y)
349             #undef  GB_FLIPPED
350             #define GB_FLIPPED 0
351             #include "GB_emult_02_template.c"
352         }
353     #else
354         // No need to handle the flip: the operator is either commutative, or
355         // has been handled by changing z=div(y,x) to z=rdiv(x,y) for example.
356         #undef  GB_FLIPPED
357         #define GB_FLIPPED 0
358         #include "GB_emult_02_template.c"
359     #endif
360     return (GrB_SUCCESS) ;
361     #endif
362 }
363 
364 //------------------------------------------------------------------------------
365 // eWiseMult: C<M> = A.*B, M sparse/hyper, A and B bitmap/full
366 //------------------------------------------------------------------------------
367 
GB(_AemultB_03__div_fc64)368 GrB_Info GB (_AemultB_03__div_fc64)
369 (
370     GrB_Matrix C,
371     const GrB_Matrix M,
372     const bool Mask_struct,
373     const GrB_Matrix A,
374     const GrB_Matrix B,
375     const int64_t *restrict Cp_kfirst,
376     const int64_t *M_ek_slicing, const int M_ntasks, const int M_nthreads
377 )
378 {
379     #if GB_DISABLE
380     return (GrB_NO_VALUE) ;
381     #else
382     #include "GB_emult_03_template.c"
383     return (GrB_SUCCESS) ;
384     #endif
385 }
386 
387 //------------------------------------------------------------------------------
388 // eWiseMult: C=A.*B, C<M>=A.*B, C<!M>=A.*B where C is bitmap
389 //------------------------------------------------------------------------------
390 
GB(_AemultB_bitmap__div_fc64)391 GrB_Info GB (_AemultB_bitmap__div_fc64)
392 (
393     GrB_Matrix C,
394     const int ewise_method,
395     const GrB_Matrix M,
396     const bool Mask_struct,
397     const bool Mask_comp,
398     const GrB_Matrix A,
399     const GrB_Matrix B,
400     const int64_t *M_ek_slicing, const int M_ntasks, const int M_nthreads,
401     const int C_nthreads,
402     GB_Context Context
403 )
404 {
405     #if GB_DISABLE
406     return (GrB_NO_VALUE) ;
407     #else
408     #include "GB_bitmap_emult_template.c"
409     return (GrB_SUCCESS) ;
410     #endif
411 }
412 
413 //------------------------------------------------------------------------------
414 // Cx = op (x,Bx):  apply a binary operator to a matrix with scalar bind1st
415 //------------------------------------------------------------------------------
416 
417 
418 
GB(_bind1st__div_fc64)419 GrB_Info GB (_bind1st__div_fc64)
420 (
421     GB_void *Cx_output,         // Cx and Bx may be aliased
422     const GB_void *x_input,
423     const GB_void *Bx_input,
424     const int8_t *restrict Bb,
425     int64_t anz,
426     int nthreads
427 )
428 {
429     #if GB_DISABLE
430     return (GrB_NO_VALUE) ;
431     #else
432     GxB_FC64_t *Cx = (GxB_FC64_t *) Cx_output ;
433     GxB_FC64_t   x = (*((GxB_FC64_t *) x_input)) ;
434     GxB_FC64_t *Bx = (GxB_FC64_t *) Bx_input ;
435     int64_t p ;
436     #pragma omp parallel for num_threads(nthreads) schedule(static)
437     for (p = 0 ; p < anz ; p++)
438     {
439         if (!GBB (Bb, p)) continue ;
440         GxB_FC64_t bij = Bx [p] ;
441         Cx [p] = GB_FC64_div (x, bij) ;
442     }
443     return (GrB_SUCCESS) ;
444     #endif
445 }
446 
447 
448 
449 //------------------------------------------------------------------------------
450 // Cx = op (Ax,y):  apply a binary operator to a matrix with scalar bind2nd
451 //------------------------------------------------------------------------------
452 
453 
454 
GB(_bind2nd__div_fc64)455 GrB_Info GB (_bind2nd__div_fc64)
456 (
457     GB_void *Cx_output,         // Cx and Ax may be aliased
458     const GB_void *Ax_input,
459     const GB_void *y_input,
460     const int8_t *restrict Ab,
461     int64_t anz,
462     int nthreads
463 )
464 {
465     #if GB_DISABLE
466     return (GrB_NO_VALUE) ;
467     #else
468     int64_t p ;
469     GxB_FC64_t *Cx = (GxB_FC64_t *) Cx_output ;
470     GxB_FC64_t *Ax = (GxB_FC64_t *) Ax_input ;
471     GxB_FC64_t   y = (*((GxB_FC64_t *) y_input)) ;
472     #pragma omp parallel for num_threads(nthreads) schedule(static)
473     for (p = 0 ; p < anz ; p++)
474     {
475         if (!GBB (Ab, p)) continue ;
476         GxB_FC64_t aij = Ax [p] ;
477         Cx [p] = GB_FC64_div (aij, y) ;
478     }
479     return (GrB_SUCCESS) ;
480     #endif
481 }
482 
483 
484 
485 //------------------------------------------------------------------------------
486 // C = op (x, A'): transpose and apply a binary operator
487 //------------------------------------------------------------------------------
488 
489 
490 
491 // cij = op (x, aij), no typecasting (in spite of the macro name)
492 #undef  GB_CAST_OP
493 #define GB_CAST_OP(pC,pA)                       \
494 {                                               \
495     GxB_FC64_t aij = Ax [pA] ;                      \
496     Cx [pC] = GB_FC64_div (x, aij) ;        \
497 }
498 
GB(_bind1st_tran__div_fc64)499 GrB_Info GB (_bind1st_tran__div_fc64)
500 (
501     GrB_Matrix C,
502     const GB_void *x_input,
503     const GrB_Matrix A,
504     int64_t *restrict *Workspaces,
505     const int64_t *restrict A_slice,
506     int nworkspaces,
507     int nthreads
508 )
509 {
510     // GB_unop_transpose.c uses GB_ATYPE, but A is
511     // the 2nd input to binary operator z=f(x,y).
512     #undef  GB_ATYPE
513     #define GB_ATYPE \
514     GxB_FC64_t
515     #if GB_DISABLE
516     return (GrB_NO_VALUE) ;
517     #else
518     GxB_FC64_t x = (*((const GxB_FC64_t *) x_input)) ;
519     #include "GB_unop_transpose.c"
520     return (GrB_SUCCESS) ;
521     #endif
522     #undef  GB_ATYPE
523     #define GB_ATYPE \
524     GxB_FC64_t
525 }
526 
527 
528 
529 //------------------------------------------------------------------------------
530 // C = op (A', y): transpose and apply a binary operator
531 //------------------------------------------------------------------------------
532 
533 
534 
535 // cij = op (aij, y), no typecasting (in spite of the macro name)
536 #undef  GB_CAST_OP
537 #define GB_CAST_OP(pC,pA)                       \
538 {                                               \
539     GxB_FC64_t aij = Ax [pA] ;                      \
540     Cx [pC] = GB_FC64_div (aij, y) ;        \
541 }
542 
GB(_bind2nd_tran__div_fc64)543 GrB_Info GB (_bind2nd_tran__div_fc64)
544 (
545     GrB_Matrix C,
546     const GrB_Matrix A,
547     const GB_void *y_input,
548     int64_t *restrict *Workspaces,
549     const int64_t *restrict A_slice,
550     int nworkspaces,
551     int nthreads
552 )
553 {
554     #if GB_DISABLE
555     return (GrB_NO_VALUE) ;
556     #else
557     GxB_FC64_t y = (*((const GxB_FC64_t *) y_input)) ;
558     #include "GB_unop_transpose.c"
559     return (GrB_SUCCESS) ;
560     #endif
561 }
562 
563 
564 
565 #endif
566 
567