1 //------------------------------------------------------------------------------
2 // GB_jappend.h: definitions of GB_jappend, and GB_jwrapup
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 // These methods are now only used by GB_Matrix_wait.
11
12 #ifndef GB_JAPPEND_H
13 #define GB_JAPPEND_H
14 #include "GB.h"
15
16 //------------------------------------------------------------------------------
17 // GB_jappend: append a new vector to the end of a matrix
18 //------------------------------------------------------------------------------
19
20 // Append a new vector to the end of a matrix C.
21
22 // If C->h != NULL, C is in hypersparse form with
23 // C->nvec <= C->plen <= C->vdim. C->h has size C->plen.
24
25 // If C->h == NULL, C is in non-hypersparse form with
26 // C->nvec == C->plen == C->vdim. C->h is NULL.
27 // In both cases, C->p has size C->plen+1.
28
GB_jappend(GrB_Matrix C,int64_t j,int64_t * jlast,int64_t cnz,int64_t * cnz_last,GB_Context Context)29 static inline GrB_Info GB_jappend
30 (
31 GrB_Matrix C, // matrix to append vector j to
32 int64_t j, // new vector to append
33 int64_t *jlast, // last vector appended, -1 if none
34 int64_t cnz, // nnz(C) after adding this vector j
35 int64_t *cnz_last, // nnz(C) before adding this vector j
36 GB_Context Context
37 )
38 {
39
40 //--------------------------------------------------------------------------
41 // check inputs
42 //--------------------------------------------------------------------------
43
44 ASSERT (C != NULL) ;
45 ASSERT (!C->p_shallow) ;
46 ASSERT (!C->h_shallow) ;
47 ASSERT (C->p != NULL) ;
48 ASSERT (!GB_IS_FULL (C)) ;
49
50 if (cnz <= (*cnz_last))
51 {
52 // nothing to do
53 return (GrB_SUCCESS) ;
54 }
55
56 // one more non-empty vector
57 C->nvec_nonempty++ ;
58
59 if (C->h != NULL)
60 {
61
62 //----------------------------------------------------------------------
63 // C is hypersparse; make sure space exists in the hyperlist
64 //----------------------------------------------------------------------
65
66 ASSERT (C->p [C->nvec] == (*cnz_last)) ;
67 ASSERT (C->h != NULL) ;
68
69 // check if space exists
70 if (C->nvec == C->plen)
71 {
72 // double the size of C->h and C->p
73 GrB_Info info ;
74 info = GB_hyper_realloc (C, GB_IMIN (C->vdim, 2*(C->plen+1)),
75 Context) ;
76 if (info != GrB_SUCCESS)
77 {
78 // out of memory
79 return (info) ;
80 }
81 }
82
83 ASSERT (C->nvec >= 0) ;
84 ASSERT (C->nvec < C->plen) ;
85 ASSERT (C->plen <= C->vdim) ;
86 ASSERT (C->p [C->nvec] == (*cnz_last)) ;
87
88 // add j to the hyperlist
89 C->h [C->nvec] = j ;
90
91 // mark the end of C(:,j)
92 C->p [C->nvec+1] = cnz ;
93 C->nvec++ ; // one more vector in the hyperlist
94
95 }
96 else
97 {
98
99 //----------------------------------------------------------------------
100 // C is non-hypersparse
101 //----------------------------------------------------------------------
102
103 int64_t *restrict Cp = C->p ;
104
105 ASSERT (C->nvec == C->plen && C->plen == C->vdim) ;
106 ASSERT (C->h == NULL) ;
107 ASSERT (Cp [(*jlast)+1] == (*cnz_last)) ;
108
109 // Even if C is non-hypersparse, the iteration that uses this function
110 // may iterate over a hypersparse input matrix, so not every vector j
111 // will be traversed. So when j is seen, the end of vectors jlast+1 to
112 // j must logged in Cp.
113
114 for (int64_t jprior = (*jlast)+1 ; jprior < j ; jprior++)
115 {
116 // mark the end of C(:,jprior)
117 Cp [jprior+1] = (*cnz_last) ;
118 }
119 // mark the end of C(:,j)
120 Cp [j+1] = cnz ;
121 }
122
123 // record the last vector added to C
124 (*cnz_last) = cnz ;
125 (*jlast) = j ;
126
127 return (GrB_SUCCESS) ;
128 }
129
130 //------------------------------------------------------------------------------
131 // GB_jwrapup: finish contructing a new matrix
132 //------------------------------------------------------------------------------
133
134 // Log the end of any vectors in C that are not yet terminated. Nothing
135 // happens if C is hypersparse (except for setting C->magic).
136
GB_jwrapup(GrB_Matrix C,int64_t jlast,int64_t cnz)137 static inline void GB_jwrapup
138 (
139 GrB_Matrix C, // matrix to finish
140 int64_t jlast, // last vector appended, -1 if none
141 int64_t cnz // final nnz(C)
142 )
143 {
144
145 if (C->h == NULL)
146 {
147
148 //----------------------------------------------------------------------
149 // C is non-hypersparse
150 //----------------------------------------------------------------------
151
152 // log the end of C(:,jlast+1) to C(:,n-1), in case the last vector
153 // j=n-1 has not yet been seen, or has been seen but was empty.
154
155 int64_t *restrict Cp = C->p ;
156 int64_t j = C->vdim - 1 ;
157
158 for (int64_t jprior = jlast+1 ; jprior <= j ; jprior++)
159 {
160 // mark the end of C(:,jprior)
161 Cp [jprior+1] = cnz ;
162 }
163 }
164
165 // C->p and C->h are now valid
166 C->magic = GB_MAGIC ;
167 }
168
169 #endif
170
171