1 //------------------------------------------------------------------------------
2 // GB_subassigner: C(I,J)<#M> = accum (C(I,J), A)
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 // Submatrix assignment: C(I,J)<M> = A, or accum (C (I,J), A), no transpose
11 
12 // All assignment operations rely on this function, including the GrB_*_assign
13 // operations in the spec, and the GxB_*_subassign operations that are a
14 // SuiteSparse:GraphBLAS extension to the spec:
15 
16 // GrB_Matrix_assign,
17 // GrB_Matrix_assign_TYPE,
18 // GrB_Vector_assign,
19 // GrB_Vector_assign_TYPE,
20 // GrB_Row_assign,
21 // GrB_Col_assign
22 
23 // GxB_Matrix_subassign,
24 // GxB_Matrix_subassign_TYPE,
25 // GxB_Vector_subassign,
26 // GxB_Vector_subassign_TYPE,
27 // GxB_Row_subassign,
28 // GxB_Col_subassign
29 
30 // This function handles the accumulator, and the mask M, and the C_replace
31 // option itself, without relying on GB_accum_mask or GB_mask.  The mask M has
32 // the same size as C(I,J) and A.  M(0,0) governs how A(0,0) is assigned
33 // into C(I[0],J[0]).  This is how GxB_subassign operates.  For GrB_assign, the
34 // mask M in this function is the SubMask, constructed via SubMask=M(I,J).
35 
36 // No transposed case is handled.  This function is also agnostic about the
37 // CSR/CSC format of C, A, and M.  The A matrix must have A->vlen == nI and
38 // A->vdim == nJ (except for scalar expansion, in which case A is NULL).  The
39 // mask M must be the same size as A, if present.
40 
41 // Any or all of the C, M, and/or A matrices may be hypersparse or standard
42 // non-hypersparse.  Some methods can operate on full and/or bitmap matrices;
43 // see GB_subassigner_method, which checks these conditions.
44 
45 // C is operated on in-place and thus cannot be aliased with the inputs A or M.
46 
47 // Since the pattern of C isn't reallocated here, and entries do not move in
48 // position, C->p, C->h, C->nvec, and C->nvec_nonempty are not modified.  C->x
49 // and C->i can be modified, but only one entry at a time.  No entries are
50 // shifted.  C->i can be changed by turning an entry into a zombie, or by
51 // bringing a zombie back to life, but no entry in C->i moves in position, and
52 // the underlying indices in C->i do not change otherwise.  C->b can be
53 // modified for a C bitmap.
54 
55 #include "GB_subassign.h"
56 #include "GB_subassign_methods.h"
57 #include "GB_dense.h"
58 #include "GB_bitmap_assign.h"
59 
60 #undef  GB_FREE_ALL
61 #define GB_FREE_ALL GB_phbix_free (C) ;
62 
GB_subassigner(GrB_Matrix C,const int subassign_method,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 GrB_Index * I,const int64_t ni,const int64_t nI,const int Ikind,const int64_t Icolon[3],const GrB_Index * J,const int64_t nj,const int64_t nJ,const int Jkind,const int64_t Jcolon[3],const bool scalar_expansion,const void * scalar,const GrB_Type atype,GB_Context Context)63 GrB_Info GB_subassigner             // C(I,J)<#M> = A or accum (C (I,J), A)
64 (
65     // input/output
66     GrB_Matrix C,                   // input/output matrix for results
67     // input
68     const int subassign_method,
69     const bool C_replace,           // C matrix descriptor
70     const GrB_Matrix M,             // optional mask for C(I,J), unused if NULL
71     const bool Mask_comp,           // mask descriptor
72     const bool Mask_struct,         // if true, use the only structure of M
73     const GrB_BinaryOp accum,       // optional accum for Z=accum(C(I,J),A)
74     const GrB_Matrix A,             // input matrix (NULL for scalar expansion)
75     const GrB_Index *I,             // list of indices
76     const int64_t   ni,             // number of indices
77     const int64_t nI,
78     const int Ikind,
79     const int64_t Icolon [3],
80     const GrB_Index *J,             // list of vector indices
81     const int64_t   nj,             // number of column indices
82     const int64_t nJ,
83     const int Jkind,
84     const int64_t Jcolon [3],
85     const bool scalar_expansion,    // if true, expand scalar to A
86     const void *scalar,             // scalar to be expanded
87     const GrB_Type atype,           // type code of scalar to expand
88     GB_Context Context
89 )
90 {
91 
92     //--------------------------------------------------------------------------
93     // check inputs
94     //--------------------------------------------------------------------------
95 
96     GrB_Info info ;
97     ASSERT_MATRIX_OK (C, "C input for subassigner", GB0) ;
98 
99     //--------------------------------------------------------------------------
100     // methods that rely on C and A being dense assume they are not jumbled
101     //--------------------------------------------------------------------------
102 
103     ASSERT (!GB_PENDING (A)) ;
104     ASSERT (!GB_ZOMBIES (A)) ;
105     if (GB_is_dense (A))
106     {
107         // methods that rely on A being dense assume A is not jumbled
108         GB_MATRIX_WAIT_IF_JUMBLED (A) ;
109     }
110 
111     if (GB_is_dense (C) && !GB_PENDING_OR_ZOMBIES (C) && !GB_IS_BITMAP (C))
112     {
113         // C is dense or full
114         GB_MATRIX_WAIT_IF_JUMBLED (C) ;
115     }
116 
117     GBURBLE ("(pending: " GBd ") ", GB_Pending_n (C)) ;
118 
119     //==========================================================================
120     // submatrix assignment C(I,J)<M> = accum (C(I,J),A): meta-algorithm
121     //==========================================================================
122 
123     // There are up to 128 combinations of options, but not all must be
124     // implemented, because they are either identical to another method
125     // (C_replace is effectively false if M=NULL and Mask_comp=false), or they
126     // are not used (the last option, whether or not S is constructed, is
127     // determined here; it is not a user input).  The first 5 options are
128     // determined by the input.  The table below has been pruned to remove
129     // combinations that are not used, or equivalent to other entries in the
130     // table.  Only 22 unique combinations of the 128 combinations are needed,
131     // with additional special cases when C(:,:) is dense.
132 
133     //      M           present or NULL
134     //      Mask_comp   true or false
135     //      Mask_struct structural or valued mask
136     //      C_replace   true or false
137     //      accum       present or NULL
138     //      A           scalar (x) or matrix (A)
139     //      S           constructed or not
140 
141     // C(I,J)<(M,comp,repl)> ( = , += ) (A, scalar), (with or without S);
142     // I and J can be anything for any of these methods (":", colon, or list).
143 
144     // See the "No work to do..." comment above:
145     // If M is not present, Mask_comp true, C_replace false: no work to do.
146     // If M is not present, Mask_comp true, C_replace true: use Method 00
147     // If M is not present, Mask_comp false:  C_replace is now false.
148 
149         //  =====================       ==============
150         //  M   cmp rpl acc A   S       method: action
151         //  =====================       ==============
152 
153         //  -   -   x   -   -   -       21:  C = x, no S, C anything
154         //  -   -   x   -   A   -       24:  C = A, no S, C and A anything
155         //  -   -   -   +   -   -       22:  C += x, no S, C dense
156         //  -   -   -   +   A   -       23:  C += A, no S, C dense
157 
158         //  -   -   -   -   -   S       01:  C(I,J) = x, with S
159         //  -   -   -   -   A   S       02:  C(I,J) = A, with S
160         //  -   -   -   +   -   S       03:  C(I,J) += x, with S
161         //  -   -   -   +   A   S       04:  C(I,J) += A, with S
162         //  -   -   r                        uses methods 01, 02, 03, 04
163         //  -   c   -                        no work to do
164         //  -   c   r           S       00:  C(I,J)<!,repl> = empty, with S
165 
166         //  M   -   -   -   -   -       05d: C<M> = x, no S, C dense
167         //  M   -   -   -   -   -       05e: C<M,s> = x, no S, C empty
168         //  M   -   -   -   -   -       05f: C<C,s> = x, no S, C == M
169         //  M   -   -   -   -   -       05:  C(I,J)<M> = x, no S
170         //  A   -   -   -   A   -       06d: C<A> = A, no S, C dense
171         //  M   -   -   -   A   -       25:  C<M,s> = A, A dense, C empty
172         //  M   -   -   -   A   -       06n: C(I,J)<M> = A, no S
173         //  M   -   -   -   A   S       06s: C(I,J)<M> = A, with S
174         //  M   -   -   +   -   -       07:  C(I,J)<M> += x, no S
175         //  M   -   -   +   A   -       08n: C(I,J)<M> += A, no S
176         //  M   -   -   +   A   -       08s: C(I,J)<M> += A, with S
177         //  M   -   r   -   -   S       09:  C(I,J)<M,repl> = x, with S
178         //  M   -   r   -   A   S       10:  C(I,J)<M,repl> = A, with S
179         //  M   -   r   +   -   S       11:  C(I,J)<M,repl> += x, with S
180         //  M   -   r   +   A   S       12:  C(I,J)<M,repl> += A, with S
181 
182         //  M   c   -   -   -   S       13:  C(I,J)<!M> = x, with S
183         //  M   c   -   -   A   S       14:  C(I,J)<!M> = A, with S
184         //  M   c   -   +   -   S       15:  C(I,J)<!M> += x, with S
185         //  M   c   -   +   A   S       16:  C(I,J)<!M> += A, with S
186         //  M   c   r   -   -   S       17:  C(I,J)<!M,repl> = x, with S
187         //  M   c   r   -   A   S       18:  C(I,J)<!M,repl> = A, with S
188         //  M   c   r   +   -   S       19:  C(I,J)<!M,repl> += x, with S
189         //  M   c   r   +   A   S       20:  C(I,J)<!M,repl> += A, with S
190 
191         //----------------------------------------------------------------------
192         // FUTURE::: 8 simpler cases when I and J are ":" (S not needed):
193         //----------------------------------------------------------------------
194 
195         // These methods could all tolerate C==M and C==A aliasing, assuming no
196         // binary search or if the binary search of C==M or C==A can be done
197         // with atomics.  These are all the methods used by GB_accum_mask.
198 
199         //  M   -   -   -   A   ?       06x: C(:,:)<M> = A
200         //  M   -   -   +   A   ?       08x: C(:,:)<M> += A
201         //  M   -   r   -   A   ?       10x: C(:,:)<M,repl> = A
202         //  M   -   r   +   A   ?       12x: C(:,:)<M,repl> += A
203         //  M   c   -   -   A   ?       14x: C(:,:)<!M> = A
204         //  M   c   -   +   A   ?       16x: C(:,:)<!M> += A
205         //  M   c   r   -   A   ?       18x: C(:,:)<!M,repl> = A
206         //  M   c   r   +   A   ?       20x: C(:,:)<!M,repl> += A
207 
208         //----------------------------------------------------------------------
209         // FUTURE::: C<C,s> = x    C == M, replace all values, C_replace ignored
210         // FUTURE::: C<C,s> += x   C == M, update all values, C_replace ignored
211         // FUTURE::: C<C,s> = A    C == M, A dense, C_replace ignored
212         //----------------------------------------------------------------------
213 
214     // For the single case C(I,J)<M>=A, two methods can be used: 06n and 06s.
215 
216     #define Istring ((Ikind == GB_ALL) ? ":" : "I")
217     #define Jstring ((Jkind == GB_ALL) ? ":" : "J")
218 
219     switch (subassign_method)
220     {
221 
222         //----------------------------------------------------------------------
223         // matrix or scalar subassign via GB_bitmap_assign
224         //----------------------------------------------------------------------
225 
226         case GB_SUBASSIGN_METHOD_BITMAP :
227         {
228             // C is bitmap, or is converted to bitmap.  M and A can have any
229             // sparsity (if present).
230             GBURBLE ("Method: bitmap_subassign ") ;
231             GB_OK (GB_bitmap_assign (C, C_replace,
232                 I, nI, Ikind, Icolon, J, nJ, Jkind, Jcolon,
233                 M, Mask_comp, Mask_struct, accum, A, scalar, atype,
234                 GB_SUBASSIGN, Context)) ;
235         }
236         break ;
237 
238         //----------------------------------------------------------------------
239         // C = x where x is a scalar; C becomes full
240         //----------------------------------------------------------------------
241 
242         case GB_SUBASSIGN_METHOD_21 :
243         {
244 
245             //  =====================       ==============
246             //  M   cmp rpl acc A   S       method: action
247             //  =====================       ==============
248 
249             //  -   -   x   -   -   -       21:  C = x, no S, C anything
250 
251             // Method 21: C = x where x is a scalar; C becomes full
252             GBURBLE ("Method 21: (C full) = scalar ") ;
253             GB_OK (GB_dense_subassign_21 (C, scalar, atype, Context)) ;
254         }
255         break ;
256 
257         //----------------------------------------------------------------------
258         // C = A
259         //----------------------------------------------------------------------
260 
261         case GB_SUBASSIGN_METHOD_24 :
262         {
263 
264             //  =====================       ==============
265             //  M   cmp rpl acc A   S       method: action
266             //  =====================       ==============
267 
268             //  -   -   x   -   A   -       24:  C = A, no S, C and A anything
269 
270             // Method 24: C = A
271             GBURBLE ("Method 24: C = Z ") ;
272             GB_OK (GB_subassign_24 (C, A, Context)) ;
273         }
274         break ;
275 
276         //----------------------------------------------------------------------
277         // C += A or x where C is dense or full (and becomes full)
278         //----------------------------------------------------------------------
279 
280         //  =====================       ==============
281         //  M   cmp rpl acc A   S       method: action
282         //  =====================       ==============
283         //  -   -   -   +   -   -       22:  C += x, no S, C dense
284         //  -   -   -   +   A   -       23:  C += A, no S, C dense
285 
286         case GB_SUBASSIGN_METHOD_22 :
287         {
288             // Method 22: C(:,:) += x where C is dense or full
289             GBURBLE ("Method 22: (C full) += scalar ") ;
290             GB_OK (GB_dense_subassign_22 (C, scalar, atype, accum, Context)) ;
291         }
292         break ;
293 
294         case GB_SUBASSIGN_METHOD_23 :
295         {
296             // Method 23: C(:,:) += A where C is dense or full
297             GBURBLE ("Method 23: (C full) += Z ") ;
298             GB_OK (GB_dense_subassign_23 (C, A, accum, Context)) ;
299         }
300         break ;
301 
302         //----------------------------------------------------------------------
303         // C(I,J)<M> = scalar or +=scalar
304         //----------------------------------------------------------------------
305 
306         //  =====================       ==============
307         //  M   cmp rpl acc A   S       method: action
308         //  =====================       ==============
309         //  M   -   -   -   -   -       05d: C(:,:)<M> = x, no S, C dense
310         //  M   -   -   -   -   -       05e: C(:,:)<M,s> = x, no S, C empty
311         //  M   -   -   -   -   -       05f: C(:,:)<C,s> = x, no S, C == M
312         //  M   -   -   -   -   -       05:  C(I,J)<M> = x, no S
313         //  M   -   -   +   -   -       07:  C(I,J)<M> += x, no S
314 
315         case GB_SUBASSIGN_METHOD_05f :
316         {
317             // Method 05f: C(:,:)<C,s> = scalar ; no S; C == M, M structural
318             GBURBLE ("Method 05f: C<C,struct> = scalar ") ;
319             GB_OK (GB_subassign_05f (C, scalar, atype, Context)) ;
320         }
321         break ;
322 
323         case GB_SUBASSIGN_METHOD_05e :
324         {
325             // Method 05e: C(:,:)<M> = scalar ; no S; C empty, M structural
326             GBURBLE ("Method 05e: (C empty)<M,struct> = scalar ") ;
327             GB_OK (GB_subassign_05e (C, M, scalar, atype, Context)) ;
328         }
329         break ;
330 
331         case GB_SUBASSIGN_METHOD_05d :
332         {
333             // Method 05d: C(:,:)<M> = scalar ; no S; C is dense or full;
334             // C becomes full.
335             GBURBLE ("Method 05d: (C full)<M> = scalar ") ;
336             GB_OK (GB_dense_subassign_05d (C,
337                 M, Mask_struct, scalar, atype, Context)) ;
338         }
339         break ;
340 
341         case GB_SUBASSIGN_METHOD_05 :
342         {
343             // Method 05: C(I,J)<M> = scalar ; no S
344             GBURBLE ("Method 05: C(%s,%s)<M> = scalar ; no S ",
345                 Istring, Jstring) ;
346             GB_OK (GB_subassign_05 (C,
347                 I, nI, Ikind, Icolon, J, nJ, Jkind, Jcolon,
348                 M, Mask_struct, scalar, atype, Context)) ;
349         }
350         break ;
351 
352         case GB_SUBASSIGN_METHOD_07 :
353         {
354             // Method 07: C(I,J)<M> += scalar ; no S
355             GBURBLE ("Method 07: C(%s,%s)<M> += scalar ; no S ",
356                 Istring, Jstring) ;
357             GB_OK (GB_subassign_07 (C,
358                 I, nI, Ikind, Icolon, J, nJ, Jkind, Jcolon,
359                 M, Mask_struct, accum, scalar, atype, Context)) ;
360         }
361         break ;
362 
363         //----------------------------------------------------------------------
364         // C(I,J)<M> = A or += A
365         //----------------------------------------------------------------------
366 
367         //  =====================       ==============
368         //  M   cmp rpl acc A   S       method: action
369         //  =====================       ==============
370         //  M   -   -   +   A   -       08n: C(I,J)<M> += A, no S
371         //  M   -   -   +   A   -       08s: C(I,J)<M> += A, with S
372         //  A   -   -   -   A   -       06d: C<A> = A, no S, C dense
373         //  M   -   x   -   A   -       25:  C<M,s> = A, A dense, C empty
374         //  M   -   -   -   A   -       06n: C(I,J)<M> = A, no S
375         //  M   -   -   -   A   S       06s: C(I,J)<M> = A, with S
376 
377         case GB_SUBASSIGN_METHOD_08n :
378         {
379             // Method 08n: C(I,J)<M> += A ; no S
380             GBURBLE ("Method 08n: C(%s,%s)<M> += Z ; no S ", Istring, Jstring) ;
381             GB_OK (GB_subassign_08n (C,
382                 I, nI, Ikind, Icolon, J, nJ, Jkind, Jcolon,
383                 M, Mask_struct, accum, A, Context)) ;
384         }
385         break ;
386 
387         case GB_SUBASSIGN_METHOD_08s :
388         {
389             // Method 08s: C(I,J)<M> += A ; with S
390             GBURBLE ("Method 08s: C(%s,%s)<M> += Z ; with S ",
391                 Istring, Jstring) ;
392             GB_OK (GB_subassign_08s_and_16 (C,
393                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
394                 M, Mask_struct, false, accum, A, Context)) ;
395         }
396         break ;
397 
398         case GB_SUBASSIGN_METHOD_06d :
399         {
400             // Method 06d: C(:,:)<A> = A ; no S, C dense or full;
401             GBURBLE ("Method 06d: (C full)<Z> = Z ") ;
402             GB_OK (GB_dense_subassign_06d (C, A, Mask_struct, Context)) ;
403         }
404         break ;
405 
406         case GB_SUBASSIGN_METHOD_25 :
407         {
408             // Method 25:  C<M,struct> = A, A dense, C empty
409             // A is dense or full; remains unchanged
410             GB_BURBLE_DENSE (A, "Method 25: (C empty)<M> = (Z %s) ") ;
411             GB_OK (GB_dense_subassign_25 (C, M, A, Context)) ;
412         }
413         break ;
414 
415         case GB_SUBASSIGN_METHOD_06n :
416         {
417             // Method 06n: C(I,J)<M> = A ; no S
418             GBURBLE ("Method 06n: C(%s,%s)<M> = Z ; no S ", Istring, Jstring) ;
419             GB_OK (GB_subassign_06n (C,
420                 I, nI, Ikind, Icolon, J, nJ, Jkind, Jcolon,
421                 M, Mask_struct, A, Context)) ;
422         }
423         break ;
424 
425         case GB_SUBASSIGN_METHOD_06s :
426         {
427             // Method 06s: C(I,J)<M> = A ; using S
428             GBURBLE ("Method 06s: C(%s,%s)<M> = Z ; using S ",
429                 Istring, Jstring) ;
430             GB_OK (GB_subassign_06s_and_14 (C,
431                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
432                 M, Mask_struct, false, A, Context)) ;
433         }
434         break ;
435 
436         //----------------------------------------------------------------------
437         // assignment using S_Extraction method, no mask M
438         //----------------------------------------------------------------------
439 
440         //  =====================       ==============
441         //  M   cmp rpl acc A   S       method: action
442         //  =====================       ==============
443         //  -   -   -   -   -   S       01:  C(I,J) = x, with S
444         //  -   -   -   -   A   S       02:  C(I,J) = A, with S
445         //  -   -   -   +   -   S       03:  C(I,J) += x, with S
446         //  -   -   -   +   A   S       04:  C(I,J) += A, with S
447 
448         case GB_SUBASSIGN_METHOD_01 :
449         {
450             // Method 01: C(I,J) = scalar ; using S
451             GBURBLE ("Method 01: C(%s,%s) = scalar ; using S ",
452                 Istring, Jstring) ;
453             GB_OK (GB_subassign_01 (C,
454                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
455                 scalar, atype, Context)) ;
456         }
457         break ;
458 
459         case GB_SUBASSIGN_METHOD_03 :
460         {
461             // Method 03: C(I,J) += scalar ; using S
462             GBURBLE ("Method 03: C(%s,%s) += scalar ; using S ",
463                 Istring, Jstring) ;
464             GB_OK (GB_subassign_03 (C,
465                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
466                 accum, scalar, atype, Context)) ;
467         }
468         break ;
469 
470         case GB_SUBASSIGN_METHOD_02 :
471         {
472             // Method 02: C(I,J) = A ; using S
473             GBURBLE ("Method 02: C(%s,%s) = Z ; using S ",
474                 Istring, Jstring) ;
475             GB_OK (GB_subassign_02 (C,
476                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
477                 A, Context)) ;
478         }
479         break ;
480 
481         case GB_SUBASSIGN_METHOD_04 :
482         {
483             // Method 04: C(I,J) += A ; using S
484             GBURBLE ("Method 04: C(%s,%s) += Z ; using S ", Istring, Jstring) ;
485             GB_OK (GB_subassign_04 (C,
486                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
487                 accum, A, Context)) ;
488         }
489         break ;
490 
491         //----------------------------------------------------------------------
492         // C(I,J)<#M> = scalar or += scalar ; using S
493         //----------------------------------------------------------------------
494 
495         //  =====================       ==============
496         //  M   cmp rpl acc A   S       method: action
497         //  =====================       ==============
498         //  M   -   r   -   -   S       09:  C(I,J)<M,repl> = x, with S
499         //  M   -   r   +   -   S       11:  C(I,J)<M,repl> += x, with S
500         //  M   c   -   -   -   S       13:  C(I,J)<!M> = x, with S
501         //  M   c   -   +   -   S       15:  C(I,J)<!M> += x, with S
502         //  M   c   r   -   -   S       17:  C(I,J)<!M,repl> = x, with S
503         //  M   c   r   +   -   S       19:  C(I,J)<!M,repl> += x, with S
504 
505         case GB_SUBASSIGN_METHOD_17 :
506         {
507             // Method 17: C(I,J)<!M,repl> = scalar ; using S
508             GBURBLE ("Method 17: C(%s,%s)<!M,repl> = scalar ; using S ",
509                 Istring, Jstring) ;
510             GB_OK (GB_subassign_17 (C,
511                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
512                 M, Mask_struct, scalar, atype, Context)) ;
513         }
514         break ;
515 
516         case GB_SUBASSIGN_METHOD_13 :
517         {
518             // Method 13: C(I,J)<!M> = scalar ; using S
519             GBURBLE ("Method 13: C(%s,%s)<!M> = scalar ; using S ",
520                 Istring, Jstring) ;
521             GB_OK (GB_subassign_13 (C,
522                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
523                 M, Mask_struct, scalar, atype, Context)) ;
524         }
525         break ;
526 
527         case GB_SUBASSIGN_METHOD_09 :
528         {
529             // Method 09: C(I,J)<M,repl> = scalar ; using S
530             GBURBLE ("Method 09: C(%s,%s)<M,repl> = scalar ; using S ",
531                 Istring, Jstring) ;
532             GB_OK (GB_subassign_09 (C,
533                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
534                 M, Mask_struct, scalar, atype, Context)) ;
535         }
536         break ;
537 
538         case GB_SUBASSIGN_METHOD_19 :
539         {
540             // Method 19: C(I,J)<!M,repl> += scalar ; using S
541             GBURBLE ("Method 19: C(%s,%s)<!M,repl> += scalar ; using S ",
542                 Istring, Jstring) ;
543             GB_OK (GB_subassign_19 (C,
544                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
545                 M, Mask_struct, accum, scalar, atype, Context)) ;
546         }
547         break ;
548 
549         case GB_SUBASSIGN_METHOD_15 :
550         {
551             // Method 15: C(I,J)<!M> += scalar ; using S
552             GBURBLE ("Method 15: C(%s,%s)<!M> += scalar ; using S ",
553                 Istring, Jstring) ;
554             GB_OK (GB_subassign_15 (C,
555                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
556                 M, Mask_struct, accum, scalar, atype, Context)) ;
557         }
558         break ;
559 
560         case GB_SUBASSIGN_METHOD_11 :
561         {
562             // Method 11: C(I,J)<M,repl> += scalar ; using S
563             GBURBLE ("Method 11: C(%s,%s)<M,repl> += scalar ; using S ",
564                 Istring, Jstring) ;
565             GB_OK (GB_subassign_11 (C,
566                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
567                 M, Mask_struct, accum, scalar, atype, Context)) ;
568         }
569         break ;
570 
571         //------------------------------------------------------------------
572         // C(I,J)<#M> = A or += A ; using S
573         //------------------------------------------------------------------
574 
575         //  =====================       ==============
576         //  M   cmp rpl acc A   S       method: action
577         //  =====================       ==============
578         //  M   -   r   -   A   S       10:  C(I,J)<M,repl> = A, with S
579         //  M   -   r   +   A   S       12:  C(I,J)<M,repl> += A, with S
580         //  M   c   -   -   A   S       14:  C(I,J)<!M> = A, with S
581         //  M   c   -   +   A   S       16:  C(I,J)<!M> += A, with S
582         //  M   c   r   -   A   S       18:  C(I,J)<!M,repl> = A, with S
583         //  M   c   r   +   A   S       20:  C(I,J)<!M,repl> += A, with S
584 
585         case GB_SUBASSIGN_METHOD_18 :
586         {
587             // Method 18: C(I,J)<!M,repl> = A ; using S
588             GBURBLE ("Method 18: C(%s,%s)<!M,repl> = Z ; using S ",
589                 Istring, Jstring) ;
590             GB_OK (GB_subassign_10_and_18 (C,
591                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
592                 M, Mask_struct, true, A, Context)) ;
593         }
594         break ;
595 
596         case GB_SUBASSIGN_METHOD_14 :
597         {
598             // Method 14: C(I,J)<!M> = A ; using S
599             GBURBLE ("Method 14: C(%s,%s)<!M> = Z ; using S ",
600                 Istring, Jstring) ;
601             GB_OK (GB_subassign_06s_and_14 (C,
602                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
603                 M, Mask_struct, true, A, Context)) ;
604         }
605         break ;
606 
607         case GB_SUBASSIGN_METHOD_10 :
608         {
609             // Method 10: C(I,J)<M,repl> = A ; using S
610             GBURBLE ("Method 10: C(%s,%s)<M,repl> = Z ; using S ",
611                 Istring, Jstring) ;
612             GB_OK (GB_subassign_10_and_18 (C,
613                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
614                 M, Mask_struct, false, A, Context)) ;
615         }
616         break ;
617 
618         case GB_SUBASSIGN_METHOD_20 :
619         {
620             // Method 20: C(I,J)<!M,repl> += A ; using S
621             GBURBLE ("Method 20: C(%s,%s)<!M,repl> += Z ; using S ",
622                 Istring, Jstring) ;
623             GB_OK (GB_subassign_12_and_20 (C,
624                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
625                 M, Mask_struct, true, accum, A, Context)) ;
626         }
627         break ;
628 
629         case GB_SUBASSIGN_METHOD_16 :
630         {
631             // Method 16: C(I,J)<!M> += A ; using S
632             GBURBLE ("Method 16: C(%s,%s)<!M> += Z ; using S ",
633                 Istring, Jstring) ;
634             GB_OK (GB_subassign_08s_and_16 (C,
635                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
636                 M, Mask_struct, true, accum, A, Context)) ;
637         }
638         break ;
639 
640         case GB_SUBASSIGN_METHOD_12 :
641         {
642             // Method 12: C(I,J)<M,repl> += A ; using S
643             GBURBLE ("Method 12: C(%s,%s)<M,repl> += Z ; using S ",
644                 Istring, Jstring) ;
645             GB_OK (GB_subassign_12_and_20 (C,
646                 I, ni, nI, Ikind, Icolon, J, nj, nJ, Jkind, Jcolon,
647                 M, Mask_struct, false, accum, A, Context)) ;
648         }
649         break ;
650 
651         default:
652             ASSERT (GB_DEAD_CODE) ;
653     }
654 
655     //--------------------------------------------------------------------------
656     // finalize C and return result
657     //--------------------------------------------------------------------------
658 
659     ASSERT_MATRIX_OK (C, "C(I,J) result", GB0) ;
660     return (GB_block (C, Context)) ;
661 }
662 
663