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