1 //------------------------------------------------------------------------------
2 // GB_emult_03_template: C<M>= A.*B, M sparse/hyper, A and B bitmap/full
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 // C is sparse, with the same sparsity structure as M.
11 // A and B are both bitmap/full.
12 
13 {
14 
15     //--------------------------------------------------------------------------
16     // get M, A, B, and C
17     //--------------------------------------------------------------------------
18 
19     const int8_t *restrict Ab = A->b ;
20     const int8_t *restrict Bb = B->b ;
21 
22     const GB_ATYPE *restrict Ax = (GB_ATYPE *) A->x ;
23     const GB_BTYPE *restrict Bx = (GB_BTYPE *) B->x ;
24 
25     const int64_t *restrict Mp = M->p ;
26     const int64_t *restrict Mh = M->h ;
27     const int64_t *restrict Mi = M->i ;
28     const GB_void *restrict Mx = (GB_void *) ((Mask_struct) ? NULL : M->x) ;
29     const int64_t vlen = M->vlen ;
30     const size_t  msize = M->type->size ;
31 
32     const int64_t  *restrict Cp = C->p ;
33           int64_t  *restrict Ci = C->i ;
34           GB_CTYPE *restrict Cx = (GB_CTYPE *) C->x ;
35 
36     const int64_t *restrict kfirst_Mslice = M_ek_slicing ;
37     const int64_t *restrict klast_Mslice  = M_ek_slicing + M_ntasks ;
38     const int64_t *restrict pstart_Mslice = M_ek_slicing + M_ntasks * 2 ;
39 
40     //--------------------------------------------------------------------------
41     // C<M>=A.*B where M is sparse/hyper, A and B are bitmap/full
42     //--------------------------------------------------------------------------
43 
44     int tid ;
45     #pragma omp parallel for num_threads(M_nthreads) schedule(dynamic,1)
46     for (tid = 0 ; tid < M_ntasks ; tid++)
47     {
48         int64_t kfirst = kfirst_Mslice [tid] ;
49         int64_t klast  = klast_Mslice  [tid] ;
50         for (int64_t k = kfirst ; k <= klast ; k++)
51         {
52             int64_t j = GBH (Mh, k) ;
53             int64_t pstart = j * vlen ;
54             int64_t pM, pM_end, pC ;
55             GB_get_pA_and_pC (&pM, &pM_end, &pC, tid, k, kfirst, klast,
56                 pstart_Mslice, Cp_kfirst, Cp, vlen, Mp, vlen) ;
57             for ( ; pM < pM_end ; pM++)
58             {
59                 int64_t i = Mi [pM] ;
60                 if (GB_mcast (Mx, pM, msize) &&
61                     (GBB (Ab, pstart + i)
62                     &&  // TODO: for GB_add, use || instead
63                     GBB (Bb, pstart + i)))
64                 {
65                     int64_t p = pstart + i ;
66                     // C (i,j) = A (i,j) .* B (i,j)
67                     Ci [pC] = i ;
68                     GB_GETA (aij, Ax, p) ;
69                     GB_GETB (bij, Bx, p) ;
70                     GB_BINOP (GB_CX (pC), aij, bij, i, j) ;
71                     pC++ ;
72                 }
73             }
74         }
75     }
76 }
77 
78