1 //------------------------------------------------------------------------------
2 // gbdegree: number of entries in each vector of a GraphBLAS matrix struct
3 //------------------------------------------------------------------------------
4
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: GPL-3.0-or-later
7
8 //------------------------------------------------------------------------------
9
10 // The input may be either a GraphBLAS matrix struct or a standard MATLAB
11 // sparse matrix.
12
13 // gbdegree (X, 'row') row degree
14 // gbdegree (X, 'col') column degree
15 // gbdegree (X, true) native (get degree of each vector):
16 // row degree if X is held by row,
17 // col degree if X is held by col.
18 // gbdegree (X, false) non-native (sum across vectors):
19 // col degree if X is held by row,
20 // row degree if X is held by col.
21
22 #include "gb_matlab.h"
23
24 #define USAGE "usage: degree = gbdegree (X, dim)"
25
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])26 void mexFunction
27 (
28 int nargout,
29 mxArray *pargout [ ],
30 int nargin,
31 const mxArray *pargin [ ]
32 )
33 {
34
35 //--------------------------------------------------------------------------
36 // check inputs
37 //--------------------------------------------------------------------------
38
39 gb_usage (nargin == 2 && nargout <= 1, USAGE) ;
40
41 //--------------------------------------------------------------------------
42 // get the inputs
43 //--------------------------------------------------------------------------
44
45 int64_t *degree = NULL ;
46 GrB_Index *list = NULL, nvec = 0 ;
47 size_t degree_size = 0 ;
48 size_t list_size = 0 ;
49 GrB_Vector d = NULL ;
50 GrB_Vector y = NULL ;
51 GrB_Matrix T = NULL ;
52 GrB_Matrix Z = NULL ;
53 GrB_Descriptor desc = NULL ;
54
55 GrB_Matrix X = gb_get_shallow (pargin [0]) ;
56 GxB_Format_Value fmt ;
57 OK (GxB_Matrix_Option_get (X, GxB_FORMAT, &fmt)) ;
58
59 bool native ;
60 if (mxIsChar (pargin [1]))
61 {
62 #define LEN 256
63 char dim_string [LEN+2] ;
64 gb_mxstring_to_string (dim_string, LEN, pargin [1], "dim") ;
65 if (MATCH (dim_string, "row"))
66 {
67 native = (fmt == GxB_BY_ROW) ;
68 }
69 else // if (MATCH (dim_string, "col"))
70 {
71 native = (fmt == GxB_BY_COL) ;
72 }
73 }
74 else
75 {
76 native = (mxGetScalar (pargin [1]) != 0) ;
77 }
78
79 //--------------------------------------------------------------------------
80 // if X is bitmap: create a copy of X and convert it to sparse
81 //--------------------------------------------------------------------------
82
83 int sparsity ;
84 OK (GxB_Matrix_Option_get (X, GxB_SPARSITY_STATUS, &sparsity)) ;
85 if (sparsity == GxB_BITMAP)
86 {
87 // Z = deep copy of the shallow matrix X
88 OK (GrB_Matrix_dup (&Z, X)) ;
89 // convert Z to sparse
90 OK (GxB_Matrix_Option_set (Z, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
91 // free the shallow X and replace it with Z
92 OK (GrB_Matrix_free (&X)) ;
93 X = Z ;
94 }
95
96 //--------------------------------------------------------------------------
97 // get the degree of each row or column of X
98 //--------------------------------------------------------------------------
99
100 GrB_Index nvals, nrows, ncols ;
101 OK (GrB_Matrix_nvals (&nvals, X)) ;
102 OK (GrB_Matrix_nrows (&nrows, X)) ;
103 OK (GrB_Matrix_ncols (&ncols, X)) ;
104
105 if (native)
106 {
107
108 //----------------------------------------------------------------------
109 // get the degree of each vector of X, where X is sparse or hypersparse
110 //----------------------------------------------------------------------
111
112 if (!GB_matlab_helper9 (X, °ree, °ree_size,
113 &list, &list_size, &nvec))
114 {
115 ERROR ("out of memory") ;
116 }
117 // TODO do not use X->vdim
118 OK (GxB_Vector_import_CSC (&d, GrB_INT64, X->vdim, &list, °ree,
119 list_size, degree_size, false, nvec, false, NULL)) ;
120
121 }
122 else
123 {
124
125 //----------------------------------------------------------------------
126 // get the degree of each index of X, where X is sparse or hypersparse
127 //----------------------------------------------------------------------
128
129 // ensure the descriptor is present, and set GxB_SORT to true
130 OK (GrB_Descriptor_new (&desc)) ;
131 OK (GxB_Desc_set (desc, GxB_SORT, true)) ;
132
133 if (fmt == GxB_BY_COL)
134 {
135
136 //------------------------------------------------------------------
137 // compute the degree of each row of X, where X is held by column
138 //------------------------------------------------------------------
139
140 if (nvals < ncols / 16 && ncols > 256)
141 {
142
143 // X is hypersparse, or might as well be, and held by column,
144 // so compute the degree of each vector of T = GrB(X,'by row')
145 // instead.
146
147 OK (GrB_Matrix_new (&T, GrB_BOOL, nrows, ncols)) ;
148 OK (GxB_Matrix_Option_set (T, GxB_FORMAT, GxB_BY_ROW)) ;
149 OK1 (T, GrB_Matrix_apply (T, NULL, NULL, GxB_ONE_BOOL, X,
150 NULL)) ;
151
152 // get the degree of nonempty rows of T
153 if (!GB_matlab_helper9 (T, °ree, °ree_size,
154 &list, &list_size, &nvec))
155 {
156 ERROR ("out of memory") ;
157 }
158 OK (GxB_Vector_import_CSC (&d, GrB_INT64, nrows, &list, °ree,
159 list_size, degree_size, false, nvec, false, NULL)) ;
160
161 }
162 else
163 {
164
165 // y = full vector of size ncols-by-1; value is not relevant
166 OK (GrB_Vector_new (&y, GrB_BOOL, ncols)) ;
167 OK (GrB_Vector_assign_BOOL (y, NULL, NULL, false, GrB_ALL,
168 ncols, NULL)) ;
169
170 // d = X*y using the PLUS_PAIR semiring
171 OK (GrB_Vector_new (&d, GrB_INT64, nrows)) ;
172 OK (GrB_mxv (d, NULL, NULL, GxB_PLUS_PAIR_INT64, X, y, desc)) ;
173 }
174
175 }
176 else
177 {
178
179 //------------------------------------------------------------------
180 // compute the degree of each column of X, where X is held by row
181 //------------------------------------------------------------------
182
183 if (nvals < nrows / 16 && nrows > 256)
184 {
185
186 // X is hypersparse, or might as well be, and held by row,
187 // so compute the degree of each vector of T = GrB(X,'by col')
188 // instead.
189
190 OK (GrB_Matrix_new (&T, GrB_BOOL, nrows, ncols)) ;
191 OK (GxB_Matrix_Option_set (T, GxB_FORMAT, GxB_BY_COL)) ;
192 OK1 (T, GrB_Matrix_apply (T, NULL, NULL, GxB_ONE_BOOL, X,
193 NULL)) ;
194
195 // get the degree of nonempty columns of T
196 if (!GB_matlab_helper9 (T, °ree, °ree_size,
197 &list, &list_size, &nvec))
198 {
199 ERROR ("out of memory") ;
200 }
201 OK (GxB_Vector_import_CSC (&d, GrB_INT64, ncols, &list, °ree,
202 list_size, degree_size, false, nvec, false, NULL)) ;
203
204 }
205 else
206 {
207
208 // y = full vector of size nrows-by-1; value is not relevant
209 OK (GrB_Vector_new (&y, GrB_BOOL, nrows)) ;
210 OK (GrB_Vector_assign_BOOL (y, NULL, NULL, false, GrB_ALL,
211 nrows, NULL)) ;
212
213 // d = y*X using the PLUS_PAIR semiring
214 OK (GrB_Vector_new (&d, GrB_INT64, ncols)) ;
215 OK (GrB_vxm (d, NULL, NULL, GxB_PLUS_PAIR_INT64, y, X, desc)) ;
216 }
217 }
218 }
219
220 //--------------------------------------------------------------------------
221 // free workspace and export d to MATLAB as a GraphBLAS matrix
222 //--------------------------------------------------------------------------
223
224 OK (GrB_Vector_free (&y)) ;
225 OK (GrB_Matrix_free (&T)) ;
226 OK (GrB_Matrix_free (&X)) ;
227 OK (GrB_Descriptor_free (&desc)) ;
228 pargout [0] = gb_export ((GrB_Matrix *) &d, KIND_GRB) ;
229 GB_WRAPUP ;
230 }
231
232