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