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
|
//------------------------------------------------------------------------------
// GB_add_bitmap_M_sparse: C<!M>=A+B, C bitmap, M sparse/hyper and comp.
//------------------------------------------------------------------------------
// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2025, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//------------------------------------------------------------------------------
// C is bitmap.
// M is sparse/hyper and complemented.
// A and B can have any format, except at least one is bitmap/full.
{
//--------------------------------------------------------------------------
// C is bitmap, M is sparse or hyper and complemented
//--------------------------------------------------------------------------
// ------------------------------------------
// C <!M> = A + B
// ------------------------------------------
// bitmap sparse sparse bitmap
// bitmap sparse sparse full
// bitmap sparse bitmap sparse
// bitmap sparse bitmap bitmap
// bitmap sparse bitmap full
// bitmap sparse full sparse
// bitmap sparse full bitmap
// bitmap sparse full full
// M is sparse and complemented. If M is sparse and not complemented, then
// C is constructed as sparse, not bitmap.
ASSERT (Mask_comp) ;
// C(i,j) = A(i,j) + B(i,j) can only be computed where M(i,j) is not
// present in the sparse pattern of M, and where it is present but equal to
// zero.
//--------------------------------------------------------------------------
// scatter M into the C bitmap
//--------------------------------------------------------------------------
const int64_t *kfirst_Mslice = M_ek_slicing ;
const int64_t *klast_Mslice = M_ek_slicing + M_ntasks ;
const int64_t *pstart_Mslice = M_ek_slicing + M_ntasks*2 ;
#pragma omp parallel for num_threads(M_nthreads) schedule(dynamic,1)
for (taskid = 0 ; taskid < M_ntasks ; taskid++)
{
int64_t kfirst = kfirst_Mslice [taskid] ;
int64_t klast = klast_Mslice [taskid] ;
for (int64_t k = kfirst ; k <= klast ; k++)
{
// find the part of M(:,k) for this task
int64_t j = GBh_M (Mh, k) ;
GB_GET_PA (pM_start, pM_end, taskid, k, kfirst, klast,
pstart_Mslice, GB_IGET (Mp, k), GB_IGET (Mp, k+1)) ;
int64_t pC_start = j * vlen ;
// traverse over M(:,j), the kth vector of M
for (int64_t pM = pM_start ; pM < pM_end ; pM++)
{
// mark C(i,j) if M(i,j) is true
bool mij = GB_MCAST (Mx, pM, msize) ;
if (mij)
{
int64_t i = GB_IGET (Mi, pM) ;
int64_t p = pC_start + i ;
Cb [p] = 2 ;
}
}
}
}
// C(i,j) has been marked, in Cb, with the value 2 where M(i,j)=1.
// These positions will not be computed in C(i,j). C(i,j) can only
// be modified where Cb [p] is zero.
//--------------------------------------------------------------------------
// compute C<!M>=A+B using the mask scattered in C
//--------------------------------------------------------------------------
#ifdef GB_JIT_KERNEL
#if (GB_A_IS_BITMAP || GB_A_IS_FULL) && (GB_B_IS_BITMAP || GB_B_IS_FULL)
{
// A and B are both bitmap/full
#include "template/GB_add_bitmap_M_sparse_24.c"
#define M_cleared true
}
#elif (GB_A_IS_BITMAP || GB_A_IS_FULL)
{
// A is bitmap/full, B is sparse/hyper
#include "template/GB_add_bitmap_M_sparse_25.c"
#define M_cleared false
}
#else
{
// A is sparse/hyper, B is bitmap/full
#include "template/GB_add_bitmap_M_sparse_26.c"
#define M_cleared false
}
#endif
#else
bool M_cleared = false ;
if ((A_is_bitmap || A_is_full) && (B_is_bitmap || B_is_full))
{
// A and B are both bitmap/full
#include "template/GB_add_bitmap_M_sparse_24.c"
M_cleared = true ; // M has also been cleared from C
}
else if (A_is_bitmap || A_is_full)
{
// A is bitmap/full, B is sparse/hyper
#include "template/GB_add_bitmap_M_sparse_25.c"
}
else
{
// A is sparse/hyper, B is bitmap/full
#include "template/GB_add_bitmap_M_sparse_26.c"
}
#endif
//-------------------------------------------------------------------------
// clear M from C
//-------------------------------------------------------------------------
if (!M_cleared)
{
// This step is required if either A or B are sparse/hyper (if
// one is sparse/hyper, the other must be bitmap). It requires
// an extra pass over the mask M, so this might be slower than
// postponing the application of the mask, and doing it later.
#pragma omp parallel for num_threads(M_nthreads) schedule(dynamic,1)
for (taskid = 0 ; taskid < M_ntasks ; taskid++)
{
int64_t kfirst = kfirst_Mslice [taskid] ;
int64_t klast = klast_Mslice [taskid] ;
for (int64_t k = kfirst ; k <= klast ; k++)
{
// find the part of M(:,k) for this task
int64_t j = GBh_M (Mh, k) ;
GB_GET_PA (pM_start, pM_end, taskid, k, kfirst, klast,
pstart_Mslice, GB_IGET (Mp, k), GB_IGET (Mp, k+1)) ;
int64_t pC_start = j * vlen ;
// traverse over M(:,j), the kth vector of M
for (int64_t pM = pM_start ; pM < pM_end ; pM++)
{
// mark C(i,j) if M(i,j) is true
bool mij = GB_MCAST (Mx, pM, msize) ;
if (mij)
{
int64_t i = GB_IGET (Mi, pM) ;
int64_t p = pC_start + i ;
Cb [p] = 0 ;
}
}
}
}
}
}
|