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