1 //------------------------------------------------------------------------------
2 // GB_bitmap_assign_M_noaccum_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: false
19 // Mask_struct: true or false
20 // C_replace: true or false
21 // accum: not 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_M_noaccum_whole(GrB_Matrix C,const bool C_replace,const GrB_Matrix M,const bool Mask_struct,const GrB_Matrix A,const void * scalar,const GrB_Type scalar_type,GB_Context Context)32 GrB_Info GB_bitmap_assign_M_noaccum_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, which is not NULL here
39 // const bool Mask_comp, // false here
40 const bool Mask_struct, // true if M is structural, false if valued
41 // const GrB_BinaryOp accum, // not 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 ("bit4:whole", M, false, NULL,
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, noaccum", GB0) ;
58 ASSERT_MATRIX_OK (M, "M for bitmap assign, M, noaccum", GB0) ;
59 ASSERT_MATRIX_OK_OR_NULL (A, "A for bitmap assign, M, noaccum", 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
69 //--------------------------------------------------------------------------
70 // C<M,repl or !repl>(I,J) = A or scalar
71 //--------------------------------------------------------------------------
72
73 //--------------------------------------------------------------------------
74 // scatter A or the scalar into C
75 //--------------------------------------------------------------------------
76
77 if (A == NULL)
78 {
79
80 //----------------------------------------------------------------------
81 // scalar assignment: C<M or !M, repl or !repl> = scalar
82 //----------------------------------------------------------------------
83
84 if (C_replace)
85 {
86
87 // Cb [pC] += 2 for each entry M(i,j) in the mask
88 GB_bitmap_M_scatter_whole (C,
89 M, Mask_struct, GB_BITMAP_M_SCATTER_PLUS_2,
90 M_ek_slicing, M_ntasks, M_nthreads, Context) ;
91 // the bitmap of C now contains:
92 // Cb (i,j) = 0: cij not present, mij zero
93 // Cb (i,j) = 1: cij present, mij zero
94 // Cb (i,j) = 2: cij not present, mij 1
95 // Cb (i,j) = 3: cij present, mij 1
96
97 //------------------------------------------------------------------
98 // C<M,replace> = scalar
99 //------------------------------------------------------------------
100
101 #undef GB_CIJ_WORK
102 #define GB_CIJ_WORK(pC) \
103 { \
104 switch (Cb [pC]) \
105 { \
106 case 1: /* C(i,j) present, M(i,j) = 0 */ \
107 Cb [pC] = 0 ; \
108 task_cnvals-- ; \
109 break ; \
110 case 2: /* C(i,j) not present, M(i,j) = 1 */ \
111 /* Cx [pC] = scalar */ \
112 GB_ASSIGN_SCALAR (pC) ; \
113 Cb [pC] = 1 ; \
114 task_cnvals++ ; \
115 break ; \
116 case 3: /* C(i,j) present, M(i,j) = 1 */ \
117 /* Cx [pC] = scalar */ \
118 GB_ASSIGN_SCALAR (pC) ; \
119 Cb [pC] = 1 ; \
120 default: ; \
121 } \
122 }
123 #include "GB_bitmap_assign_C_whole_template.c"
124
125 }
126 else
127 {
128
129 //------------------------------------------------------------------
130 // C<M> = scalar
131 //------------------------------------------------------------------
132
133 #undef GB_MASK_WORK
134 #define GB_MASK_WORK(pC) \
135 { \
136 if (Cb [pC]) \
137 { \
138 /* C(i,j) present, M(i,j) = 1 */ \
139 /* Cx [pC] = scalar */ \
140 GB_ASSIGN_SCALAR (pC) ; \
141 } \
142 else \
143 { \
144 /* 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 } \
150 }
151 #include "GB_bitmap_assign_M_all_template.c"
152
153 }
154
155 }
156 else
157 {
158
159 //----------------------------------------------------------------------
160 // matrix assignment: C<M,repl or !repl> = A
161 //----------------------------------------------------------------------
162
163 if (GB_IS_BITMAP (A) || GB_IS_FULL (A))
164 {
165
166 //------------------------------------------------------------------
167 // C<M, replace or !replace> = A where A is bitmap or full
168 //------------------------------------------------------------------
169
170 if (C_replace)
171 {
172
173 //--------------------------------------------------------------
174 // C<M,replace> = A where A is bitmap or full
175 //--------------------------------------------------------------
176
177 // Cb [pC] += 2 for each entry M(i,j) in the mask
178 GB_bitmap_M_scatter_whole (C,
179 M, Mask_struct, GB_BITMAP_M_SCATTER_PLUS_2,
180 M_ek_slicing, M_ntasks, M_nthreads, Context) ;
181 // the bitmap of C now contains:
182 // Cb (i,j) = 0: cij not present, mij zero
183 // Cb (i,j) = 1: cij present, mij zero
184 // Cb (i,j) = 2: cij not present, mij 1
185 // Cb (i,j) = 3: cij present, mij 1
186
187 #undef GB_CIJ_WORK
188 #define GB_CIJ_WORK(pC) \
189 { \
190 switch (Cb [pC]) \
191 { \
192 case 1: /* C(i,j) present, M(i,j) = 0 */ \
193 Cb [pC] = 0 ; \
194 task_cnvals-- ; \
195 break ; \
196 case 2: /* C(i,j) not present, M(i,j) = 1 */ \
197 if (GBB (Ab, pC)) \
198 { \
199 /* Cx [pC] = Ax [pC] */ \
200 GB_ASSIGN_AIJ (pC, pC) ; \
201 Cb [pC] = 1 ; \
202 task_cnvals++ ; \
203 } \
204 else \
205 { \
206 /* clear the mask from C */ \
207 Cb [pC] = 0 ; \
208 } \
209 break ; \
210 case 3: /* C(i,j) present, M(i,j) = 1 */ \
211 if (GBB (Ab, pC)) \
212 { \
213 /* Cx [pC] = Ax [pC] */ \
214 GB_ASSIGN_AIJ (pC, pC) ; \
215 Cb [pC] = 1 ; \
216 } \
217 else \
218 { \
219 /* delete C(i,j) */ \
220 Cb [pC] = 0 ; \
221 task_cnvals-- ; \
222 } \
223 break ; \
224 default: ; \
225 } \
226 }
227 #include "GB_bitmap_assign_C_whole_template.c"
228
229 }
230 else
231 {
232
233 //--------------------------------------------------------------
234 // C<M> = A where A is bitmap or full
235 //--------------------------------------------------------------
236
237 #undef GB_MASK_WORK
238 #define GB_MASK_WORK(pC) \
239 { \
240 if (Cb [pC]) \
241 { \
242 /* C(i,j) present, M(i,j) = 1 */ \
243 if (GBB (Ab, pC)) \
244 { \
245 /* Cx [pC] = Ax [pC] */ \
246 GB_ASSIGN_AIJ (pC, pC) ; \
247 } \
248 else \
249 { \
250 /* delete C(i,j) */ \
251 Cb [pC] = 0 ; \
252 task_cnvals-- ; \
253 } \
254 } \
255 else \
256 { \
257 /* C(i,j) not present, M(i,j) = 1 */ \
258 if (GBB (Ab, pC)) \
259 { \
260 /* Cx [pC] = Ax [pC] */ \
261 GB_ASSIGN_AIJ (pC, pC) ; \
262 Cb [pC] = 1 ; \
263 task_cnvals++ ; \
264 } \
265 } \
266 }
267 #include "GB_bitmap_assign_M_all_template.c"
268
269 }
270 }
271 else
272 {
273
274 //------------------------------------------------------------------
275 // C<M, replace or !replace> = A where A is sparse or hyper
276 //------------------------------------------------------------------
277
278 if (C_replace)
279 {
280
281 //--------------------------------------------------------------
282 // C<M,replace> = A where A is sparse or hyper
283 //--------------------------------------------------------------
284
285 // Cb [pC] += 2 for each entry M(i,j) in the mask
286 GB_bitmap_M_scatter_whole (C,
287 M, Mask_struct, GB_BITMAP_M_SCATTER_PLUS_2,
288 M_ek_slicing, M_ntasks, M_nthreads, Context) ;
289 // the bitmap of C now contains:
290 // Cb (i,j) = 0: cij not present, mij zero
291 // Cb (i,j) = 1: cij present, mij zero
292 // Cb (i,j) = 2: cij not present, mij 1
293 // Cb (i,j) = 3: cij present, mij 1
294
295 // assign entries from A into C
296 #undef GB_AIJ_WORK
297 #define GB_AIJ_WORK(pC,pA) \
298 { \
299 int8_t cb = Cb [pC] ; \
300 if (cb >= 2) \
301 { \
302 /* M(i,j)=1 and A(i,j) present */ \
303 /* Cx [pC] = Ax [pA] ; */ \
304 GB_ASSIGN_AIJ (pC, pA) ; \
305 Cb [pC] = 4 ; \
306 task_cnvals += (cb == 2) ; \
307 } \
308 }
309 #include "GB_bitmap_assign_A_whole_template.c"
310
311 // clear the mask and delete entries not assigned
312 #undef GB_CIJ_WORK
313 #define GB_CIJ_WORK(pC) \
314 { \
315 int8_t cb = Cb [pC] ; \
316 Cb [pC] = (cb == 4) ; \
317 task_cnvals -= (cb == 1 || cb == 3) ; \
318 }
319 #include "GB_bitmap_assign_C_whole_template.c"
320
321 }
322 else if (GB_NNZ (A) == 0)
323 {
324
325 //--------------------------------------------------------------
326 // C<M> = A where A is sparse or hyper, with no entries
327 //--------------------------------------------------------------
328
329 GBURBLE ("(A empty) ") ;
330
331 // delete entries via the mask
332 #undef GB_MASK_WORK
333 #define GB_MASK_WORK(pC) \
334 { \
335 int8_t cb = Cb [pC] ; \
336 Cb [pC] = 0 ; \
337 task_cnvals -= (cb == 1) ; \
338 }
339 #include "GB_bitmap_assign_M_all_template.c"
340
341 }
342 else
343 {
344
345 //--------------------------------------------------------------
346 // C<M> = A where A is sparse or hyper
347 //--------------------------------------------------------------
348
349 // Cb [pC] += 2 for each entry M(i,j) in the mask
350 GB_bitmap_M_scatter_whole (C,
351 M, Mask_struct, GB_BITMAP_M_SCATTER_PLUS_2,
352 M_ek_slicing, M_ntasks, M_nthreads, Context) ;
353 // the bitmap of C now contains:
354 // Cb (i,j) = 0: cij not present, mij zero
355 // Cb (i,j) = 1: cij present, mij zero
356 // Cb (i,j) = 2: cij not present, mij 1
357 // Cb (i,j) = 3: cij present, mij 1
358
359 // assign entries from A into C
360 #undef GB_AIJ_WORK
361 #define GB_AIJ_WORK(pC,pA) \
362 { \
363 int8_t cb = Cb [pC] ; \
364 if (cb >= 2) \
365 { \
366 /* M(i,j)=1 and A(i,j) present */ \
367 /* Cx [pC] = Ax [pA] ; */ \
368 GB_ASSIGN_AIJ (pC, pA) ; \
369 Cb [pC] = 1 ; \
370 task_cnvals += (cb == 2) ; \
371 } \
372 }
373 #include "GB_bitmap_assign_A_whole_template.c"
374
375 // clear the mask and delete entries not assigned
376 #undef GB_MASK_WORK
377 #define GB_MASK_WORK(pC) \
378 { \
379 int8_t cb = Cb [pC] ; \
380 Cb [pC] = (cb == 1) ; \
381 task_cnvals -= (cb == 3) ; \
382 }
383 #include "GB_bitmap_assign_M_all_template.c"
384
385 }
386 }
387 }
388
389 //--------------------------------------------------------------------------
390 // free workspace and return result
391 //--------------------------------------------------------------------------
392
393 C->nvals = cnvals ;
394 GB_FREE_ALL ;
395 ASSERT_MATRIX_OK (C, "final C for bitmap assign, M, noaccum, whole", GB0) ;
396 return (GrB_SUCCESS) ;
397 }
398
399