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