1 //------------------------------------------------------------------------------
2 // GB_AxB_saxpy3_fineGus_phase2: C=A*B, saxpy3 method, 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)=A*B(:,j)
14     //--------------------------------------------------------------------------
15 
16     // Hf [i] is initially 0.
17     // 0 -> 3 : to lock, if i seen for first time
18     // 2 -> 3 : to lock, if i seen already
19     // 3 -> 2 : to unlock; now i has been seen
20 
21     for ( ; pB < pB_end ; pB++)     // scan B(:,j)
22     {
23         GB_GET_B_kj_INDEX ;         // get index k of B(k,j)
24         GB_GET_A_k ;                // get A(:,k)
25         if (aknz == 0) continue ;
26         GB_GET_B_kj ;               // bkj = B(k,j)
27         // scan A(:,k)
28         for (int64_t pA = pA_start ; pA < pA_end ; pA++)
29         {
30             GB_GET_A_ik_INDEX ;     // get index i of A(i,k)
31             GB_MULT_A_ik_B_kj ;     // t = A(i,k) * B(k,j)
32             int8_t f ;
33 
34             #if GB_IS_ANY_MONOID
35 
36                 //--------------------------------------------------------------
37                 // C(i,j) += t ; with the ANY monoid
38                 //--------------------------------------------------------------
39 
40                 GB_ATOMIC_READ
41                 f = Hf [i] ;            // grab the entry
42                 if (f == 2) continue ;  // check if already updated
43                 GB_ATOMIC_WRITE_HX (i, t) ;    // Hx [i] = t
44 
45             #else
46 
47                 //--------------------------------------------------------------
48                 // C(i,j) += t ; with all other monoids
49                 //--------------------------------------------------------------
50 
51                 #if GB_HAS_ATOMIC
52 
53                     // if C(i,j) is already present (f==2), and the monoid can
54                     // be done atomically, then do the atomic update.  No need
55                     // to modify Hf [i].
56                     GB_ATOMIC_READ
57                     f = Hf [i] ;        // grab the entry
58                     if (f == 2)         // if true, update C(i,j)
59                     {
60                         GB_ATOMIC_UPDATE_HX (i, t) ; // Hx [i] += t
61                         continue ;      // C(i,j) has been updated
62                     }
63 
64                 #endif
65 
66                 do  // lock the entry
67                 {
68                     // do this atomically:
69                     // { f = Hf [i] ; Hf [i] = 3 ; }
70                     GB_ATOMIC_CAPTURE_INT8 (f, Hf [i], 3) ;
71                 } while (f == 3) ; // lock owner gets f=0 or 2
72                 if (f == 0)
73                 {
74                     // C(i,j) is a new entry
75                     GB_ATOMIC_WRITE_HX (i, t) ;    // Hx [i] = t
76                 }
77                 else // f == 2
78                 {
79                     // C(i,j) already appears in C(:,j)
80                     GB_ATOMIC_UPDATE_HX (i, t) ;   // Hx [i] += t
81                 }
82 
83             #endif
84 
85             GB_ATOMIC_WRITE
86             Hf [i] = 2 ;            // flag/unlock the entry
87         }
88     }
89 }
90 
91