1 //------------------------------------------------------------------------------
2 // GB_dense_subassign_22: C += b where C is dense and b is a scalar
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 += b where C is a dense or full matrix and b is a scalar
11 // C can have any sparsity format, as long as all entries are present;
12 // GB_is_dense (C)) must hold.
13 
14 #include "GB_dense.h"
15 #include "GB_binop.h"
16 #include "GB_unused.h"
17 #ifndef GBCOMPACT
18 #include "GB_binop__include.h"
19 #endif
20 
21 #define GB_FREE_ALL ;
22 
GB_dense_subassign_22(GrB_Matrix C,const void * scalar,const GrB_Type btype,const GrB_BinaryOp accum,GB_Context Context)23 GrB_Info GB_dense_subassign_22      // C += b where C is dense and b is a scalar
24 (
25     GrB_Matrix C,                   // input/output matrix
26     const void *scalar,             // input scalar
27     const GrB_Type btype,           // type of the input scalar
28     const GrB_BinaryOp accum,       // operator to apply
29     GB_Context Context
30 )
31 {
32 
33     //--------------------------------------------------------------------------
34     // check inputs
35     //--------------------------------------------------------------------------
36 
37     GrB_Info info ;
38     ASSERT_MATRIX_OK (C, "C for C+=b", GB0) ;
39     ASSERT (GB_is_dense (C)) ;
40     ASSERT (!GB_PENDING (C)) ;
41     ASSERT (!GB_JUMBLED (C)) ;
42     ASSERT (!GB_ZOMBIES (C)) ;
43 
44     ASSERT (scalar != NULL) ;
45     ASSERT_TYPE_OK (btype, "btype for C+=b", GB0) ;
46     ASSERT_BINARYOP_OK (accum, "accum for C+=b", GB0) ;
47     ASSERT (!GB_OP_IS_POSITIONAL (accum)) ;
48 
49     GB_ENSURE_FULL (C) ;        // convert C to full
50 
51     //--------------------------------------------------------------------------
52     // get the operator
53     //--------------------------------------------------------------------------
54 
55     if (accum->opcode == GB_FIRST_opcode)
56     {
57         // nothing to do
58         return (GrB_SUCCESS) ;
59     }
60 
61     // C = accum (C,b) will be computed
62     ASSERT (C->type == accum->ztype) ;
63     ASSERT (C->type == accum->xtype) ;
64     ASSERT (GB_Type_compatible (btype, accum->ytype)) ;
65 
66     //--------------------------------------------------------------------------
67     // determine the number of threads to use
68     //--------------------------------------------------------------------------
69 
70     int64_t cnz = GB_NNZ (C) ;
71 
72     GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
73     int nthreads = GB_nthreads (cnz, chunk, nthreads_max) ;
74 
75     //--------------------------------------------------------------------------
76     // typecast the scalar into the same type as Y
77     //--------------------------------------------------------------------------
78 
79     int64_t csize = C->type->size ;
80     size_t ysize = accum->ytype->size ;
81     GB_cast_function
82         cast_B_to_Y = GB_cast_factory (accum->ytype->code, btype->code) ;
83     GB_void bwork [GB_VLA(ysize)] ;
84     cast_B_to_Y (bwork, scalar, btype->size) ;
85 
86     //--------------------------------------------------------------------------
87     // C += b, scalar accum into dense, with built-in binary operators
88     //--------------------------------------------------------------------------
89 
90     bool done = false ;
91 
92     #ifndef GBCOMPACT
93 
94         //----------------------------------------------------------------------
95         // define the worker for the switch factory
96         //----------------------------------------------------------------------
97 
98         #define GB_Cdense_accumb(accum,xname) \
99             GB (_Cdense_accumb_ ## accum ## xname)
100 
101         #define GB_BINOP_WORKER(accum,xname)                                \
102         {                                                                   \
103             info = GB_Cdense_accumb(accum,xname) (C, bwork, nthreads) ;     \
104             done = (info != GrB_NO_VALUE) ;                                 \
105         }                                                                   \
106         break ;
107 
108         //----------------------------------------------------------------------
109         // launch the switch factory
110         //----------------------------------------------------------------------
111 
112         GB_Opcode opcode ;
113         GB_Type_code xcode, ycode, zcode ;
114         if (GB_binop_builtin (C->type, false, btype, false, // C = C + b
115             accum, false, &opcode, &xcode, &ycode, &zcode))
116         {
117             // accumulate sparse matrix into dense matrix with built-in operator
118             #include "GB_binop_factory.c"
119         }
120 
121     #endif
122 
123     //--------------------------------------------------------------------------
124     // C += b, scalar accum into dense, with typecasting or user-defined op
125     //--------------------------------------------------------------------------
126 
127     if (!done)
128     {
129         GB_BURBLE_MATRIX (C, "(generic C(:,:)+=x assign) ") ;
130 
131         //----------------------------------------------------------------------
132         // get operators, functions, workspace, contents of b and C
133         //----------------------------------------------------------------------
134 
135         GxB_binary_function fadd = accum->function ;
136 
137         //----------------------------------------------------------------------
138         // C += b via function pointers, and typecasting
139         //----------------------------------------------------------------------
140 
141         // C(i,j) = C(i,j) + scalar
142         #define GB_BINOP(cout_ij, cin_aij, bwork, i, j) \
143             fadd (cout_ij, cin_aij, bwork)
144 
145         // address of Cx [p]
146         #define GB_CX(p) Cx +((p)*csize)
147 
148         #define GB_CTYPE GB_void
149 
150         // no vectorization
151         #define GB_PRAGMA_SIMD_VECTORIZE ;
152 
153         #include "GB_dense_subassign_22_template.c"
154     }
155 
156     //--------------------------------------------------------------------------
157     // return result
158     //--------------------------------------------------------------------------
159 
160     ASSERT_MATRIX_OK (C, "C+=b output", GB0) ;
161     return (GrB_SUCCESS) ;
162 }
163 
164