1 //------------------------------------------------------------------------------
2 // GB_ix_realloc: reallocate a matrix to hold a given number of entries
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 // Does not modify A->p. Reallocates A->x and A->i to the requested size,
11 // preserving the existing content of A->x and A->i. Preserves pending tuples
12 // and zombies, if any. If numeric is false, then A->x is freed instead.
13
14 #include "GB.h"
15
16 GB_PUBLIC // accessed by the MATLAB tests in GraphBLAS/Test only
GB_ix_realloc(GrB_Matrix A,const int64_t nzmax_new,const bool numeric,GB_Context Context)17 GrB_Info GB_ix_realloc // reallocate space in a matrix
18 (
19 GrB_Matrix A, // matrix to allocate space for
20 const int64_t nzmax_new, // new number of entries the matrix can hold
21 const bool numeric, // if true, reallocate A->x, else A->x is NULL
22 GB_Context Context
23 )
24 {
25
26 //--------------------------------------------------------------------------
27 // check inputs
28 //--------------------------------------------------------------------------
29
30 // This method is used only by GB_ix_resize, which itself is used only by
31 // GrB_Matrix_wait. Full and bitmap matrices never have pending work, so
32 // this function is only called for hypersparse and sparse matrices.
33 ASSERT (!GB_IS_FULL (A)) ;
34 ASSERT (!GB_IS_BITMAP (A)) ;
35 ASSERT (GB_IS_SPARSE (A) || GB_IS_HYPERSPARSE (A)) ;
36
37 // A->p has been allocated but might not be initialized. GB_Matrix_check
38 // fails in this case. Thus, ASSERT_MATRIX_OK (A, "A", ...) ; cannot be
39 // used here.
40 ASSERT (A != NULL && A->p != NULL) ;
41 ASSERT (!A->i_shallow && !A->x_shallow) ;
42
43 // This function tolerates pending tuples, zombies, and jumbled matrices.
44 ASSERT (GB_ZOMBIES_OK (A)) ;
45 ASSERT (GB_JUMBLED_OK (A)) ;
46 ASSERT (GB_PENDING_OK (A)) ;
47
48 if (nzmax_new > GxB_INDEX_MAX)
49 {
50 // problem too large
51 return (GrB_OUT_OF_MEMORY) ;
52 }
53
54 //--------------------------------------------------------------------------
55 // reallocate the space
56 //--------------------------------------------------------------------------
57
58 size_t nzmax_new1 = GB_IMAX (nzmax_new, 1) ;
59 bool ok1 = true, ok2 = true ;
60 GB_REALLOC (A->i, nzmax_new1, A->nzmax, int64_t, &(A->i_size), &ok1,
61 Context) ;
62 if (numeric)
63 {
64 size_t asize = A->type->size ;
65 GB_REALLOC (A->x, nzmax_new1*asize, (A->nzmax)*asize, GB_void,
66 &(A->x_size), &ok2, Context) ;
67 }
68 else
69 {
70 GB_FREE (&(A->x), A->x_size) ;
71 }
72 bool ok = ok1 && ok2 ;
73
74 // always succeeds if the space shrinks
75 ASSERT (GB_IMPLIES (nzmax_new1 <= A->nzmax, ok)) ;
76
77 if (ok)
78 {
79 A->nzmax = nzmax_new1 ;
80 }
81
82 // The matrix is always left in a valid state. If the reallocation fails
83 // it just won't have the requested size (and ok is false in this case).
84 if (!ok)
85 {
86 return (GrB_OUT_OF_MEMORY) ;
87 }
88
89 return (GrB_SUCCESS) ;
90 }
91
92