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