1 //------------------------------------------------------------------------------
2 // GB_dense_subassign_05d: C(:,:)<M> = scalar where C is dense
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 05d: C(:,:)<M> = scalar ; no S, C is dense
11
12 // M: present
13 // Mask_comp: false
14 // C_replace: false
15 // accum: NULL
16 // A: scalar
17 // S: none
18
19 // C can have any sparsity structure, but it must be entirely dense with
20 // all entries present.
21
22 #include "GB_subassign_methods.h"
23 #include "GB_dense.h"
24 #include "GB_unused.h"
25 #ifndef GBCOMPACT
26 #include "GB_type__include.h"
27 #endif
28
29 #undef GB_FREE_WORK
30 #define GB_FREE_WORK \
31 { \
32 GB_WERK_POP (M_ek_slicing, int64_t) ; \
33 }
34
35 #undef GB_FREE_ALL
36 #define GB_FREE_ALL GB_FREE_WORK
37
GB_dense_subassign_05d(GrB_Matrix C,const GrB_Matrix M,const bool Mask_struct,const void * scalar,const GrB_Type atype,GB_Context Context)38 GrB_Info GB_dense_subassign_05d
39 (
40 GrB_Matrix C,
41 // input:
42 const GrB_Matrix M,
43 const bool Mask_struct,
44 const void *scalar,
45 const GrB_Type atype,
46 GB_Context Context
47 )
48 {
49
50 //--------------------------------------------------------------------------
51 // check inputs
52 //--------------------------------------------------------------------------
53
54 ASSERT (!GB_aliased (C, M)) ; // NO ALIAS of C==M
55
56 //--------------------------------------------------------------------------
57 // get inputs
58 //--------------------------------------------------------------------------
59
60 GrB_Info info ;
61 GB_WERK_DECLARE (M_ek_slicing, int64_t) ;
62
63 ASSERT_MATRIX_OK (C, "C for subassign method_05d", GB0) ;
64 ASSERT (!GB_ZOMBIES (C)) ;
65 ASSERT (!GB_JUMBLED (C)) ;
66 ASSERT (!GB_PENDING (C)) ;
67 ASSERT (GB_is_dense (C)) ;
68
69 ASSERT_MATRIX_OK (M, "M for subassign method_05d", GB0) ;
70 ASSERT (!GB_ZOMBIES (M)) ;
71 ASSERT (GB_JUMBLED_OK (M)) ;
72 ASSERT (!GB_PENDING (M)) ;
73
74 const GB_Type_code ccode = C->type->code ;
75 const size_t csize = C->type->size ;
76 GB_GET_SCALAR ;
77
78 GB_ENSURE_FULL (C) ; // convert C to full
79
80 //--------------------------------------------------------------------------
81 // Method 05d: C(:,:)<M> = scalar ; no S; C is dense
82 //--------------------------------------------------------------------------
83
84 // Time: Optimal: the method must iterate over all entries in M,
85 // and the time is O(nnz(M)).
86
87 //--------------------------------------------------------------------------
88 // Parallel: slice M into equal-sized chunks
89 //--------------------------------------------------------------------------
90
91 GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
92
93 //--------------------------------------------------------------------------
94 // slice the entries for each task
95 //--------------------------------------------------------------------------
96
97 int M_ntasks, M_nthreads ;
98 GB_SLICE_MATRIX (M, 8, chunk) ;
99
100 //--------------------------------------------------------------------------
101 // C<M> = x for built-in types
102 //--------------------------------------------------------------------------
103
104 bool done = false ;
105
106 #ifndef GBCOMPACT
107
108 //----------------------------------------------------------------------
109 // define the worker for the switch factory
110 //----------------------------------------------------------------------
111
112 #define GB_Cdense_05d(cname) GB (_Cdense_05d_ ## cname)
113
114 #define GB_WORKER(cname) \
115 { \
116 info = GB_Cdense_05d(cname) (C, M, Mask_struct, cwork, \
117 M_ek_slicing, M_ntasks, M_nthreads) ; \
118 done = (info != GrB_NO_VALUE) ; \
119 } \
120 break ;
121
122 //----------------------------------------------------------------------
123 // launch the switch factory
124 //----------------------------------------------------------------------
125
126 // C<M> = x
127 switch (ccode)
128 {
129 case GB_BOOL_code : GB_WORKER (_bool )
130 case GB_INT8_code : GB_WORKER (_int8 )
131 case GB_INT16_code : GB_WORKER (_int16 )
132 case GB_INT32_code : GB_WORKER (_int32 )
133 case GB_INT64_code : GB_WORKER (_int64 )
134 case GB_UINT8_code : GB_WORKER (_uint8 )
135 case GB_UINT16_code : GB_WORKER (_uint16)
136 case GB_UINT32_code : GB_WORKER (_uint32)
137 case GB_UINT64_code : GB_WORKER (_uint64)
138 case GB_FP32_code : GB_WORKER (_fp32 )
139 case GB_FP64_code : GB_WORKER (_fp64 )
140 case GB_FC32_code : GB_WORKER (_fc32 )
141 case GB_FC64_code : GB_WORKER (_fc64 )
142 default: ;
143 }
144
145 #endif
146
147 //--------------------------------------------------------------------------
148 // C<M> = x for user-defined types
149 //--------------------------------------------------------------------------
150
151 if (!done)
152 {
153
154 //----------------------------------------------------------------------
155 // get operators, functions, workspace, contents of A and C
156 //----------------------------------------------------------------------
157
158 GB_BURBLE_MATRIX (M, "(generic C(:,:)<M>=x assign) ") ;
159
160 const size_t csize = C->type->size ;
161
162 // Cx [p] = scalar
163 #define GB_COPY_SCALAR_TO_C(p,x) \
164 memcpy (Cx + ((p)*csize), x, csize)
165
166 #define GB_CTYPE GB_void
167
168 // no vectorization
169 #define GB_PRAGMA_SIMD_VECTORIZE ;
170
171 #include "GB_dense_subassign_05d_template.c"
172 }
173
174 //--------------------------------------------------------------------------
175 // free workspace and return result
176 //--------------------------------------------------------------------------
177
178 GB_FREE_WORK ;
179 ASSERT_MATRIX_OK (C, "C output for subassign method_05d", GB0) ;
180 return (GrB_SUCCESS) ;
181 }
182
183