1 //------------------------------------------------------------------------------
2 // GB_bitmap_subref: C = A(I,J) where A 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
10 // C=A(I,J), where A is bitmap or full, symbolic and numeric.
11 // See GB_subref for details.
12
13 #include "GB_subref.h"
14 #include "GB_subassign_IxJ_slice.h"
15
16 #define GB_FREE_ALL \
17 { \
18 GB_phbix_free (C) ; \
19 }
20
GB_bitmap_subref(GrB_Matrix C,const bool C_is_csc,const GrB_Matrix A,const GrB_Index * I,const int64_t ni,const GrB_Index * J,const int64_t nj,const bool symbolic,GB_Context Context)21 GrB_Info GB_bitmap_subref // C = A(I,J): either symbolic or numeric
22 (
23 // output
24 GrB_Matrix C, // output matrix, static header
25 // input, not modified
26 const bool C_is_csc, // requested format of C
27 const GrB_Matrix A,
28 const GrB_Index *I, // index list for C = A(I,J), or GrB_ALL, etc.
29 const int64_t ni, // length of I, or special
30 const GrB_Index *J, // index list for C = A(I,J), or GrB_ALL, etc.
31 const int64_t nj, // length of J, or special
32 const bool symbolic, // if true, construct C as symbolic
33 GB_Context Context
34 )
35 {
36
37 //--------------------------------------------------------------------------
38 // check inputs
39 //--------------------------------------------------------------------------
40
41 GrB_Info info ;
42 ASSERT (C != NULL && C->static_header) ;
43 ASSERT_MATRIX_OK (A, "A for C=A(I,J) bitmap subref", GB0) ;
44 ASSERT (GB_IS_BITMAP (A) || GB_IS_FULL (A)) ;
45 ASSERT (!GB_IS_SPARSE (A)) ;
46 ASSERT (!GB_IS_HYPERSPARSE (A)) ;
47 ASSERT (!GB_ZOMBIES (A)) ;
48 ASSERT (!GB_JUMBLED (A)) ;
49 ASSERT (!GB_PENDING (A)) ;
50
51 //--------------------------------------------------------------------------
52 // get A
53 //--------------------------------------------------------------------------
54
55 const int8_t *restrict Ab = A->b ;
56 const GB_void *restrict Ax = (GB_void *) A->x ;
57 const int64_t avlen = A->vlen ;
58 const int64_t avdim = A->vdim ;
59 const size_t asize = A->type->size ;
60
61 //--------------------------------------------------------------------------
62 // check the properties of I and J
63 //--------------------------------------------------------------------------
64
65 // C = A(I,J) so I is in range 0:avlen-1 and J is in range 0:avdim-1
66 int64_t nI, nJ, Icolon [3], Jcolon [3] ;
67 int Ikind, Jkind ;
68 GB_ijlength (I, ni, avlen, &nI, &Ikind, Icolon) ;
69 GB_ijlength (J, nj, avdim, &nJ, &Jkind, Jcolon) ;
70
71 bool I_unsorted, I_has_dupl, I_contig, J_unsorted, J_has_dupl, J_contig ;
72 int64_t imin, imax, jmin, jmax ;
73
74 info = GB_ijproperties (I, ni, nI, avlen, &Ikind, Icolon,
75 &I_unsorted, &I_has_dupl, &I_contig, &imin, &imax, Context) ;
76 if (info != GrB_SUCCESS)
77 {
78 // I invalid
79 return (info) ;
80 }
81
82 info = GB_ijproperties (J, nj, nJ, avdim, &Jkind, Jcolon,
83 &J_unsorted, &J_has_dupl, &J_contig, &jmin, &jmax, Context) ;
84 if (info != GrB_SUCCESS)
85 {
86 // J invalid
87 return (info) ;
88 }
89
90 //--------------------------------------------------------------------------
91 // allocate C
92 //--------------------------------------------------------------------------
93
94 int64_t cnzmax ;
95 bool ok = GB_Index_multiply ((GrB_Index *) (&cnzmax), nI, nJ) ;
96 if (!ok)
97 {
98 // problem too large
99 return (GrB_OUT_OF_MEMORY) ;
100 }
101 GrB_Type ctype = symbolic ? GrB_INT64 : A->type ;
102 int sparsity = GB_IS_BITMAP (A) ? GxB_BITMAP : GxB_FULL ;
103 GB_OK (GB_new_bix (&C, true, // bitmap or full, static header
104 ctype, nI, nJ, GB_Ap_null, C_is_csc,
105 sparsity, true, A->hyper_switch, -1, cnzmax, true, Context)) ;
106
107 //--------------------------------------------------------------------------
108 // get C
109 //--------------------------------------------------------------------------
110
111 int8_t *restrict Cb = C->b ;
112
113 // In GB_bitmap_assign_IxJ_template, vlen is the vector length of the
114 // submatrix C(I,J), but here the template is used to access A(I,J), and so
115 // the vector length is A->vlen, not C->vlen. The pointers pA and pC are
116 // swapped in the macros below, since C=A(I,J) is being computed, instead
117 // of C(I,J)=A for the bitmap assignment.
118
119 int64_t vlen = avlen ;
120
121 //--------------------------------------------------------------------------
122 // C = A(I,J)
123 //--------------------------------------------------------------------------
124
125 int64_t cnvals = 0 ;
126
127 if (sparsity == GxB_BITMAP)
128 {
129
130 //----------------------------------------------------------------------
131 // C = A (I,J) where A and C are both bitmap
132 //----------------------------------------------------------------------
133
134 // symbolic subref is only used by GB_subassign_symbolic, which only
135 // operates on a matrix that is hypersparse, sparse, or full, but not
136 // bitmap. As a result, the symbolic subref C=A(I,J) where both A and
137 // C are bitmap is not needed. The code is left here in case it is
138 // needed in the future.
139
140 ASSERT (!symbolic) ;
141
142 #if 0
143 if (symbolic)
144 {
145 // C=A(I,J) symbolic with A and C bitmap
146 ASSERT (GB_DEAD_CODE) ;
147 int64_t *restrict Cx = (int64_t *) C->x ;
148 #undef GB_IXJ_WORK
149 #define GB_IXJ_WORK(pA,pC) \
150 { \
151 int8_t ab = Ab [pA] ; \
152 Cb [pC] = ab ; \
153 Cx [pC] = pA ; \
154 task_cnvals += ab ; \
155 }
156 #include "GB_bitmap_assign_IxJ_template.c"
157 }
158 else
159 #endif
160 {
161 // C=A(I,J) numeric with A and C bitmap
162 GB_void *restrict Cx = (GB_void *) C->x ;
163 #undef GB_IXJ_WORK
164 #define GB_IXJ_WORK(pA,pC) \
165 { \
166 int8_t ab = Ab [pA] ; \
167 Cb [pC] = ab ; \
168 if (ab) \
169 { \
170 /* Cx [pC] = Ax [pA] */ \
171 memcpy (Cx +((pC)*asize), Ax +((pA)*asize), asize) ; \
172 task_cnvals++ ; \
173 } \
174 }
175 #include "GB_bitmap_assign_IxJ_template.c"
176 }
177 C->nvals = cnvals ;
178
179 }
180 else
181 {
182
183 //----------------------------------------------------------------------
184 // C = A (I,J) where A and C are both full
185 //----------------------------------------------------------------------
186
187 if (symbolic)
188 {
189 // C=A(I,J) symbolic with A and C full (from GB_subassign_symbolic)
190 int64_t *restrict Cx = (int64_t *) C->x ;
191 #undef GB_IXJ_WORK
192 #define GB_IXJ_WORK(pA,pC) \
193 { \
194 Cx [pC] = pA ; \
195 }
196 #include "GB_bitmap_assign_IxJ_template.c"
197 }
198 else
199 {
200 // C=A(I,J) numeric with A and C full
201 GB_void *restrict Cx = (GB_void *) C->x ;
202 #undef GB_IXJ_WORK
203 #define GB_IXJ_WORK(pA,pC) \
204 { \
205 /* Cx [pC] = Ax [pA] */ \
206 memcpy (Cx +((pC)*asize), Ax +((pA)*asize), asize) ; \
207 }
208 #include "GB_bitmap_assign_IxJ_template.c"
209 }
210 }
211
212 //--------------------------------------------------------------------------
213 // return result
214 //--------------------------------------------------------------------------
215
216 C->magic = GB_MAGIC ;
217 ASSERT_MATRIX_OK (C, "C output for bitmap subref C=A(I,J)", GB0) ;
218 return (GrB_SUCCESS) ;
219 }
220
221