1 //------------------------------------------------------------------------------
2 // GB_add_template:  phase1 and phase2 for C=A+B, C<M>=A+B, C<!M>=A+B
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 // Computes C=A+B, C<M>=A+B, or C<!M>=A+B.
11 
12 // M can have any sparsity structure:
13 
14 //      If M is not present, bitmap, or full, then A and B are sparse or
15 //      hypersparse.  They are not bitmap or full, since in those cases,
16 //      C will not be sparse/hypersparse, and this method is not used.
17 
18 //      Otherwise, if M is present and sparse/hypersparse, then A and B can
19 //      have any sparsity pattern (hyper, sparse, bitmap, or full).
20 
21 // phase1: does not compute C itself, but just counts the # of entries in each
22 // vector of C.  Fine tasks compute the # of entries in their slice of a
23 // single vector of C, and the results are cumsum'd.
24 
25 // phase2: computes C, using the counts computed by phase1.
26 
27 #undef  GB_FREE_WORK
28 #define GB_FREE_WORK                        \
29 {                                           \
30     GB_WERK_POP (B_ek_slicing, int64_t) ;   \
31     GB_WERK_POP (A_ek_slicing, int64_t) ;   \
32     GB_WERK_POP (M_ek_slicing, int64_t) ;   \
33 }
34 
35 #undef  GB_FREE_ALL
36 #define GB_FREE_ALL                 \
37 {                                   \
38     GB_FREE_WORK ;                  \
39     GB_phbix_free (C) ;             \
40 }
41 
42 {
43 
44     //--------------------------------------------------------------------------
45     // get A, B, M, and C
46     //--------------------------------------------------------------------------
47 
48     int taskid ;
49 
50     const int64_t *restrict Ap = A->p ;
51     const int64_t *restrict Ah = A->h ;
52     const int8_t  *restrict Ab = A->b ;
53     const int64_t *restrict Ai = A->i ;
54     const int64_t vlen = A->vlen ;
55     const bool A_is_hyper = GB_IS_HYPERSPARSE (A) ;
56     const bool A_is_sparse = GB_IS_SPARSE (A) ;
57     const bool A_is_bitmap = GB_IS_BITMAP (A) ;
58     const bool A_is_full = GB_as_if_full (A) ;
59     int A_nthreads, A_ntasks ;
60 
61     const int64_t *restrict Bp = B->p ;
62     const int64_t *restrict Bh = B->h ;
63     const int8_t  *restrict Bb = B->b ;
64     const int64_t *restrict Bi = B->i ;
65     const bool B_is_hyper = GB_IS_HYPERSPARSE (B) ;
66     const bool B_is_sparse = GB_IS_SPARSE (B) ;
67     const bool B_is_bitmap = GB_IS_BITMAP (B) ;
68     const bool B_is_full = GB_as_if_full (B) ;
69     int B_nthreads, B_ntasks ;
70 
71     const int64_t *restrict Mp = NULL ;
72     const int64_t *restrict Mh = NULL ;
73     const int8_t  *restrict Mb = NULL ;
74     const int64_t *restrict Mi = NULL ;
75     const GB_void *restrict Mx = NULL ;
76     const bool M_is_hyper = GB_IS_HYPERSPARSE (M) ;
77     const bool M_is_sparse = GB_IS_SPARSE (M) ;
78     const bool M_is_bitmap = GB_IS_BITMAP (M) ;
79     const bool M_is_full = GB_as_if_full (M) ;
80     const bool M_is_sparse_or_hyper = M_is_sparse || M_is_hyper ;
81     int M_nthreads, M_ntasks ;
82     size_t msize = 0 ;
83     if (M != NULL)
84     {
85         Mp = M->p ;
86         Mh = M->h ;
87         Mb = M->b ;
88         Mi = M->i ;
89         Mx = (GB_void *) (Mask_struct ? NULL : (M->x)) ;
90         msize = M->type->size ;
91     }
92 
93     #if defined ( GB_PHASE_2_OF_2 )
94     const GB_ATYPE *restrict Ax = (GB_ATYPE *) A->x ;
95     const GB_BTYPE *restrict Bx = (GB_BTYPE *) B->x ;
96     const int64_t  *restrict Cp = C->p ;
97     const int64_t  *restrict Ch = C->h ;
98           int8_t   *restrict Cb = C->b ;
99           int64_t  *restrict Ci = C->i ;
100           GB_CTYPE *restrict Cx = (GB_CTYPE *) C->x ;
101     // when C is bitmap or full:
102     const int64_t cnz = GB_NNZ_HELD (C) ;
103     GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
104     #endif
105 
106     //--------------------------------------------------------------------------
107     // C=A+B, C<M>=A+B, or C<!M>=A+B: 3 cases for the sparsity of C
108     //--------------------------------------------------------------------------
109 
110     #if defined ( GB_PHASE_1_OF_2 )
111 
112         // phase1: symbolic phase
113         // C is sparse or hypersparse (never bitmap or full)
114         // Werk allocated: none
115         #include "GB_sparse_add_template.c"
116 
117     #else
118 
119         // phase2: numerical phase
120         if (C_sparsity == GxB_SPARSE || C_sparsity == GxB_HYPERSPARSE)
121         {
122             // C is sparse or hypersparse
123             // Werk allocated: none
124             #include "GB_sparse_add_template.c"
125         }
126         else if (C_sparsity == GxB_BITMAP)
127         {
128             // C is bitmap (phase2 only)
129             // Werk: slice M and A, M and B, just A, or just B, or none
130             #include "GB_bitmap_add_template.c"
131         }
132         else
133         {
134             // C is full (phase2 only)
135             ASSERT (C_sparsity == GxB_FULL) ;
136             // Werk: slice just A, just B, or none
137             #include "GB_full_add_template.c"
138         }
139 
140     #endif
141 }
142 
143