1 //------------------------------------------------------------------------------
2 // GB_build_template: T=build(S), and assemble any duplicate tuples
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 // This template is used in GB_builder and the Generated/GB__red_build__*
11 // workers.  This is the same for both vectors and matrices, since this step is
12 // agnostic about which vectors the entries appear.
13 
14 {
15 
16     // k unused for some uses of this template
17     #include "GB_unused.h"
18 
19     if (ndupl == 0)
20     {
21 
22         //----------------------------------------------------------------------
23         // no duplicates, just permute S into Tx
24         //----------------------------------------------------------------------
25 
26         // If no duplicates are present, then GB_builder has already
27         // transplanted I_work into T->i, so this step does not need to
28         // construct T->i.  The tuple values, in S, are copied or permuted into
29         // T->x.
30 
31         if (K_work == NULL)
32         {
33 
34             int tid ;
35             #pragma omp parallel for num_threads(nthreads) schedule(static)
36             for (tid = 0 ; tid < nthreads ; tid++)
37             {
38                 int64_t tstart = tstart_slice [tid] ;
39                 int64_t tend   = tstart_slice [tid+1] ;
40                 for (int64_t t = tstart ; t < tend ; t++)
41                 {
42                     // Tx [t] = (ttype) S [t] ; with typecast
43                     GB_CAST_ARRAY_TO_ARRAY (Tx, t, S, t) ;
44                 }
45             }
46 
47         }
48         else
49         {
50 
51             int tid ;
52             #pragma omp parallel for num_threads(nthreads) schedule(static)
53             for (tid = 0 ; tid < nthreads ; tid++)
54             {
55                 int64_t tstart = tstart_slice [tid] ;
56                 int64_t tend   = tstart_slice [tid+1] ;
57                 for (int64_t t = tstart ; t < tend ; t++)
58                 {
59                     // Tx [t] = (ttype) S [K_work [t]] ; with typecast
60                     GB_CAST_ARRAY_TO_ARRAY (Tx, t, S, K_work [t]) ;
61                 }
62             }
63         }
64 
65     }
66     else
67     {
68 
69         //----------------------------------------------------------------------
70         // assemble duplicates
71         //----------------------------------------------------------------------
72 
73         // Entries in S must be copied into T->x, with any duplicates summed
74         // via the operator.  T->i must also be constructed.
75 
76         int tid ;
77         #pragma omp parallel for num_threads(nthreads) schedule(static)
78         for (tid = 0 ; tid < nthreads ; tid++)
79         {
80             int64_t my_tnz = tnz_slice [tid] ;
81             int64_t tstart = tstart_slice [tid] ;
82             int64_t tend   = tstart_slice [tid+1] ;
83 
84             // find the first unique tuple owned by this slice
85             int64_t t ;
86             for (t = tstart ; t < tend ; t++)
87             {
88                 // get the tuple and break if it is not a duplicate
89                 if (I_work [t] >= 0) break ;
90             }
91 
92             // scan all tuples and assemble any duplicates
93             for ( ; t < tend ; t++)
94             {
95                 // get the t-th tuple, a unique tuple
96                 int64_t i = I_work [t] ;
97                 int64_t k = (K_work == NULL) ? t : K_work [t] ;
98                 ASSERT (i >= 0) ;
99                 // Tx [my_tnz] = S [k] ; with typecast
100                 GB_CAST_ARRAY_TO_ARRAY (Tx, my_tnz, S, k) ;
101                 Ti [my_tnz] = i ;
102 
103                 // assemble all duplicates that follow it.  This may assemble
104                 // the first duplicates in the next slice(s) (up to but not
105                 // including the first unique tuple in the subsequent slice(s)).
106                 for ( ; t+1 < nvals && I_work [t+1] < 0 ; t++)
107                 {
108                     // assemble the duplicate tuple
109                     int64_t k = (K_work == NULL) ? (t+1) : K_work [t+1] ;
110                     // Tx [my_tnz] += S [k] with typecast
111                     GB_ADD_CAST_ARRAY_TO_ARRAY (Tx, my_tnz, S, k) ;
112                 }
113                 my_tnz++ ;
114             }
115         }
116     }
117 }
118 
119