File: GxB_Matrix_Iterator.c

package info (click to toggle)
suitesparse-graphblas 7.4.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, 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 (308 lines) | stat: -rw-r--r-- 10,383 bytes parent folder | download | duplicates (3)
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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
//------------------------------------------------------------------------------
// GxB_Matrix_Iterator: seek to a specific entry for a matrix iterator 
//------------------------------------------------------------------------------

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

#include "GB.h"
#include "GB_search_for_vector_template.c"

//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_attach: attach an entry iterator to a matrix
//------------------------------------------------------------------------------

// On input, the iterator must already exist, having been created by
// GxB_Iterator_new.

// GxB_Matrix_Iterator_attach attaches an entry iterator to a matrix.  If the
// iterator is already attached to a matrix, it is detached and then attached
// to the given matrix A.

// The following error conditions are returned:
// GrB_NULL_POINTER:    if the iterator or A are NULL.
// GrB_INVALID_OBJECT:  if the matrix A is invalid.
// GrB_OUT_OF_MEMORY:   if the method runs out of memory.

// If successful, the entry iterator is attached to the matrix, but not to any
// specific entry.  Use GxB_Matrix_Iterator_*seek* to move the iterator to a
// particular entry.

GrB_Info GxB_Matrix_Iterator_attach
(
    GxB_Iterator iterator,
    GrB_Matrix A,
    GrB_Descriptor desc
)
{ 
    return (GB_Iterator_attach (iterator, A, GxB_NO_FORMAT, desc)) ;
}

//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_getpmax: return the range of the iterator
//------------------------------------------------------------------------------

// On input, the entry iterator must be already attached to a matrix via
// GxB_Matrix_Iterator_attach; results are undefined if this condition is not
// met.

// Entries in a matrix are given an index p, ranging from 0 to pmax-1, where
// pmax >= nvals(A).  For sparse, hypersparse, and full matrices, pmax is equal
// to nvals(A).  For an m-by-n bitmap matrix, pmax=m*n, or pmax=0 if the
// matrix has no entries.

GrB_Index GxB_Matrix_Iterator_getpmax (GxB_Iterator iterator)
{ 
    return (iterator->pmax) ;
}

//------------------------------------------------------------------------------
// GB_full_position: find the vector containing p for a full/bitmap matrix
//------------------------------------------------------------------------------

static inline GrB_Info GB_full_position (GxB_Iterator iterator)
{ 
    iterator->k = iterator->p / iterator->avlen ;
    iterator->pstart = iterator->k * iterator->avlen ;
    iterator->pend = iterator->pstart + iterator->avlen ;
    return (GrB_SUCCESS) ;
}

//------------------------------------------------------------------------------
// GB_check_for_end_of_vector: move to next vector if current vector is done
//------------------------------------------------------------------------------

static inline GrB_Info GB_check_for_end_of_vector (GxB_Iterator iterator)
{
    // move to the next vector if p has reached the end of the current vector 
    switch (iterator->A_sparsity)
    {
        default: 
        case GxB_SPARSE : 
        case GxB_HYPERSPARSE : 
        {
            if (iterator->p >= iterator->pend)
            {
                // the kth vector is done; move to the next non-empty vector
                iterator->pstart = iterator->pend ;
                iterator->k++ ;
                while (iterator->Ap [iterator->k+1] == iterator->pend)
                { 
                    // iterator->k is an empty vector; move to the next one
                    iterator->k++ ;
                    ASSERT (iterator->k < iterator->anvec) ;
                }
                // iterator->k is now the next non-empty vector
                iterator->pend = iterator->Ap [iterator->k+1] ;
                return (GrB_SUCCESS) ;
            }
        }
        break ;

        case GxB_BITMAP : 
        {
            for ( ; iterator->p < iterator->pmax ; iterator->p++)
            {
                if (iterator->Ab [iterator->p])
                {
                    // found the next entry; check if it is past the kth vector
                    if (iterator->p >= iterator->pend)
                    { 
                        // find the vector of this entry
                        return (GB_full_position (iterator)) ;
                    }
                    return (GrB_SUCCESS) ;
                }
            }
            return (GxB_EXHAUSTED) ;
        }
        break ;

        case GxB_FULL : 
        {
            if (iterator->p >= iterator->pend)
            { 
                // kth vector is done; move to the next vector
                iterator->k++ ;
                iterator->pstart += iterator->avlen ;
                iterator->pend += iterator->avlen ;
            }
        }
        break ;
    }

    return (GrB_SUCCESS) ;
}

//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_next: move an entry iterator to the next entry
//------------------------------------------------------------------------------

