File: GB_deserialize.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 (230 lines) | stat: -rw-r--r-- 8,577 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
//------------------------------------------------------------------------------
// GB_deserialize: decompress and deserialize a blob into a GrB_Matrix
//------------------------------------------------------------------------------

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

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

// A parallel decompression of a serialized blob into a GrB_Matrix.

#include "GB.h"
#include "GB_serialize.h"

#define GB_FREE_ALL                         \
{                                           \
    GB_Matrix_free (&T) ;                   \
    GB_Matrix_free (&C) ;                   \
}

GrB_Info GB_deserialize             // deserialize a matrix from a blob
(
    // output:
    GrB_Matrix *Chandle,            // output matrix created from the blob
    // input:
    GrB_Type type_expected,         // type expected (NULL for any built-in)
    const GB_void *blob,            // serialized matrix 
    size_t blob_size,               // size of the blob
    GB_Context Context
)
{

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

    GrB_Info info ;
    ASSERT (blob != NULL && Chandle != NULL) ;
    (*Chandle) = NULL ;
    GrB_Matrix C = NULL, T = NULL ;

    //--------------------------------------------------------------------------
    // read the content of the header (160 bytes)
    //--------------------------------------------------------------------------

    size_t s = 0 ;

    if (blob_size < GB_BLOB_HEADER_SIZE)
    { 
        // blob is invalid
        return (GrB_INVALID_OBJECT)  ;
    }

    GB_BLOB_READ (blob_size2, uint64_t) ;
    GB_BLOB_READ (typecode, int32_t) ;
    uint64_t blob_size1 = (uint64_t) blob_size ;

    if (blob_size1 != blob_size2
        || typecode < GB_BOOL_code || typecode > GB_UDT_code
        || (typecode == GB_UDT_code &&
            blob_size < GB_BLOB_HEADER_SIZE + GxB_MAX_NAME_LEN))
    { 
        // blob is invalid
        return (GrB_INVALID_OBJECT)  ;
    }

    GB_BLOB_READ (version, int32_t) ;
    GB_BLOB_READ (vlen, int64_t) ;
    GB_BLOB_READ (vdim, int64_t) ;
    GB_BLOB_READ (nvec, int64_t) ;
    GB_BLOB_READ (nvec_nonempty, int64_t) ;     ASSERT (nvec_nonempty >= 0) ;
    GB_BLOB_READ (nvals, int64_t) ;
    GB_BLOB_READ (typesize, int64_t) ;
    GB_BLOB_READ (Cp_len, int64_t) ;
    GB_BLOB_READ (Ch_len, int64_t) ;
    GB_BLOB_READ (Cb_len, int64_t) ;
    GB_BLOB_READ (Ci_len, int64_t) ;
    GB_BLOB_READ (Cx_len, int64_t) ;
    GB_BLOB_READ (hyper_switch, float) ;
    GB_BLOB_READ (bitmap_switch, float) ;
    GB_BLOB_READ (sparsity_control, int32_t) ;
    GB_BLOB_READ (sparsity_iso_csc, int32_t) ;
    GB_BLOB_READ (Cp_nblocks, int32_t) ; GB_BLOB_READ (Cp_method, int32_t) ;
    GB_BLOB_READ (Ch_nblocks, int32_t) ; GB_BLOB_READ (Ch_method, int32_t) ;
    GB_BLOB_READ (Cb_nblocks, int32_t) ; GB_BLOB_READ (Cb_method, int32_t) ;
    GB_BLOB_READ (Ci_nblocks, int32_t) ; GB_BLOB_READ (Ci_method, int32_t) ;
    GB_BLOB_READ (Cx_nblocks, int32_t) ; GB_BLOB_READ (Cx_method, int32_t) ;

    int32_t sparsity = sparsity_iso_csc / 4 ;
    bool iso = ((sparsity_iso_csc & 2) == 2) ;
    bool is_csc = ((sparsity_iso_csc & 1) == 1) ;

    //--------------------------------------------------------------------------
    // determine the matrix type
    //--------------------------------------------------------------------------

    GB_Type_code ccode = (GB_Type_code) typecode ;
    GrB_Type ctype = GB_code_type (ccode, type_expected) ;

    // ensure the type has the right size
    if (ctype == NULL || ctype->size != typesize)
    { 
        // blob is invalid; type is missing or the wrong size
        return (GrB_DOMAIN_MISMATCH) ;
    }

    if (ccode == GB_UDT_code)
    {
        // user-defined name is 128 bytes, if present
        // ensure the user-defined type has the right name
        ASSERT (ctype == type_expected) ;
        if (strncmp ((const char *) (blob + s), ctype->name,
            GxB_MAX_NAME_LEN) != 0)
        { 
            // blob is invalid
            return (GrB_DOMAIN_MISMATCH) ;
        }
        s += GxB_MAX_NAME_LEN ;
    }
    else if (type_expected != NULL && ctype != type_expected)
    { 
        // built-in type must match type_expected
        // blob is invalid
        return (GrB_DOMAIN_MISMATCH) ;
    }

    //--------------------------------------------------------------------------
    // get the compressed block sizes from the blob for each array
    //--------------------------------------------------------------------------

    GB_BLOB_READS (Cp_Sblocks, Cp_nblocks) ;
    GB_BLOB_READS (Ch_Sblocks, Ch_nblocks) ;
    GB_BLOB_READS (Cb_Sblocks, Cb_nblocks) ;
    GB_BLOB_READS (Ci_Sblocks, Ci_nblocks) ;
    GB_BLOB_READS (Cx_Sblocks, Cx_nblocks) ;

    //--------------------------------------------------------------------------
    // allocate the output matrix C
    //--------------------------------------------------------------------------

    // allocate the matrix with info from the header
    GB_OK (GB_new (&C,  // new header (C is NULL on input)
        ctype, vlen, vdim, GB_Ap_null, is_csc,
        sparsity, hyper_switch, nvec, Context)) ;

    C->nvec = nvec ;
    C->nvec_nonempty = nvec_nonempty ;
    C->nvals = nvals ;      // revised below
    C->bitmap_switch = bitmap_switch ;
    C->sparsity_control = sparsity_control ;
    C->iso = iso ;

    // the matrix has no pending work
    ASSERT (C->Pending == NULL) ;
    ASSERT (C->nzombies == 0) ;
    ASSERT (!C->jumbled) ;

    //--------------------------------------------------------------------------
    // decompress each array (Cp, Ch, Cb, Ci, and Cx)
    //--------------------------------------------------------------------------

    switch (sparsity)
    {
        case GxB_HYPERSPARSE : 
            // decompress Cp, Ch, and Ci
            GB_OK (GB_deserialize_from_blob ((GB_void **) &(C->p), &(C->p_size),
                Cp_len, blob, blob_size, Cp_Sblocks, Cp_nblocks, Cp_method,
                &s, Context)) ;

            GB_OK (GB_deserialize_from_blob ((GB_void **) &(C->h), &(C->h_size),
                Ch_len, blob, blob_size, Ch_Sblocks, Ch_nblocks, Ch_method,
                &s, Context)) ;

            GB_OK (GB_deserialize_from_blob ((GB_void **) &(C->i), &(C->i_size),
                Ci_len, blob, blob_size, Ci_Sblocks, Ci_nblocks, Ci_method,
                &s, Context)) ;
            break ;

        case GxB_SPARSE : 

            // decompress Cp and Ci
            GB_OK (GB_deserialize_from_blob ((GB_void **) &(C->p), &(C->p_size),
                Cp_len, blob, blob_size, Cp_Sblocks, Cp_nblocks, Cp_method,
                &s, Context)) ;

            GB_OK (GB_deserialize_from_blob ((GB_void **) &(C->i), &(C->i_size),
                Ci_len, blob, blob_size, Ci_Sblocks, Ci_nblocks, Ci_method,
                &s, Context)) ;
            break ;

        case GxB_BITMAP : 

            // decompress Cb
            GB_OK (GB_deserialize_from_blob ((GB_void **) &(C->b), &(C->b_size),
                Cb_len, blob, blob_size, Cb_Sblocks, Cb_nblocks, Cb_method,
                &s, Context)) ;
            break ;

        case GxB_FULL : 
            break ;
        default: ;
    }

    // decompress Cx
    GB_OK (GB_deserialize_from_blob ((GB_void **) &(C->x), &(C->x_size), Cx_len,
        blob, blob_size, Cx_Sblocks, Cx_nblocks, Cx_method, &s, Context)) ;

    if (C->p != NULL)
    { 
        // C is sparse or hypersparse.  v7.2.1 and later have the new C->nvals
        // value inside the blob already.  The blob prior to v7.2.1 had nvals
        // of zero for sparse and hypersparse matrices.  Set it here to the
        // correct value, so that blobs written by v7.2.0 and earlier can be
        // read by v7.2.1 and later.  For both variants, ignore nvals in the
        // blob and use Cp [nvec] when C is sparse or hypersparse.
        ASSERT (GB_IMPLIES (version > GxB_VERSION (7,2,0),
            C->nvals == C->p [C->nvec])) ;
        C->nvals = C->p [C->nvec] ;
    }
    C->magic = GB_MAGIC ;

    //--------------------------------------------------------------------------
    // return result
    //--------------------------------------------------------------------------

    (*Chandle) = C ;
    ASSERT_MATRIX_OK (*Chandle, "Final result from deserialize", GB0) ;
    return (GrB_SUCCESS) ;
}