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