1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
//------------------------------------------------------------------------------
// GB_add_template: phase1 and phase2 for C=A+B, C<M>=A+B, C<!M>=A+B
//------------------------------------------------------------------------------
// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//------------------------------------------------------------------------------
// Computes C=A+B, C<M>=A+B, or C<!M>=A+B.
// M can have any sparsity structure:
// If M is not present, bitmap, or full, then A and B are sparse or
// hypersparse. They are not bitmap or full, since in those cases,
// C will not be sparse/hypersparse, and this method is not used.
// Otherwise, if M is present and sparse/hypersparse, then A and B can
// have any sparsity pattern (hyper, sparse, bitmap, or full).
// phase1: does not compute C itself, but just counts the # of entries in each
// vector of C. Fine tasks compute the # of entries in their slice of a
// single vector of C, and the results are cumsum'd.
// phase2: computes C, using the counts computed by phase1.
#undef GB_FREE_WORKSPACE
#define GB_FREE_WORKSPACE \
{ \
GB_WERK_POP (B_ek_slicing, int64_t) ; \
GB_WERK_POP (A_ek_slicing, int64_t) ; \
GB_WERK_POP (M_ek_slicing, int64_t) ; \
}
#undef GB_FREE_ALL
#define GB_FREE_ALL \
{ \
GB_FREE_WORKSPACE ; \
GB_phybix_free (C) ; \
}
{
//--------------------------------------------------------------------------
// get A, B, M, and C
//--------------------------------------------------------------------------
int taskid ;
const int64_t *restrict Ap = A->p ;
const int64_t *restrict Ah = A->h ;
const int8_t *restrict Ab = A->b ;
const int64_t *restrict Ai = A->i ;
const int64_t vlen = A->vlen ;
const bool A_is_hyper = GB_IS_HYPERSPARSE (A) ;
const bool A_is_sparse = GB_IS_SPARSE (A) ;
const bool A_is_bitmap = GB_IS_BITMAP (A) ;
const bool A_is_full = GB_as_if_full (A) ;
int A_nthreads, A_ntasks ;
const int64_t *restrict Bp = B->p ;
const int64_t *restrict Bh = B->h ;
const int8_t *restrict Bb = B->b ;
const int64_t *restrict Bi = B->i ;
const bool B_is_hyper = GB_IS_HYPERSPARSE (B) ;
const bool B_is_sparse = GB_IS_SPARSE (B) ;
const bool B_is_bitmap = GB_IS_BITMAP (B) ;
const bool B_is_full = GB_as_if_full (B) ;
int B_nthreads, B_ntasks ;
const int64_t *restrict Mp = NULL ;
const int64_t *restrict Mh = NULL ;
const int8_t *restrict Mb = NULL ;
const int64_t *restrict Mi = NULL ;
const GB_void *restrict Mx = NULL ;
const bool M_is_hyper = GB_IS_HYPERSPARSE (M) ;
const bool M_is_sparse = GB_IS_SPARSE (M) ;
const bool M_is_bitmap = GB_IS_BITMAP (M) ;
const bool M_is_full = GB_as_if_full (M) ;
const bool M_is_sparse_or_hyper = M_is_sparse || M_is_hyper ;
int M_nthreads, M_ntasks ;
size_t msize = 0 ;
if (M != NULL)
{
Mp = M->p ;
Mh = M->h ;
Mb = M->b ;
Mi = M->i ;
Mx = (GB_void *) (Mask_struct ? NULL : (M->x)) ;
msize = M->type->size ;
}
#if defined ( GB_PHASE_2_OF_2 )
#ifdef GB_ISO_ADD
ASSERT (C->iso) ;
#else
const GB_ATYPE *restrict Ax = (GB_ATYPE *) A->x ;
const GB_BTYPE *restrict Bx = (GB_BTYPE *) B->x ;
GB_CTYPE *restrict Cx = (GB_CTYPE *) C->x ;
ASSERT (!C->iso) ;
#endif
// unlike GB_emult, both A and B may be iso
const bool A_iso = A->iso ;
const bool B_iso = B->iso ;
const int64_t *restrict Cp = C->p ;
const int64_t *restrict Ch = C->h ;
int8_t *restrict Cb = C->b ;
int64_t *restrict Ci = C->i ;
// when C is bitmap or full:
const int64_t cnz = GB_nnz_held (C) ;
GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
#endif
//--------------------------------------------------------------------------
// C=A+B, C<M>=A+B, or C<!M>=A+B: 3 cases for the sparsity of C
//--------------------------------------------------------------------------
#if defined ( GB_PHASE_1_OF_2 )
// phase1: symbolic phase
// C is sparse or hypersparse (never bitmap or full)
// Werk allocated: none
#include "GB_sparse_add_template.c"
#else
// phase2: numerical phase
#ifdef GB_POSITIONAL_OP
// op doesn't depend aij, bij, alpha_scalar, or beta_scalar
#define GB_LOAD_A(aij, Ax,pA,A_iso)
#define GB_LOAD_B(bij, Bx,pB,B_iso)
#else
#define GB_LOAD_A(aij, Ax,pA,A_iso) GB_GETA(aij, Ax,pA,A_iso)
#define GB_LOAD_B(bij, Bx,pB,B_iso) GB_GETB(bij, Bx,pB,B_iso)
#endif
#ifndef GB_ISO_ADD
if (is_eWiseUnion)
{
//------------------------------------------------------------------
// eWiseUnion, using alpha and beta scalars
//------------------------------------------------------------------
#define GB_EWISEUNION
// if A(i,j) is not present: C(i,j) = alpha + B(i,j)
// if B(i,j) is not present: C(i,j) = A(i,j) + beta
if (C_sparsity == GxB_SPARSE || C_sparsity == GxB_HYPERSPARSE)
{
// C is sparse or hypersparse
// Werk allocated: none
#include "GB_sparse_add_template.c"
}
else if (C_sparsity == GxB_BITMAP)
{
// C is bitmap (phase2 only)
// Werk: slice M and A, M and B, just A, or just B, or none
#include "GB_bitmap_add_template.c"
}
else
{
// C is full (phase2 only)
ASSERT (C_sparsity == GxB_FULL) ;
// Werk: slice just A, just B, or none
#include "GB_full_add_template.c"
}
}
else
#endif
{
//------------------------------------------------------------------
// eWiseAdd:
//------------------------------------------------------------------
#undef GB_EWISEUNION
// if A(i,j) is not present: C(i,j) = B(i,j)
// if B(i,j) is not present: C(i,j) = A(i,j)
if (C_sparsity == GxB_SPARSE || C_sparsity == GxB_HYPERSPARSE)
{
// C is sparse or hypersparse
// Werk allocated: none
#include "GB_sparse_add_template.c"
}
else if (C_sparsity == GxB_BITMAP)
{
// C is bitmap (phase2 only)
// Werk: slice M and A, M and B, just A, or just B, or none
#include "GB_bitmap_add_template.c"
}
else
{
// C is full (phase2 only)
ASSERT (C_sparsity == GxB_FULL) ;
// Werk: slice just A, just B, or none
#include "GB_full_add_template.c"
}
}
#endif
}
#undef GB_ISO_ADD
#undef GB_LOAD_A
#undef GB_LOAD_B
|