1 //------------------------------------------------------------------------------
2 // GB_concat_sparse_template: concatenate a tile into a sparse matrix
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 // The tile A is hypersparse, sparse, or full, not bitmap.
11 
12 {
13 
14     //--------------------------------------------------------------------------
15     // get C and the tile A
16     //--------------------------------------------------------------------------
17 
18     const GB_CTYPE *restrict Ax = (GB_CTYPE *) A->x ;
19     GB_CTYPE *restrict Cx = (GB_CTYPE *) C->x ;
20 
21     //--------------------------------------------------------------------------
22     // copy the tile A into C
23     //--------------------------------------------------------------------------
24 
25     int tid ;
26     #pragma omp parallel for num_threads(A_nthreads) schedule(static)
27     for (tid = 0 ; tid < A_ntasks ; tid++)
28     {
29         int64_t kfirst = kfirst_Aslice [tid] ;
30         int64_t klast  = klast_Aslice  [tid] ;
31         for (int64_t k = kfirst ; k <= klast ; k++)
32         {
33             int64_t j = GBH (Ah, k) ;
34             const int64_t pC_start = W [j] ;
35 
36             //------------------------------------------------------------------
37             // find the part of the kth vector A(:,j) for this task
38             //------------------------------------------------------------------
39 
40             int64_t pA_start, pA_end ;
41             // as done by GB_get_pA, but also get p0 = Ap [k]
42             const int64_t p0 = GBP (Ap, k, avlen) ;
43             const int64_t p1 = GBP (Ap, k+1, avlen) ;
44             if (k == kfirst)
45             {
46                 // First vector for task tid; may only be partially owned.
47                 pA_start = pstart_Aslice [tid] ;
48                 pA_end   = GB_IMIN (p1, pstart_Aslice [tid+1]) ;
49             }
50             else if (k == klast)
51             {
52                 // Last vector for task tid; may only be partially owned.
53                 pA_start = p0 ;
54                 pA_end   = pstart_Aslice [tid+1] ;
55             }
56             else
57             {
58                 // task tid entirely owns this vector A(:,k).
59                 pA_start = p0 ;
60                 pA_end   = p1 ;
61             }
62 
63             //------------------------------------------------------------------
64             // append A(:,j) onto C(:,j)
65             //------------------------------------------------------------------
66 
67             GB_PRAGMA_SIMD
68             for (int64_t pA = pA_start ; pA < pA_end ; pA++)
69             {
70                 int64_t i = GBI (Ai, pA, avlen) ;       // i = Ai [pA]
71                 int64_t pC = pC_start + pA - p0 ;
72                 Ci [pC] = cistart + i ;
73                 // Cx [pC] = Ax [pA] ;
74                 GB_COPY (pC, pA) ;
75             }
76         }
77     }
78 
79     done = true ;
80 }
81 
82 #undef GB_CTYPE
83 
84