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