1 //------------------------------------------------------------------------------
2 // GB_dense_ewise3_noaccum: C = A+B where A and B are dense, C is anything
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 // C can have any sparsity on input; it becomes a full matrix on output.
11
12 #include "GB_dense.h"
13 #include "GB_binop.h"
14 #ifndef GBCOMPACT
15 #include "GB_binop__include.h"
16
17 #define GB_FREE_ALL ;
18
GB_dense_ewise3_noaccum(GrB_Matrix C,const bool C_is_dense,const GrB_Matrix A,const GrB_Matrix B,const GrB_BinaryOp op,GB_Context Context)19 GrB_Info GB_dense_ewise3_noaccum // C = A+B
20 (
21 GrB_Matrix C, // input/output matrix
22 const bool C_is_dense, // true if C is dense on input
23 const GrB_Matrix A,
24 const GrB_Matrix B,
25 const GrB_BinaryOp op, // must not be a positional op
26 GB_Context Context
27 )
28 {
29
30 //--------------------------------------------------------------------------
31 // check inputs
32 //--------------------------------------------------------------------------
33
34 GrB_Info info ;
35
36 ASSERT_MATRIX_OK (C, "C for dense C=A+B", GB0) ;
37 ASSERT (GB_ZOMBIES_OK (C)) ;
38 ASSERT (GB_JUMBLED_OK (C)) ; // C is entirely overwritten by A+B
39 ASSERT (!GB_PENDING (C)) ;
40 ASSERT (GB_IMPLIES (!C_is_dense, (C != A && C != B))) ;
41
42 ASSERT_MATRIX_OK (A, "A for dense C=A+B", GB0) ;
43 ASSERT (!GB_ZOMBIES (A)) ;
44 ASSERT (!GB_JUMBLED (A)) ;
45 ASSERT (!GB_PENDING (A)) ;
46 ASSERT (GB_is_dense (A)) ;
47
48 ASSERT_MATRIX_OK (B, "B for dense C=A+B", GB0) ;
49 ASSERT (!GB_ZOMBIES (B)) ;
50 ASSERT (!GB_JUMBLED (B)) ;
51 ASSERT (!GB_PENDING (B)) ;
52 ASSERT (GB_is_dense (B)) ;
53
54 ASSERT (!GB_IS_BITMAP (A)) ;
55 ASSERT (!GB_IS_BITMAP (B)) ;
56
57 ASSERT_BINARYOP_OK (op, "op for dense C=A+B", GB0) ;
58 ASSERT (!GB_OP_IS_POSITIONAL (op)) ;
59 ASSERT (op->ztype == C->type) ;
60 ASSERT (op->xtype == A->type) ;
61 ASSERT (op->ytype == B->type) ;
62
63 //--------------------------------------------------------------------------
64 // determine the number of threads to use
65 //--------------------------------------------------------------------------
66
67 int64_t anz = GB_NNZ (A) ;
68
69 GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
70 int nthreads = GB_nthreads (2 * anz, chunk, nthreads_max) ;
71
72 //--------------------------------------------------------------------------
73 // if C not already dense, allocate it as full
74 //--------------------------------------------------------------------------
75
76 // clear prior content and create C as a full matrix. Keep the same type
77 // and CSR/CSC for C. Allocate the values of C but do not initialize them.
78
79 if (!C_is_dense)
80 {
81 // convert C to full; just allocate C->x. Keep the dimensions of C.
82 GB_OK (GB_convert_to_full (C)) ; // prior content deleted
83 }
84 else if (!GB_IS_FULL (C))
85 {
86 // C is dense, but not full; convert to full
87 GB_convert_any_to_full (C) ;
88 }
89 ASSERT (GB_IS_FULL (C)) ;
90
91 //--------------------------------------------------------------------------
92 // define the worker for the switch factory
93 //--------------------------------------------------------------------------
94
95 #define GB_Cdense_ewise3_noaccum(op,xname) \
96 GB (_Cdense_ewise3_noaccum_ ## op ## xname)
97
98 #define GB_BINOP_WORKER(op,xname) \
99 { \
100 info = GB_Cdense_ewise3_noaccum(op,xname) (C, A, B, nthreads) ; \
101 } \
102 break ;
103
104 //--------------------------------------------------------------------------
105 // launch the switch factory
106 //--------------------------------------------------------------------------
107
108 GB_Opcode opcode ;
109 GB_Type_code xcode, ycode, zcode ;
110 if (GB_binop_builtin (A->type, false, B->type, false,
111 op, false, &opcode, &xcode, &ycode, &zcode))
112 {
113 #include "GB_binop_factory.c"
114 }
115 else
116 {
117 // this function is not called if the op cannot be applied
118 ASSERT (GB_DEAD_CODE) ;
119 }
120
121 //--------------------------------------------------------------------------
122 // return result
123 //--------------------------------------------------------------------------
124
125 ASSERT_MATRIX_OK (C, "C=A+B output", GB0) ;
126 return (GrB_SUCCESS) ;
127 }
128
129 #endif
130
131