File: GB_bitmap_subref.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 (265 lines) | stat: -rw-r--r-- 10,631 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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
//------------------------------------------------------------------------------
// GB_bitmap_subref: C = A(I,J) where A is bitmap or full
//------------------------------------------------------------------------------

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

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

// C=A(I,J), where A is bitmap or full, symbolic and numeric.
// See GB_subref for details.

#include "GB_subref.h"
#include "GB_subassign_IxJ_slice.h"

#define GB_FREE_ALL             \
{                               \
    GB_phybix_free (C) ;        \
}

GrB_Info GB_bitmap_subref       // C = A(I,J): either symbolic or numeric
(
    // output
    GrB_Matrix C,               // output matrix, static header
    // input, not modified
    const bool C_iso,           // if true, C is iso
    const GB_void *cscalar,     // scalar value of C, if iso
    const bool C_is_csc,        // requested format of C
    const GrB_Matrix A,
    const GrB_Index *I,         // index list for C = A(I,J), or GrB_ALL, etc.
    const int64_t ni,           // length of I, or special
    const GrB_Index *J,         // index list for C = A(I,J), or GrB_ALL, etc.
    const int64_t nj,           // length of J, or special
    const bool symbolic,        // if true, construct C as symbolic
    GB_Context Context
)
{

    //--------------------------------------------------------------------------
    // check inputs
    //--------------------------------------------------------------------------

    GrB_Info info ;
    ASSERT (C != NULL && (C->static_header || GBNSTATIC)) ;
    ASSERT_MATRIX_OK (A, "A for C=A(I,J) bitmap subref", GB0) ;
    ASSERT (GB_IS_BITMAP (A) || GB_IS_FULL (A)) ;
    ASSERT (!GB_IS_SPARSE (A)) ;
    ASSERT (!GB_IS_HYPERSPARSE (A)) ;
    ASSERT (!GB_ZOMBIES (A)) ;
    ASSERT (!GB_JUMBLED (A)) ;
    ASSERT (!GB_PENDING (A)) ;

    //--------------------------------------------------------------------------
    // get A
    //--------------------------------------------------------------------------

    const int8_t *restrict Ab = A->b ;
    const int64_t avlen = A->vlen ;
    const int64_t avdim = A->vdim ;
    const size_t asize = A->type->size ;

    //--------------------------------------------------------------------------
    // check the properties of I and J
    //--------------------------------------------------------------------------

    // C = A(I,J) so I is in range 0:avlen-1 and J is in range 0:avdim-1
    int64_t nI, nJ, Icolon [3], Jcolon [3] ;
    int Ikind, Jkind ;
    GB_ijlength (I, ni, avlen, &nI, &Ikind, Icolon) ;
    GB_ijlength (J, nj, avdim, &nJ, &Jkind, Jcolon) ;

    bool I_unsorted, I_has_dupl, I_contig, J_unsorted, J_has_dupl, J_contig ;
    int64_t imin, imax, jmin, jmax ;

    info = GB_ijproperties (I, ni, nI, avlen, &Ikind, Icolon,
        &I_unsorted, &I_has_dupl, &I_contig, &imin, &imax, Context) ;
    if (info != GrB_SUCCESS)
    { 
        // I invalid
        return (info) ;
    }

    info = GB_ijproperties (J, nj, nJ, avdim, &Jkind, Jcolon,
        &J_unsorted, &J_has_dupl, &J_contig, &jmin, &jmax, Context) ;
    if (info != GrB_SUCCESS)
    { 
        // J invalid
        return (info) ;
    }

    //--------------------------------------------------------------------------
    // allocate C
    //--------------------------------------------------------------------------

    int64_t cnzmax ;
    bool ok = GB_int64_multiply ((GrB_Index *) (&cnzmax), nI, nJ) ;
    if (!ok) cnzmax = INT64_MAX ;
    GrB_Type ctype = symbolic ? GrB_INT64 : A->type ;
    int sparsity = GB_IS_BITMAP (A) ? GxB_BITMAP : GxB_FULL ;
    // set C->iso = C_iso   OK
    GB_OK (GB_new_bix (&C, // bitmap or full, existing header
        ctype, nI, nJ, GB_Ap_null, C_is_csc,
        sparsity, true, A->hyper_switch, -1, cnzmax, true, C_iso, Context)) ;

    //--------------------------------------------------------------------------
    // get C
    //--------------------------------------------------------------------------

    int8_t *restrict Cb = C->b ;

    // In GB_bitmap_assign_IxJ_template, vlen is the vector length of the
    // submatrix C(I,J), but here the template is used to access A(I,J), and so
    // the vector length is A->vlen, not C->vlen.  The pointers pA and pC are
    // swapped in the macros below, since C=A(I,J) is being computed, instead
    // of C(I,J)=A for the bitmap assignment.

    int64_t vlen = avlen ;

    //--------------------------------------------------------------------------
    // C = A(I,J)
    //--------------------------------------------------------------------------

    int64_t cnvals = 0 ;

    if (sparsity == GxB_BITMAP)
    {

        //----------------------------------------------------------------------
        // C = A (I,J) where A and C are both bitmap
        //----------------------------------------------------------------------

        // symbolic subref is only used by GB_subassign_symbolic, which only
        // operates on a matrix that is hypersparse, sparse, or full, but not
        // bitmap.  As a result, the symbolic subref C=A(I,J) where both A and
        // C are bitmap is not needed.  The code is left here in case it is
        // needed in the future.

        ASSERT (!symbolic) ;

        #if 0
        if (symbolic)
        {
            // C=A(I,J) symbolic with A and C bitmap
            ASSERT (GB_DEAD_CODE) ;
            int64_t *restrict Cx = (int64_t *) C->x ;
            #undef  GB_IXJ_WORK
            #define GB_IXJ_WORK(pA,pC)                                      \
            {                                                               \
                int8_t ab = Ab [pA] ;                                       \
                Cb [pC] = ab ;                                              \
                Cx [pC] = pA ;                                              \
                task_cnvals += ab ;                                         \
            }
            #include "GB_bitmap_assign_IxJ_template.c"
        }
        else
        #endif

        if (C_iso)
        { 

            //------------------------------------------------------------------
            // C=A(I,J) iso numeric with A and C bitmap
            //------------------------------------------------------------------

            memcpy (C->x, cscalar, ctype->size) ;
            #undef  GB_IXJ_WORK
            #define GB_IXJ_WORK(pA,pC)                                      \
            {                                                               \
                int8_t ab = Ab [pA] ;                                       \
                Cb [pC] = ab ;                                              \
                task_cnvals += ab ;                                         \
            }
            #include "GB_bitmap_assign_IxJ_template.c"

        }
        else
        { 

            //------------------------------------------------------------------
            // C=A(I,J) non-iso numeric with A and C bitmap; both non-iso
            //------------------------------------------------------------------

            const GB_void *restrict Ax = (GB_void *) A->x ;
                  GB_void *restrict Cx = (GB_void *) C->x ;
            #undef  GB_IXJ_WORK
            #define GB_IXJ_WORK(pA,pC)                                      \
            {                                                               \
                int8_t ab = Ab [pA] ;                                       \
                Cb [pC] = ab ;                                              \
                if (ab)                                                     \
                {                                                           \
                    /* Cx [pC] = Ax [pA] */                                 \
                    memcpy (Cx +((pC)*asize), Ax +((pA)*asize), asize) ;    \
                    task_cnvals++ ;                                         \
                }                                                           \
            }
            #include "GB_bitmap_assign_IxJ_template.c"

        }

        C->nvals = cnvals ;

    }
    else
    {

        //----------------------------------------------------------------------
        // C = A (I,J) where A and C are both full
        //----------------------------------------------------------------------

        if (symbolic)
        { 

            //------------------------------------------------------------------
            // C=A(I,J) symbolic with A and C full (from GB_subassign_symbolic)
            //------------------------------------------------------------------

            int64_t *restrict Cx = (int64_t *) C->x ;
            #undef  GB_IXJ_WORK
            #define GB_IXJ_WORK(pA,pC)                                      \
            {                                                               \
                Cx [pC] = pA ;                                              \
            }
            #include "GB_bitmap_assign_IxJ_template.c"

        }
        else if (C_iso)
        { 

            //------------------------------------------------------------------
            // C=A(I,J) iso numeric with A and C full
            //------------------------------------------------------------------

            memcpy (C->x, cscalar, ctype->size) ;

        }
        else
        { 

            //------------------------------------------------------------------
            // C=A(I,J) non-iso numeric with A and C full, both are non-iso
            //------------------------------------------------------------------

            const GB_void *restrict Ax = (GB_void *) A->x ;
                  GB_void *restrict Cx = (GB_void *) C->x ;
            #undef  GB_IXJ_WORK
            #define GB_IXJ_WORK(pA,pC)                                      \
            {                                                               \
                /* Cx [pC] = Ax [pA] */                                     \
                memcpy (Cx +((pC)*asize), Ax +((pA)*asize), asize) ;        \
            }
            #include "GB_bitmap_assign_IxJ_template.c"
        }
    }

    //--------------------------------------------------------------------------
    // return result
    //--------------------------------------------------------------------------

    C->magic = GB_MAGIC ;
    ASSERT_MATRIX_OK (C, "C output for bitmap subref C=A(I,J)", GB0) ;
    return (GrB_SUCCESS) ;
}