1 //------------------------------------------------------------------------------
2 // GB_mex_dup: copy a matrix
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 // copy and typecast a matrix
11 
12 #include "GB_mex.h"
13 
14 #define USAGE "C = GB_mex_dup (A, type, method, sparsity)"
15 
16 #define FREE_ALL                        \
17 {                                       \
18     GrB_Matrix_free_(&A) ;              \
19     GrB_Matrix_free_(&C) ;              \
20     GrB_Descriptor_free_(&desc) ;       \
21     GB_mx_put_global (true) ;           \
22 }
23 
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])24 void mexFunction
25 (
26     int nargout,
27     mxArray *pargout [ ],
28     int nargin,
29     const mxArray *pargin [ ]
30 )
31 {
32 
33     bool malloc_debug = GB_mx_get_global (true) ;
34     GrB_Matrix A = NULL, C = NULL ;
35     GrB_Descriptor desc = NULL ;
36 
37     // check inputs
38     if (nargout > 1 || nargin < 1 || nargin > 4)
39     {
40         mexErrMsgTxt ("Usage: " USAGE) ;
41     }
42 
43     #define GET_DEEP_COPY  ;
44     #define FREE_DEEP_COPY ;
45 
46     // get A (shallow copy)
47     A = GB_mx_mxArray_to_Matrix (pargin [0], "A input", false, true) ;
48     if (A == NULL)
49     {
50         FREE_ALL ;
51         mexErrMsgTxt ("A failed") ;
52     }
53 
54     // get ctype of output matrix
55     GrB_Type ctype = GB_mx_string_to_Type (PARGIN (1), A->type) ;
56 
57     // get method
58     int GET_SCALAR (2, int, method, 0) ;
59 
60     // get sparsity
61     int GET_SCALAR (3, int, sparsity, GxB_DEFAULT) ;
62 
63     if (ctype == A->type)
64     {
65         // copy C with the same type as A, with default sparsity
66         if (method == 0 && sparsity == GxB_DEFAULT)
67         {
68             METHOD (GrB_Matrix_dup (&C, A)) ;
69         }
70         else
71         {
72             // try another method, just for testing (see User Guide)
73 
74             // C = create an exact copy of A, just like GrB_Matrix_dup
75             GrB_Type type ;
76             GrB_Index nrows, ncols ;
77 
78             #undef GET_DEEP_COPY
79             #undef FREE_DEEP_COPY
80 
81             #define GET_DEEP_COPY                               \
82             {                                                   \
83                 GxB_Matrix_type (&type, A) ;                    \
84                 GrB_Matrix_nrows (&nrows, A) ;                  \
85                 GrB_Matrix_ncols (&ncols, A) ;                  \
86                 GrB_Matrix_new (&C, type, nrows, ncols) ;       \
87                 GrB_Descriptor_new (&desc) ;                    \
88                 if (sparsity != GxB_DEFAULT)                    \
89                 {                                               \
90                     GxB_Matrix_Option_set (C, GxB_SPARSITY_CONTROL, sparsity) ;\
91                 }                                               \
92                 GxB_Desc_set (desc, GrB_INP0, GrB_TRAN) ;       \
93             }
94             #define FREE_DEEP_COPY                              \
95             {                                                   \
96                 GrB_Matrix_free_(&C) ;                          \
97                 GrB_Descriptor_free_(&desc) ;                   \
98             }
99 
100             GET_DEEP_COPY ;
101 
102             if (method == 1)
103             {
104                 // C = A using GrB_transpose with a desc.inp0 = transpose
105                 METHOD (GrB_transpose (C, NULL, NULL, A, desc)) ;
106             }
107             else
108             {
109                 // C = A using GrB_assign
110                 METHOD (GrB_assign (C, NULL, NULL, A,
111                     GrB_ALL, nrows, GrB_ALL, ncols, NULL)) ;
112             }
113 
114             #undef GET_DEEP_COPY
115             #undef FREE_DEEP_COPY
116 
117         }
118     }
119     else
120     {
121         // typecast
122         if (A->type == Complex && Complex != GxB_FC64)
123         {
124             A->type = GxB_FC64 ;
125         }
126 
127         // C = (ctype) A
128         GrB_Index nrows, ncols ;
129 
130         #define GET_DEEP_COPY                               \
131         {                                                   \
132             GrB_Matrix_nrows (&nrows, A) ;                  \
133             GrB_Matrix_ncols (&ncols, A) ;                  \
134             GrB_Matrix_new (&C, ctype, nrows, ncols) ;      \
135             GrB_Descriptor_new (&desc) ;                    \
136             if (sparsity != GxB_DEFAULT)                    \
137             {                                               \
138                 GxB_Matrix_Option_set (C, GxB_SPARSITY_CONTROL, sparsity) ; \
139             }                                               \
140             GxB_Desc_set (desc, GrB_INP0, GrB_TRAN) ;       \
141         }
142         #define FREE_DEEP_COPY                              \
143         {                                                   \
144             GrB_Matrix_free_(&C) ;                          \
145             GrB_Descriptor_free_(&desc) ;                   \
146         }
147 
148         GET_DEEP_COPY ;
149 
150         if (method == 1)
151         {
152             // C = A using GrB_transpose with a desc.inp0 = transpose
153             METHOD (GrB_transpose (C, NULL, NULL, A, desc)) ;
154         }
155         else
156         {
157             // C = A using GrB_assign
158             METHOD (GrB_assign (C, NULL, NULL, A,
159                 GrB_ALL, nrows, GrB_ALL, ncols, NULL)) ;
160         }
161 
162         #undef GET_DEEP_COPY
163         #undef FREE_DEEP_COPY
164     }
165 
166     // return C to MATLAB as a struct and free the GraphBLAS C
167     pargout [0] = GB_mx_Matrix_to_mxArray (&C, "C output", true) ;
168 
169     FREE_ALL ;
170 }
171 
172