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