1 //------------------------------------------------------------------------------
2 // GB_bitmap_assign_M_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:   false
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_M_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_M_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, 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,   // present here
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 ("bit3:whole", M, false, 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 C, M, A, and accum
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     // do the assignment
72     //--------------------------------------------------------------------------
73 
74     if (A == NULL)
75     {
76 
77         //----------------------------------------------------------------------
78         // scalar assignment: C<M, replace or !replace> += scalar
79         //----------------------------------------------------------------------
80 
81         if (C_replace)
82         {
83 
84             //------------------------------------------------------------------
85             // C<M,replace> += scalar
86             //------------------------------------------------------------------
87 
88             // Cb [pC] += 2 for each entry M(i,j) in the mask
89             GB_bitmap_M_scatter_whole (C,
90                 M, Mask_struct, GB_BITMAP_M_SCATTER_PLUS_2,
91                 M_ek_slicing, M_ntasks, M_nthreads, Context) ;
92             // the bitmap of C now contains:
93             //  Cb (i,j) = 0:   cij not present, mij zero
94             //  Cb (i,j) = 1:   cij present, mij zero
95             //  Cb (i,j) = 2:   cij not present, mij 1
96             //  Cb (i,j) = 3:   cij present, mij 1
97 
98             #undef  GB_CIJ_WORK
99             #define GB_CIJ_WORK(pC)                                 \
100             {                                                       \
101                 switch (Cb [pC])                                    \
102                 {                                                   \
103                     case 1: /* C(i,j) present, M(i,j) = 0 */        \
104                         /* delete this entry */                     \
105                         Cb [pC] = 0 ;                               \
106                         task_cnvals-- ;                             \
107                         break ;                                     \
108                     case 2: /* C(i,j) not present, M(i,j) = 1 */    \
109                         /* Cx [pC] = scalar */                      \
110                         GB_ASSIGN_SCALAR (pC) ;                     \
111                         Cb [pC] = 1 ;                               \
112                         task_cnvals++ ;                             \
113                         break ;                                     \
114                     case 3: /* C(i,j) present, M(i,j) = 1 */        \
115                         /* Cx [pC] += scalar */                     \
116                         GB_ACCUM_SCALAR (pC) ;                      \
117                         Cb [pC] = 1 ;                               \
118                         break ;                                     \
119                     default: ;                                      \
120                 }                                                   \
121             }
122             #include "GB_bitmap_assign_C_whole_template.c"
123 
124         }
125         else
126         {
127 
128             //------------------------------------------------------------------
129             // C<M> += scalar
130             //------------------------------------------------------------------
131 
132             #undef  GB_MASK_WORK
133             #define GB_MASK_WORK(pC)                        \
134             {                                               \
135                 if (Cb [pC])                                \
136                 {                                           \
137                     /* C(i,j) present, M(i,j) = 1 */        \
138                     /* Cx [pC] += scalar */                 \
139                     GB_ACCUM_SCALAR (pC) ;                  \
140                 }                                           \
141                 else                                        \
142                 {                                           \
143                     /* C(i,j) not present, M(i,j) = 1 */    \
144                     /* Cx [pC] = scalar */                  \
145                     GB_ASSIGN_SCALAR (pC) ;                 \
146                     Cb [pC] = 1 ;                           \
147                     task_cnvals++ ;                         \
148                 }                                           \
149             }
150             #include "GB_bitmap_assign_M_all_template.c"
151         }
152 
153     }
154     else
155     {
156 
157         //----------------------------------------------------------------------
158         // matrix assignment: C<M, replace or !replace> += A
159         //----------------------------------------------------------------------
160 
161         if (GB_IS_BITMAP (A) || GB_IS_FULL (A))
162         {
163 
164             //------------------------------------------------------------------
165             // C<M, replace or !replace> += A where A is bitmap or full
166             //------------------------------------------------------------------
167 
168             if (C_replace)
169             {
170 
171                 //--------------------------------------------------------------
172                 // C<M, replace> += A where A is bitmap or full
173                 //--------------------------------------------------------------
174 
175                 // Cb [pC] += 2 for each entry M(i,j) in the mask
176                 GB_bitmap_M_scatter_whole (C,
177                     M, Mask_struct, GB_BITMAP_M_SCATTER_PLUS_2,
178                     M_ek_slicing, M_ntasks, M_nthreads, Context) ;
179                 // the bitmap of C now contains:
180                 //  Cb (i,j) = 0:   cij not present, mij zero
181                 //  Cb (i,j) = 1:   cij present, mij zero
182                 //  Cb (i,j) = 2:   cij not present, mij 1
183                 //  Cb (i,j) = 3:   cij present, mij 1
184 
185                 #undef  GB_CIJ_WORK
186                 #define GB_CIJ_WORK(pC)                                 \
187                 {                                                       \
188                     switch (Cb [pC])                                    \
189                     {                                                   \
190                         case 1: /* C(i,j) present, M(i,j) = 0 */        \
191                             /* delete this entry */                     \
192                             Cb [pC] = 0 ;                               \
193                             task_cnvals-- ;                             \
194                             break ;                                     \
195                         case 2: /* 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                             else                                        \
204                             {                                           \
205                                 /* clear the mask from C */             \
206                                 Cb [pC] = 0 ;                           \
207                             }                                           \
208                             break ;                                     \
209                         case 3: /* C(i,j) present, M(i,j) = 1 */        \
210                             if (GBB (Ab, pC))                           \
211                             {                                           \
212                                 /* Cx [pC] += Ax [pC] */                \
213                                 GB_ACCUM_AIJ (pC, pC) ;                 \
214                             }                                           \
215                             Cb [pC] = 1 ;                               \
216                             break ;                                     \
217                         default: ;                                      \
218                     }                                                   \
219                 }
220                 #include "GB_bitmap_assign_C_whole_template.c"
221 
222             }
223             else
224             {
225 
226                 //--------------------------------------------------------------
227                 // C<M> += A where A is bitmap or full
228                 //--------------------------------------------------------------
229 
230                 #undef  GB_MASK_WORK
231                 #define GB_MASK_WORK(pC)                            \
232                 {                                                   \
233                     if (GBB (Ab, pC))                               \
234                     {                                               \
235                         /* A(i,j) is present */                     \
236                         if (Cb [pC])                                \
237                         {                                           \
238                             /* C(i,j) present, M(i,j) = 1 */        \
239                             /* Cx [pC] += Ax [pC] */                \
240                             GB_ACCUM_AIJ (pC, pC) ;                 \
241                         }                                           \
242                         else                                        \
243                         {                                           \
244                             /* C(i,j) not present, M(i,j) = 1 */    \
245                             /* Cx [pC] = Ax [pC] */                 \
246                             GB_ASSIGN_AIJ (pC, pC) ;                \
247                             Cb [pC] = 1 ;                           \
248                             task_cnvals++ ;                         \
249                         }                                           \
250                     }                                               \
251                 }
252                 #include "GB_bitmap_assign_M_all_template.c"
253 
254             }
255         }
256         else
257         {
258 
259             //------------------------------------------------------------------
260             // C<M, replace or !replace> += A where A is sparse or hyper
261             //------------------------------------------------------------------
262 
263             // Cb [pC] += 2 for each entry M(i,j) in the mask
264             GB_bitmap_M_scatter_whole (C,
265                 M, Mask_struct, GB_BITMAP_M_SCATTER_PLUS_2,
266                 M_ek_slicing, M_ntasks, M_nthreads, Context) ;
267             // the bitmap of C now contains:
268             //  Cb (i,j) = 0:   cij not present, mij zero
269             //  Cb (i,j) = 1:   cij present, mij zero
270             //  Cb (i,j) = 2:   cij not present, mij 1
271             //  Cb (i,j) = 3:   cij present, mij 1
272 
273             // assign or accumulate entries from A into C
274             #undef  GB_AIJ_WORK
275             #define GB_AIJ_WORK(pC,pA)                      \
276             {                                               \
277                 /* A(i,j) is present */                     \
278                 int8_t cb = Cb [pC] ;                       \
279                 if (cb == 2)                                \
280                 {                                           \
281                     /* C(i,j) not present, M(i,j) = 1 */    \
282                     /* Cx [pC] = Ax [pA] */                 \
283                     GB_ASSIGN_AIJ (pC, pA) ;                \
284                     Cb [pC] = 3 ;                           \
285                     task_cnvals++ ;                         \
286                 }                                           \
287                 else if (cb == 3)                           \
288                 {                                           \
289                     /* C(i,j) present, M(i,j) = 1 */        \
290                     /* Cx [pC] += Ax [pA] */                \
291                     GB_ACCUM_AIJ (pC, pA) ;                 \
292                 }                                           \
293             }
294             #include "GB_bitmap_assign_A_whole_template.c"
295 
296             if (C_replace)
297             {
298                 // clear the mask and delete entries not assigned
299                 #undef  GB_CIJ_WORK
300                 #define GB_CIJ_WORK(pC)                 \
301                 {                                       \
302                     int8_t cb = Cb [pC] ;               \
303                     Cb [pC] = (cb == 3) ;               \
304                     task_cnvals -= (cb == 1) ;          \
305                 }
306                 #include "GB_bitmap_assign_C_whole_template.c"
307             }
308             else
309             {
310                 // clear the mask
311                 // Cb [pC] -= 2 for each entry M(i,j) in the mask
312                 GB_bitmap_M_scatter_whole (C,
313                     M, Mask_struct, GB_BITMAP_M_SCATTER_MINUS_2,
314                     M_ek_slicing, M_ntasks, M_nthreads, Context) ;
315             }
316         }
317     }
318 
319     //--------------------------------------------------------------------------
320     // free workspace and return result
321     //--------------------------------------------------------------------------
322 
323     C->nvals = cnvals ;
324     GB_FREE_ALL ;
325     ASSERT_MATRIX_OK (C, "final C for bitmap assign, M, accum, whole", GB0) ;
326     return (GrB_SUCCESS) ;
327 }
328 
329