1 //------------------------------------------------------------------------------
2 // GB_AxB_dot3_meta: C<M>=A'*B via dot products, where C is sparse/hypersparse
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 #define GB_DOT3
11 #define GB_DOT3_PHASE2
12 
13 #include "GB_unused.h"
14 #include "GB_AxB_dot_cij.h"
15 
16 // GB_DOT_ALWAYS_SAVE_CIJ: C(i,j) = cij
17 #if GB_CIJ_CHECK
18 
19     #define GB_DOT_ALWAYS_SAVE_CIJ      \
20     {                                   \
21         cij_exists = true ;             \
22         GB_PUTC (cij, pC) ;             \
23         Ci [pC] = i ;                   \
24     }
25 
26 #else
27 
28     #define GB_DOT_ALWAYS_SAVE_CIJ      \
29     {                                   \
30         GB_PUTC (cij, pC) ;             \
31         Ci [pC] = i ;                   \
32     }
33 
34 #endif
35 
36 // GB_DOT_SAVE_CIJ: C(i,j) = cij, if it exists
37 #define GB_DOT_SAVE_CIJ             \
38 {                                   \
39     if (GB_CIJ_EXISTS)              \
40     {                               \
41         GB_PUTC (cij, pC) ;         \
42         Ci [pC] = i ;               \
43     }                               \
44 }
45 
46 {
47 
48     //--------------------------------------------------------------------------
49     // get M, A, B, and C
50     //--------------------------------------------------------------------------
51 
52     // C and M have the same sparsity patter (both are sparse or hyper),
53     // except entries of C may become zombies.  M is not complemented.
54 
55     int64_t nzombies = 0 ;
56 
57     ASSERT (GB_IS_SPARSE (C) || GB_IS_HYPERSPARSE (C)) ;
58     const int64_t *restrict Cp = C->p ;
59     const int64_t *restrict Ch = C->h ;
60     int64_t  *restrict Ci = C->i ;
61     GB_CTYPE *restrict Cx = (GB_CTYPE *) C->x ;
62     const int64_t cvlen = C->vlen ;
63 
64     const int64_t *restrict Bp = B->p ;
65     const int64_t *restrict Bh = B->h ;
66     const int8_t  *restrict Bb = B->b ;
67     const int64_t *restrict Bi = B->i ;
68     const GB_BTYPE *restrict Bx = (GB_BTYPE *) (B_is_pattern ? NULL : B->x) ;
69     const int64_t bnvec = B->nvec ;
70     const bool B_is_hyper = GB_IS_HYPERSPARSE (B) ;
71     const bool B_is_bitmap = GB_IS_BITMAP (B) ;
72     const bool B_is_sparse = GB_IS_SPARSE (B) ;
73 
74     const int64_t *restrict Ap = A->p ;
75     const int64_t *restrict Ah = A->h ;
76     const int8_t  *restrict Ab = A->b ;
77     const int64_t *restrict Ai = A->i ;
78     const GB_ATYPE *restrict Ax = (GB_ATYPE *) (A_is_pattern ? NULL : A->x) ;
79     const int64_t anvec = A->nvec ;
80     const bool A_is_hyper = GB_IS_HYPERSPARSE (A) ;
81     const bool A_is_bitmap = GB_IS_BITMAP (A) ;
82     const bool A_is_sparse = GB_IS_SPARSE (A) ;
83 
84     const int64_t vlen = A->vlen ;
85     ASSERT (A->vlen == B->vlen) ;
86 
87     const bool M_is_sparse = GB_IS_SPARSE (M) ;
88     ASSERT (M_is_sparse || GB_IS_HYPERSPARSE (M)) ;
89     const int64_t *restrict Mi = M->i ;
90     const size_t mvlen = M->vlen ;
91 
92     //--------------------------------------------------------------------------
93     // C<M> = A'*B via dot products, where C and M are both sparse/hyper
94     //--------------------------------------------------------------------------
95 
96     // 4 possible cases of the mask are handled:
97 
98     // M can be sparse or hyper, and always present
99     // M can be structural or valued
100     // M is not complemented
101 
102     // The other 12 cases of the mask, and the one no-mask case, are handled
103     // by dot2.
104 
105     if (M_is_sparse && Mask_struct && A_is_sparse && B_is_sparse)
106     {
107         // special case: M is sparse and structural, and A and B are sparse
108         #define GB_MASK_SPARSE_AND_STRUCTURAL
109         #define GB_A_IS_SPARSE 1
110         #define GB_A_IS_HYPER  0
111         #define GB_A_IS_BITMAP 0
112         #define GB_A_IS_FULL   0
113         #define GB_B_IS_SPARSE 1
114         #define GB_B_IS_HYPER  0
115         #define GB_B_IS_BITMAP 0
116         #define GB_B_IS_FULL   0
117         #include "GB_AxB_dot3_template.c"
118         #undef GB_MASK_SPARSE_AND_STRUCTURAL
119     }
120     else
121     {
122         // general case
123         const GB_void *restrict Mx = (GB_void *) (Mask_struct ? NULL : (M->x)) ;
124         const size_t msize = M->type->size ;
125         #include "GB_meta16_factory.c"
126     }
127 
128     C->nzombies = nzombies ;
129 }
130 
131 #undef GB_DOT_ALWAYS_SAVE_CIJ
132 #undef GB_DOT_SAVE_CIJ
133 
134 #undef GB_DOT3
135 #undef GB_DOT3_PHASE2
136 
137