1 //------------------------------------------------------------------------------
2 // GB_mex_reduce_to_vector: c = accum(c,reduce_to_vector(A))
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 // Reduce a matrix to a vector: w<mask> = accum (w, reduce_to_vector (A))
11
12 // MATLAB interface to GrB_reduce, which relies on GrB_Matrix_reduce_BinaryOp
13 // and GrB_Matrix_reduce_Monoid to reduce a matrix to a vector.
14
15 #include "GB_mex.h"
16
17 #define USAGE "w = GB_mex_reduce_to_vector (w, mask, accum, reduce, A, desc)"
18
19 #define FREE_ALL \
20 { \
21 GrB_Matrix_free_(&A) ; \
22 GrB_Vector_free_(&w) ; \
23 GrB_Vector_free_(&mask) ; \
24 GrB_Descriptor_free_(&desc) ; \
25 if (!user_complex) \
26 { \
27 GrB_Monoid_free_(&reduce) ; \
28 } \
29 GB_mx_put_global (true) ; \
30 }
31
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])32 void mexFunction
33 (
34 int nargout,
35 mxArray *pargout [ ],
36 int nargin,
37 const mxArray *pargin [ ]
38 )
39 {
40
41 bool malloc_debug = GB_mx_get_global (true) ;
42 GrB_Matrix A = NULL ;
43 GrB_Vector w = NULL ;
44 GrB_Vector mask = NULL ;
45 GrB_Descriptor desc = NULL ;
46 GrB_Monoid reduce = NULL ;
47 bool user_complex = false ;
48
49 // check inputs
50 if (nargout > 1 || nargin < 5 || nargin > 6)
51 {
52 mexErrMsgTxt ("Usage: " USAGE) ;
53 }
54
55 // get w (make a deep copy)
56 #define GET_DEEP_COPY \
57 w = GB_mx_mxArray_to_Vector (pargin [0], "w input", true, true) ;
58 #define FREE_DEEP_COPY GrB_Vector_free_(&w) ;
59 GET_DEEP_COPY ;
60 if (w == NULL)
61 {
62 FREE_ALL ;
63 mexErrMsgTxt ("w failed") ;
64 }
65
66 // get mask (shallow copy)
67 mask = GB_mx_mxArray_to_Vector (pargin [1], "mask", false, false) ;
68 if (mask == NULL && !mxIsEmpty (pargin [1]))
69 {
70 FREE_ALL ;
71 mexErrMsgTxt ("mask failed") ;
72 }
73
74 // get A (shallow copy)
75 A = GB_mx_mxArray_to_Matrix (pargin [4], "A input", false, true) ;
76 if (A == NULL)
77 {
78 FREE_ALL ;
79 mexErrMsgTxt ("A failed") ;
80 }
81
82 // get reduce operator
83 user_complex = (Complex != GxB_FC64) && (A->type == Complex) ;
84 GrB_BinaryOp op ;
85 if (!GB_mx_mxArray_to_BinaryOp (&op, pargin [3], "op",
86 w->type, user_complex) || op == NULL)
87 {
88 FREE_ALL ;
89 mexErrMsgTxt ("op failed") ;
90 }
91
92 // get the reduce monoid
93 if (user_complex)
94 {
95 if (op == Complex_plus)
96 {
97 reduce = Complex_plus_monoid ;
98 }
99 else if (op == Complex_times)
100 {
101 reduce = Complex_times_monoid ;
102 }
103 else
104 {
105 FREE_ALL ;
106 mexErrMsgTxt ("reduce failed") ;
107 }
108 }
109 else
110 {
111 // create the reduce monoid
112 if (!GB_mx_Monoid (&reduce, op, malloc_debug))
113 {
114 FREE_ALL ;
115 mexErrMsgTxt ("reduce failed") ;
116 }
117 }
118
119 // get accum, if present
120 user_complex = (Complex != GxB_FC64) && (w->type == Complex) ;
121 GrB_BinaryOp accum ;
122 if (!GB_mx_mxArray_to_BinaryOp (&accum, pargin [2], "accum",
123 w->type, user_complex))
124 {
125 FREE_ALL ;
126 mexErrMsgTxt ("accum failed") ;
127 }
128
129 // get desc
130 if (!GB_mx_mxArray_to_Descriptor (&desc, PARGIN (5), "desc"))
131 {
132 FREE_ALL ;
133 mexErrMsgTxt ("desc failed") ;
134 }
135
136 // test GrB_Matrix_reduce_BinaryOp, if possible
137
138 if (op == GrB_MIN_INT8
139 || op == GrB_MIN_INT16
140 || op == GrB_MIN_INT32
141 || op == GrB_MIN_INT64
142 || op == GrB_MIN_UINT8
143 || op == GrB_MIN_UINT16
144 || op == GrB_MIN_UINT32
145 || op == GrB_MIN_UINT64
146 || op == GrB_MIN_FP32
147 || op == GrB_MIN_FP64
148 || op == GrB_MAX_INT8
149 || op == GrB_MAX_INT16
150 || op == GrB_MAX_INT32
151 || op == GrB_MAX_INT64
152 || op == GrB_MAX_UINT8
153 || op == GrB_MAX_UINT16
154 || op == GrB_MAX_UINT32
155 || op == GrB_MAX_UINT64
156 || op == GrB_MAX_FP32
157 || op == GrB_MAX_FP64
158 || op == GrB_PLUS_INT8
159 || op == GrB_PLUS_INT16
160 || op == GrB_PLUS_INT32
161 || op == GrB_PLUS_INT64
162 || op == GrB_PLUS_UINT8
163 || op == GrB_PLUS_UINT16
164 || op == GrB_PLUS_UINT32
165 || op == GrB_PLUS_UINT64
166 || op == GrB_PLUS_FP32
167 || op == GrB_PLUS_FP64
168 || op == GxB_PLUS_FC32
169 || op == GxB_PLUS_FC64
170 || op == GrB_TIMES_INT8
171 || op == GrB_TIMES_INT16
172 || op == GrB_TIMES_INT32
173 || op == GrB_TIMES_INT64
174 || op == GrB_TIMES_UINT8
175 || op == GrB_TIMES_UINT16
176 || op == GrB_TIMES_UINT32
177 || op == GrB_TIMES_UINT64
178 || op == GrB_TIMES_FP32
179 || op == GrB_TIMES_FP64
180 || op == GxB_TIMES_FC32
181 || op == GxB_TIMES_FC64
182 || op == GxB_ANY_BOOL
183 || op == GxB_ANY_INT8
184 || op == GxB_ANY_INT16
185 || op == GxB_ANY_INT32
186 || op == GxB_ANY_INT64
187 || op == GxB_ANY_UINT8
188 || op == GxB_ANY_UINT16
189 || op == GxB_ANY_UINT32
190 || op == GxB_ANY_UINT64
191 || op == GxB_ANY_FP32
192 || op == GxB_ANY_FP64
193 || op == GxB_ANY_FC32
194 || op == GxB_ANY_FC64
195 || op == GrB_LOR
196 || op == GrB_LAND
197 || op == GrB_LXOR
198 || op == GrB_LXNOR
199 || op == GrB_BOR_UINT8
200 || op == GrB_BOR_UINT16
201 || op == GrB_BOR_UINT32
202 || op == GrB_BOR_UINT64
203 || op == GrB_BAND_UINT8
204 || op == GrB_BAND_UINT16
205 || op == GrB_BAND_UINT32
206 || op == GrB_BAND_UINT64
207 || op == GrB_BXOR_UINT8
208 || op == GrB_BXOR_UINT16
209 || op == GrB_BXOR_UINT32
210 || op == GrB_BXOR_UINT64
211 || op == GrB_BXNOR_UINT8
212 || op == GrB_BXNOR_UINT16
213 || op == GrB_BXNOR_UINT32
214 || op == GrB_BXNOR_UINT64)
215 {
216 // w<mask> = accum (w, reduce_to_vector (A)) using a binary op
217 METHOD (GrB_Matrix_reduce_BinaryOp_(w, mask, accum, op, A, desc)) ;
218 }
219 else
220 {
221 // w<mask> = accum (w, reduce_to_vector (A)) using a monoid
222 METHOD (GrB_Matrix_reduce_Monoid_(w, mask, accum, reduce, A, desc)) ;
223 }
224
225 // return w to MATLAB as a struct and free the GraphBLAS w
226 pargout [0] = GB_mx_Vector_to_mxArray (&w, "w output", true) ;
227
228 FREE_ALL ;
229 }
230
231