1 //------------------------------------------------------------------------------
2 // GB_split: split a matrix into an array of matrices
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 #define GB_FREE_WORK                        \
11     GB_WERK_POP (Tile_cols, int64_t) ;      \
12     GB_WERK_POP (Tile_rows, int64_t) ;
13 
14 #define GB_FREE_ALL                         \
15     GB_FREE_WORK ;                          \
16     for (int64_t k = 0 ; k < m*n ; k++)     \
17     {                                       \
18         GB_Matrix_free (&(Tiles [k])) ;     \
19     }
20 
21 #include "GB_split.h"
22 
GB_split(GrB_Matrix * Tiles,const GrB_Index m,const GrB_Index n,const GrB_Index * Tile_nrows,const GrB_Index * Tile_ncols,const GrB_Matrix A,GB_Context Context)23 GrB_Info GB_split                   // split a matrix
24 (
25     GrB_Matrix *Tiles,              // 2D row-major array of size m-by-n
26     const GrB_Index m,
27     const GrB_Index n,
28     const GrB_Index *Tile_nrows,    // array of size m
29     const GrB_Index *Tile_ncols,    // array of size n
30     const GrB_Matrix A,             // input matrix
31     GB_Context Context
32 )
33 {
34 
35     //--------------------------------------------------------------------------
36     // allocate workspace
37     //--------------------------------------------------------------------------
38 
39     // set all Tiles to NULL
40     GrB_Info info ;
41     ASSERT (Tiles != NULL) ;
42     memset (Tiles, 0, m * n * sizeof (GrB_Matrix)) ;
43 
44     GB_WERK_DECLARE (Tile_rows, int64_t) ;
45     GB_WERK_DECLARE (Tile_cols, int64_t) ;
46     GB_WERK_PUSH (Tile_rows, m+1, int64_t) ;
47     GB_WERK_PUSH (Tile_cols, n+1, int64_t) ;
48     if (Tile_rows == NULL || Tile_cols == NULL)
49     {
50         // out of memory
51         GB_FREE_ALL ;
52         return (GrB_OUT_OF_MEMORY) ;
53     }
54 
55     //--------------------------------------------------------------------------
56     // check inputs
57     //--------------------------------------------------------------------------
58 
59     ASSERT_MATRIX_OK (A, "A input for GB_concat", GB0) ;
60     GB_MATRIX_WAIT (A) ;
61 
62     //--------------------------------------------------------------------------
63     // check the sizes of each tile
64     //--------------------------------------------------------------------------
65 
66     int64_t nrows = GB_NROWS (A) ;
67     int64_t ncols = GB_NCOLS (A) ;
68 
69     #define offset (GB_Global_print_one_based_get ( ) ? 1 : 0)
70 
71     int64_t s = 0 ;
72     for (int64_t i = 0 ; i < m ; i++)
73     {
74         GrB_Index tile_nrows = Tile_nrows [i] ;     // # of rows in Tile{i,:}
75         if (tile_nrows < 0 || tile_nrows > nrows)
76         {
77             return (GrB_DIMENSION_MISMATCH) ;
78         }
79         Tile_rows [i] = s ;                         // cumulative sum
80         s += tile_nrows ;
81     }
82     if (s != nrows)
83     {
84         return (GrB_DIMENSION_MISMATCH) ;
85     }
86     Tile_rows [m] = nrows ;
87 
88     s = 0 ;
89     for (int64_t j = 0 ; j < n ; j++)
90     {
91         GrB_Index tile_ncols = Tile_ncols [j] ;     // # of cols in Tile{:,j}
92         if (tile_ncols < 0 || tile_ncols > ncols)
93         {
94             return (GrB_DIMENSION_MISMATCH) ;
95         }
96         Tile_cols [j] = s ;                         // cumulative sum
97         s += tile_ncols ;
98     }
99     if (s != ncols)
100     {
101         return (GrB_DIMENSION_MISMATCH) ;
102     }
103     Tile_cols [n] = ncols ;
104 
105     //--------------------------------------------------------------------------
106     // Tiles = split (A)
107     //--------------------------------------------------------------------------
108 
109     if (GB_is_dense (A))
110     {
111         // A is full
112         GB_OK (GB_split_full (Tiles, m, n, Tile_rows, Tile_cols, A, Context)) ;
113     }
114     else if (GB_IS_BITMAP (A))
115     {
116         // A is bitmap
117         GB_OK (GB_split_bitmap (Tiles, m, n, Tile_rows, Tile_cols, A, Context));
118     }
119     else
120     {
121         // A is sparse/hypersparse, each Tile has the same sparsity as A
122         GB_OK (GB_split_sparse (Tiles, m, n, Tile_rows, Tile_cols, A, Context));
123     }
124 
125     //--------------------------------------------------------------------------
126     // free workspace and return result
127     //--------------------------------------------------------------------------
128 
129     GB_FREE_WORK ;
130     return (GrB_SUCCESS) ;
131 }
132 
133