1
- mutable struct GxBIterator{O, T, G<: AbstractGBArray{T} }
1
+ # TODO : Make this file less loathsome.
2
+
3
+ abstract type IndexIteratorType end
4
+ struct IndicesIterator <: IndexIteratorType end # return the indices as integers
5
+ struct NeighborIterator <: IndexIteratorType end # Used only for Vector iterators
6
+ struct NoIndexIterator <: IndexIteratorType end # Used when we don't want the indices, just the value
7
+ # just returns the free index, only useful for single column/row iterators.
8
+
9
+ abstract type AbstractGBIterator end
10
+
11
+ """
12
+ GxBIterator{Order, Eltype, AbstractGBArray}
13
+ """
14
+ mutable struct GxBIterator{O, T, IterateValues, IterationType, G} # internal, don't subtype AbstractGBIterator
2
15
p:: Blobs.Blob{LibGraphBLAS.GB_Iterator_opaque}
3
16
A:: G
4
- function GxBIterator (A:: G ) where {T, G<: AbstractGBArray{T} }
17
+ function GxBIterator {IterateValues, IterationType} (A:: G ) where {T, IterateValues, IterationType , G<: AbstractGBArray{T} }
5
18
# garbaage collection
19
+ IterationType isa IndexIteratorType ||
20
+ throw (ArgumentError (" IterationType must be an IndexIteratorType." ))
21
+ IterateValues isa Bool ||
22
+ throw (ArgumentError (" IterateValues must be a Bool." ))
6
23
p = Ref {LibGraphBLAS.GxB_Iterator} ()
7
24
LibGraphBLAS. GxB_Iterator_new (p)
8
- return _attach (
9
- finalizer (new {storageorder(A), T, G} (
25
+ I = _attach (
26
+ finalizer (new {storageorder(A), T, IterateValues, IterationType, G} (
10
27
Blobs. Blob {LibGraphBLAS.GB_Iterator_opaque} (
11
28
Ptr {Nothing} (p[]), 0 , sizeof (LibGraphBLAS. GB_Iterator_opaque)),
12
- A
29
+ wait (A)
13
30
)
14
31
) do I
15
32
LibGraphBLAS. GxB_Iterator_free (
16
33
Ref (LibGraphBLAS. GxB_Iterator (getfield (I. p, :base )))
17
34
)
18
35
end
19
36
)
37
+ return I
20
38
end
21
39
end
22
40
Base. unsafe_convert (:: Type{LibGraphBLAS.GxB_Iterator} , I:: GxBIterator ) =
40
58
return LibGraphBLAS. GB_Iterator_rc_seek (I, decrement (col), false )
41
59
end
42
60
43
- function _kseek (I:: GxBIterator{StorageOrders.RowMajor()} , row)
61
+ @inline function _kseek (I:: GxBIterator{StorageOrders.RowMajor()} , row)
44
62
return LibGraphBLAS. GB_Iterator_rc_seek (I, decrement (row), true )
45
63
end
46
- function _kseek (I:: GxBIterator{StorageOrders.ColMajor()} , col)
64
+ @inline function _kseek (I:: GxBIterator{StorageOrders.ColMajor()} , col)
47
65
return LibGraphBLAS. GB_Iterator_rc_seek (I, decrement (col), true )
48
66
end
49
67
50
- function _kount (I:: GxBIterator )
68
+ @inline function _kount (I:: GxBIterator )
51
69
return I. p. anvec[]
52
70
end
53
71
54
- function _rc_knext (I:: GxBIterator )
72
+ # column by column or row by row iterators:
73
+ @inline function _rc_knext (I:: GxBIterator )
55
74
k = I. p. k[] + 1
56
75
anvec = I. p. anvec[]
57
76
if k >= anvec
@@ -80,7 +99,7 @@ function _rc_knext(I::GxBIterator)
80
99
end
81
100
end
82
101
83
- function _rc_inext (I:: GxBIterator )
102
+ @inline function _rc_inext (I:: GxBIterator )
84
103
p = I. p. p[]
85
104
I. p. p[] = p + 1
86
105
if p + 1 >= I. p. pend[]
@@ -94,7 +113,7 @@ function _rc_inext(I::GxBIterator)
94
113
end
95
114
end
96
115
97
- function _rc_getj (I:: GxBIterator )
116
+ @inline function _rc_getj (I:: GxBIterator )
98
117
k = I. p. k[]
99
118
return k >= I. p. anvec[] ?
100
119
I. p. avdim[] :
@@ -103,25 +122,137 @@ function _rc_getj(I::GxBIterator)
103
122
k
104
123
end
105
124
106
- function _rc_geti (I:: GxBIterator )
125
+ @inline function _rc_geti (I:: GxBIterator )
107
126
return I. p. Ai[] != C_NULL ?
108
- unsafe_load (I. p. Ai[], i . p. p[]) : I. p. p[] - I. p. pstart[]
127
+ unsafe_load (I. p. Ai[], I . p. p[]) : I. p. p[] - I. p. pstart[]
109
128
end
110
129
111
- nextrow (I:: GxBIterator{RowMajor()} ) = _rc_knext (I)
112
- nextcol (I:: GxBIterator{RowMajor()} ) = _rc_inext (I)
130
+ @inline nextrow (I:: GxBIterator{RowMajor()} ) = _rc_knext (I)
131
+ @inline nextcol (I:: GxBIterator{RowMajor()} ) = _rc_inext (I)
113
132
114
- getrow (I:: GxBIterator{RowMajor()} ) = _rc_getj (I) + 1
115
- getcol (I:: GxBIterator{RowMajor()} ) = _rc_geti (I) + 1
133
+ @inline getrow (I:: GxBIterator{RowMajor()} ) = increment ( _rc_getj (I))
134
+ @inline getcol (I:: GxBIterator{RowMajor()} ) = increment ( _rc_geti (I))
116
135
117
- nextcol (I:: GxBIterator{ColMajor()} ) = _rc_knext (I)
118
- nextrow (I:: GxBIterator{ColMajor()} ) = _rc_inext (I)
136
+ @inline nextcol (I:: GxBIterator{ColMajor()} ) = _rc_knext (I)
137
+ @inline nextrow (I:: GxBIterator{ColMajor()} ) = _rc_inext (I)
119
138
120
- getcol (I:: GxBIterator{ColMajor()} ) = _rc_getj (I) + 1
121
- getrow (I:: GxBIterator{ColMajor()} ) = _rc_geti (I) + 1
139
+ @inline getcol (I:: GxBIterator{ColMajor()} ) = increment ( _rc_getj (I))
140
+ @inline getrow (I:: GxBIterator{ColMajor()} ) = increment ( _rc_geti (I))
122
141
123
- function getval (I:: GxBIterator{<:Any, T} ) where T
142
+ @inline function getval (I:: GxBIterator{<:Any, T} ) where T
124
143
return unsafe_load (Ptr {T} (I. p. Ax[]), I. p. iso[] ? 1 : I. p. p[] + 1 )
125
144
end
126
145
127
- get_tuple (I:: GxBIterator ) = (getrow (I), getcol (I), getval (I))
146
+ # TODO : Inelegant
147
+ @inline get_element (I:: GxBIterator{<:Any, <:Any, true, IndicesIterator()} ) = ((getrow (I), getcol (I)), getval (I))
148
+ @inline get_element (I:: GxBIterator{<:Any, <:Any, false, IndicesIterator()} ) = (getrow (I), getcol (I))
149
+ @inline get_element (I:: GxBIterator{<:Any, <:Any, true, NeighborIterator()} ) = (increment (_rc_geti (I)), getval (I))
150
+ @inline get_element (I:: GxBIterator{<:Any, <:Any, false, NeighborIterator()} ) = increment (_rc_geti (I))
151
+ @inline get_element (I:: GxBIterator{<:Any, <:Any, true, NoIndexIterator()} ) = getval (I)
152
+ @inline get_element (:: GxBIterator{<:Any, <:Any, false, NoIndexIterator()} ) = throw (ArgumentError (" Must iterate over either indices or values." ))
153
+
154
+ struct VectorIterator{B, O, T, IterateValues, IterationType, I<: GxBIterator }
155
+ iterator:: I
156
+ v:: B # vector(s) to iterate over, column of CSC or row of CSR
157
+ function VectorIterator (iterator:: I , v:: B ) where
158
+ {
159
+ B<: Union{Integer, UnitRange} , O, T, IterateValues, IterationType,
160
+ G<: AbstractGBArray , I<: GxBIterator{O, T, IterateValues, IterationType, G}
161
+ }
162
+ B <: Integer && (v = convert (Int64, v))
163
+ B <: UnitRange && (v = convert (UnitRange{Int64}, v))
164
+ (B <: UnitRange && IterationType === NeighborIterator () && v. start != v. stop) &&
165
+ throw (ArgumentError (" Cannot use NeighborIterator() with more than one vector." ))
166
+ new {B, O, T, IterateValues, IterationType, I} (iterator, v)
167
+ end
168
+ end
169
+ function VectorIterator {IterateValues, IterationType} (A:: AbstractGBArray{T, F} , v) where
170
+ {T, F, IterateValues, IterationType}
171
+ @boundscheck StorageOrders. storageorder (A) === RowMajor () ? checkbounds (A, v, :) : checkbounds (A, :, v)
172
+ I = GxBIterator {IterateValues, IterationType} (A)
173
+ return VectorIterator (I, v)
174
+ end
175
+
176
+
177
+ @inline function knext (I:: VectorIterator{UnitRange{Int64}} )
178
+ V = I
179
+ I = V. iterator
180
+ k = I. p. k[] + 1
181
+ I. p. k[] = k
182
+ anvec = I. p. anvec[]
183
+ if k >= anvec || k > (V. v. stop - 1 )
184
+ I. p. pstart[] = 0
185
+ I. p. pend[] = 0
186
+ I. p. p[] = typemax (Int64) - 10 # Hmm is this correct? We don't want this iterator to be reused.
187
+ I. p. k[] = anvec
188
+ return nothing
189
+ else
190
+ if I. p. A_sparsity[] <= Int (LibGraphBLAS. GxB_SPARSE)
191
+ I. p. pstart[] = unsafe_load (I. p. Ap[], k)
192
+ I. p. pend[] = unsafe_load (I. p. Ap[], k + 1 )
193
+ I. p. p[] = I. p. pstart[]
194
+ return I. p. p[] >= I. p. pend[] ? knext (V) : (get_element (I), nothing )
195
+ else
196
+ avlen = I. p. avlen[]
197
+ I. p. pstart[] = I. p. pstart[] + avlen
198
+ I. p. pend[] = I. p. pend[] + avlen
199
+ I. p. p[] = I. p. pstart[]
200
+ if I. p. A_sparsity[] <= Int (LibGraphBLAS. GxB_BITMAP)
201
+ return LibGraphBLAS. GB_Iterator_rc_bitmap_next (I) == LibGraphBLAS. GrB_SUCCESS ?
202
+ (get_element (I), nothing ) : knext (V)
203
+ else
204
+ return I. p. p[] >= I. p. pend[] ? knext (V) : (get_element (I), nothing )
205
+ end
206
+ end
207
+ end
208
+ end
209
+ @inline knext (:: VectorIterator{Int64} ) = nothing
210
+
211
+ @inline function inext (I:: VectorIterator )
212
+ p = I. iterator. p. p[]
213
+ I. iterator. p. p[] = p + 1
214
+ if p + 1 >= I. iterator. p. pend[]
215
+ return knext (I)
216
+ else
217
+ if I. iterator. p. A_sparsity[] == LibGraphBLAS. GxB_BITMAP
218
+ result = LibGraphBLAS. GB_Iterator_rc_bitmap_next (I. iterator)
219
+ if result == LibGraphBLAS. GrB_SUCCESS
220
+ return get_element (I), nothing
221
+ else
222
+ return knext (I)
223
+ end
224
+ else
225
+ return get_element (I), nothing
226
+ end
227
+ end
228
+ end
229
+
230
+ get_element (I:: VectorIterator ) = get_element (I. iterator)
231
+
232
+ const RowIterator{B, T, IterateValues, IterationType} = VectorIterator{B, RowMajor (), T, IterateValues, IterationType}
233
+ const ColIterator{B, T, IterateValues, IterationType} = VectorIterator{B, ColMajor (), T, IterateValues, IterationType}
234
+
235
+ RowIterator (A:: AbstractGBArray , v, iteratevalues:: Bool , indexiteration:: IndexIteratorType = NeighborIterator ()) =
236
+ storageorder (A) === RowMajor () ? VectorIterator {iteratevalues, indexiteration} (A, v) :
237
+ throw (ArgumentError (" A is not in RowMajor() order. Row iteration is only supported on RowMajor AbstractGBArrays. Try setstorageorder[!]" ))
238
+ ColIterator (A:: AbstractGBArray , v, iteratevalues:: Bool , indexiteration:: IndexIteratorType = NeighborIterator ()) =
239
+ storageorder (A) === ColMajor () ? VectorIterator {iteratevalues, indexiteration} (A, v) :
240
+ throw (ArgumentError (" A is not in ColMajor() order. Col iteration is only supported on ColMajor AbstractGBArrays. Try setstorageorder[!]" ))
241
+
242
+ RowIterator (A:: AbstractGBArray , v, indexiteration:: IndexIteratorType = NeighborIterator ()) = RowIterator (A, v, true , indexiteration)
243
+ ColIterator (A:: AbstractGBArray , v, indexiteration:: IndexIteratorType = NeighborIterator ()) = ColIterator (A, v, true , indexiteration)
244
+
245
+ iteratecols (A:: AbstractGBArray , v, iteratevalues:: Bool , indexiteration:: IndexIteratorType = NeighborIterator ()) =
246
+ ColIterator (A, v, iteratevalues, indexiteration)
247
+ iteratecols (A:: AbstractGBArray , v, indexiteration:: IndexIteratorType = NeighborIterator ()) =
248
+ ColIterator (A, v, indexiteration)
249
+
250
+ iteraterows (A:: AbstractGBArray , v, iteratevalues:: Bool , indexiteration:: IndexIteratorType = NeighborIterator ()) =
251
+ RowIterator (A, v, iteratevalues, indexiteration)
252
+ iteraterows (A:: AbstractGBArray , v, indexiteration:: IndexIteratorType = NeighborIterator ()) =
253
+ RowIterator (A, v, indexiteration)
254
+
255
+ function Base. iterate (I:: VectorIterator )
256
+ return _seek (I. iterator, I. v isa Int64 ? I. v : I. v. start) == LibGraphBLAS. GrB_NO_VALUE ? knext (I) : (get_element (I), nothing )
257
+ end
258
+ Base. iterate (I:: VectorIterator , :: Nothing ) = inext (I)
0 commit comments