1 //------------------------------------------------------------------------------
2 // GB_mex_Matrix_extractElement: MATLAB interface for x = A(i,j)
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 // x = A (i,j), where i and j are zero-based.  If i and j arrays, then
11 // x (k) = A (i (k), j (k)) is done for all k.
12 
13 // I and J and zero-based
14 
15 #include "GB_mex.h"
16 
17 #define USAGE "x = GB_mex_Matrix_extractElement (A, I, J, xtype)"
18 
19 #define FREE_ALL                        \
20 {                                       \
21     GrB_Matrix_free_(&A) ;              \
22     GB_mx_put_global (true) ;           \
23 }
24 
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])25 void mexFunction
26 (
27     int nargout,
28     mxArray *pargout [ ],
29     int nargin,
30     const mxArray *pargin [ ]
31 )
32 {
33 
34     bool malloc_debug = GB_mx_get_global (true) ;
35     GrB_Matrix A = NULL ;
36     GB_void *Y = NULL ;
37     GrB_Index *I = NULL, ni = 0, I_range [3] ;
38     GrB_Index *J = NULL, nj = 0, J_range [3] ;
39     bool is_list ;
40 
41     // check inputs
42     if (nargout > 1 || nargin < 3 || nargin > 4)
43     {
44         mexErrMsgTxt ("Usage: " USAGE) ;
45     }
46 
47     #define GET_DEEP_COPY ;
48     #define FREE_DEEP_COPY ;
49 
50     // get A (shallow copy)
51     A = GB_mx_mxArray_to_Matrix (pargin [0], "A input", false, true) ;
52     if (A == NULL)
53     {
54         FREE_ALL ;
55         mexErrMsgTxt ("A failed") ;
56     }
57 
58     // get I
59     if (!GB_mx_mxArray_to_indices (&I, pargin [1], &ni, I_range, &is_list))
60     {
61         FREE_ALL ;
62         mexErrMsgTxt ("I failed") ;
63     }
64     if (!is_list)
65     {
66         mexErrMsgTxt ("I is invalid; must be a list") ;
67     }
68 
69     // get J
70     if (!GB_mx_mxArray_to_indices (&J, pargin [2], &nj, J_range, &is_list))
71     {
72         FREE_ALL ;
73         mexErrMsgTxt ("J failed") ;
74     }
75     if (!is_list)
76     {
77         mexErrMsgTxt ("J is invalid; must be a list") ;
78     }
79 
80     if (ni != nj)
81     {
82         FREE_ALL ;
83         mexErrMsgTxt ("I and J must be the same size") ;
84     }
85 
86     // create Y
87     GrB_Type xtype = GB_mx_string_to_Type (PARGIN (3), A->type) ;
88     pargout [0] = GB_mx_create_full (ni, 1, xtype) ;
89     Y = mxGetData (pargout [0]) ;
90 
91     size_t s = 2 * sizeof (double) ;
92 
93     GrB_Index nrows, ncols ;
94     GrB_Matrix_nrows (&nrows, A) ;
95     GrB_Matrix_ncols (&ncols, A) ;
96     bool is_scalar = GB_SCALAR_OK (A) ;
97 
98     // x = A (i,j)
99     switch (xtype->code)
100     {
101         case GB_BOOL_code   :
102 
103             for (int64_t k = 0 ; k < ni ; k++)
104             {
105                 bool *X = (bool *) Y ;
106                 if (is_scalar)
107                 {
108                     METHOD (GxB_Scalar_extractElement_BOOL_(&X [k], A)) ;
109                 }
110                 else
111                 {
112                     METHOD (GrB_Matrix_extractElement_BOOL_(&X [k], A, I [k], J [k])) ;
113                 }
114             }
115             break ;
116 
117         case GB_INT8_code   :
118 
119             for (int64_t k = 0 ; k < ni ; k++)
120             {
121                 int8_t *X = (int8_t *) Y ;
122                 if (is_scalar)
123                 {
124                     METHOD (GxB_Scalar_extractElement_INT8_(&X [k], A)) ;
125                 }
126                 else
127                 {
128                     METHOD (GrB_Matrix_extractElement_INT8_(&X [k], A, I [k], J [k])) ;
129                 }
130             }
131             break ;
132 
133         case GB_UINT8_code  :
134 
135             for (int64_t k = 0 ; k < ni ; k++)
136             {
137                 uint8_t *X = (uint8_t *) Y ;
138                 if (is_scalar)
139                 {
140                     METHOD (GxB_Scalar_extractElement_UINT8_(&X [k], A)) ;
141                 }
142                 else
143                 {
144                     METHOD (GrB_Matrix_extractElement_UINT8_(&X [k], A, I [k], J [k])) ;
145                 }
146             }
147             break ;
148 
149         case GB_INT16_code  :
150 
151             for (int64_t k = 0 ; k < ni ; k++)
152             {
153                 int16_t *X = (int16_t *) Y ;
154                 if (is_scalar)
155                 {
156                     METHOD (GxB_Scalar_extractElement_INT16_(&X [k], A)) ;
157                 }
158                 else
159                 {
160                     METHOD (GrB_Matrix_extractElement_INT16_(&X [k], A, I [k], J [k])) ;
161                 }
162             }
163             break ;
164 
165         case GB_UINT16_code :
166 
167             for (int64_t k = 0 ; k < ni ; k++)
168             {
169                 uint16_t *X = (uint16_t *) Y ;
170                 if (is_scalar)
171                 {
172                     METHOD (GxB_Scalar_extractElement_UINT16_(&X [k], A)) ;
173                 }
174                 else
175                 {
176                     METHOD (GrB_Matrix_extractElement_UINT16_(&X [k], A, I [k], J [k])) ;
177                 }
178             }
179             break ;
180 
181         case GB_INT32_code  :
182 
183             for (int64_t k = 0 ; k < ni ; k++)
184             {
185                 int32_t *X = (int32_t *) Y ;
186                 if (is_scalar)
187                 {
188                     METHOD (GxB_Scalar_extractElement_INT32_(&X [k], A)) ;
189                 }
190                 else
191                 {
192                     METHOD (GrB_Matrix_extractElement_INT32_(&X [k], A, I [k], J [k])) ;
193                 }
194             }
195             break ;
196 
197         case GB_UINT32_code :
198 
199             for (int64_t k = 0 ; k < ni ; k++)
200             {
201                 uint32_t *X = (uint32_t *) Y ;
202                 if (is_scalar)
203                 {
204                     METHOD (GxB_Scalar_extractElement_UINT32_(&X [k], A)) ;
205                 }
206                 else
207                 {
208                     METHOD (GrB_Matrix_extractElement_UINT32_(&X [k], A, I [k], J [k])) ;
209                 }
210             }
211             break ;
212 
213         case GB_INT64_code  :
214 
215             for (int64_t k = 0 ; k < ni ; k++)
216             {
217                 int64_t *X = (int64_t *) Y ;
218                 if (is_scalar)
219                 {
220                     METHOD (GxB_Scalar_extractElement_INT64_(&X [k], A)) ;
221                 }
222                 else
223                 {
224                     METHOD (GrB_Matrix_extractElement_INT64_(&X [k], A, I [k], J [k])) ;
225                 }
226             }
227             break ;
228 
229         case GB_UINT64_code :
230 
231             for (int64_t k = 0 ; k < ni ; k++)
232             {
233                 uint64_t *X = (uint64_t *) Y ;
234                 if (is_scalar)
235                 {
236                     METHOD (GxB_Scalar_extractElement_UINT64_(&X [k], A)) ;
237                 }
238                 else
239                 {
240                     METHOD (GrB_Matrix_extractElement_UINT64_(&X [k], A, I [k], J [k])) ;
241                 }
242             }
243             break ;
244 
245         case GB_FP32_code   :
246 
247             for (int64_t k = 0 ; k < ni ; k++)
248             {
249                 float *X = (float *) Y ;
250                 if (is_scalar)
251                 {
252                     METHOD (GxB_Scalar_extractElement_FP32_(&X [k], A)) ;
253                 }
254                 else
255                 {
256                     METHOD (GrB_Matrix_extractElement_FP32_(&X [k], A, I [k], J [k])) ;
257                 }
258             }
259             break ;
260 
261         case GB_FP64_code   :
262 
263             for (int64_t k = 0 ; k < ni ; k++)
264             {
265                 double *X = (double *) Y ;
266                 if (is_scalar)
267                 {
268                     METHOD (GxB_Scalar_extractElement_FP64_(&X [k], A)) ;
269                 }
270                 else
271                 {
272                     METHOD (GrB_Matrix_extractElement_FP64_(&X [k], A, I [k], J [k])) ;
273                 }
274             }
275             break;
276 
277         case GB_FC32_code   :
278 
279             for (int64_t k = 0 ; k < ni ; k++)
280             {
281                 GxB_FC32_t *X = (void *) Y ;
282                 if (is_scalar)
283                 {
284                     METHOD (GxB_Scalar_extractElement_FC32_(&X [k], A)) ;
285                 }
286                 else
287                 {
288                     METHOD (GxB_Matrix_extractElement_FC32_(&X [k], A, I [k], J [k])) ;
289                 }
290             }
291             break;
292 
293         case GB_FC64_code   :
294 
295             for (int64_t k = 0 ; k < ni ; k++)
296             {
297                 GxB_FC64_t *X = (void *) Y ;
298                 if (is_scalar)
299                 {
300                     METHOD (GxB_Scalar_extractElement_FC64_(&X [k], A)) ;
301                 }
302                 else
303                 {
304                     METHOD (GxB_Matrix_extractElement_FC64_(&X [k], A, I [k], J [k])) ;
305                 }
306             }
307             break;
308 
309         case GB_UDT_code   :
310 
311             // user-defined Complex
312             for (int64_t k = 0 ; k < ni ; k++)
313             {
314                 GxB_FC64_t *X = (void *) Y ;
315                 if (is_scalar)
316                 {
317                     METHOD (GxB_Scalar_extractElement_UDT (&X [k], A)) ;
318                 }
319                 else
320                 {
321                     METHOD (GrB_Matrix_extractElement_UDT (&X [k], A, I [k], J [k])) ;
322                 }
323             }
324             break;
325 
326         default              :
327 
328             FREE_ALL ;
329             mexErrMsgTxt ("unsupported type") ;
330     }
331 
332     FREE_ALL ;
333 
334 }
335 
336