File: GrB_Matrix_import.c

package info (click to toggle)
suitesparse-graphblas 7.4.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 67,112 kB
  • sloc: ansic: 1,072,243; cpp: 8,081; sh: 512; makefile: 506; asm: 369; python: 125; awk: 10
file content (372 lines) | stat: -rw-r--r-- 15,213 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
//------------------------------------------------------------------------------
// GrB_Matrix_import: import a matrix in CSR, CSC, FullC, FullR, or COO format
//------------------------------------------------------------------------------

// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//------------------------------------------------------------------------------

// No typecasting is done.  The type of entries in the Ax array must match
// the GrB_Type type parameter.

#include "GB_export.h"
#include "GB_build.h"

#define GB_FREE_ALL                 \
{                                   \
    GB_Matrix_free (A) ;            \
    GB_FREE (&Ap_copy, Ap_size) ;   \
    GB_FREE (&Ai_copy, Ai_size) ;   \
    GB_FREE (&Ax_copy, Ax_size) ;   \
}

//------------------------------------------------------------------------------
// GB_import_worker: import a matrix of any type
//------------------------------------------------------------------------------

static GrB_Info GB_import_worker   // import a matrix of any type
(
    GrB_Matrix *A,          // handle of matrix to create
    GrB_Type type,          // type of matrix to create
    GrB_Index nrows,        // number of rows of the matrix
    GrB_Index ncols,        // number of columns of the matrix
    const GrB_Index *Ap,    // pointers for CSR, CSC, row indices for COO
    const GrB_Index *Ai,    // row indices for CSR, CSC, col indices for COO
    const void *Ax,         // values (must match the GrB_Type type parameter)
    GrB_Index Ap_len,       // number of entries in Ap (not # of bytes)
    GrB_Index Ai_len,       // number of entries in Ai (not # of bytes)
    GrB_Index Ax_len,       // number of entries in Ax (not # of bytes)
    GrB_Format format,      // import format
    GB_Context Context
)
{ 

    //--------------------------------------------------------------------------
    // check inputs
    //--------------------------------------------------------------------------

    GB_RETURN_IF_NULL (A) ;
    (*A) = NULL ;
    GB_RETURN_IF_NULL (Ax) ;
    ASSERT_TYPE_OK (type, "type for GrB_Matrix_import", GB0) ;
    GrB_Info info ;

    // GrB_Matrix_import has no descritptor so it only supports a secure import
    bool fast_import = false ;

    if (nrows > GB_NMAX || ncols > GB_NMAX || Ap_len > GB_NMAX
        || Ai_len > GB_NMAX || Ax_len > GB_NMAX)
    { 
        // problem is too large
        return (GrB_INVALID_VALUE) ;
    }

    GrB_Index nvals = 0 ;
    bool ok = true ;
    int64_t plen = (format == GrB_CSR_FORMAT) ? (nrows+1) : (ncols+1) ;

    switch (format)
    {

        case GrB_CSR_FORMAT :
        case GrB_CSC_FORMAT :

            GB_RETURN_IF_NULL (Ap) ;
            GB_RETURN_IF_NULL (Ai) ;
            if (Ap_len < plen)
            { 
                // Ap is too small
                return (GrB_INVALID_VALUE) ;
            }
            nvals = Ap [plen-1] ;
            if (Ai_len < nvals || Ax_len < nvals || nvals > GB_NMAX)
            { 
                // Ai and/or Ax are too small or problem is too large
                return (GrB_INVALID_VALUE) ;
            }
            break ;

//      case GrB_DENSE_ROW_FORMAT :
//      case GrB_DENSE_COL_FORMAT :
//
//          ok = GB_int64_multiply (&nvals, (int64_t) nrows, (int64_t) ncols) ;
//          if (!ok || Ax_len < nvals)
//          {
//              // Ap, Ai, and Ax must all have the same size
//              return (GrB_INVALID_VALUE) ;
//          }
//          break ;

        case GrB_COO_FORMAT :

            GB_RETURN_IF_NULL (Ap) ;
            GB_RETURN_IF_NULL (Ai) ;
            nvals = Ap_len ;
            if (Ai_len != nvals || Ax_len != nvals)
            { 
                // Ap, Ai, and Ax must all have the same size
                return (GrB_INVALID_VALUE) ;
            }
            break ;

        default :

            // unknown format
            return (GrB_INVALID_VALUE) ;
    }

    //--------------------------------------------------------------------------
    // allocate copies of Ap, Ai, and Ax to be imported
    //--------------------------------------------------------------------------

    GrB_Index *Ap_copy = NULL ; size_t Ap_size = 0 ;
    GrB_Index *Ai_copy = NULL ; size_t Ai_size = 0 ;
    GB_void   *Ax_copy = NULL ; size_t Ax_size = 0 ;
    size_t typesize = type->size ;

    // Ap_copy, Ai_copy, Ax_copy are GB_MALLOC'ed so they are already in the
    // debug memtable.  Thus, GB_import does not add them again to the
    // memtable (with add_to_memtable set to false).

    switch (format)
    {
        case GrB_CSR_FORMAT : 
        case GrB_CSC_FORMAT : 
            Ap_copy = GB_MALLOC (plen,           GrB_Index, &Ap_size) ;
            Ai_copy = GB_MALLOC (nvals,          GrB_Index, &Ai_size) ;
            Ax_copy = GB_MALLOC (nvals*typesize, GB_void,   &Ax_size) ; // x:OK
            ok = (Ap_copy != NULL && Ai_copy != NULL && Ax_copy != NULL) ;
            break ;

//      case GrB_DENSE_ROW_FORMAT :
//      case GrB_DENSE_COL_FORMAT :
//          Ax_copy = GB_MALLOC (nvals*typesize, GB_void,   &Ax_size) ; // x:OK
//          ok = (Ax_copy != NULL) ;
//          break ;

        default : // GrB_COO_FORMAT, nothing to allocate
            break ;
    }

    if (!ok)
    { 
        // out of memory
        GB_FREE_ALL ;
        return (GrB_OUT_OF_MEMORY) ;
    }

    //--------------------------------------------------------------------------
    // determine the # of threads to use
    //--------------------------------------------------------------------------

    GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;

    //--------------------------------------------------------------------------
    // copy the user input arrays
    //--------------------------------------------------------------------------

    switch (format)
    {
        case GrB_CSR_FORMAT : 
        case GrB_CSC_FORMAT : 
            GB_memcpy (Ap_copy, Ap, plen  * sizeof (GrB_Index), nthreads_max) ;
            GB_memcpy (Ai_copy, Ai, nvals * sizeof (GrB_Index), nthreads_max) ;
//      case GrB_DENSE_ROW_FORMAT :
//      case GrB_DENSE_COL_FORMAT :
            GB_memcpy (Ax_copy, Ax, nvals * typesize          , nthreads_max) ;
            break ;
        default : // GrB_COO_FORMAT, nothing to copy
            break ;
    }

    //--------------------------------------------------------------------------
    // import the matrix
    //--------------------------------------------------------------------------

    switch (format)
    {

        case GrB_CSR_FORMAT : 

            GB_OK (GB_import (false, A, type, ncols, nrows, false,
                &Ap_copy, Ap_size,  // Ap
                NULL, 0,            // Ah
                NULL, 0,            // Ab
                &Ai_copy, Ai_size,  // Ai
                (void **)
                &Ax_copy, Ax_size,  // Ax
                0, true, 0,         // CSR format may be jumbled
                GxB_SPARSE, false,  // sparse by row
                false,              // not iso
                fast_import,
                false,              // do not add to memtable
                Context)) ;
            break ;

        case GrB_CSC_FORMAT : 

            GB_OK (GB_import (false, A, type, nrows, ncols, false,
                &Ap_copy, Ap_size,  // Ap
                NULL, 0,            // Ah
                NULL, 0,            // Ab
                &Ai_copy, Ai_size,  // Ai
                (void **)
                &Ax_copy, Ax_size,  // Ax
                0, true, 0,         // CSC format may be jumbled
                GxB_SPARSE, true,   // sparse by column
                false,              // not iso
                fast_import,
                false,              // do not add to memtable
                Context)) ;
            break ;

//      case GrB_DENSE_ROW_FORMAT :
//
//          GB_OK (GB_import (false, A, type, ncols, nrows, false,
//              NULL, 0,            // Ap
//              NULL, 0,            // Ah
//              NULL, 0,            // Ab
//              NULL, 0,            // Ai
//              (void **)
//              &Ax_copy, Ax_size,  // Ax
//              0, false, 0,        // cannot be jumbled
//              GxB_FULL, false,    // full by row
//              false,              // not iso
//              fast_import,
//              false,              // do not add to memtable
//              Context)) ;
//          break ;

//      case GrB_DENSE_COL_FORMAT :
//
//          GB_OK (GB_import (false, A, type, nrows, ncols, false,
//              NULL, 0,            // Ap
//              NULL, 0,            // Ah
//              NULL, 0,            // Ab
//              NULL, 0,            // Ai
//              (void **)
//              &Ax_copy, Ax_size,  // Ax
//              0, false, 0,        // cannot be jumbled
//              GxB_FULL, true,     // full by column
//              false,              // not iso
//              fast_import,
//              false,              // do not add to memtable
//              Context)) ;
//          break ;

        default : // GrB_COO_FORMAT
            {
                // build A as hypersparse by row or by column
                int64_t *no_I_work = NULL ; size_t I_work_size = 0 ;
                int64_t *no_J_work = NULL ; size_t J_work_size = 0 ;
                GB_void *no_X_work = NULL ; size_t X_work_size = 0 ;
                bool is_csc = GB_Global_is_csc_get ( ) ;
                int64_t vlen = is_csc ? nrows : ncols ;
                int64_t vdim = is_csc ? ncols : nrows ;

                // allocate the header for A
                GB_OK (GB_new (A, // new header
                    type, vlen, vdim, GB_Ap_null, is_csc, GxB_AUTO_SPARSITY,
                    GB_Global_hyper_switch_get ( ), 0, Context)) ;

                // build A from the input triplets
                GB_OK (GB_builder (
                    *A,             // create A using a dynamic header
                    type,           // the type of A
                    vlen,
                    vdim,
                    is_csc,         // CSR/CSC format
                    &no_I_work,     // I_work_handle, not used here
                    &I_work_size,
                    &no_J_work,     // J_work_handle, not used here
                    &J_work_size,
                    &no_X_work,     // X_work_handle, not used here
                    &X_work_size,
                    false,          // known_sorted: not yet known
                    false,          // known_no_duplicates: not yet known
                    0,              // I_work, J_work, and X_work not used here
                    true,           // A is a GrB_Matrix
                    (int64_t *) (is_csc ? Ap : Ai),     // row/col indices
                    (int64_t *) (is_csc ? Ai : Ap),     // col/row indices
                    (const GB_void *) Ax,               // values
                    false,          // matrix is not iso
                    nvals,          // number of tuples
                    NULL,           // implicit SECOND operator for duplicates
                    type,           // type of the X array
                    true,           // burble is allowed
                    Context
                )) ;
            }
            break ;
    }

    ASSERT_MATRIX_OK (*A, "A imported", GB0) ;

    //--------------------------------------------------------------------------
    // determine if A is iso
    //--------------------------------------------------------------------------

    if (GB_iso_check (*A, Context))
    { 
        // All entries in A are the same; convert A to iso
        GBURBLE ("(post iso) ") ;
        (*A)->iso = true ;
        GB_OK (GB_convert_any_to_iso (*A, NULL, Context)) ;
    }

    //--------------------------------------------------------------------------
    // conform the matrix to its desired sparsity and return result
    //--------------------------------------------------------------------------

    GB_OK (GB_conform (*A, Context)) ;
    ASSERT_MATRIX_OK (*A, "final A imported", GB0) ;
    return (GrB_SUCCESS) ;
}

