1 //------------------------------------------------------------------------------
2 // GB_import: import a matrix in any format
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 // TODO: import shallow for MATLAB
11
12 #include "GB_export.h"
13
GB_import(GrB_Matrix * A,GrB_Type type,GrB_Index vlen,GrB_Index vdim,bool is_sparse_vector,GrB_Index ** Ap,GrB_Index Ap_size,GrB_Index ** Ah,GrB_Index Ah_size,int8_t ** Ab,GrB_Index Ab_size,GrB_Index ** Ai,GrB_Index Ai_size,void ** Ax,GrB_Index Ax_size,GrB_Index nvals,bool jumbled,GrB_Index nvec,int sparsity,bool is_csc,bool is_uniform,GB_Context Context)14 GrB_Info GB_import // import a matrix in any format
15 (
16 GrB_Matrix *A, // handle of matrix to create
17 GrB_Type type, // type of matrix to create
18 GrB_Index vlen, // vector length
19 GrB_Index vdim, // vector dimension
20 bool is_sparse_vector, // true if A is a sparse GrB_Vector
21
22 // the 5 arrays:
23 GrB_Index **Ap, // pointers, for sparse and hypersparse formats.
24 GrB_Index Ap_size, // size of Ap in bytes
25
26 GrB_Index **Ah, // vector indices for hypersparse matrices
27 GrB_Index Ah_size, // size of Ah in bytes
28
29 int8_t **Ab, // bitmap, for bitmap format only.
30 GrB_Index Ab_size, // size of Ab in bytes
31
32 GrB_Index **Ai, // indices for hyper and sparse formats
33 GrB_Index Ai_size, // size of Ai in bytes
34
35 void **Ax, // values
36 GrB_Index Ax_size, // size of Ax in bytes
37
38 // additional information for specific formats:
39 GrB_Index nvals, // # of entries for bitmap format, or for a vector
40 // in CSC format.
41 bool jumbled, // if true, sparse/hypersparse may be jumbled.
42 GrB_Index nvec, // size of Ah for hypersparse format.
43
44 // information for all formats:
45 int sparsity, // hypersparse, sparse, bitmap, or full
46 bool is_csc, // if true then matrix is by-column, else by-row
47 bool is_uniform, // if true then A has uniform values and only one
48 // entry is provided in Ax, regardless of nvals(A).
49 // TODO::: uniform valued matrices not yet supported
50 GB_Context Context
51 )
52 {
53
54 //--------------------------------------------------------------------------
55 // check inputs
56 //--------------------------------------------------------------------------
57
58 GB_RETURN_IF_NULL (A) ;
59 (*A) = NULL ;
60 GB_RETURN_IF_NULL_OR_FAULTY (type) ;
61 if (vlen > GxB_INDEX_MAX || vdim > GxB_INDEX_MAX ||
62 nvals > GxB_INDEX_MAX || nvec > GxB_INDEX_MAX ||
63 Ap_size > GxB_INDEX_MAX ||
64 Ah_size > GxB_INDEX_MAX || Ab_size > GxB_INDEX_MAX ||
65 Ai_size > GxB_INDEX_MAX || Ax_size > GxB_INDEX_MAX)
66 {
67 return (GrB_INVALID_VALUE) ;
68 }
69
70 if (is_uniform)
71 {
72 return (GrB_INVALID_VALUE) ; // TODO::: not yet supported
73 }
74
75 // full_size = vlen*vdim, for bitmap and full formats
76 bool ok = true ;
77 int64_t full_size ;
78 if (sparsity == GxB_BITMAP || sparsity == GxB_FULL)
79 {
80 ok = GB_Index_multiply ((GrB_Index *) &full_size, vlen, vdim) ;
81 if (!ok)
82 {
83 // problem too large: only Ax_size == 1 is possible for GxB_FULL.
84 // GxB_BITMAP is infeasible and an error is returned below.
85 full_size = 1 ;
86 }
87 }
88
89 if (Ax_size > 0)
90 {
91 // Ax and (*Ax) are ignored if Ax_size is zero
92 GB_RETURN_IF_NULL (Ax) ;
93 GB_RETURN_IF_NULL (*Ax) ;
94 }
95
96 switch (sparsity)
97 {
98 case GxB_HYPERSPARSE :
99 // check Ap and get nvals
100 if (nvec > vdim) return (GrB_INVALID_VALUE) ;
101 if (Ap_size < (nvec+1) * sizeof (int64_t))
102 {
103 return (GrB_INVALID_VALUE) ;
104 }
105 GB_RETURN_IF_NULL (Ap) ;
106 GB_RETURN_IF_NULL (*Ap) ;
107 nvals = (*Ap) [nvec] ;
108 // check Ah
109 GB_RETURN_IF_NULL (Ah) ;
110 GB_RETURN_IF_NULL (*Ah) ;
111 if (Ah_size < nvec * sizeof (int64_t))
112 {
113 return (GrB_INVALID_VALUE) ;
114 }
115 // check Ai
116 if (Ai_size > 0)
117 {
118 GB_RETURN_IF_NULL (Ai) ;
119 GB_RETURN_IF_NULL (*Ai) ;
120 }
121 if (Ai_size < nvals * sizeof (int64_t))
122 {
123 return (GrB_INVALID_VALUE) ;
124 }
125 // check Ax
126 if (Ax_size > 0 && Ax_size < nvals * type->size)
127 {
128 return (GrB_INVALID_VALUE) ;
129 }
130 break ;
131
132 case GxB_SPARSE :
133 // check Ap and get nvals
134 if (!is_sparse_vector)
135 {
136 // GxB_Vector_import_CSC passes in Ap as a NULL, and nvals as
137 // the # of entries in the vector. All other uses of GB_import
138 // pass in Ap for the sparse case
139 if (Ap_size < (vdim+1) * sizeof (int64_t))
140 {
141 return (GrB_INVALID_VALUE) ;
142 }
143 GB_RETURN_IF_NULL (Ap) ;
144 GB_RETURN_IF_NULL (*Ap) ;
145 nvals = (*Ap) [vdim] ;
146 }
147 // check Ai
148 if (Ai_size > 0)
149 {
150 GB_RETURN_IF_NULL (Ai) ;
151 GB_RETURN_IF_NULL (*Ai) ;
152 }
153 if (Ai_size < nvals * sizeof (int64_t))
154 {
155 return (GrB_INVALID_VALUE) ;
156 }
157 // check Ax
158 if (Ax_size > 1 && Ax_size < nvals * type->size)
159 {
160 return (GrB_INVALID_VALUE) ;
161 }
162 break ;
163
164 case GxB_BITMAP :
165 // check Ab
166 if (!ok) return (GrB_INVALID_VALUE) ;
167 if (Ab_size > 0)
168 {
169 GB_RETURN_IF_NULL (Ab) ;
170 GB_RETURN_IF_NULL (*Ab) ;
171 }
172 if (nvals > full_size) return (GrB_INVALID_VALUE) ;
173 if (Ab_size < full_size) return (GrB_INVALID_VALUE) ;
174 // check Ax
175 if (Ax_size > 0 && Ax_size < full_size * type->size)
176 {
177 return (GrB_INVALID_VALUE) ;
178 }
179 break ;
180
181 case GxB_FULL :
182 // check Ax
183 if (Ax_size > 0 && Ax_size < full_size * type->size)
184 {
185 return (GrB_INVALID_VALUE) ;
186 }
187 break ;
188
189 default: ;
190 }
191
192 //--------------------------------------------------------------------------
193 // allocate just the header of the matrix, not the content
194 //--------------------------------------------------------------------------
195
196 // also create A->p if this is a sparse GrB_Vector
197 GrB_Info info = GB_new (A, false, // any sparsity, new user header
198 type, vlen, vdim, is_sparse_vector ? GB_Ap_calloc : GB_Ap_null, is_csc,
199 sparsity, GB_Global_hyper_switch_get ( ), nvec, Context) ;
200 if (info != GrB_SUCCESS)
201 {
202 // out of memory
203 ASSERT ((*A) == NULL) ;
204 return (info) ;
205 }
206
207 //--------------------------------------------------------------------------
208 // import the matrix
209 //--------------------------------------------------------------------------
210
211 // transplant the user's content into the matrix
212 (*A)->magic = GB_MAGIC ;
213
214 switch (sparsity)
215 {
216 case GxB_HYPERSPARSE :
217 (*A)->nvec = nvec ;
218
219 // import A->h
220 (*A)->h = (int64_t *) (*Ah) ; (*Ah) = NULL ;
221 (*A)->h_size = Ah_size ;
222 #ifdef GB_DEBUG
223 GB_Global_memtable_add ((*A)->h, (*A)->h_size) ;
224 #endif
225
226 case GxB_SPARSE :
227 (*A)->jumbled = jumbled ; // import jumbled status
228 (*A)->nvec_nonempty = -1 ; // not computed; delay until required
229 (*A)->nzmax = GB_IMIN (Ai_size / sizeof (int64_t),
230 Ax_size / type->size) ;
231
232 if (is_sparse_vector)
233 {
234 // GxB_Vector_import_CSC passes in Ap as NULL
235 (*A)->p [1] = nvals ;
236 }
237 else
238 {
239 // import A->p, unless already created for a sparse CSC vector
240 (*A)->p = (int64_t *) (*Ap) ; (*Ap) = NULL ;
241 (*A)->p_size = Ap_size ;
242 #ifdef GB_DEBUG
243 GB_Global_memtable_add ((*A)->p, (*A)->p_size) ;
244 #endif
245 }
246
247 // import A->i
248 (*A)->i = (int64_t *) (*Ai) ; (*Ai) = NULL ;
249 (*A)->i_size = Ai_size ;
250 #ifdef GB_DEBUG
251 GB_Global_memtable_add ((*A)->i, (*A)->i_size) ;
252 #endif
253 break ;
254
255 case GxB_BITMAP :
256 (*A)->nvals = nvals ;
257 (*A)->nzmax = GB_IMIN (Ab_size, Ax_size / type->size) ;
258
259 // import A->b
260 (*A)->b = (*Ab) ; (*Ab) = NULL ;
261 (*A)->b_size = Ab_size ;
262 #ifdef GB_DEBUG
263 GB_Global_memtable_add ((*A)->b, (*A)->b_size) ;
264 #endif
265 break ;
266
267 case GxB_FULL :
268 (*A)->nzmax = Ax_size / type->size ;
269 break ;
270
271 default: ;
272 }
273
274 if (Ax != NULL)
275 {
276 // import A->x
277 (*A)->x = (*Ax) ; (*Ax) = NULL ;
278 (*A)->x_size = Ax_size ;
279 #ifdef GB_DEBUG
280 GB_Global_memtable_add ((*A)->x, (*A)->x_size) ;
281 #endif
282 }
283
284 //--------------------------------------------------------------------------
285 // import is successful
286 //--------------------------------------------------------------------------
287
288 ASSERT_MATRIX_OK (*A, "A imported", GB0) ;
289 return (GrB_SUCCESS) ;
290 }
291
292