File: GB_AxB_dot3_meta.c

package info (click to toggle)
suitesparse-graphblas 7.4.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 67,112 kB
  • sloc: ansic: 1,072,243; cpp: 8,081; sh: 512; makefile: 506; asm: 369; python: 125; awk: 10
file content (157 lines) | stat: -rw-r--r-- 5,161 bytes parent folder | download | duplicates (2)
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
//------------------------------------------------------------------------------
// GB_AxB_dot3_meta: C<M>=A'*B via dot products, where C is sparse/hypersparse
//------------------------------------------------------------------------------

// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//------------------------------------------------------------------------------

#define GB_DOT3
#define GB_DOT3_PHASE2

#include "GB_unused.h"
#include "GB_AxB_dot_cij.h"

// GB_DOT_ALWAYS_SAVE_CIJ: C(i,j) = cij
#if GB_CIJ_CHECK

    #define GB_DOT_ALWAYS_SAVE_CIJ      \
    {                                   \
        cij_exists = true ;             \
        GB_PUTC (cij, pC) ;             \
        Ci [pC] = i ;                   \
    }

#else

    #define GB_DOT_ALWAYS_SAVE_CIJ      \
    {                                   \
        GB_PUTC (cij, pC) ;             \
        Ci [pC] = i ;                   \
    }

#endif

// GB_DOT_SAVE_CIJ: C(i,j) = cij, if it exists
#define GB_DOT_SAVE_CIJ             \
{                                   \
    if (GB_CIJ_EXISTS)              \
    {                               \
        GB_PUTC (cij, pC) ;         \
        Ci [pC] = i ;               \
    }                               \
}

{

    //--------------------------------------------------------------------------
    // get M, A, B, and C
    //--------------------------------------------------------------------------

    // C and M have the same sparsity patter (both are sparse or hyper),
    // except entries of C may become zombies.  M is not complemented.

    int64_t nzombies = 0 ;

    ASSERT (GB_IS_SPARSE (C) || GB_IS_HYPERSPARSE (C)) ;
    const int64_t *restrict Cp = C->p ;
    const int64_t *restrict Ch = C->h ;
    int64_t  *restrict Ci = C->i ;
    const int64_t cvlen = C->vlen ;

    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 int64_t bnvec = B->nvec ;
    const bool B_is_hyper = GB_IS_HYPERSPARSE (B) ;
    const bool B_is_bitmap = GB_IS_BITMAP (B) ;
    const bool B_is_sparse = GB_IS_SPARSE (B) ;
    const bool B_iso = B->iso ;

    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 anvec = A->nvec ;
    const bool A_is_hyper = GB_IS_HYPERSPARSE (A) ;
    const bool A_is_bitmap = GB_IS_BITMAP (A) ;
    const bool A_is_sparse = GB_IS_SPARSE (A) ;
    const bool A_iso = A->iso ;

    const GrB_Matrix A_Y = A->Y ;
    const int64_t *restrict A_Yp = (A_is_hyper) ? A_Y->p : NULL ;
    const int64_t *restrict A_Yi = (A_is_hyper) ? A_Y->i : NULL ;
    const int64_t *restrict A_Yx = (A_is_hyper) ? A_Y->x : NULL ;
    const int64_t A_hash_bits = (A_is_hyper) ? (A_Y->vdim - 1) : 0 ;

    const GrB_Matrix B_Y = B->Y ;
    const int64_t *restrict B_Yp = (B_is_hyper) ? B_Y->p : NULL ;
    const int64_t *restrict B_Yi = (B_is_hyper) ? B_Y->i : NULL ;
    const int64_t *restrict B_Yx = (B_is_hyper) ? B_Y->x : NULL ;
    const int64_t B_hash_bits = (B_is_hyper) ? (B_Y->vdim - 1) : 0 ;

    #if !GB_A_IS_PATTERN
    const GB_ATYPE *restrict Ax = (GB_ATYPE *) A->x ;
    #endif
    #if !GB_B_IS_PATTERN
    const GB_BTYPE *restrict Bx = (GB_BTYPE *) B->x ;
    #endif
    #if !GB_IS_ANY_PAIR_SEMIRING
          GB_CTYPE *restrict Cx = (GB_CTYPE *) C->x ;
    #endif

    const int64_t vlen = A->vlen ;
    ASSERT (A->vlen == B->vlen) ;

    const bool M_is_sparse = GB_IS_SPARSE (M) ;
    ASSERT (M_is_sparse || GB_IS_HYPERSPARSE (M)) ;
    const int64_t *restrict Mi = M->i ;
    const size_t mvlen = M->vlen ;

    //--------------------------------------------------------------------------
    // C<M> = A'*B via dot products, where C and M are both sparse/hyper
    //--------------------------------------------------------------------------

    // 4 possible cases of the mask are handled:

    // M can be sparse or hyper, and always present
    // M can be structural or valued
    // M is not complemented

    // The other 12 cases of the mask, and the one no-mask case, are handled
    // by dot2.

    if (M_is_sparse && Mask_struct && A_is_sparse && B_is_sparse)
    { 
        // special case: M is sparse and structural, and A and B are sparse
        #define GB_MASK_SPARSE_AND_STRUCTURAL
        #define GB_A_IS_SPARSE 1
        #define GB_A_IS_HYPER  0
        #define GB_A_IS_BITMAP 0
        #define GB_A_IS_FULL   0
        #define GB_B_IS_SPARSE 1
        #define GB_B_IS_HYPER  0
        #define GB_B_IS_BITMAP 0
        #define GB_B_IS_FULL   0
        #include "GB_AxB_dot3_template.c"
        #undef GB_MASK_SPARSE_AND_STRUCTURAL
    }
    else
    { 
        // general case
        const GB_void *restrict Mx = (GB_void *) (Mask_struct ? NULL : (M->x)) ;
        const size_t msize = M->type->size ;
        #include "GB_meta16_factory.c"
    }

    C->nzombies = nzombies ;
}

#undef GB_DOT_ALWAYS_SAVE_CIJ
#undef GB_DOT_SAVE_CIJ

#undef GB_DOT3
#undef GB_DOT3_PHASE2