1 //------------------------------------------------------------------------------
2 // GB_AxB_saxpy3_fineGus_notM_phase2: C<!M>=A*B, fine Gustavson, phase2
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 {
11 
12     //--------------------------------------------------------------------------
13     // phase2: fine Gustavson task, C(:,j)<!M(:,j)>=A*B(:,j)
14     //--------------------------------------------------------------------------
15 
16     // Hf [i] is 0 if M(i,j) not present or M(i,j)=0.
17     // 0 -> 1 : has already been done in phase0 if M(i,j)=1
18 
19     // 1 -> 1 : to ignore, if M(i,j)=1
20     // 0 -> 3 : to lock, if i seen for first time
21     // 2 -> 3 : to lock, if i seen already
22     // 3 -> 2 : to unlock; now i has been seen
23 
24     for ( ; pB < pB_end ; pB++)     // scan B(:,j)
25     {
26         GB_GET_B_kj_INDEX ;         // get index k of B(k,j)
27         GB_GET_A_k ;                // get A(:,k)
28         if (aknz == 0) continue ;
29         GB_GET_B_kj ;               // bkj = B(k,j)
30         // scan A(:,k)
31         for (int64_t pA = pA_start ; pA < pA_end ; pA++)
32         {
33             GB_GET_A_ik_INDEX ;     // get index i of A(i,k)
34             GB_MULT_A_ik_B_kj ;     // t = A(i,k) * B(k,j)
35             int8_t f ;
36 
37             #if GB_IS_ANY_MONOID
38 
39                 //--------------------------------------------------------------
40                 // ANY monoid
41                 //--------------------------------------------------------------
42 
43                 // lock state (3) not needed
44                 // 0: not seen: update with new value, f becomes 2
45                 // 1: masked, do nothing, f stays 1
46                 // 2: already updated, do nothing, f stays 2
47                 // 3: state not used, f can be 2
48                 GB_ATOMIC_READ
49                 f = Hf [i] ;
50                 if (!f)
51                 {
52                     GB_ATOMIC_WRITE
53                     Hf [i] = 2 ;
54                     GB_ATOMIC_WRITE_HX (i, t) ;    // Hx [i] = t
55                 }
56 
57 
58             #else
59 
60                 //--------------------------------------------------------------
61                 // all other monoids
62                 //--------------------------------------------------------------
63 
64                 GB_ATOMIC_READ
65                 f = Hf [i] ;            // grab the entry
66 
67                 #if GB_HAS_ATOMIC
68                 {
69                     // the monoid can be done with a single atomic update
70                     if (f == 2)             // if true, update C(i,j)
71                     {
72                         GB_ATOMIC_UPDATE_HX (i, t) ;   // Hx [i] += t
73                         continue ;          // C(i,j) has been updated
74                     }
75                 }
76                 #endif
77 
78                 if (f == 1) continue ; // M(i,j)=1; ignore C(i,j)
79                 do  // lock the entry
80                 {
81                     // do this atomically:
82                     // { f = Hf [i] ; Hf [i] = 3 ; }
83                     GB_ATOMIC_CAPTURE_INT8 (f, Hf [i], 3) ;
84                 } while (f == 3) ; // lock owner of gets f=0 or 2
85                 if (f == 0)
86                 {
87                     // C(i,j) is a new entry
88                     GB_ATOMIC_WRITE_HX (i, t) ;    // Hx [i] = t
89                 }
90                 else // f == 2
91                 {
92                     // C(i,j) already seen
93                     GB_ATOMIC_UPDATE_HX (i, t) ;   // Hx [i] += t
94                 }
95                 GB_ATOMIC_WRITE
96                 Hf [i] = 2 ;                // unlock the entry
97 
98             #endif
99         }
100     }
101 }
102 
103