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