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