GrB_Info GxB_Matrix_Iterator_next (GxB_Iterator iterator)
{
    // move to the next entry
    if (++(iterator->p) >= iterator->pmax)
    { 
        // the iterator is exhausted
        iterator->p = iterator->pmax ;
        return (GxB_EXHAUSTED) ;
    }
    else
    { 
        // move to next vector if iterator has reached the end of a vector
        return (GB_check_for_end_of_vector (iterator)) ;
    }
}

//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_seek: seek an entry iterator to any entry
//------------------------------------------------------------------------------

GrB_Info GxB_Matrix_Iterator_seek
(
    GxB_Iterator iterator,
    GrB_Index p
)
{
    if (p >= iterator->pmax)
    { 
        // the iterator is exhausted
        iterator->p = iterator->pmax ;
        return (GxB_EXHAUSTED) ;
    }
    else if (p == 0)
    { 
        // seek to the first entry of the first vector A(:,0)
        iterator->pstart = 0 ;
        iterator->pend = (iterator->Ap != NULL) ?
            iterator->Ap [1] : iterator->avlen ;
        iterator->p = 0 ;
        iterator->k = 0 ;
        // move to the next non-empty vector if A(:,0) is empty
        return (GB_check_for_end_of_vector (iterator)) ;
    }
    else
    {
        // seek to an arbitrary position in the matrix
        iterator->p = p ;
        switch (iterator->A_sparsity)
        {
            default: 
            case GxB_SPARSE : 
            case GxB_HYPERSPARSE : 
            { 
                // find the vector k that contains position p
                iterator->k = GB_search_for_vector (p, iterator->Ap,
                    0, iterator->anvec, iterator->avlen) ;
                iterator->pstart = iterator->Ap [iterator->k] ;
                iterator->pend = iterator->Ap [iterator->k+1] ;
            }
            break ;
            case GxB_BITMAP : 
            {
                for ( ; iterator->p < iterator->pmax ; iterator->p++)
                {
                    if (iterator->Ab [iterator->p])
                    { 
                        // found next entry; find the vector that contains it
                        return (GB_full_position (iterator)) ;
                    }
                }
                return (GxB_EXHAUSTED) ;
            }
            break ;
            case GxB_FULL : 
            { 
                // find the vector k that contains position p
                return (GB_full_position (iterator)) ;
            }
            break ;
        }
    }
    return (GrB_SUCCESS) ;
}

//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_getp: get the current position of a matrix iterator
//------------------------------------------------------------------------------

// On input, the entry iterator must be already attached to a matrix via
// GxB_Matrix_Iterator_attach, and the position of the iterator must also have
// been defined by a prior call to GxB_Matrix_Iterator_seek or
// GxB_Matrix_Iterator_next.  Results are undefined if these conditions are not
// met.

GrB_Index GxB_Matrix_Iterator_getp (GxB_Iterator iterator)
{ 
    return (iterator->p) ;
}

//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_getIndex: get the row and column index of a matrix entry
//------------------------------------------------------------------------------

// On input, the entry iterator must be already attached to a matrix via
// GxB_Matrix_Iterator_attach, and the position of the iterator must also have
// been defined by a prior call to GxB_Matrix_Iterator_seek or
// GxB_Matrix_Iterator_next, with a return value of GrB_SUCCESS.  Results are
// undefined if these conditions are not met.

void GxB_Matrix_Iterator_getIndex
(
    GxB_Iterator iterator,
    GrB_Index *row,
    GrB_Index *col
)
{
    // get row and column index of current entry, for matrix iterator
    switch (iterator->A_sparsity)
    {
        default:  
        case GxB_SPARSE : 
        {
            if (iterator->by_col)
            { 
                (*row) = iterator->Ai [iterator->p] ;
                (*col) = iterator->k ;
            }
            else
            { 
                (*row) = iterator->k ;
                (*col) = iterator->Ai [iterator->p] ;
            }
        }
        break ;

        case GxB_HYPERSPARSE : 
        {
            if (iterator->by_col)
            { 
                (*row) = iterator->Ai [iterator->p] ;
                (*col) = iterator->Ah [iterator->k] ;
            }
            else
            { 
                (*row) = iterator->Ah [iterator->k] ;
                (*col) = iterator->Ai [iterator->p] ;
            }
        }
        break ;

        case GxB_BITMAP : 
        case GxB_FULL : 
        {
            if (iterator->by_col)
            { 
                (*row) = iterator->p - iterator->pstart ;
                (*col) = iterator->k ;
            }
            else
            { 
                (*row) = iterator->k ;
                (*col) = iterator->p - iterator->pstart ;
            }
        }
        break ;
    }
}