1 //------------------------------------------------------------------------------
2 // GB_split_bitmap: split a bitmap 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_ALL         \
11     GB_Matrix_free (&C) ;
12 
13 #include "GB_split.h"
14 
GB_split_bitmap(GrB_Matrix * Tiles,const GrB_Index m,const GrB_Index n,const int64_t * restrict Tile_rows,const int64_t * restrict Tile_cols,const GrB_Matrix A,GB_Context Context)15 GrB_Info GB_split_bitmap            // split a bitmap matrix
16 (
17     GrB_Matrix *Tiles,              // 2D row-major array of size m-by-n
18     const GrB_Index m,
19     const GrB_Index n,
20     const int64_t *restrict Tile_rows,  // size m+1
21     const int64_t *restrict Tile_cols,  // size n+1
22     const GrB_Matrix A,             // input matrix
23     GB_Context Context
24 )
25 {
26 
27     //--------------------------------------------------------------------------
28     // get inputs
29     //--------------------------------------------------------------------------
30 
31     GrB_Info info ;
32     ASSERT (GB_IS_BITMAP (A)) ;
33     GrB_Matrix C = NULL ;
34 
35     int sparsity_control = A->sparsity ;
36     float hyper_switch = A->hyper_switch ;
37     bool csc = A->is_csc ;
38     GrB_Type atype = A->type ;
39     int64_t avlen = A->vlen ;
40     int64_t avdim = A->vdim ;
41     size_t asize = atype->size ;
42     const int8_t *restrict Ab = A->b ;
43 
44     GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
45 
46     int64_t nouter = csc ? n : m ;
47     int64_t ninner = csc ? m : n ;
48 
49     const int64_t *Tile_vdim = csc ? Tile_cols : Tile_rows ;
50     const int64_t *Tile_vlen = csc ? Tile_rows : Tile_cols ;
51 
52     //--------------------------------------------------------------------------
53     // split A into tiles
54     //--------------------------------------------------------------------------
55 
56     for (int64_t outer = 0 ; outer < nouter ; outer++)
57     {
58 
59         const int64_t avstart = Tile_vdim [outer] ;
60         const int64_t avend   = Tile_vdim [outer+1] ;
61 
62         for (int64_t inner = 0 ; inner < ninner ; inner++)
63         {
64 
65             //------------------------------------------------------------------
66             // allocate the tile C
67             //------------------------------------------------------------------
68 
69             // The tile appears in vectors avstart:avend-1 of A, and indices
70             // aistart:aiend-1.
71 
72             const int64_t aistart = Tile_vlen [inner] ;
73             const int64_t aiend   = Tile_vlen [inner+1] ;
74             const int64_t cvdim = avend - avstart ;
75             const int64_t cvlen = aiend - aistart ;
76             int64_t cnzmax = cvdim * cvlen ;
77 
78             C = NULL ;
79             GB_OK (GB_new_bix (&C, false,      // new header
80                 atype, cvlen, cvdim, GB_Ap_null, csc, GxB_BITMAP, false,
81                 hyper_switch, 0, cnzmax, true, Context)) ;
82             int8_t *restrict Cb = C->b ;
83             C->sparsity = sparsity_control ;
84             C->hyper_switch = hyper_switch ;
85             int C_nthreads = GB_nthreads (cnzmax, chunk, nthreads_max) ;
86             int64_t cnz = 0 ;
87 
88             //------------------------------------------------------------------
89             // copy the tile from A into C
90             //------------------------------------------------------------------
91 
92             bool done = false ;
93 
94             #ifndef GBCOMPACT
95             {
96                 // no typecasting needed
97                 switch (asize)
98                 {
99                     #define GB_COPY(pC,pA) Cx [pC] = Ax [pA]
100 
101                     case 1 : // uint8, int8, bool, or 1-byte user-defined
102                         #define GB_CTYPE uint8_t
103                         #include "GB_split_bitmap_template.c"
104                         break ;
105 
106                     case 2 : // uint16, int16, or 2-byte user-defined
107                         #define GB_CTYPE uint16_t
108                         #include "GB_split_bitmap_template.c"
109                         break ;
110 
111                     case 4 : // uint32, int32, float, or 4-byte user-defined
112                         #define GB_CTYPE uint32_t
113                         #include "GB_split_bitmap_template.c"
114                         break ;
115 
116                     case 8 : // uint64, int64, double, float complex,
117                              // or 8-byte user defined
118                         #define GB_CTYPE uint64_t
119                         #include "GB_split_bitmap_template.c"
120                         break ;
121 
122                     case 16 : // double complex or 16-byte user-defined
123                         #define GB_CTYPE uint64_t
124                         #undef  GB_COPY
125                         #define GB_COPY(pC,pA)                      \
126                             Cx [2*pC  ] = Ax [2*pA  ] ;             \
127                             Cx [2*pC+1] = Ax [2*pA+1] ;
128                         #include "GB_split_bitmap_template.c"
129                         break ;
130 
131                     default:;
132                 }
133             }
134             #endif
135 
136             if (!done)
137             {
138                 // user-defined types
139                 #define GB_CTYPE GB_void
140                 #undef  GB_COPY
141                 #define GB_COPY(pC,pA)  \
142                     memcpy (Cx + (pC)*asize, Ax + (pA)*asize, asize) ;
143                 #include "GB_split_bitmap_template.c"
144             }
145 
146             //------------------------------------------------------------------
147             // conform the tile and save it in the Tiles array
148             //------------------------------------------------------------------
149 
150             C->magic = GB_MAGIC ;
151             C->nvals = cnz ;
152             ASSERT_MATRIX_OK (C, "C for GB_split", GB0) ;
153             GB_OK (GB_conform (C, Context)) ;
154             if (csc)
155             {
156                 GB_TILE (Tiles, inner, outer) = C ;
157             }
158             else
159             {
160                 GB_TILE (Tiles, outer, inner) = C ;
161             }
162             C = NULL ;
163         }
164     }
165 
166     return (GrB_SUCCESS) ;
167 }
168 
169