1 //------------------------------------------------------------------------------
2 // gbapply: apply a unary operator to a sparse matrix
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 // gbapply is an interface to GrB_Matrix_apply.
11
12 // Usage:
13
14 // C = gbapply (unop, A)
15 // C = gbapply (unop, A, desc)
16 // C = gbapply (Cin, accum, unop, A, desc)
17 // C = gbapply (Cin, M, unop, A, desc)
18 // C = gbapply (Cin, M, accum, unop, A, desc)
19
20 // If Cin is not present then it is implicitly a matrix with no entries, of the
21 // right size (which depends on A, B, and the descriptor).
22
23 #include "gb_matlab.h"
24
25 #define USAGE "usage: C = GrB.apply (Cin, M, accum, op, A, desc)"
26
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])27 void mexFunction
28 (
29 int nargout,
30 mxArray *pargout [ ],
31 int nargin,
32 const mxArray *pargin [ ]
33 )
34 {
35
36 //--------------------------------------------------------------------------
37 // check inputs
38 //--------------------------------------------------------------------------
39
40 gb_usage (nargin >= 2 && nargin <= 6 && nargout <= 2, USAGE) ;
41
42 //--------------------------------------------------------------------------
43 // find the arguments
44 //--------------------------------------------------------------------------
45
46 mxArray *Matrix [4], *String [2], *Cell [2] ;
47 base_enum_t base ;
48 kind_enum_t kind ;
49 GxB_Format_Value fmt ;
50 int nmatrices, nstrings, ncells, sparsity ;
51 GrB_Descriptor desc ;
52 gb_get_mxargs (nargin, pargin, USAGE, Matrix, &nmatrices, String, &nstrings,
53 Cell, &ncells, &desc, &base, &kind, &fmt, &sparsity) ;
54
55 CHECK_ERROR (nmatrices < 1 || nmatrices > 3 || nstrings < 1 || ncells > 0,
56 USAGE) ;
57
58 //--------------------------------------------------------------------------
59 // get the matrices
60 //--------------------------------------------------------------------------
61
62 GrB_Type atype, ctype = NULL ;
63 GrB_Matrix C = NULL, M = NULL, A ;
64
65 if (nmatrices == 1)
66 {
67 A = gb_get_shallow (Matrix [0]) ;
68 }
69 else if (nmatrices == 2)
70 {
71 C = gb_get_deep (Matrix [0]) ;
72 A = gb_get_shallow (Matrix [1]) ;
73 }
74 else // if (nmatrices == 3)
75 {
76 C = gb_get_deep (Matrix [0]) ;
77 M = gb_get_shallow (Matrix [1]) ;
78 A = gb_get_shallow (Matrix [2]) ;
79 }
80
81 OK (GxB_Matrix_type (&atype, A)) ;
82 if (C != NULL)
83 {
84 OK (GxB_Matrix_type (&ctype, C)) ;
85 }
86
87 //--------------------------------------------------------------------------
88 // get the operators
89 //--------------------------------------------------------------------------
90
91 GrB_BinaryOp accum = NULL ;
92 GrB_UnaryOp op ;
93
94 if (nstrings == 1)
95 {
96 op = gb_mxstring_to_unop (String [0], atype) ;
97 }
98 else
99 {
100 // if accum appears, then Cin must also appear
101 CHECK_ERROR (C == NULL, USAGE) ;
102 accum = gb_mxstring_to_binop (String [0], ctype, ctype) ;
103 op = gb_mxstring_to_unop (String [1], atype) ;
104 }
105
106 //--------------------------------------------------------------------------
107 // construct C if not present on input
108 //--------------------------------------------------------------------------
109
110 // If C is NULL, then it is not present on input.
111 // Construct C of the right size and type.
112
113 if (C == NULL)
114 {
115
116 // get the descriptor contents to determine if A is transposed
117 GrB_Desc_Value in0 ;
118 OK (GxB_Desc_get (desc, GrB_INP0, &in0)) ;
119 bool A_transpose = (in0 == GrB_TRAN) ;
120
121 // get the size of A
122 GrB_Index anrows, ancols ;
123 OK (GrB_Matrix_nrows (&anrows, A)) ;
124 OK (GrB_Matrix_ncols (&ancols, A)) ;
125
126 // determine the size of C
127 GrB_Index cnrows = (A_transpose) ? ancols : anrows ;
128 GrB_Index cncols = (A_transpose) ? anrows : ancols ;
129
130 // use the ztype of the op as the type of C
131 OK (GxB_UnaryOp_ztype (&ctype, op)) ;
132
133 // create the matrix C and set its format and sparsity
134 fmt = gb_get_format (cnrows, cncols, A, NULL, fmt) ;
135 sparsity = gb_get_sparsity (A, NULL, sparsity) ;
136 C = gb_new (ctype, cnrows, cncols, fmt, sparsity) ;
137 }
138
139 //--------------------------------------------------------------------------
140 // compute C<M> += f(A)
141 //--------------------------------------------------------------------------
142
143 OK1 (C, GrB_Matrix_apply (C, M, accum, op, A, desc)) ;
144
145 //--------------------------------------------------------------------------
146 // free shallow copies
147 //--------------------------------------------------------------------------
148
149 OK (GrB_Matrix_free (&M)) ;
150 OK (GrB_Matrix_free (&A)) ;
151 OK (GrB_Descriptor_free (&desc)) ;
152
153 //--------------------------------------------------------------------------
154 // export the output matrix C back to MATLAB
155 //--------------------------------------------------------------------------
156
157 pargout [0] = gb_export (&C, kind) ;
158 pargout [1] = mxCreateDoubleScalar (kind) ;
159 GB_WRAPUP ;
160 }
161
162