1 //------------------------------------------------------------------------------
2 // GB_bitmap_assign_fullM_accum: assign to C bitmap, M is bitmap or full
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 // C<!M>(I,J) += A assign
16 // C(I,J)<!M> += A subassign
17
18 // C<!M,repl>(I,J) += A assign
19 // C(I,J)<!M,repl> += A subassign
20 //------------------------------------------------------------------------------
21
22 // C: bitmap
23 // M: present, bitmap or full (not hypersparse or sparse)
24 // Mask_comp: true or false
25 // Mask_struct: true or false
26 // C_replace: true or false
27 // accum: present
28 // A: matrix (hyper, sparse, bitmap, or full), or scalar
29 // kind: assign, row assign, col assign, or subassign
30
31 #include "GB_bitmap_assign_methods.h"
32
33 #define GB_FREE_ALL ;
34
GB_bitmap_assign_fullM_accum(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_comp,const bool Mask_struct,const GrB_BinaryOp accum,const GrB_Matrix A,const void * scalar,const GrB_Type scalar_type,const int assign_kind,GB_Context Context)35 GrB_Info GB_bitmap_assign_fullM_accum
36 (
37 // input/output:
38 GrB_Matrix C, // input/output matrix in bitmap format
39 // inputs:
40 const bool C_replace, // descriptor for C
41 const GrB_Index *I, // I index list
42 const int64_t nI,
43 const int Ikind,
44 const int64_t Icolon [3],
45 const GrB_Index *J, // J index list
46 const int64_t nJ,
47 const int Jkind,
48 const int64_t Jcolon [3],
49 const GrB_Matrix M, // mask matrix, which is present here
50 const bool Mask_comp, // true for !M, false for M
51 const bool Mask_struct, // true if M is structural, false if valued
52 const GrB_BinaryOp accum, // present here
53 const GrB_Matrix A, // input matrix, not transposed
54 const void *scalar, // input scalar
55 const GrB_Type scalar_type, // type of input scalar
56 const int assign_kind, // row assign, col assign, assign, or subassign
57 GB_Context Context
58 )
59 {
60
61 //--------------------------------------------------------------------------
62 // check inputs
63 //--------------------------------------------------------------------------
64
65 GBURBLE_BITMAP_ASSIGN ("bit1", M, Mask_comp, accum,
66 Ikind, Jkind, assign_kind) ;
67 ASSERT (GB_IS_BITMAP (M) || GB_IS_FULL (M)) ;
68 ASSERT_MATRIX_OK (C, "C for bitmap assign, M full, accum", GB0) ;
69 ASSERT_MATRIX_OK (M, "M for bitmap assign, M full, accum", GB0) ;
70 ASSERT_MATRIX_OK_OR_NULL (A, "A for bitmap assign, M full, accum", GB0) ;
71
72 //--------------------------------------------------------------------------
73 // get inputs
74 //--------------------------------------------------------------------------
75
76 GB_GET_C_BITMAP ; // C must be bitmap
77 GB_GET_M
78 GB_GET_A_AND_SCALAR
79 GB_GET_ACCUM_FOR_BITMAP
80
81 //--------------------------------------------------------------------------
82 // to get the effective value of the mask entry mij
83 //--------------------------------------------------------------------------
84
85 #define GB_GET_MIJ(mij,pM) \
86 bool mij = (GBB (Mb, pM) && GB_mcast (Mx, pM, msize)) ^ Mask_comp ;
87
88 //--------------------------------------------------------------------------
89 // assignment phase
90 //--------------------------------------------------------------------------
91
92 if (A == NULL)
93 {
94
95 //----------------------------------------------------------------------
96 // scalar assignment: C<M or !M>(I,J) += scalar
97 //----------------------------------------------------------------------
98
99 // for all IxJ
100 // get the effective value of the mask, via GB_GET_MIJ:
101 // for row assign: get mij = m(jC,0)
102 // for col assign: get mij = m(iC,0)
103 // for assign: get mij = M(iC,jC)
104 // for subassign: get mij = M(i,j)
105 // if complemented: mij = !mij
106 // if mij == 1:
107 // if Cb(p) == 0
108 // Cx(p) = scalar
109 // Cb(p) = 1 // C(iC,jC) is now present, insert
110 // else // if Cb(p) == 1:
111 // Cx(p) += scalar // C(iC,jC) still present, updated
112
113 // if C FULL: no change, just cb = GBB (Cb,pC)
114
115 #undef GB_IXJ_WORK
116 #define GB_IXJ_WORK(pC,pA) \
117 { \
118 int64_t pM = GB_GET_pM ; \
119 GB_GET_MIJ (mij, pM) ; \
120 if (mij) \
121 { \
122 int8_t cb = Cb [pC] ; \
123 if (cb == 0) \
124 { \
125 /* Cx [pC] = scalar */ \
126 GB_ASSIGN_SCALAR (pC) ; \
127 Cb [pC] = 1 ; \
128 task_cnvals++ ; \
129 } \
130 else /* (cb == 1) */ \
131 { \
132 /* Cx [pC] += scalar */ \
133 GB_ACCUM_SCALAR (pC) ; \
134 } \
135 } \
136 }
137
138 ASSERT (assign_kind == GB_ASSIGN || assign_kind == GB_SUBASSIGN) ;
139
140 switch (assign_kind)
141 {
142 case GB_ASSIGN :
143 // C<M>(I,J) += scalar where M has the same size as C
144 #undef GB_GET_pM
145 #define GB_GET_pM pC
146 #include "GB_bitmap_assign_IxJ_template.c"
147 break ;
148 case GB_SUBASSIGN :
149 // C(I,J)<M> += scalar where M has the same size as A
150 #undef GB_GET_pM
151 #define GB_GET_pM pA
152 #include "GB_bitmap_assign_IxJ_template.c"
153 break ;
154 default: ;
155 }
156
157 }
158 else
159 {
160
161 //----------------------------------------------------------------------
162 // matrix assignment: C<M or !M>(I,J) += A
163 //----------------------------------------------------------------------
164
165 // for all entries aij in A (A can be hyper, sparse, bitmap, or full)
166 // get the effective value of the mask, via GB_GET_MIJ:
167 // for row assign: get mij = m(jC,0)
168 // for col assign: get mij = m(iC,0)
169 // for assign: get mij = M(iC,jC)
170 // for subassign: get mij = M(i,j)
171 // if complemented: mij = !mij
172 // if mij == 1:
173 // if Cb(p) == 0
174 // Cx(p) = aij
175 // Cb(p) = 1 // C(iC,jC) is now present, insert
176 // task_cnvals++
177 // else // if Cb(p) == 1:
178 // Cx(p) += aij // C(iC,jC) still present, updated
179
180 // if C FULL: no change, just cb = GBB (Cb,pC)
181
182 #define GB_AIJ_WORK(pC,pA) \
183 { \
184 int64_t pM = GB_GET_pM ; \
185 GB_GET_MIJ (mij, pM) ; \
186 if (mij) \
187 { \
188 int8_t cb = Cb [pC] ; \
189 if (cb == 0) \
190 { \
191 /* Cx [pC] = Ax [pA] */ \
192 GB_ASSIGN_AIJ (pC, pA) ; \
193 Cb [pC] = 1 ; \
194 task_cnvals++ ; \
195 } \
196 else /* (cb == 1) */ \
197 { \
198 /* Cx [pC] += Ax [pA] */ \
199 GB_ACCUM_AIJ (pC, pA) ; \
200 } \
201 } \
202 }
203
204 switch (assign_kind)
205 {
206 case GB_ROW_ASSIGN :
207 // C<m>(i,J) += A where m is a 1-by-C->vdim row vector
208 #undef GB_GET_pM
209 #define GB_GET_pM jC
210 #include "GB_bitmap_assign_A_template.c"
211 break ;
212 case GB_COL_ASSIGN :
213 // C<m>(I,j) += A where m is a C->vlen-by-1 column vector
214 #undef GB_GET_pM
215 #define GB_GET_pM iC
216 #include "GB_bitmap_assign_A_template.c"
217 break ;
218 case GB_ASSIGN :
219 // C<M>(I,J) += A where M has the same size as C
220 #undef GB_GET_pM
221 #define GB_GET_pM pC
222 #include "GB_bitmap_assign_A_template.c"
223 break ;
224 case GB_SUBASSIGN :
225 // C(I,J)<M> += A where M has the same size as A
226 #undef GB_GET_pM
227 #define GB_GET_pM (iA + jA * nI)
228 #include "GB_bitmap_assign_A_template.c"
229 break ;
230 default: ;
231 }
232 }
233
234 //--------------------------------------------------------------------------
235 // C_replace phase
236 //--------------------------------------------------------------------------
237
238 if (C_replace)
239 {
240 // if C FULL: use two passes: first pass checks if any
241 // entry must be deleted. If none: do nothing. Else: change C
242 // to full and do 2nd pass as below.
243
244 // for row assign: for all entries in C(i,:)
245 // for col assign: for all entries in C(:,j)
246 // for assign: for all entries in C(:,:)
247 // for subassign: for all entries in C(I,J)
248 // get effective value mij of the mask via GB_GET_MIJ
249 // if mij == 0 set Cb(p) = 0
250 #define GB_CIJ_WORK(pC) \
251 { \
252 if (!mij) \
253 { \
254 int8_t cb = Cb [pC] ; \
255 Cb [pC] = 0 ; \
256 task_cnvals -= (cb == 1) ; \
257 } \
258 }
259 #include "GB_bitmap_assign_C_template.c"
260 }
261
262 //--------------------------------------------------------------------------
263 // return result
264 //--------------------------------------------------------------------------
265
266 C->nvals = cnvals ;
267 ASSERT_MATRIX_OK (C, "final C for bitmap assign, M full, accum", GB0) ;
268 return (GrB_SUCCESS) ;
269 }
270
271