1 //------------------------------------------------------------------------------
2 // GB_AxB_dot2_meta: C=A'*B, C<M>=A'*B or C<!M>=A'*B via dot products
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_DOT2
11 
12 #include "GB_unused.h"
13 #include "GB_AxB_dot_cij.h"
14 
15 // GB_DOT_ALWAYS_SAVE_CIJ: C(i,j) = cij
16 #define GB_DOT_ALWAYS_SAVE_CIJ      \
17 {                                   \
18     GB_PUTC (cij, pC) ;             \
19     Cb [pC] = 1 ;                   \
20     task_cnvals++ ;                 \
21 }
22 
23 // GB_DOT_SAVE_CIJ: C(i,j) = cij, unless already done by GB_DOT
24 #if GB_IS_ANY_MONOID
25 
26     // for the ANY monoid, GB_DOT saves C(i,j) as soon as a value is found
27     #define GB_DOT_SAVE_CIJ
28 
29 #else
30 
31     // all other monoids: C(i,j) = cij if it exists
32     #define GB_DOT_SAVE_CIJ             \
33     {                                   \
34         if (GB_CIJ_EXISTS)              \
35         {                               \
36             GB_DOT_ALWAYS_SAVE_CIJ ;    \
37         }                               \
38     }
39 
40 #endif
41 
42 {
43 
44     //--------------------------------------------------------------------------
45     // get A, B, and C
46     //--------------------------------------------------------------------------
47 
48     // A and B are never hypersparse.  If they are hypersparse on input, they
49     // are converted to packed sparse form first, and the C matrix has smaller
50     // dimensions.  The C bitmap matrix is unpacked into a sparse or
51     // hypersparse matrix when done.
52 
53     int64_t cnvals = 0 ;
54 
55     ASSERT (GB_IS_BITMAP (C)) ;
56     int8_t   *restrict Cb = C->b ;
57     GB_CTYPE *restrict Cx = (GB_CTYPE *) C->x ;
58     const int64_t cvlen = C->vlen ;
59 
60     const int64_t *restrict Bp = B->p ;
61     const int8_t  *restrict Bb = B->b ;
62     const int64_t *restrict Bi = B->i ;
63     const GB_BTYPE *restrict Bx = (GB_BTYPE *) (B_is_pattern ? NULL : B->x) ;
64     const bool B_is_bitmap = GB_IS_BITMAP (B) ;
65     const bool B_is_sparse = GB_IS_SPARSE (B) ;
66     ASSERT (!GB_IS_HYPERSPARSE (B)) ;
67     #define B_is_hyper false
68 
69     const int64_t *restrict Ap = A->p ;
70     const int8_t  *restrict Ab = A->b ;
71     const int64_t *restrict Ai = A->i ;
72     const GB_ATYPE *restrict Ax = (GB_ATYPE *) (A_is_pattern ? NULL : A->x) ;
73     const bool A_is_bitmap = GB_IS_BITMAP (A) ;
74     const bool A_is_sparse = GB_IS_SPARSE (A) ;
75     ASSERT (!GB_IS_HYPERSPARSE (A)) ;
76     #define A_is_hyper false
77 
78     const int64_t vlen = A->vlen ;
79     ASSERT (A->vlen == B->vlen) ;
80 
81     const int ntasks = naslice * nbslice ;
82 
83     //--------------------------------------------------------------------------
84     // C=A'*B, C<M>=A'*B, or C<!M>=A'*B via dot products
85     //--------------------------------------------------------------------------
86 
87     if (M == NULL)
88     {
89 
90         //----------------------------------------------------------------------
91         // C = A'*B
92         //----------------------------------------------------------------------
93 
94         #undef GB_MASK_IS_PRESENT
95         #include "GB_meta16_factory.c"
96 
97     }
98     else
99     {
100 
101         //----------------------------------------------------------------------
102         // C<M>=A'*B or C<!M>=A'*B
103         //----------------------------------------------------------------------
104 
105         // 12 possible cases of the mask are handled:
106 
107         // if M is not complemented (Mask_comp is false): 4 cases
108         // M can be bitmap or full, not sparse or hyper (dot3 handles that)
109         // M can be structural or valued
110 
111         // if M is complemented (Mask_comp is true): 8 cases
112         // M can be sparse, hyper, bitmap, or full
113         // M can be structural or valued
114 
115         const int8_t *restrict Mb = M->b ;
116         const bool M_is_bitmap = GB_IS_BITMAP (M) ;
117         const bool M_is_full = GB_IS_FULL (M) ;
118 
119         #if ( GB_IS_ANY_MONOID )
120         if (B_is_bitmap && A_is_sparse && M_is_bitmap && Mask_struct
121             && Mask_comp)
122         {
123 
124             //------------------------------------------------------------------
125             // C<#M,struct> = A'*B, special case
126             //------------------------------------------------------------------
127 
128             // GB_ANY_SPECIALIZED is defined if the following conditions hold:
129             // semirings: all built-in semirings with the ANY monoid
130             // A: sparse
131             // B: bitmap
132             // M: bitmap
133             // Mask_comp: true
134             // Mask_struct: true
135 
136             GBURBLE ("(specialized) ") ;
137             #define GB_ANY_SPECIALIZED
138             #define GB_MASK_IS_PRESENT
139             #define GB_A_IS_SPARSE 1
140             #define GB_A_IS_HYPER  0
141             #define GB_A_IS_BITMAP 0
142             #define GB_A_IS_FULL   0
143             #define GB_B_IS_SPARSE 0
144             #define GB_B_IS_SPARSE 0
145             #define GB_B_IS_BITMAP 1
146             #define GB_B_IS_FULL   0
147             #include "GB_AxB_dot2_template.c"
148             #undef  GB_ANY_SPECIALIZED
149             #undef GB_MASK_IS_PRESENT
150 
151         }
152         else
153         #endif
154         {
155 
156             //------------------------------------------------------------------
157             // C<M>=A'*B or C<!M>=A'*B
158             //------------------------------------------------------------------
159 
160             const GB_void *restrict Mx = (GB_void *)
161                 (Mask_struct ? NULL : (M->x)) ;
162             const size_t msize = M->type->size ;
163 
164             #define GB_MASK_IS_PRESENT
165             #include "GB_meta16_factory.c"
166             #undef GB_MASK_IS_PRESENT
167 
168         }
169     }
170 
171     C->nvals = cnvals ;
172 }
173 
174 #undef A_is_hyper
175 #undef B_is_hyper
176 
177 #undef GB_DOT_ALWAYS_SAVE_CIJ
178 #undef GB_DOT_SAVE_CIJ
179 
180 #undef GB_DOT2
181 
182