1 //------------------------------------------------------------------------------
2 // GB_convert.h: converting between sparsity structures
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 #ifndef GB_CONVERT_H
11 #define GB_CONVERT_H
12
13 // these parameters define the hyper_switch needed to ensure matrix stays
14 // either always hypersparse, or never hypersparse.
15 #define GB_ALWAYS_HYPER (1.0)
16 #define GB_NEVER_HYPER (-1.0)
17
18 // true if A is bitmap
19 #define GB_IS_BITMAP(A) ((A) != NULL && ((A)->b != NULL))
20
21 // true if A is full (but not bitmap)
22 #define GB_IS_FULL(A) \
23 ((A) != NULL && (A)->h == NULL && (A)->p == NULL && (A)->i == NULL \
24 && (A)->b == NULL)
25
26 // true if A is hypersparse
27 #define GB_IS_HYPERSPARSE(A) ((A) != NULL && ((A)->h != NULL))
28
29 // true if A is sparse (but not hypersparse)
30 #define GB_IS_SPARSE(A) ((A) != NULL && ((A)->h == NULL) && (A)->p != NULL)
31
32 // determine the sparsity control for a matrix
33 int GB_sparsity_control // revised sparsity
34 (
35 int sparsity, // sparsity control
36 int64_t vdim // A->vdim, or -1 to ignore this condition
37 ) ;
38
39 // GB_sparsity: determine the current sparsity status of a matrix
GB_sparsity(GrB_Matrix A)40 static inline int GB_sparsity (GrB_Matrix A)
41 {
42 if (A == NULL)
43 {
44 // if A is NULL, pretend it is sparse
45 return (GxB_SPARSE) ;
46 }
47 else if (GB_IS_HYPERSPARSE (A))
48 {
49 return (GxB_HYPERSPARSE) ;
50 }
51 else if (GB_IS_FULL (A))
52 {
53 return (GxB_FULL) ;
54 }
55 else if (GB_IS_BITMAP (A))
56 {
57 return (GxB_BITMAP) ;
58 }
59 else
60 {
61 return (GxB_SPARSE) ;
62 }
63 }
64
65 GB_PUBLIC // accessed by the MATLAB tests in GraphBLAS/Test only
66 GrB_Info GB_convert_hyper_to_sparse // convert hypersparse to sparse
67 (
68 GrB_Matrix A, // matrix to convert from hypersparse to sparse
69 GB_Context Context
70 ) ;
71
72 GB_PUBLIC // accessed by the MATLAB tests in GraphBLAS/Test only
73 GrB_Info GB_convert_sparse_to_hyper // convert from sparse to hypersparse
74 (
75 GrB_Matrix A, // matrix to convert to hypersparse
76 GB_Context Context
77 ) ;
78
79 bool GB_convert_hyper_to_sparse_test // test for hypersparse to sparse
80 (
81 float hyper_switch, // A->hyper_switch
82 int64_t k, // # of non-empty vectors of A (an estimate is OK)
83 int64_t vdim // A->vdim
84 ) ;
85
86 bool GB_convert_sparse_to_hyper_test // test sparse to hypersparse conversion
87 (
88 float hyper_switch, // A->hyper_switch
89 int64_t k, // # of non-empty vectors of A (an estimate is OK)
90 int64_t vdim // A->vdim
91 ) ;
92
93 bool GB_convert_bitmap_to_sparse_test // test for hyper/sparse to bitmap
94 (
95 float bitmap_switch, // A->bitmap_switch
96 int64_t anz, // # of entries in A = GB_NNZ (A)
97 int64_t vlen, // A->vlen
98 int64_t vdim // A->vdim
99 ) ;
100
101 bool GB_convert_sparse_to_bitmap_test // test for hyper/sparse to bitmap
102 (
103 float bitmap_switch, // A->bitmap_switch
104 int64_t anz, // # of entries in A = GB_NNZ (A)
105 int64_t vlen, // A->vlen
106 int64_t vdim // A->vdim
107 ) ;
108
109 GrB_Info GB_convert_full_to_sparse // convert matrix from full to sparse
110 (
111 GrB_Matrix A, // matrix to convert from full to sparse
112 GB_Context Context
113 ) ;
114
115 GrB_Info GB_convert_full_to_bitmap // convert matrix from full to bitmap
116 (
117 GrB_Matrix A, // matrix to convert from full to bitmap
118 GB_Context Context
119 ) ;
120
121 GrB_Info GB_convert_sparse_to_bitmap // convert sparse/hypersparse to bitmap
122 (
123 GrB_Matrix A, // matrix to convert from sparse to bitmap
124 GB_Context Context
125 ) ;
126
127 GrB_Info GB_convert_bitmap_to_sparse // convert matrix from bitmap to sparse
128 (
129 GrB_Matrix A, // matrix to convert from bitmap to sparse
130 GB_Context Context
131 ) ;
132
133 GrB_Info GB_convert_bitmap_worker // extract CSC/CSR or triplets from bitmap
134 (
135 // outputs:
136 int64_t *restrict Ap, // vector pointers for CSC/CSR form
137 int64_t *restrict Ai, // indices for CSC/CSR or triplet form
138 int64_t *restrict Aj, // vector indices for triplet form
139 GB_void *restrict Ax_new, // values for CSC/CSR or triplet form
140 int64_t *anvec_nonempty, // # of non-empty vectors
141 // inputs: not modified
142 const GrB_Matrix A, // matrix to extract; not modified
143 GB_Context Context
144 ) ;
145
146 GrB_Info GB_convert_to_full // convert matrix to full; delete prior values
147 (
148 GrB_Matrix A // matrix to convert to full
149 ) ;
150
151 GrB_Info GB_convert_any_to_bitmap // convert to bitmap
152 (
153 GrB_Matrix A, // matrix to convert to bitmap
154 GB_Context Context
155 ) ;
156
157 GB_PUBLIC // used by MATLAB interface
158 void GB_convert_any_to_full // convert any matrix to full
159 (
160 GrB_Matrix A // matrix to convert to full
161 ) ;
162
163 GrB_Info GB_convert_any_to_hyper // convert to hypersparse
164 (
165 GrB_Matrix A, // matrix to convert to hypersparse
166 GB_Context Context
167 ) ;
168
169 GrB_Info GB_convert_any_to_sparse // convert to sparse
170 (
171 GrB_Matrix A, // matrix to convert to sparse
172 GB_Context Context
173 ) ;
174
175 GrB_Info GB_convert_to_nonfull // ensure a matrix is not full
176 (
177 GrB_Matrix A,
178 GB_Context Context
179 ) ;
180
181 /* ensure C is sparse or hypersparse */
182 #define GB_ENSURE_SPARSE(C) \
183 { \
184 if (GB_IS_BITMAP (C)) \
185 { \
186 /* convert C from bitmap to sparse */ \
187 GB_OK (GB_convert_bitmap_to_sparse (C, Context)) ; \
188 } \
189 else if (GB_IS_FULL (C)) \
190 { \
191 /* convert C from full to sparse */ \
192 GB_OK (GB_convert_full_to_sparse (C, Context)) ; \
193 } \
194 }
195
196 #define GB_ENSURE_FULL(C) \
197 { \
198 ASSERT (GB_is_dense (C)) ; \
199 if (GB_sparsity_control (C->sparsity, C->vdim) & GxB_FULL) \
200 { \
201 /* convert C from any structure to full, */ \
202 /* if permitted by C->sparsity */ \
203 GB_convert_any_to_full (C) ; \
204 } \
205 }
206
207 //------------------------------------------------------------------------------
208 // GB_is_dense
209 //------------------------------------------------------------------------------
210
GB_is_dense(const GrB_Matrix A)211 static inline bool GB_is_dense
212 (
213 const GrB_Matrix A
214 )
215 {
216 // check if A is competely dense: all entries present.
217 // zombies, pending tuples, and jumbled status are not considered.
218 // A can have any sparsity structure: hyper, sparse, bitmap, or full.
219 // It can be converted to full, if zombies/tuples/jumbled are discarded.
220 if (A == NULL)
221 {
222 return (false) ;
223 }
224 if (GB_IS_FULL (A))
225 {
226 // A is full; the pattern is not present
227 return (true) ;
228 }
229 // A is sparse, hyper, or bitmap: check if all entries present
230 GrB_Index anzmax ;
231 bool ok = GB_Index_multiply (&anzmax, A->vlen, A->vdim) ;
232 return (ok && (anzmax == GB_NNZ (A))) ;
233 }
234
235 //------------------------------------------------------------------------------
236 // GB_as_if_full
237 //------------------------------------------------------------------------------
238
GB_as_if_full(const GrB_Matrix A)239 static inline bool GB_as_if_full
240 (
241 const GrB_Matrix A
242 )
243 {
244 // check if A is competely dense: all entries present.
245 // zombies, pending tuples, and jumbled status are checked.
246 // A can have any sparsity structure: hyper, sparse, bitmap, or full.
247 // It can be converted to full.
248 if (A == NULL)
249 {
250 return (false) ;
251 }
252 if (GB_IS_FULL (A))
253 {
254 // A is full; the pattern is not present
255 return (true) ;
256 }
257 if (GB_ANY_PENDING_WORK (A))
258 {
259 // A has pending work and so cannot be treated as if full.
260 return (false) ;
261 }
262 // A is sparse, hyper, or bitmap: check if all entries present
263 GrB_Index anzmax ;
264 bool ok = GB_Index_multiply (&anzmax, A->vlen, A->vdim) ;
265 return (ok && (anzmax == GB_NNZ (A))) ;
266 }
267
268 //------------------------------------------------------------------------------
269 // GB_is_packed
270 //------------------------------------------------------------------------------
271
GB_is_packed(const GrB_Matrix A)272 static inline bool GB_is_packed
273 (
274 const GrB_Matrix A
275 )
276 {
277 // check if A is a packed matrix. A is packed if it is bitmap or full. If
278 // A is hypersparse or sparse, it is packed if it is not jumbled, all
279 // entries are present, and it has no zombies or pending tuples.
280 // If A is sparse or hypersparse, it can be converted to full via
281 // GB_convert_any_to_full, by deleting A->p, A->h, and A->i. If bitmap,
282 // it cannot be converted to full unless GB_is_dense (A) is also true
283 // (it must have all entries present).
284
285 return (GB_IS_BITMAP (A) || GB_as_if_full (A)) ;
286 }
287
288 //------------------------------------------------------------------------------
289
290 GrB_Info GB_conform // conform a matrix to its desired sparsity structure
291 (
292 GrB_Matrix A, // matrix to conform
293 GB_Context Context
294 ) ;
295
GB_sparsity_char(int sparsity)296 static inline char *GB_sparsity_char (int sparsity)
297 {
298 switch (sparsity)
299 {
300 case GxB_HYPERSPARSE: return ("H") ;
301 case GxB_SPARSE: return ("S") ;
302 case GxB_BITMAP: return ("B") ;
303 case GxB_FULL: return ("F") ;
304 default: ASSERT (0) ; return ("?") ;
305 }
306 }
307
GB_sparsity_char_matrix(GrB_Matrix A)308 static inline const char *GB_sparsity_char_matrix (GrB_Matrix A)
309 {
310 bool A_as_if_full = GB_as_if_full (A) ;
311 if (A == NULL) return (".") ;
312 if (GB_IS_HYPERSPARSE (A)) return (A_as_if_full ? "Hf" : "H") ;
313 if (GB_IS_SPARSE (A)) return (A_as_if_full ? "Sf" : "S") ;
314 if (GB_IS_BITMAP (A)) return (A_as_if_full ? "Bf" : "B") ;
315 if (GB_IS_FULL (A)) return ("F") ;
316 ASSERT (0) ; return ("?") ;
317 }
318
319 GrB_Matrix GB_hyper_pack // return C
320 (
321 GrB_Matrix C, // output matrix
322 const GrB_Matrix A // input matrix
323 ) ;
324
325 #endif
326
327