1 //------------------------------------------------------------------------------
2 // GB_dense_subassign_25: C(:,:)<M,s> = A; C empty, A dense, M structural
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 // Method 25: C(:,:)<M,s> = A ; C is empty, M structural, A dense
11
12 // M: present
13 // Mask_comp: false
14 // Mask_struct: true
15 // C_replace: effectively false (not relevant since C is empty)
16 // accum: NULL
17 // A: matrix
18 // S: none
19
20 // C and M are sparse or hypersparse.
21 // A can have any sparsity structure, even bitmap. M may be jumbled.
22 // If so, C is constructed as jumbled. C is reconstructed with the same
23 // structure as M and can have any sparsity structure on input. The only
24 // constraint is nnz(C) is zero on input. A must be dense with no pending
25 // work, or bitmap.
26
27 #include "GB_subassign_methods.h"
28 #include "GB_dense.h"
29 #ifndef GBCOMPACT
30 #include "GB_type__include.h"
31 #endif
32
33 #undef GB_FREE_ALL
34 #define GB_FREE_ALL \
35 { \
36 GB_WERK_POP (M_ek_slicing, int64_t) ; \
37 }
38
GB_dense_subassign_25(GrB_Matrix C,const GrB_Matrix M,const GrB_Matrix A,GB_Context Context)39 GrB_Info GB_dense_subassign_25
40 (
41 GrB_Matrix C,
42 // input:
43 const GrB_Matrix M,
44 const GrB_Matrix A,
45 GB_Context Context
46 )
47 {
48
49 //--------------------------------------------------------------------------
50 // check inputs
51 //--------------------------------------------------------------------------
52
53 ASSERT (!GB_IS_BITMAP (M)) ; ASSERT (!GB_IS_FULL (M)) ;
54 ASSERT (!GB_aliased (C, M)) ; // NO ALIAS of C==M
55 ASSERT (!GB_aliased (C, A)) ; // NO ALIAS of C==A
56
57 //--------------------------------------------------------------------------
58 // get inputs
59 //--------------------------------------------------------------------------
60
61 GrB_Info info ;
62 ASSERT_MATRIX_OK (C, "C for subassign method_25", GB0) ;
63 ASSERT (GB_NNZ (C) == 0) ;
64 ASSERT (!GB_ZOMBIES (C)) ;
65 ASSERT (!GB_JUMBLED (C)) ;
66 ASSERT (!GB_PENDING (C)) ;
67
68 ASSERT_MATRIX_OK (M, "M for subassign method_25", GB0) ;
69 ASSERT (!GB_ZOMBIES (M)) ;
70 ASSERT (GB_JUMBLED_OK (M)) ;
71 ASSERT (!GB_PENDING (M)) ;
72
73 ASSERT_MATRIX_OK (A, "A for subassign method_25", GB0) ;
74 ASSERT (GB_as_if_full (A) || GB_IS_BITMAP (A)) ;
75
76 const GB_Type_code ccode = C->type->code ;
77
78 //--------------------------------------------------------------------------
79 // Method 25: C(:,:)<M> = A ; C is empty, A is dense, M is structural
80 //--------------------------------------------------------------------------
81
82 // Time: Optimal: the method must iterate over all entries in M,
83 // and the time is O(nnz(M)). This is also the size of C.
84
85 //--------------------------------------------------------------------------
86 // Parallel: slice M into equal-sized chunks
87 //--------------------------------------------------------------------------
88
89 GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
90
91 //--------------------------------------------------------------------------
92 // slice the entries for each task
93 //--------------------------------------------------------------------------
94
95 GB_WERK_DECLARE (M_ek_slicing, int64_t) ;
96 int M_nthreads, M_ntasks ;
97 GB_SLICE_MATRIX (M, 8, chunk) ;
98
99 //--------------------------------------------------------------------------
100 // allocate C and create its pattern
101 //--------------------------------------------------------------------------
102
103 // clear prior content and then create a copy of the pattern of M. Keep
104 // the same type and CSR/CSC for C. Allocate the values of C but do not
105 // initialize them.
106
107 bool C_is_csc = C->is_csc ;
108 GB_phbix_free (C) ;
109 GB_OK (GB_dup2 (&C, M, false, C->type, Context)) ; // reuse old header
110 C->is_csc = C_is_csc ;
111
112 //--------------------------------------------------------------------------
113 // C<M> = A for built-in types
114 //--------------------------------------------------------------------------
115
116 bool done = false ;
117
118 #ifndef GBCOMPACT
119
120 //----------------------------------------------------------------------
121 // define the worker for the switch factory
122 //----------------------------------------------------------------------
123
124 #define GB_Cdense_25(cname) GB (_Cdense_25_ ## cname)
125
126 #define GB_WORKER(cname) \
127 { \
128 info = GB_Cdense_25(cname) (C, M, A, \
129 M_ek_slicing, M_ntasks, M_nthreads) ; \
130 done = (info != GrB_NO_VALUE) ; \
131 } \
132 break ;
133
134 //----------------------------------------------------------------------
135 // launch the switch factory
136 //----------------------------------------------------------------------
137
138 if (C->type == A->type && ccode < GB_UDT_code)
139 {
140 // C<M> = A
141 switch (ccode)
142 {
143 case GB_BOOL_code : GB_WORKER (_bool )
144 case GB_INT8_code : GB_WORKER (_int8 )
145 case GB_INT16_code : GB_WORKER (_int16 )
146 case GB_INT32_code : GB_WORKER (_int32 )
147 case GB_INT64_code : GB_WORKER (_int64 )
148 case GB_UINT8_code : GB_WORKER (_uint8 )
149 case GB_UINT16_code : GB_WORKER (_uint16)
150 case GB_UINT32_code : GB_WORKER (_uint32)
151 case GB_UINT64_code : GB_WORKER (_uint64)
152 case GB_FP32_code : GB_WORKER (_fp32 )
153 case GB_FP64_code : GB_WORKER (_fp64 )
154 case GB_FC32_code : GB_WORKER (_fc32 )
155 case GB_FC64_code : GB_WORKER (_fc64 )
156 default: ;
157 }
158 }
159
160 #endif
161
162 //--------------------------------------------------------------------------
163 // C<M> = A for user-defined types, and typecasting
164 //--------------------------------------------------------------------------
165
166 if (!done)
167 {
168
169 //----------------------------------------------------------------------
170 // get operators, functions, workspace, contents of A and C
171 //----------------------------------------------------------------------
172
173 GB_BURBLE_MATRIX (A, "(generic C(:,:)<M,struct>=A assign, method 25) ");
174
175 const size_t csize = C->type->size ;
176 const size_t asize = A->type->size ;
177 const GB_Type_code acode = A->type->code ;
178 GB_cast_function cast_A_to_C = GB_cast_factory (ccode, acode) ;
179
180 // Cx [pC] = (ctype) Ax [pA]
181 #define GB_COPY_A_TO_C(Cx,pC,Ax,pA) \
182 cast_A_to_C (Cx + ((pC)*csize), Ax + ((pA)*asize), asize)
183
184 #define GB_CTYPE GB_void
185 #define GB_ATYPE GB_void
186
187 // no vectorization
188 #define GB_PRAGMA_SIMD_VECTORIZE ;
189
190 #include "GB_dense_subassign_25_template.c"
191 }
192
193 //--------------------------------------------------------------------------
194 // free workspace and return result
195 //--------------------------------------------------------------------------
196
197 GB_FREE_ALL ;
198 ASSERT_MATRIX_OK (C, "C output for subassign method_25", GB0) ;
199 ASSERT (GB_ZOMBIES_OK (C)) ;
200 ASSERT (GB_JUMBLED_OK (C)) ;
201 ASSERT (!GB_PENDING (C)) ;
202 return (GrB_SUCCESS) ;
203 }
204
205