1 //------------------------------------------------------------------------------
2 // GB_bitmap_assign_notM_accum_whole: assign to C bitmap
3 //------------------------------------------------------------------------------
4
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7
8 //------------------------------------------------------------------------------
9 // C<!M> += A assign
10 // C<!M> += A subassign
11
12 // C<!M,repl> += A assign
13 // C<!M,repl> += A subassign
14 //------------------------------------------------------------------------------
15
16 // C: bitmap
17 // M: present, hypersparse or sparse (not bitmap or full)
18 // Mask_comp: true
19 // Mask_struct: true or false
20 // C_replace: true or false
21 // accum: present
22 // A: matrix (hyper, sparse, bitmap, or full), or scalar
23 // kind: assign or subassign (same action)
24
25 #include "GB_bitmap_assign_methods.h"
26
27 #define GB_FREE_ALL \
28 { \
29 GB_WERK_POP (M_ek_slicing, int64_t) ; \
30 }
31
GB_bitmap_assign_notM_accum_whole(GrB_Matrix C,const bool C_replace,const GrB_Matrix M,const bool Mask_struct,const GrB_BinaryOp accum,const GrB_Matrix A,const void * scalar,const GrB_Type scalar_type,GB_Context Context)32 GrB_Info GB_bitmap_assign_notM_accum_whole
33 (
34 // input/output:
35 GrB_Matrix C, // input/output matrix in bitmap format
36 // inputs:
37 const bool C_replace, // descriptor for C
38 const GrB_Matrix M, // mask matrix
39 // const bool Mask_comp, // true here, for !M only
40 const bool Mask_struct, // true if M is structural, false if valued
41 const GrB_BinaryOp accum, // present
42 const GrB_Matrix A, // input matrix, not transposed
43 const void *scalar, // input scalar
44 const GrB_Type scalar_type, // type of input scalar
45 GB_Context Context
46 )
47 {
48
49 //--------------------------------------------------------------------------
50 // check inputs
51 //--------------------------------------------------------------------------
52
53 GBURBLE_BITMAP_ASSIGN ("bit7:whole", M, true, accum,
54 GB_ALL, GB_ALL, GB_ASSIGN) ;
55 ASSERT (GB_IS_HYPERSPARSE (M) || GB_IS_SPARSE (M)) ;
56 ASSERT (GB_JUMBLED_OK (M)) ;
57 ASSERT_MATRIX_OK (C, "C for bitmap assign, !M, accum", GB0) ;
58 ASSERT_MATRIX_OK (M, "M for bitmap assign, !M, accum", GB0) ;
59 ASSERT_MATRIX_OK_OR_NULL (A, "A for bitmap assign, !M, accum", GB0) ;
60
61 //--------------------------------------------------------------------------
62 // get inputs
63 //--------------------------------------------------------------------------
64
65 GB_GET_C_BITMAP ; // C must be bitmap
66 GB_SLICE_M
67 GB_GET_A_AND_SCALAR
68 GB_GET_ACCUM_FOR_BITMAP
69
70 //--------------------------------------------------------------------------
71 // scatter M
72 //--------------------------------------------------------------------------
73
74 // Cb [pC] += 2 for each entry M(i,j) in the mask
75 GB_bitmap_M_scatter_whole (C,
76 M, Mask_struct, GB_BITMAP_M_SCATTER_PLUS_2,
77 M_ek_slicing, M_ntasks, M_nthreads, Context) ;
78 // the bitmap of C now contains:
79 // Cb (i,j) = 0: cij not present, mij zero
80 // Cb (i,j) = 1: cij present, mij zero
81 // Cb (i,j) = 2: cij not present, mij 1
82 // Cb (i,j) = 3: cij present, mij 1
83
84 //--------------------------------------------------------------------------
85 // do the assignment
86 //--------------------------------------------------------------------------
87
88 if (A == NULL)
89 {
90
91 //----------------------------------------------------------------------
92 // scalar assignment: C<!M, replace or !replace> += scalar
93 //----------------------------------------------------------------------
94
95 if (C_replace)
96 {
97
98 //------------------------------------------------------------------
99 // C<!M,replace> += scalar
100 //------------------------------------------------------------------
101
102 #undef GB_CIJ_WORK
103 #define GB_CIJ_WORK(pC) \
104 { \
105 switch (Cb [pC]) \
106 { \
107 case 0: /* C(i,j) not present, !M(i,j) = 1 */ \
108 /* Cx [pC] = scalar */ \
109 GB_ASSIGN_SCALAR (pC) ; \
110 Cb [pC] = 1 ; \
111 task_cnvals++ ; \
112 break ; \
113 case 1: /* C(i,j) present, !M(i,j) = 1 */ \
114 /* Cx [pC] += scalar */ \
115 GB_ACCUM_SCALAR (pC) ; \
116 break ; \
117 case 2: /* C(i,j) not present, !M(i,j) = 0 */ \
118 /* clear the mask from C */ \
119 Cb [pC] = 0 ; \
120 break ; \
121 case 3: /* C(i,j) present, !M(i,j) = 0 */ \
122 /* delete this entry */ \
123 Cb [pC] = 0 ; \
124 task_cnvals-- ; \
125 break ; \
126 default: ; \
127 } \
128 }
129 #include "GB_bitmap_assign_C_whole_template.c"
130
131 }
132 else
133 {
134
135 //------------------------------------------------------------------
136 // C<!M> += scalar
137 //------------------------------------------------------------------
138
139 #undef GB_CIJ_WORK
140 #define GB_CIJ_WORK(pC) \
141 { \
142 switch (Cb [pC]) \
143 { \
144 case 0: /* C(i,j) not present, !M(i,j) = 1 */ \
145 /* Cx [pC] = scalar */ \
146 GB_ASSIGN_SCALAR (pC) ; \
147 Cb [pC] = 1 ; \
148 task_cnvals++ ; \
149 break ; \
150 case 1: /* C(i,j) present, !M(i,j) = 1 */ \
151 /* Cx [pC] += scalar */ \
152 GB_ACCUM_SCALAR (pC) ; \
153 break ; \
154 case 2: /* C(i,j) not present, !M(i,j) = 0 */ \
155 /* clear the mask from C */ \
156 Cb [pC] = 0 ; \
157 break ; \
158 case 3: /* C(i,j) present, !M(i,j) = 0 */ \
159 /* C(i,j) remains; clear the mask from C */ \
160 Cb [pC] = 1 ; \
161 break ; \
162 default: ; \
163 } \
164 }
165 #include "GB_bitmap_assign_C_whole_template.c"
166 }
167
168 }
169 else
170 {
171
172 //----------------------------------------------------------------------
173 // matrix assignment: C<!M, replace or !replace> += A
174 //----------------------------------------------------------------------
175
176 if (GB_IS_BITMAP (A) || GB_IS_FULL (A))
177 {
178
179 //------------------------------------------------------------------
180 // C<!M, replace or !replace> += A where A is bitmap or full
181 //------------------------------------------------------------------
182
183 if (C_replace)
184 {
185
186 //--------------------------------------------------------------
187 // C<!M, replace> += A where A is bitmap or full
188 //--------------------------------------------------------------
189
190 #undef GB_CIJ_WORK
191 #define GB_CIJ_WORK(pC) \
192 { \
193 switch (Cb [pC]) \
194 { \
195 case 0: /* C(i,j) not present, !M(i,j) = 1 */ \
196 if (GBB (Ab, pC)) \
197 { \
198 /* Cx [pC] = Ax [pC] */ \
199 GB_ASSIGN_AIJ (pC, pC) ; \
200 Cb [pC] = 1 ; \
201 task_cnvals++ ; \
202 } \
203 break ; \
204 case 1: /* C(i,j) present, !M(i,j) = 1 */ \
205 if (GBB (Ab, pC)) \
206 { \
207 /* Cx [pC] += Ax [pC] */ \
208 GB_ACCUM_AIJ (pC, pC) ; \
209 } \
210 break ; \
211 case 2: /* C(i,j) not present, !M(i,j) = 0 */ \
212 /* clear the mask from C */ \
213 Cb [pC] = 0 ; \
214 break ; \
215 case 3: /* C(i,j) present, !M(i,j) = 0 */ \
216 /* delete this entry */ \
217 Cb [pC] = 0 ; \
218 task_cnvals-- ; \
219 break ; \
220 default: ; \
221 } \
222 }
223 #include "GB_bitmap_assign_C_whole_template.c"
224
225 }
226 else
227 {
228
229 //--------------------------------------------------------------
230 // C<!M> += A where A is bitmap or full
231 //--------------------------------------------------------------
232
233 #undef GB_CIJ_WORK
234 #define GB_CIJ_WORK(pC) \
235 { \
236 switch (Cb [pC]) \
237 { \
238 case 0: /* C(i,j) not present, !M(i,j) = 1 */ \
239 if (GBB (Ab, pC)) \
240 { \
241 /* Cx [pC] = Ax [pC] */ \
242 GB_ASSIGN_AIJ (pC, pC) ; \
243 Cb [pC] = 1 ; \
244 task_cnvals++ ; \
245 } \
246 break ; \
247 case 1: /* C(i,j) present, !M(i,j) = 1 */ \
248 if (GBB (Ab, pC)) \
249 { \
250 /* Cx [pC] += Ax [pC] */ \
251 GB_ACCUM_AIJ (pC, pC) ; \
252 } \
253 Cb [pC] = 1 ; \
254 break ; \
255 case 2: /* C(i,j) not present, !M(i,j) = 0 */ \
256 /* clear the mask from C */ \
257 Cb [pC] = 0 ; \
258 break ; \
259 case 3: /* C(i,j) present, !M(i,j) = 0 */ \
260 /* keep the entry */ \
261 Cb [pC] = 1 ; \
262 break ; \
263 default: ; \
264 } \
265 }
266 #include "GB_bitmap_assign_C_whole_template.c"
267 }
268
269 }
270 else
271 {
272
273 //------------------------------------------------------------------
274 // C<!M, replace or !replace> += A where A is sparse or hyper
275 //------------------------------------------------------------------
276
277 // assign or accumulate entries from A into C
278 #undef GB_AIJ_WORK
279 #define GB_AIJ_WORK(pC,pA) \
280 { \
281 int8_t cb = Cb [pC] ; \
282 if (cb == 0) \
283 { \
284 /* Cx [pC] = Ax [pA] */ \
285 GB_ASSIGN_AIJ (pC, pA) ; \
286 Cb [pC] = 1 ; \
287 task_cnvals++ ; \
288 } \
289 else if (cb == 1) \
290 { \
291 /* Cx [pC] += Ax [pA] */ \
292 GB_ACCUM_AIJ (pC, pA) ; \
293 } \
294 }
295 #include "GB_bitmap_assign_A_whole_template.c"
296
297 if (C_replace)
298 {
299 // clear the mask and delete entries not assigned
300 #undef GB_MASK_WORK
301 #define GB_MASK_WORK(pC) \
302 { \
303 int8_t cb = Cb [pC] ; \
304 Cb [pC] = 0 ; \
305 task_cnvals -= (cb == 3) ; \
306 }
307 #include "GB_bitmap_assign_M_all_template.c"
308 }
309 else
310 {
311 // clear the mask
312 // Cb [pC] -= 2 for each entry M(i,j) in the mask
313 GB_bitmap_M_scatter_whole (C,
314 M, Mask_struct, GB_BITMAP_M_SCATTER_MINUS_2,
315 M_ek_slicing, M_ntasks, M_nthreads, Context) ;
316 }
317 }
318 }
319
320 //--------------------------------------------------------------------------
321 // free workspace and return result
322 //--------------------------------------------------------------------------
323
324 C->nvals = cnvals ;
325 GB_FREE_ALL ;
326 ASSERT_MATRIX_OK (C, "final C for bitmap assign, !M, accum, whole", GB0) ;
327 return (GrB_SUCCESS) ;
328 }
329
330