1 //------------------------------------------------------------------------------
2 // GB_mex_split: C = split (Tiles)
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 #include "GB_mex.h"
11 
12 #define USAGE "C = GB_mex_split (A, ms, ns)"
13 
14 #define FREE_ALL                        \
15 {                                       \
16     GrB_Matrix_free_(&A) ;              \
17     mxFree (Tiles) ;                    \
18     GB_mx_put_global (true) ;           \
19 }
20 
21 #define OK(method)                      \
22 {                                       \
23     info = method ;                     \
24     if (info != GrB_SUCCESS)            \
25     {                                   \
26         printf ("%d at %d\n", info, __LINE__) ;  \
27         mexErrMsgTxt ("failed") ;       \
28     }                                   \
29 }
30 
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])31 void mexFunction
32 (
33     int nargout,
34     mxArray *pargout [ ],
35     int nargin,
36     const mxArray *pargin [ ]
37 )
38 {
39 
40     GrB_Info info ;
41     bool malloc_debug = GB_mx_get_global (true) ;
42     GrB_Matrix A = NULL ;
43     GrB_Matrix *Tiles = NULL ;
44 
45     // check inputs
46     if (nargout > 1 || nargin != 3)
47     {
48         mexErrMsgTxt ("Usage: " USAGE) ;
49     }
50 
51     // get A (shallow copy)
52     A = GB_mx_mxArray_to_Matrix (pargin [0], "A input", false, true) ;
53     if (A == NULL)
54     {
55         FREE_ALL ;
56         mexErrMsgTxt ("A failed") ;
57     }
58 
59     // get ms (deep copy)
60     if (mxGetClassID (pargin [1]) != mxDOUBLE_CLASS)
61     {
62         mexErrMsgTxt ("ms must be double") ;
63     }
64     double *ms_double = mxGetDoubles (pargin [1]) ;
65     GrB_Index m = mxGetNumberOfElements (pargin [1]) ;
66     GrB_Index *Tile_nrows = mxMalloc (m * sizeof (GrB_Index)) ;
67     for (int64_t k = 0 ; k < m ; k++)
68     {
69         Tile_nrows [k] = (GrB_Index) (ms_double [k]) ;
70     }
71 
72     // get ns (deep copy)
73     if (mxGetClassID (pargin [2]) != mxDOUBLE_CLASS)
74     {
75         mexErrMsgTxt ("ns must be double") ;
76     }
77     double *ns_double = mxGetDoubles (pargin [2]) ;
78     GrB_Index n = mxGetNumberOfElements (pargin [2]) ;
79     GrB_Index *Tile_ncols = mxMalloc (n * sizeof (GrB_Index)) ;
80     for (int64_t k = 0 ; k < n ; k++)
81     {
82         Tile_ncols [k] = (GrB_Index) (ns_double [k]) ;
83     }
84 
85     // create Tiles
86     Tiles = mxCalloc (m * n, sizeof (GrB_Matrix)) ;
87 
88     // construct the empty Tiles array
89     #define GET_DEEP_COPY                                   \
90         memset (Tiles, 0, m * n * sizeof (GrB_Matrix)) ;
91     #define FREE_DEEP_COPY                                  \
92         for (int64_t k = 0 ; k < m*n ; k++)                 \
93         {                                                   \
94             GrB_Matrix_free (&(Tiles [k])) ;                \
95         }
96 
97     // Tiles = split (A, ms, ns)
98     METHOD (GxB_Matrix_split (Tiles, m, n, Tile_nrows, Tile_ncols, A, NULL)) ;
99 
100     // return C to MATLAB as a cell array and free the GraphBLAS tiles
101     pargout [0] = mxCreateCellMatrix (m, n) ;
102     for (int64_t j = 0 ; j < n ; j++)
103     {
104         for (int64_t i = 0 ; i < m ; i++)
105         {
106             mxArray *T = GB_mx_Matrix_to_mxArray (&(Tiles [i*n+j]),
107                 "Tile output", true) ;
108             mxSetCell (pargout [0], i+j*m, T) ;
109         }
110     }
111     FREE_ALL ;
112 }
113 
114