Skip to content

Commit c51ee58

Browse files
committed
merge the old iterator work with the new
1 parent 76c1b69 commit c51ee58

File tree

3 files changed

+162
-25
lines changed

3 files changed

+162
-25
lines changed

src/iterator.jl

Lines changed: 154 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,40 @@
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
215
p::Blobs.Blob{LibGraphBLAS.GB_Iterator_opaque}
316
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}}
518
#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."))
623
p = Ref{LibGraphBLAS.GxB_Iterator}()
724
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}(
1027
Blobs.Blob{LibGraphBLAS.GB_Iterator_opaque}(
1128
Ptr{Nothing}(p[]), 0, sizeof(LibGraphBLAS.GB_Iterator_opaque)),
12-
A
29+
wait(A)
1330
)
1431
) do I
1532
LibGraphBLAS.GxB_Iterator_free(
1633
Ref(LibGraphBLAS.GxB_Iterator(getfield(I.p, :base)))
1734
)
1835
end
1936
)
37+
return I
2038
end
2139
end
2240
Base.unsafe_convert(::Type{LibGraphBLAS.GxB_Iterator}, I::GxBIterator) =
@@ -40,18 +58,19 @@ end
4058
return LibGraphBLAS.GB_Iterator_rc_seek(I, decrement(col), false)
4159
end
4260

43-
function _kseek(I::GxBIterator{StorageOrders.RowMajor()}, row)
61+
@inline function _kseek(I::GxBIterator{StorageOrders.RowMajor()}, row)
4462
return LibGraphBLAS.GB_Iterator_rc_seek(I, decrement(row), true)
4563
end
46-
function _kseek(I::GxBIterator{StorageOrders.ColMajor()}, col)
64+
@inline function _kseek(I::GxBIterator{StorageOrders.ColMajor()}, col)
4765
return LibGraphBLAS.GB_Iterator_rc_seek(I, decrement(col), true)
4866
end
4967

50-
function _kount(I::GxBIterator)
68+
@inline function _kount(I::GxBIterator)
5169
return I.p.anvec[]
5270
end
5371

54-
function _rc_knext(I::GxBIterator)
72+
# column by column or row by row iterators:
73+
@inline function _rc_knext(I::GxBIterator)
5574
k = I.p.k[] + 1
5675
anvec = I.p.anvec[]
5776
if k >= anvec
@@ -80,7 +99,7 @@ function _rc_knext(I::GxBIterator)
8099
end
81100
end
82101

83-
function _rc_inext(I::GxBIterator)
102+
@inline function _rc_inext(I::GxBIterator)
84103
p = I.p.p[]
85104
I.p.p[] = p + 1
86105
if p + 1 >= I.p.pend[]
@@ -94,7 +113,7 @@ function _rc_inext(I::GxBIterator)
94113
end
95114
end
96115

97-
function _rc_getj(I::GxBIterator)
116+
@inline function _rc_getj(I::GxBIterator)
98117
k = I.p.k[]
99118
return k >= I.p.anvec[] ?
100119
I.p.avdim[] :
@@ -103,25 +122,137 @@ function _rc_getj(I::GxBIterator)
103122
k
104123
end
105124

106-
function _rc_geti(I::GxBIterator)
125+
@inline function _rc_geti(I::GxBIterator)
107126
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[]
109128
end
110129

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)
113132

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))
116135

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)
119138

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))
122141

123-
function getval(I::GxBIterator{<:Any, T}) where T
142+
@inline function getval(I::GxBIterator{<:Any, T}) where T
124143
return unsafe_load(Ptr{T}(I.p.Ax[]), I.p.iso[] ? 1 : I.p.p[] + 1)
125144
end
126145

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)

src/options.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ function GxB_Matrix_Option_set(A::AbstractGBArray, field, value)
6060
value isa LibGraphBLAS.GxB_Format_Value ||
6161
throw(ArgumentError("$field specifies a value of type GxB_Format_Value"))
6262
elseif field == GxB_SPARSITY_CONTROL
63-
value isa Cint || throw(ArgumentError("$field specifies a value of type Cint"))
63+
value isa Integer || value isa GBSparsity ||
64+
throw(ArgumentError("$field specifies a value of type Int"))
6465
else
6566
throw(ArgumentError("$field is not a valid Matrix option."))
6667
end
@@ -127,6 +128,11 @@ function setstorageorder!(A::AbstractGBArray, o::StorageOrders.StorageOrder)
127128
gbset(A, :format, o)
128129
end
129130

131+
function setstorageorder(A::AbstractGBArray, o::StorageOrders.StorageOrder)
132+
B = copy(A)
133+
gbset(A, :format, o)
134+
end
135+
130136
shapetoconst(::Dense) = GBDENSE
131137
shapetoconst(::Bytemap) = GBBITMAP
132138
shapetoconst(::Sparse) = GBSPARSE

src/types.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ end
3535
if Base.issingletontype(F)
3636
:(@cfunction($(F.instance), Cvoid, (Ptr{Z}, Ref{X})))
3737
else
38-
throw("Unsupported function $f")
38+
throw("Unsupported function $f. Closure functions are not supported.")
3939
end
4040
end
4141

0 commit comments

Comments
 (0)