1 //------------------------------------------------------------------------------
2 // GB_bitmap_assign_fullM_noaccum:  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:       not 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_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_comp,const bool Mask_struct,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_noaccum
36 (
37     // input/output:
38     GrB_Matrix C,               // input/output matrix in bitmap format
39     const bool C_replace,       // descriptor for C
40     // inputs:
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,   // not present
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 ("bit2", M, Mask_comp, NULL,
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, noaccum", GB0) ;
69     ASSERT_MATRIX_OK (M, "M for bitmap assign, M full, noaccum", GB0) ;
70     ASSERT_MATRIX_OK_OR_NULL (A, "A for bitmap assign, M full, noaccum", 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 
80     //--------------------------------------------------------------------------
81     // to get the effective value of the mask entry mij
82     //--------------------------------------------------------------------------
83 
84     #undef  GB_GET_MIJ
85     #define GB_GET_MIJ(mij,pM)                                  \
86         bool mij = (GBB (Mb, pM) && GB_mcast (Mx, pM, msize)) ^ Mask_comp ;
87 
88     //--------------------------------------------------------------------------
89     // C_replace phase
90     //--------------------------------------------------------------------------
91 
92     if (C_replace)
93     {
94         // if C FULL: use two passes: first pass checks if any
95         // entry must be deleted.  If none: do nothing.  Else:  change C
96         // to full and do 2nd pass as below.
97 
98         // for row assign: set Cb(i,:) to zero if mij == 0
99         // for col assign: set Cb(:,j) to zero if mij == 0
100         // for assign: set Cb(:,:) to zero if mij == 0
101         // for subassign set Cb(I,J) to zero if mij == 0
102         #undef  GB_CIJ_WORK
103         #define GB_CIJ_WORK(pC)             \
104         {                                   \
105             if (!mij)                       \
106             {                               \
107                 int8_t cb = Cb [pC] ;       \
108                 Cb [pC] = 0 ;               \
109                 task_cnvals -= (cb == 1) ;  \
110             }                               \
111         }
112         #include "GB_bitmap_assign_C_template.c"
113     }
114 
115     //--------------------------------------------------------------------------
116     // assignment phase
117     //--------------------------------------------------------------------------
118 
119     if (A == NULL)
120     {
121 
122         //----------------------------------------------------------------------
123         // scalar assignment: C<M or !M>(I,J) = scalar
124         //----------------------------------------------------------------------
125 
126         // if C FULL: no change, just cb = GBB (CB,pC)
127 
128         // for all entries in IxJ
129         #undef  GB_IXJ_WORK
130         #define GB_IXJ_WORK(pC,pA)              \
131         {                                       \
132             int64_t pM = GB_GET_pM ;            \
133             GB_GET_MIJ (mij, pM) ;              \
134             if (mij)                            \
135             {                                   \
136                 int8_t cb = Cb [pC] ;           \
137                 /* Cx [pC] = scalar */          \
138                 GB_ASSIGN_SCALAR (pC) ;         \
139                 Cb [pC] = 1 ;                   \
140                 task_cnvals += (cb == 0) ;      \
141             }                                   \
142         }
143 
144         ASSERT (assign_kind == GB_ASSIGN || assign_kind == GB_SUBASSIGN) ;
145 
146         switch (assign_kind)
147         {
148             case GB_ASSIGN :
149                 // C<M>(I,J) = scalar where M has the same size as C
150                 #undef  GB_GET_pM
151                 #define GB_GET_pM pC
152                 #include "GB_bitmap_assign_IxJ_template.c"
153                 break ;
154             case GB_SUBASSIGN :
155                 // C(I,J)<M> = scalar where M has the same size as A
156                 #undef  GB_GET_pM
157                 #define GB_GET_pM pA
158                 #include "GB_bitmap_assign_IxJ_template.c"
159                 break ;
160             default: ;
161         }
162 
163     }
164     else
165     {
166 
167         //----------------------------------------------------------------------
168         // matrix assignment: C<M or !M>(I,J) = A
169         //----------------------------------------------------------------------
170 
171         // assign A into C:
172 
173             //  for all entries aij in A
174             //      get the effective value of the mask:
175             //          for row assign: get mij = m(jC,0)
176             //          for col assign: get mij = m(iC,0)
177             //          for assign: get mij = M(iC,jC)
178             //          for subassign: get mij = M(i,j)
179             //          if complemented: mij = !mij
180             //      if mij == 1:
181             //          Cx(p) = aij     // C(iC,jC) inserted or updated
182             //          Cb(p) = 4
183 
184         // clear entries from C that were not in A:
185 
186             // for all entries in IxJ
187                 // get the effective value of the mask
188                 // if mij == 1
189                     // 0 -> 0
190                     // 1 -> 0           delete because aij not present
191                     // 4 -> 1
192 
193         // TODO: if A is bitmap or full, use a single pass
194 
195         #define GB_AIJ_WORK(pC,pA)              \
196         {                                       \
197             int64_t pM = GB_GET_pM ;            \
198             GB_GET_MIJ (mij, pM) ;              \
199             if (mij)                            \
200             {                                   \
201                 int8_t cb = Cb [pC] ;           \
202                 /* Cx [pC] = Ax [pA] */         \
203                 GB_ASSIGN_AIJ (pC, pA) ;        \
204                 Cb [pC] = 4 ;                   \
205                 task_cnvals += (cb == 0) ;      \
206             }                                   \
207         }
208 
209         #undef  GB_IXJ_WORK
210         #define GB_IXJ_WORK(pC,pA)          \
211         {                                   \
212             int64_t pM = GB_GET_pM ;        \
213             GB_GET_MIJ (mij, pM) ;          \
214             if (mij)                        \
215             {                               \
216                 int8_t cb = Cb [pC] ;       \
217                 Cb [pC] = (cb > 1) ;        \
218                 task_cnvals -= (cb == 1) ;  \
219             }                               \
220         }
221 
222         switch (assign_kind)
223         {
224             case GB_ROW_ASSIGN :
225                 // C<m>(i,J) = A where m is a 1-by-C->vdim row vector
226                 #undef  GB_GET_pM
227                 #define GB_GET_pM jC
228                 #include "GB_bitmap_assign_A_template.c"
229                 #include "GB_bitmap_assign_IxJ_template.c"
230                 break ;
231 
232             case GB_COL_ASSIGN :
233                 // C<m>(I,j) = A where m is a C->vlen-by-1 column vector
234                 #undef  GB_GET_pM
235                 #define GB_GET_pM iC
236                 #include "GB_bitmap_assign_A_template.c"
237                 #include "GB_bitmap_assign_IxJ_template.c"
238                 break ;
239 
240             case GB_ASSIGN :
241                 // C<M>(I,J) = A where M has the same size as C
242                 #undef  GB_GET_pM
243                 #define GB_GET_pM pC
244                 #include "GB_bitmap_assign_A_template.c"
245                 #include "GB_bitmap_assign_IxJ_template.c"
246                 break ;
247 
248             case GB_SUBASSIGN :
249                 // C(I,J)<M> = A where M has the same size as A
250                 #undef  GB_GET_pM
251                 #define GB_GET_pM (iA + jA * nI)
252                 #include "GB_bitmap_assign_A_template.c"
253                 #include "GB_bitmap_assign_IxJ_template.c"
254                 break ;
255 
256             default: ;
257         }
258     }
259 
260     //--------------------------------------------------------------------------
261     // return result
262     //--------------------------------------------------------------------------
263 
264     C->nvals = cnvals ;
265     ASSERT_MATRIX_OK (C, "final C for bitmap assign, M full, noaccum", GB0) ;
266     return (GrB_SUCCESS) ;
267 }
268 
269