1 //------------------------------------------------------------------------------
2 // GB_bitmap_assign_notM_noaccum:  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>(I,J) = A       assign
10 // C(I,J)<!M> = A       subassign
11 
12 // C<!M,repl>(I,J) = A       assign
13 // C(I,J)<!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, row assign, col assign, or subassign
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(GrB_Matrix C,const bool C_replace,const GrB_Index * I,const int64_t nI,const int Ikind,const int64_t Icolon[3],const GrB_Index * J,const int64_t nJ,const int Jkind,const int64_t Jcolon[3],const GrB_Matrix M,const bool Mask_struct,const GrB_Matrix A,const void * scalar,const GrB_Type scalar_type,const int assign_kind,GB_Context Context)32 GrB_Info GB_bitmap_assign_notM_noaccum
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_Index *I,         // I index list
39     const int64_t nI,
40     const int Ikind,
41     const int64_t Icolon [3],
42     const GrB_Index *J,         // J index list
43     const int64_t nJ,
44     const int Jkind,
45     const int64_t Jcolon [3],
46     const GrB_Matrix M,         // mask matrix
47 //  const bool Mask_comp,       // true here, for !M only
48     const bool Mask_struct,     // true if M is structural, false if valued
49 //  const GrB_BinaryOp accum,   // not present
50     const GrB_Matrix A,         // input matrix, not transposed
51     const void *scalar,         // input scalar
52     const GrB_Type scalar_type, // type of input scalar
53     const int assign_kind,      // row assign, col assign, assign, or subassign
54     GB_Context Context
55 )
56 {
57 
58     //--------------------------------------------------------------------------
59     // check inputs
60     //--------------------------------------------------------------------------
61 
62     GBURBLE_BITMAP_ASSIGN ("bit8", M, true, NULL,
63         Ikind, Jkind, assign_kind) ;
64     ASSERT (GB_IS_HYPERSPARSE (M) || GB_IS_SPARSE (M)) ;
65     ASSERT_MATRIX_OK (C, "C for bitmap assign, !M, noaccum", GB0) ;
66     ASSERT_MATRIX_OK (M, "M for bitmap assign, !M, noaccum", GB0) ;
67     ASSERT_MATRIX_OK_OR_NULL (A, "A for bitmap assign, !M, noaccum", GB0) ;
68 
69     //--------------------------------------------------------------------------
70     // get inputs
71     //--------------------------------------------------------------------------
72 
73     GB_GET_C_BITMAP ;           // C must be bitmap
74     GB_SLICE_M
75     GB_GET_A_AND_SCALAR
76 
77     //--------------------------------------------------------------------------
78     // scatter M into the bitmap of C
79     //--------------------------------------------------------------------------
80 
81     // Cb [pC] += 2 for each entry M(i,j) in the mask
82     GB_bitmap_M_scatter (C, I, nI, Ikind, Icolon, J, nJ, Jkind, Jcolon,
83         M, Mask_struct, assign_kind, GB_BITMAP_M_SCATTER_PLUS_2,
84         M_ek_slicing, M_ntasks, M_nthreads, Context) ;
85 
86     // Cb (i,j) = 0:   cij not present, mij zero: can be modified
87     // Cb (i,j) = 1:   cij present, mij zero: can be modified,
88     //                      but delete if aij not present
89     // Cb (i,j) = 2:   cij not present, mij == 1: do not modify
90     // Cb (i,j) = 3:   cij present, mij == 1: do not modify
91 
92     //--------------------------------------------------------------------------
93     // assign A into C
94     //--------------------------------------------------------------------------
95 
96     if (A == NULL)
97     {
98 
99         //----------------------------------------------------------------------
100         // scalar assignment: C<!M>(I,J) = scalar
101         //----------------------------------------------------------------------
102 
103         // for all IxJ
104         #define GB_IXJ_WORK(pC,ignore)      \
105         {                                   \
106             int8_t cb = Cb [pC] ;           \
107             if (cb <= 1)                    \
108             {                               \
109                 /* Cx [pC] = scalar */      \
110                 GB_ASSIGN_SCALAR (pC) ;     \
111                 Cb [pC] = 1 ;               \
112                 task_cnvals += (cb == 0) ;  \
113             }                               \
114             else if (C_replace)             \
115             {                               \
116                 /* delete this entry */     \
117                 Cb [pC] = 0 ;               \
118                 task_cnvals -= (cb == 3) ;  \
119             }                               \
120             else                            \
121             {                               \
122                 /* keep this entry */       \
123                 Cb [pC] = (cb == 3) ;       \
124             }                               \
125         }
126         #include "GB_bitmap_assign_IxJ_template.c"
127 
128     }
129     else
130     {
131 
132         //----------------------------------------------------------------------
133         // matrix assignment: C<!M>(I,J) = A
134         //----------------------------------------------------------------------
135 
136         // for all entries aij in A (A can be hyper, sparse, bitmap, or full)
137         //     if Cb(p) == 0       // C(iC,jC) is now present, insert
138         //         Cx(p) = aij     //
139         //         Cb(p) = 4       // keep it
140         //         task_cnvals++
141         //     if Cb(p) == 1       // C(iC,jC) still present, updated
142         //         Cx(p) = aij     //
143         //         Cb(p) = 4       // keep it
144         //     if Cb(p) == 2       // do nothing
145         //     if Cb(p) == 3       // do nothing
146 
147         #define GB_AIJ_WORK(pC,pA)          \
148         {                                   \
149             int8_t cb = Cb [pC] ;           \
150             if (cb <= 1)                    \
151             {                               \
152                 /* Cx [pC] = Ax [pA] */     \
153                 GB_ASSIGN_AIJ (pC, pA) ;    \
154                 Cb [pC] = 4 ;               \
155                 task_cnvals += (cb == 0) ;  \
156             }                               \
157         }
158         #include "GB_bitmap_assign_A_template.c"
159 
160         //----------------------------------------------------------------------
161         // handle entries in IxJ
162         //----------------------------------------------------------------------
163 
164         if (C_replace)
165         {
166             // for all IxJ
167             #undef  GB_IXJ_WORK
168             #define GB_IXJ_WORK(pC,ignore)              \
169             {                                           \
170                 int8_t cb = Cb [pC] ;                   \
171                 Cb [pC] = (cb == 4) ;                   \
172                 task_cnvals -= (cb == 1 || cb == 3) ;   \
173             }
174             #include "GB_bitmap_assign_IxJ_template.c"
175         }
176         else
177         {
178             // for all IxJ
179             #undef  GB_IXJ_WORK
180             #define GB_IXJ_WORK(pC,ignore)              \
181             {                                           \
182                 int8_t cb = Cb [pC] ;                   \
183                 Cb [pC] = (cb == 4 || cb == 3) ;        \
184                 task_cnvals -= (cb == 1) ;              \
185             }
186             #include "GB_bitmap_assign_IxJ_template.c"
187         }
188     }
189 
190     //--------------------------------------------------------------------------
191     // handle entries outside of IxJ
192     //--------------------------------------------------------------------------
193 
194     if (assign_kind == GB_SUBASSIGN)
195     {
196         // see above.  no more work to do
197     }
198     else
199     {
200         #define GB_NO_SUBASSIGN_CASE
201         if (C_replace)
202         {
203             // for all entries in C.  Also clears M from C
204             #define GB_CIJ_WORK(pC)                 \
205             {                                       \
206                 int8_t cb = Cb [pC] ;               \
207                 Cb [pC] = (cb == 1) ;               \
208                 task_cnvals -= (cb == 3) ;          \
209             }
210             #include "GB_bitmap_assign_C_template.c"
211         }
212         else
213         {
214             // clear M from C
215             // Cb [pC] %= 2 for each entry M(i,j) in the mask
216             GB_bitmap_M_scatter (C, I, nI, Ikind, Icolon, J, nJ, Jkind, Jcolon,
217                 M, Mask_struct, assign_kind, GB_BITMAP_M_SCATTER_MOD_2,
218                 M_ek_slicing, M_ntasks, M_nthreads, Context) ;
219         }
220     }
221 
222     //--------------------------------------------------------------------------
223     // free workspace and return result
224     //--------------------------------------------------------------------------
225 
226     C->nvals = cnvals ;
227     GB_FREE_ALL ;
228     ASSERT_MATRIX_OK (C, "final C for bitmap assign, !M, noaccum", GB0) ;
229     return (GrB_SUCCESS) ;
230 }
231 
232