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