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