//------------------------------------------------------------------------------
// GrB_Matrix_import_*: import a matrix of a given type
//------------------------------------------------------------------------------

#define GB_IMPORT(prefix,ctype,T,acode)                                        \
GrB_Info GB_EVAL3 (prefix, _Matrix_import_, T) /* import a matrix */           \
(                                                                              \
    GrB_Matrix *A,          /* handle of matrix to create                    */\
    GrB_Type type,          /* type of matrix to create                      */\
    GrB_Index nrows,        /* number of rows of the matrix                  */\
    GrB_Index ncols,        /* number of columns of the matrix               */\
    const GrB_Index *Ap,    /* pointers for CSR, CSC, row indices for COO    */\
    const GrB_Index *Ai,    /* row indices for CSR, CSC, col indices for COO */\
    const ctype *Ax,        /* values (must match GrB_Type type parameter)   */\
    GrB_Index Ap_len,       /* number of entries in Ap (not # of bytes)      */\
    GrB_Index Ai_len,       /* number of entries in Ai (not # of bytes)      */\
    GrB_Index Ax_len,       /* number of entries in Ax (not # of bytes)      */\
    GrB_Format format       /* import format                                 */\
)                                                                              \
{                                                                              \
    GB_WHERE1 (GB_STR(prefix) "_Matrix_import_" GB_STR(T) " (&A, type, nrows," \
        " ncols, Ap, Ai, Ax, Ap_len, Ai_len, Ax_len, format)") ;               \
    GB_BURBLE_START (GB_STR(prefix) "_Matrix_import_" GB_STR(T)) ;             \
    GB_RETURN_IF_NULL_OR_FAULTY (type) ;                                       \
    if (type->code != acode) return (GrB_DOMAIN_MISMATCH) ;                    \
    GrB_Info info = GB_import_worker (A, type, nrows, ncols, Ap, Ai,           \
        (const void *) Ax, Ap_len, Ai_len, Ax_len, format, Context) ;          \
    GB_BURBLE_END ;                                                            \
    return (info) ;                                                            \
}

GB_IMPORT (GrB, bool      , BOOL   , GB_BOOL_code  )
GB_IMPORT (GrB, int8_t    , INT8   , GB_INT8_code  )
GB_IMPORT (GrB, int16_t   , INT16  , GB_INT16_code )
GB_IMPORT (GrB, int32_t   , INT32  , GB_INT32_code )
GB_IMPORT (GrB, int64_t   , INT64  , GB_INT64_code )
GB_IMPORT (GrB, uint8_t   , UINT8  , GB_UINT8_code )
GB_IMPORT (GrB, uint16_t  , UINT16 , GB_UINT16_code)
GB_IMPORT (GrB, uint32_t  , UINT32 , GB_UINT32_code)
GB_IMPORT (GrB, uint64_t  , UINT64 , GB_UINT64_code)
GB_IMPORT (GrB, float     , FP32   , GB_FP32_code  )
GB_IMPORT (GrB, double    , FP64   , GB_FP64_code  )
GB_IMPORT (GxB, GxB_FC32_t, FC32   , GB_FC32_code  )
GB_IMPORT (GxB, GxB_FC64_t, FC64   , GB_FC64_code  )
GB_IMPORT (GrB, void      , UDT    , GB_UDT_code   )