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