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