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