1 //------------------------------------------------------------------------------
2 // GB_subassigner_method: determine method for GB_subassign
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 #include "GB_subassign.h"
11
GB_subassigner_method(const GrB_Matrix C,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 int Ikind,const int Jkind,const bool scalar_expansion)12 int GB_subassigner_method // return method to use in GB_subassigner
13 (
14 const GrB_Matrix C, // input/output matrix for results
15 const bool C_replace, // C matrix descriptor
16 const GrB_Matrix M, // optional mask for C(I,J), unused if NULL
17 const bool Mask_comp, // mask descriptor
18 const bool Mask_struct, // if true, use the only structure of M
19 const GrB_BinaryOp accum, // optional accum for Z=accum(C(I,J),A)
20 const GrB_Matrix A, // input matrix (NULL for scalar expansion)
21 const int Ikind,
22 const int Jkind,
23 const bool scalar_expansion // if true, expand scalar to A
24 )
25 {
26
27 //--------------------------------------------------------------------------
28 // check mask conditions
29 //--------------------------------------------------------------------------
30
31 #ifdef GB_DEBUG
32 // empty_mask: mask not present and complemented. This condition has
33 // already handled by GB_assign_prep.
34 bool empty_mask = (M == NULL) && Mask_comp ;
35 ASSERT (!empty_mask) ;
36 #endif
37
38 // no_mask: mask not present and not complemented
39 bool no_mask = (M == NULL) && !Mask_comp ;
40
41 // GB_assign_prep has already disabled C_replace if no mask present
42 ASSERT (GB_IMPLIES (no_mask, !C_replace)) ;
43
44 bool M_is_bitmap = GB_IS_BITMAP (M) ;
45
46 //--------------------------------------------------------------------------
47 // check if C is empty
48 //--------------------------------------------------------------------------
49
50 bool C_is_empty = (GB_NNZ (C) == 0 && !GB_PENDING (C) && !GB_ZOMBIES (C)) ;
51
52 // if C is empty, C_replace is effectively false and already disabled
53 ASSERT (GB_IMPLIES (C_is_empty, !C_replace)) ;
54
55 //--------------------------------------------------------------------------
56 // check if A is dense; a scalar is an implicit dense matrix, or bitmap
57 //--------------------------------------------------------------------------
58
59 bool A_is_bitmap = GB_IS_BITMAP (A) ;
60
61 //--------------------------------------------------------------------------
62 // determine the method to use
63 //--------------------------------------------------------------------------
64
65 // whole_C_matrix is true if all of C(:,:) is being assigned to
66 bool whole_C_matrix = (Ikind == GB_ALL) && (Jkind == GB_ALL) ;
67
68 bool C_splat_scalar = false ; // C(:,:) = x
69 bool C_splat_matrix = false ; // C(:,:) = A
70
71 if (whole_C_matrix && no_mask && (accum == NULL))
72 {
73
74 //----------------------------------------------------------------------
75 // C(:,:) = x or A: whole matrix assignment with no mask
76 //----------------------------------------------------------------------
77
78 if (scalar_expansion)
79 {
80 // Method 21: C(:,:) = x
81 C_splat_scalar = true ;
82 }
83 else
84 {
85 // Method 24: C(:,:) = A
86 C_splat_matrix = true ;
87 }
88 }
89
90 // check if C is competely dense: all entries present and no pending work.
91 bool C_is_bitmap = GB_IS_BITMAP (C) ;
92 bool C_as_if_full = GB_as_if_full (C) ;
93 bool C_dense_update = false ;
94 if (C_as_if_full)
95 {
96 // C is dense with no pending work
97 if (whole_C_matrix && no_mask && (accum != NULL)
98 && (C->type == accum->ztype) && (C->type == accum->xtype))
99 {
100 // C(:,:) += x or A, where C is dense, no typecasting of C
101 C_dense_update = true ;
102 }
103 }
104
105 // simple_mask: C(I,J)<M> = ... ; or C(I,J)<M> += ...
106 bool simple_mask = (!C_replace && M != NULL && !Mask_comp) ;
107
108 // C_Mask_scalar: C(I,J)<M> = scalar or += scalar
109 bool C_Mask_scalar = (scalar_expansion && simple_mask) ;
110
111 // C_Mask_matrix: C(I,J)<M> = A or += A
112 bool C_Mask_matrix = (!scalar_expansion && simple_mask) ;
113
114 bool S_Extraction ;
115 bool method_06d = false ;
116 bool method_25 = false ;
117
118 if (C_splat_scalar)
119 {
120 // Method 21: C(:,:) = x where x is a scalar; C becomes dense
121 S_Extraction = false ;
122 }
123 else if (C_splat_matrix)
124 {
125 // Method 24: C(:,:) = A
126 S_Extraction = false ;
127 }
128 else if (C_dense_update)
129 {
130 // Methods 22 and 23: C(:,:) += x or A where C is dense
131 S_Extraction = false ;
132 }
133 else if (C_Mask_scalar)
134 {
135 // Method 05*, or 07: C(I,J)<M> = or += scalar; C_replace false
136 S_Extraction = false ;
137 }
138 else if (C_Mask_matrix)
139 {
140 // C(I,J)<M> = A or += A
141 if (accum != NULL)
142 {
143 // Method 08n: C(I,J)<M> += A, no S. Cannot use M or A as bitmap.
144 // Method 08s: C(I,J)<M> += A, with S. Can use M or A as bitmap.
145 // if S_Extraction is true, Method 08s is used (with S).
146 // Method 08n is not used if any matrix is bitmap.
147 // If C is bitmap, GB_bitmap_assign_M_accum is used instead.
148 S_Extraction = M_is_bitmap || A_is_bitmap ;
149 }
150 else
151 {
152 // C(I,J)<M> = A ; use 06s (with S) or 06n (without S)
153 // method 06s (with S) is faster when nnz (A) < nnz (M).
154 if ((C_as_if_full || C_is_bitmap) && whole_C_matrix && M == A)
155 {
156 // Method 06d: C<A> = A
157 method_06d = true ;
158 S_Extraction = false ;
159 }
160 else if (C_is_empty && whole_C_matrix && Mask_struct &&
161 (scalar_expansion || GB_as_if_full (A) || A_is_bitmap))
162 {
163 // Method 25: C<M,s> = A, where M is structural, A is
164 // dense, and C starts out empty. The pattern of C will be the
165 // same as M, and the subassign method is extremely simple.
166 method_25 = true ;
167 S_Extraction = false ;
168 }
169 else
170 {
171 // Method 06n (no S) or Method 06s (with S):
172 // Method 06n is not used if M or A are bitmap. If M and A are
173 // aliased and Method 06d is not used, then 06s is used instead
174 // of 06n since M==A implies nnz(A) == nnz(M).
175 S_Extraction = (GB_NNZ (A) < GB_NNZ (M))
176 || M_is_bitmap || A_is_bitmap ;
177 }
178 }
179 }
180 else
181 {
182 // all other methods require S
183 S_Extraction = true ;
184 }
185
186 //==========================================================================
187 // submatrix assignment C(I,J)<M> = accum (C(I,J),A): meta-algorithm
188 //==========================================================================
189
190 // There are up to 128 combinations of options, but not all must be
191 // implemented, because they are either identical to another method
192 // (C_replace is effectively false if M=NULL and Mask_comp=false), or they
193 // are not used (the last option, whether or not S is constructed, is
194 // determined here; it is not a user input). The first 5 options are
195 // determined by the input. The table below has been pruned to remove
196 // combinations that are not used, or equivalent to other entries in the
197 // table. Only 22 unique combinations of the 128 combinations are needed,
198 // with additional special cases when C(:,:) is dense.
199
200 // M present or NULL
201 // Mask_comp true or false
202 // Mask_struct structural or valued mask
203 // C_replace true or false
204 // accum present or NULL
205 // A scalar (x) or matrix (A)
206 // S constructed or not
207
208 // C(I,J)<(M,comp,repl)> ( = , += ) (A, scalar), (with or without S);
209 // I and J can be anything for any of these methods (":", colon, or list).
210
211 // See the "No work to do..." comment above:
212 // If M is not present, Mask_comp true, C_replace false: no work to do.
213 // If M is not present, Mask_comp true, C_replace true: use Method 00
214 // If M is not present, Mask_comp false: C_replace is now false.
215
216 // ===================== ==============
217 // M cmp rpl acc A S method: action
218 // ===================== ==============
219
220 // - - x - - - 21: C = x, no S, C anything
221 // - - x - A - 24: C = A, no S, C and A anything
222 // - - - + - - 22: C += x, no S, C dense
223 // - - - + A - 23: C += A, no S, C dense
224
225 // - - - - - S 01: C(I,J) = x, with S
226 // - - - - A S 02: C(I,J) = A, with S
227 // - - - + - S 03: C(I,J) += x, with S
228 // - - - + A S 04: C(I,J) += A, with S
229 // - - r uses methods 01, 02, 03, 04
230 // - c - no work to do
231 // - c r S 00: C(I,J)<!,repl> = empty, with S
232
233 // M - - - - - 05d: C<M> = x, no S, C dense
234 // M - - - - - 05e: C<M,s> = x, no S, C empty
235 // M - - - - - 05f: C<C,s> = x, no S, C == M
236 // M - - - - - 05: C(I,J)<M> = x, no S
237 // A - - - A - 06d: C<A> = A, no S, C dense
238 // M - - - A - 25: C<M,s> = A, A dense, C empty
239 // M - - - A - 06n: C(I,J)<M> = A, no S
240 // M - - - A S 06s: C(I,J)<M> = A, with S
241 // M - - + - - 07: C(I,J)<M> += x, no S
242 // M - - + A - 08n: C(I,J)<M> += A, no S
243 // M - - + A - 08s: C(I,J)<M> += A, with S
244 // M - r - - S 09: C(I,J)<M,repl> = x, with S
245 // M - r - A S 10: C(I,J)<M,repl> = A, with S
246 // M - r + - S 11: C(I,J)<M,repl> += x, with S
247 // M - r + A S 12: C(I,J)<M,repl> += A, with S
248
249 // M c - - - S 13: C(I,J)<!M> = x, with S
250 // M c - - A S 14: C(I,J)<!M> = A, with S
251 // M c - + - S 15: C(I,J)<!M> += x, with S
252 // M c - + A S 16: C(I,J)<!M> += A, with S
253 // M c r - - S 17: C(I,J)<!M,repl> = x, with S
254 // M c r - A S 18: C(I,J)<!M,repl> = A, with S
255 // M c r + - S 19: C(I,J)<!M,repl> += x, with S
256 // M c r + A S 20: C(I,J)<!M,repl> += A, with S
257
258 //----------------------------------------------------------------------
259 // FUTURE::: 8 simpler cases when I and J are ":" (S not needed):
260 //----------------------------------------------------------------------
261
262 // M - - - A - 06x: C(:,:)<M> = A
263 // M - - + A - 08x: C(:,:)<M> += A
264 // M - r - A - 10x: C(:,:)<M,repl> = A
265 // M - r + A - 12x: C(:,:)<M,repl> += A
266 // M c - - A - 14x: C(:,:)<!M> = A
267 // M c - + A - 16x: C(:,:)<!M> += A
268 // M c r - A - 18x: C(:,:)<!M,repl> = A
269 // M c r + A - 20x: C(:,:)<!M,repl> += A
270
271 //----------------------------------------------------------------------
272 // FUTURE::: C<C,s> += x C == M, update all values, C_replace ignored
273 // FUTURE::: C<C,s> = A C == M, A dense, C_replace ignored
274 //----------------------------------------------------------------------
275
276 // For the single case C(I,J)<M>=A, two methods can be used: 06n and 06s.
277
278 int subassign_method = -1 ;
279
280 if (C_splat_scalar)
281 {
282
283 //----------------------------------------------------------------------
284 // C = x where x is a scalar; C becomes full
285 //----------------------------------------------------------------------
286
287 // ===================== ==============
288 // M cmp rpl acc A S method: action
289 // ===================== ==============
290
291 // - - x - - - 21: C = x, no S, C anything
292
293 ASSERT (whole_C_matrix) ; // C(:,:) is modified
294 ASSERT (M == NULL) ; // no mask present
295 ASSERT (accum == NULL) ; // accum is not present
296 ASSERT (!C_replace) ; // C_replace is effectively false
297 ASSERT (!S_Extraction) ; // S is not used
298 ASSERT (scalar_expansion) ; // x is a scalar
299
300 // Method 21: C = x where x is a scalar; C becomes full
301 subassign_method = GB_SUBASSIGN_METHOD_21 ;
302
303 }
304 else if (C_splat_matrix)
305 {
306
307 //----------------------------------------------------------------------
308 // C = A
309 //----------------------------------------------------------------------
310
311 // ===================== ==============
312 // M cmp rpl acc A S method: action
313 // ===================== ==============
314
315 // - - x - A - 24: C = A, no S, C and A anything
316
317 ASSERT (whole_C_matrix) ; // C(:,:) is modified
318 ASSERT (M == NULL) ; // no mask present
319 ASSERT (accum == NULL) ; // accum is not present
320 ASSERT (!C_replace) ; // C_replace is effectively false
321 ASSERT (!S_Extraction) ; // S is not used
322 ASSERT (!scalar_expansion) ; // A is a matrix
323
324 // Method 24: C = A
325 subassign_method = GB_SUBASSIGN_METHOD_24 ;
326
327 }
328 else if (C_dense_update)
329 {
330
331 //----------------------------------------------------------------------
332 // C += A or x where C is dense or full (and becomes full)
333 //----------------------------------------------------------------------
334
335 // ===================== ==============
336 // M cmp rpl acc A S method: action
337 // ===================== ==============
338 // - - - + - - 22: C += x, no S, C dense
339 // - - - + A - 23: C += A, no S, C dense
340
341 ASSERT (C_as_if_full) ; // C is dense
342 ASSERT (whole_C_matrix) ; // C(:,:) is modified
343 ASSERT (M == NULL) ; // no mask present
344 ASSERT (accum != NULL) ; // accum is present
345 ASSERT (!C_replace) ; // C_replace is false
346 ASSERT (!S_Extraction) ; // S is not used
347
348 if (scalar_expansion)
349 {
350 // Method 22: C(:,:) += x where C is dense or full
351 subassign_method = GB_SUBASSIGN_METHOD_22 ;
352 }
353 else
354 {
355 // Method 23: C(:,:) += A where C is dense or full
356 subassign_method = GB_SUBASSIGN_METHOD_23 ;
357 }
358
359 }
360 else if (C_Mask_scalar)
361 {
362
363 //----------------------------------------------------------------------
364 // C(I,J)<M> = scalar or +=scalar
365 //----------------------------------------------------------------------
366
367 // ===================== ==============
368 // M cmp rpl acc A S method: action
369 // ===================== ==============
370 // M - - - - - 05d: C(:,:)<M> = x, no S, C dense
371 // M - - - - - 05e: C(:,:)<M,s> = x, no S, C empty
372 // M - - - - - 05f: C(:,:)<C,s> = x, no S, C == M
373 // M - - - - - 05: C(I,J)<M> = x, no S
374 // M - - + - - 07: C(I,J)<M> += x, no S
375
376 ASSERT (scalar_expansion) ; // A is a scalar
377 ASSERT (M != NULL && !Mask_comp) ; // mask M present, not compl.
378 ASSERT (!C_replace) ; // C_replace is false
379 ASSERT (!S_Extraction) ; // S is not used
380
381 if (accum == NULL)
382 {
383 if (C == M && whole_C_matrix && Mask_struct)
384 {
385 // Method 05f: C(:,:)<C,s> = scalar ; no S ; C == M ; M struct
386 subassign_method = GB_SUBASSIGN_METHOD_05f ;
387 }
388 else if (C_is_empty && whole_C_matrix && Mask_struct)
389 {
390 // Method 05e: C(:,:)<M,s> = scalar ; no S; C empty, M struct
391 subassign_method = GB_SUBASSIGN_METHOD_05e ;
392 }
393 else if (C_as_if_full && whole_C_matrix)
394 {
395 // Method 05d: C(:,:)<M> = scalar ; no S; C is dense or full;
396 // C becomes full.
397 subassign_method = GB_SUBASSIGN_METHOD_05d ;
398 }
399 else
400 {
401 // Method 05: C(I,J)<M> = scalar ; no S
402 subassign_method = GB_SUBASSIGN_METHOD_05 ;
403 }
404 }
405 else
406 {
407 // Method 07: C(I,J)<M> += scalar ; no S
408 subassign_method = GB_SUBASSIGN_METHOD_07 ;
409 }
410
411 }
412 else if (C_Mask_matrix)
413 {
414
415 //----------------------------------------------------------------------
416 // C(I,J)<M> = A or += A
417 //----------------------------------------------------------------------
418
419 // ===================== ==============
420 // M cmp rpl acc A S method: action
421 // ===================== ==============
422 // M - - + A - 08n: C(I,J)<M> += A, no S
423 // M - - + A - 08s: C(I,J)<M> += A, with S
424 // A - - - A - 06d: C<A> = A, no S, C dense
425 // M - x - A - 25: C<M,s> = A, A dense, C empty
426 // M - - - A - 06n: C(I,J)<M> = A, no S
427 // M - - - A S 06s: C(I,J)<M> = A, with S
428
429 ASSERT (!scalar_expansion) ; // A is a matrix
430 ASSERT (M != NULL && !Mask_comp) ; // mask M present, not compl.
431 ASSERT (!C_replace) ;
432
433 if (accum != NULL)
434 {
435 if (S_Extraction)
436 {
437 // Method 08s: C(I,J)<M> += A ; with S
438 subassign_method = GB_SUBASSIGN_METHOD_08s ;
439 }
440 else
441 {
442 // Method 08n: C(I,J)<M> += A ; no S
443 // No matrix can be bitmap.
444 subassign_method = GB_SUBASSIGN_METHOD_08n ;
445 }
446 }
447 else if (method_06d)
448 {
449 // Method 06d: C(:,:)<A> = A ; no S, C dense or full;
450 subassign_method = GB_SUBASSIGN_METHOD_06d ;
451 ASSERT ((C_as_if_full || C_is_bitmap) && whole_C_matrix && M == A) ;
452 ASSERT ((C_as_if_full || C_is_bitmap) && whole_C_matrix && M == A) ;
453 }
454 else if (method_25)
455 {
456 // Method 25: C<M,struct> = A, C empty; A is dense, full, or bitmap
457 subassign_method = GB_SUBASSIGN_METHOD_25 ;
458 }
459 else if (!S_Extraction)
460 {
461 // Method 06n: C(I,J)<M> = A ; no S
462 // If M or A are bitmap, this method is not used;
463 // 06s is used instead.
464 subassign_method = GB_SUBASSIGN_METHOD_06n ;
465 }
466 else
467 {
468 // Method 06s: C(I,J)<M> = A ; using S
469 subassign_method = GB_SUBASSIGN_METHOD_06s ;
470 }
471
472 }
473 else if (M == NULL)
474 {
475
476 //----------------------------------------------------------------------
477 // assignment using S_Extraction method, no mask M
478 //----------------------------------------------------------------------
479
480 // ===================== ==============
481 // M cmp rpl acc A S method: action
482 // ===================== ==============
483 // - - - - - S 01: C(I,J) = x, with S
484 // - - - - A S 02: C(I,J) = A, with S
485 // - - - + - S 03: C(I,J) += x, with S
486 // - - - + A S 04: C(I,J) += A, with S
487
488 ASSERT (!Mask_comp) ;
489 ASSERT (!C_replace) ;
490 ASSERT (S_Extraction) ; // S is used
491
492 if (scalar_expansion)
493 {
494 if (accum == NULL)
495 {
496 // Method 01: C(I,J) = scalar ; using S
497 subassign_method = GB_SUBASSIGN_METHOD_01 ;
498 }
499 else
500 {
501 // Method 03: C(I,J) += scalar ; using S
502 subassign_method = GB_SUBASSIGN_METHOD_03 ;
503 }
504 }
505 else
506 {
507 if (accum == NULL)
508 {
509 // Method 02: C(I,J) = A ; using S
510 subassign_method = GB_SUBASSIGN_METHOD_02 ;
511 }
512 else
513 {
514 // Method 04: C(I,J) += A ; using S
515 subassign_method = GB_SUBASSIGN_METHOD_04 ;
516 }
517 }
518
519 }
520 else if (scalar_expansion)
521 {
522
523 //----------------------------------------------------------------------
524 // C(I,J)<#M> = scalar or += scalar ; using S
525 //----------------------------------------------------------------------
526
527 // ===================== ==============
528 // M cmp rpl acc A S method: action
529 // ===================== ==============
530 // M - r - - S 09: C(I,J)<M,repl> = x, with S
531 // M - r + - S 11: C(I,J)<M,repl> += x, with S
532 // M c - - - S 13: C(I,J)<!M> = x, with S
533 // M c - + - S 15: C(I,J)<!M> += x, with S
534 // M c r - - S 17: C(I,J)<!M,repl> = x, with S
535 // M c r + - S 19: C(I,J)<!M,repl> += x, with S
536
537 ASSERT (!C_Mask_scalar) ;
538 ASSERT (C_replace || Mask_comp) ;
539 ASSERT (S_Extraction) ; // S is used
540
541 if (accum == NULL)
542 {
543 if (Mask_comp && C_replace)
544 {
545 // Method 17: C(I,J)<!M,repl> = scalar ; using S
546 subassign_method = GB_SUBASSIGN_METHOD_17 ;
547 }
548 else if (Mask_comp)
549 {
550 // Method 13: C(I,J)<!M> = scalar ; using S
551 subassign_method = GB_SUBASSIGN_METHOD_13 ;
552 }
553 else // if (C_replace)
554 {
555 // Method 09: C(I,J)<M,repl> = scalar ; using S
556 ASSERT (C_replace) ;
557 subassign_method = GB_SUBASSIGN_METHOD_09 ;
558 }
559 }
560 else
561 {
562 if (Mask_comp && C_replace)
563 {
564 // Method 19: C(I,J)<!M,repl> += scalar ; using S
565 subassign_method = GB_SUBASSIGN_METHOD_19 ;
566 }
567 else if (Mask_comp)
568 {
569 // Method 15: C(I,J)<!M> += scalar ; using S
570 subassign_method = GB_SUBASSIGN_METHOD_15 ;
571 }
572 else // if (C_replace)
573 {
574 // Method 11: C(I,J)<M,repl> += scalar ; using S
575 ASSERT (C_replace) ;
576 subassign_method = GB_SUBASSIGN_METHOD_11 ;
577 }
578 }
579
580 }
581 else
582 {
583
584 //------------------------------------------------------------------
585 // C(I,J)<#M> = A or += A ; using S
586 //------------------------------------------------------------------
587
588 // ===================== ==============
589 // M cmp rpl acc A S method: action
590 // ===================== ==============
591 // M - r - A S 10: C(I,J)<M,repl> = A, with S
592 // M - r + A S 12: C(I,J)<M,repl> += A, with S
593 // M c - - A S 14: C(I,J)<!M> = A, with S
594 // M c - + A S 16: C(I,J)<!M> += A, with S
595 // M c r - A S 18: C(I,J)<!M,repl> = A, with S
596 // M c r + A S 20: C(I,J)<!M,repl> += A, with S
597
598 ASSERT (Mask_comp || C_replace) ;
599 ASSERT (S_Extraction) ; // S is used
600
601 if (accum == NULL)
602 {
603 if (Mask_comp && C_replace)
604 {
605 // Method 18: C(I,J)<!M,repl> = A ; using S
606 subassign_method = GB_SUBASSIGN_METHOD_18 ;
607 }
608 else if (Mask_comp)
609 {
610 // Method 14: C(I,J)<!M> = A ; using S
611 subassign_method = GB_SUBASSIGN_METHOD_14 ;
612 }
613 else // if (C_replace)
614 {
615 // Method 10: C(I,J)<M,repl> = A ; using S
616 ASSERT (C_replace) ;
617 subassign_method = GB_SUBASSIGN_METHOD_10 ;
618 }
619 }
620 else
621 {
622 if (Mask_comp && C_replace)
623 {
624 // Method 20: C(I,J)<!M,repl> += A ; using S
625 subassign_method = GB_SUBASSIGN_METHOD_20 ;
626 }
627 else if (Mask_comp)
628 {
629 subassign_method = GB_SUBASSIGN_METHOD_16 ;
630 }
631 else // if (C_replace)
632 {
633 // Method 12: C(I,J)<M,repl> += A ; using S
634 ASSERT (C_replace) ;
635 subassign_method = GB_SUBASSIGN_METHOD_12 ;
636 }
637 }
638 }
639
640 //--------------------------------------------------------------------------
641 // determine if the subassign method can handle this case for bitmaps
642 //--------------------------------------------------------------------------
643
644 bool C_is_full = GB_IS_FULL (C) ;
645
646 #define GB_USE_BITMAP_IF(condition) \
647 if (condition) subassign_method = GB_SUBASSIGN_METHOD_BITMAP ;
648
649 switch (subassign_method)
650 {
651
652 //----------------------------------------------------------------------
653 // scalar assignent methods
654 //----------------------------------------------------------------------
655
656 case GB_SUBASSIGN_METHOD_01 : // C(I,J) = scalar
657 case GB_SUBASSIGN_METHOD_03 : // C(I,J) += scalar
658 case GB_SUBASSIGN_METHOD_05 : // C(I,J)<M> = scalar
659 case GB_SUBASSIGN_METHOD_07 : // C(I,J)<M> += scalar
660 case GB_SUBASSIGN_METHOD_13 : // C(I,J)<!M> = scalar
661 case GB_SUBASSIGN_METHOD_15 : // C(I,J)<!M> += scalar
662 case GB_SUBASSIGN_METHOD_21 : // C(:,:) = scalar
663 // M can have any sparsity structure, including bitmap
664 GB_USE_BITMAP_IF (C_is_bitmap) ;
665 break ;
666
667 case GB_SUBASSIGN_METHOD_05d : // C(:,:)<M> = scalar ; C is dense
668 case GB_SUBASSIGN_METHOD_05e : // C(:,:)<M,struct> = scalar ; C empty
669 case GB_SUBASSIGN_METHOD_05f : // C(:,:)<C,struct> = scalar
670 case GB_SUBASSIGN_METHOD_22 : // C += scalar ; C is dense
671 // C and M can have any sparsity pattern, including bitmap
672 break ;
673
674 case GB_SUBASSIGN_METHOD_09 : // C(I,J)<M,replace> = scalar
675 case GB_SUBASSIGN_METHOD_11 : // C(I,J)<M,replace> += scalar
676 case GB_SUBASSIGN_METHOD_17 : // C(I,J)<!M,replace> = scalar
677 case GB_SUBASSIGN_METHOD_19 : // C(I,J)<!M,replace> = scalar
678 // M can have any sparsity structure, including bitmap
679 GB_USE_BITMAP_IF (C_is_bitmap || C_is_full) ;
680 break ;
681
682 //----------------------------------------------------------------------
683 // matrix assignent methods
684 //----------------------------------------------------------------------
685
686 // GB_accum_mask may use any of these methods, with I and J as GB_ALL.
687
688 case GB_SUBASSIGN_METHOD_02 : // C(I,J) = A
689 case GB_SUBASSIGN_METHOD_06s : // C(I,J)< M> = A ; with S
690 case GB_SUBASSIGN_METHOD_14 : // C(I,J)<!M> = A
691 case GB_SUBASSIGN_METHOD_10 : // C(I,J)< M,replace> = A
692 case GB_SUBASSIGN_METHOD_18 : // C(I,J)<!M,replace> = A
693 case GB_SUBASSIGN_METHOD_12 : // C(I,J)< M,replace> += A
694 case GB_SUBASSIGN_METHOD_20 : // C(I,J)<!M,replace> += A
695 // M can have any sparsity structure, including bitmap
696 GB_USE_BITMAP_IF (C_is_bitmap || C_is_full) ;
697 break ;
698
699 case GB_SUBASSIGN_METHOD_04 : // C(I,J) += A
700 case GB_SUBASSIGN_METHOD_08s : // C(I,J)< M> += A, with S
701 case GB_SUBASSIGN_METHOD_16 : // C(I,J)<!M> += A
702 case GB_SUBASSIGN_METHOD_24 : // C = A
703 // M can have any sparsity structure, including bitmap
704 GB_USE_BITMAP_IF (C_is_bitmap) ;
705 break ;
706
707 case GB_SUBASSIGN_METHOD_06d : // C(:,:)<A> = A ; C is dense
708 case GB_SUBASSIGN_METHOD_23 : // C += A ; C is dense
709 // C, M, and A can have any sparsity structure, including bitmap
710 break ;
711
712 case GB_SUBASSIGN_METHOD_25 : // C(:,:)<M,struct> = A ; C empty
713 // C, M, and A can have any sparsity structure, including bitmap,
714 // but if M is bitmap or full, use bitmap assignment instead.
715 GB_USE_BITMAP_IF (M_is_bitmap || GB_IS_FULL (M)) ;
716 break ;
717
718 case GB_SUBASSIGN_METHOD_06n : // C(I,J)<M> = A ; no S
719 // If M or A are bitmap, Method 06s is used instead of 06n.
720 GB_USE_BITMAP_IF (C_is_bitmap || C_is_full) ;
721 ASSERT (!M_is_bitmap) ;
722 ASSERT (!A_is_bitmap) ;
723 break ;
724
725 case GB_SUBASSIGN_METHOD_08n : // C(I,J)<M> += A, no S
726 // Method 08s is used instead of 08n if M or A are bitmap.
727 GB_USE_BITMAP_IF (C_is_bitmap) ;
728 ASSERT (!M_is_bitmap) ;
729 ASSERT (!A_is_bitmap) ;
730 break ;
731
732 // case GB_SUBASSIGN_METHOD_BITMAP:
733 default :;
734 subassign_method = GB_SUBASSIGN_METHOD_BITMAP ;
735 }
736
737 //--------------------------------------------------------------------------
738 // return result
739 //--------------------------------------------------------------------------
740
741 return (subassign_method) ;
742 }
743
744