1 //------------------------------------------------------------------------------
2 // GB_extract: C<M> = accum(C,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 // Not user-callable. Implements the user-callable GrB_*_extract functions.
11
12 // C<M> = accum (C, A (Rows,Cols)) or
13
14 // C<M> = accum (C, AT(Rows,Cols)) where AT = A'
15
16 // equivalently:
17
18 // C<M> = accum (C, A(Rows,Cols) )
19
20 // C<M> = accum (C, A(Cols,Rows)')
21
22 #include "GB_extract.h"
23 #include "GB_subref.h"
24 #include "GB_accum_mask.h"
25
26 #define GB_FREE_ALL ;
27
GB_extract(GrB_Matrix C,const bool C_replace,const GrB_Matrix M,const bool Mask_comp,const bool Mask_struct,const GrB_BinaryOp accum,const GrB_Matrix A,const bool A_transpose,const GrB_Index * Rows,const GrB_Index nRows_in,const GrB_Index * Cols,const GrB_Index nCols_in,GB_Context Context)28 GrB_Info GB_extract // C<M> = accum (C, A(I,J))
29 (
30 GrB_Matrix C, // input/output matrix for results
31 const bool C_replace, // C matrix descriptor
32 const GrB_Matrix M, // optional mask for C, unused if NULL
33 const bool Mask_comp, // mask descriptor
34 const bool Mask_struct, // if true, use the only structure of M
35 const GrB_BinaryOp accum, // optional accum for Z=accum(C,T)
36 const GrB_Matrix A, // input matrix
37 const bool A_transpose, // A matrix descriptor
38 const GrB_Index *Rows, // row indices
39 const GrB_Index nRows_in, // number of row indices
40 const GrB_Index *Cols, // column indices
41 const GrB_Index nCols_in, // number of column indices
42 GB_Context Context
43 )
44 {
45
46 //--------------------------------------------------------------------------
47 // check inputs
48 //--------------------------------------------------------------------------
49
50 // C may be aliased with M and/or A
51
52 GrB_Info info ;
53 GB_RETURN_IF_NULL (Rows) ;
54 GB_RETURN_IF_NULL (Cols) ;
55 GB_RETURN_IF_FAULTY_OR_POSITIONAL (accum) ;
56
57 ASSERT_MATRIX_OK (C, "C input for GB_Matrix_extract", GB0) ;
58 ASSERT_MATRIX_OK_OR_NULL (M, "M for GB_Matrix_extract", GB0) ;
59 ASSERT_BINARYOP_OK_OR_NULL (accum, "accum for GB_Matrix_extract", GB0) ;
60 ASSERT_MATRIX_OK (A, "A input for GB_Matrix_extract", GB0) ;
61
62 // check domains and dimensions for C<M> = accum (C,T)
63 GB_OK (GB_compatible (C->type, C, M, Mask_struct, accum, A->type,
64 Context)) ;
65
66 // check the dimensions of C
67 int64_t cnrows = GB_NROWS (C) ;
68 int64_t cncols = GB_NCOLS (C) ;
69
70 int64_t nRows, nCols, RowColon [3], ColColon [3] ;
71 int rkind, ckind ;
72
73 if (!A_transpose)
74 {
75 // T = A(Rows,Cols)
76 GB_ijlength (Rows, nRows_in, GB_NROWS (A), &nRows, &rkind, RowColon) ;
77 GB_ijlength (Cols, nCols_in, GB_NCOLS (A), &nCols, &ckind, ColColon) ;
78 }
79 else
80 {
81 // T = A(Cols,Rows)
82 GB_ijlength (Rows, nRows_in, GB_NCOLS (A), &nRows, &rkind, RowColon) ;
83 GB_ijlength (Cols, nCols_in, GB_NROWS (A), &nCols, &ckind, ColColon) ;
84 }
85
86 if (cnrows != nRows || cncols != nCols)
87 {
88 GB_ERROR (GrB_DIMENSION_MISMATCH,
89 "Dimensions not compatible:\n"
90 "required size of output is " GBd "-by-" GBd "\n"
91 "but actual size output is " GBd "-by-" GBd "\n",
92 nRows, nCols, cnrows, cncols) ;
93 }
94
95 // quick return if an empty mask is complemented
96 GB_RETURN_IF_QUICK_MASK (C, C_replace, M, Mask_comp, Mask_struct) ;
97
98 // delete any lingering zombies and assemble any pending tuples
99 GB_MATRIX_WAIT (M) ; // cannot be jumbled
100 GB_MATRIX_WAIT (A) ; // cannot be jumbled
101
102 GB_BURBLE_DENSE (C, "(C %s) ") ;
103 GB_BURBLE_DENSE (M, "(M %s) ") ;
104 GB_BURBLE_DENSE (A, "(A %s) ") ;
105
106 //--------------------------------------------------------------------------
107 // handle the CSR/CSC format and transpose; T = A (I,J) or T = A (J,I)
108 //--------------------------------------------------------------------------
109
110 const GrB_Index *I, *J ;
111 int64_t ni, nj ;
112 bool T_is_csc ;
113
114 if (A->is_csc)
115 {
116 if (!A_transpose)
117 {
118 // T = A(Rows,Cols) where both A and T are in CSC format
119 I = Rows ; ni = nRows_in ; // indices into the vectors
120 J = Cols ; nj = nCols_in ; // vectors
121 T_is_csc = true ; // return T in CSC format
122 }
123 else
124 {
125 // T = A(Cols,Rows) where A is CSC and T is returned as CSR format
126 I = Cols ; ni = nCols_in ; // indices into the vectors
127 J = Rows ; nj = nRows_in ; // vectors
128 T_is_csc = false ; // return T in CSR format
129 }
130 }
131 else
132 {
133 if (!A_transpose)
134 {
135 // T = A(Rows,Cols) where both A and T are in CSR format
136 I = Cols ; ni = nCols_in ; // indices into the vectors
137 J = Rows ; nj = nRows_in ; // vectors
138 T_is_csc = false ; // return T in CSR format
139 }
140 else
141 {
142 // T = A(Cols,Rows) where A is CSR but T is returned as CSC format
143 I = Rows ; ni = nRows_in ; // indices into the vectors
144 J = Cols ; nj = nCols_in ; // vectors
145 T_is_csc = true ; // return T in CSC format
146 }
147 }
148
149 // T has T->vdim = |J|, each vector of length T->vlen = |J|, regardless of
150 // its CSR/CSC format.
151
152 // J is a list of length |J| of vectors in the range 0:A->vdim-1
153 // I is a list of length |I| of indices in the range 0:A->vlen-1
154
155 // |I| and |J| are either nRows or nCols, depending on the 4 cases above.
156
157 // T has the same hypersparsity as A.
158
159 //--------------------------------------------------------------------------
160 // T = A (I,J)
161 //--------------------------------------------------------------------------
162
163 struct GB_Matrix_opaque T_header ;
164 GrB_Matrix T = GB_clear_static_header (&T_header) ;
165 GB_OK (GB_subref (T, T_is_csc, A, I, ni, J, nj, false, Context)) ;
166 ASSERT_MATRIX_OK (T, "T extracted", GB0) ;
167 ASSERT (GB_JUMBLED_OK (T)) ;
168
169 //--------------------------------------------------------------------------
170 // C<M> = accum (C,T): accumulate the results into C via the mask M
171 //--------------------------------------------------------------------------
172
173 return (GB_accum_mask (C, M, NULL, accum, &T, C_replace, Mask_comp,
174 Mask_struct, Context)) ;
175 }
176
177