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