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