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