Skip to content

Commit ebb004d

Browse files
committed
fix serialization and a few other issues on current release
1 parent 51075df commit ebb004d

File tree

10 files changed

+231
-338
lines changed

10 files changed

+231
-338
lines changed

src/abstracts.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ const AbstractGBVector{T, F, O} = AbstractGBArray{T, F, O, 1}
1212

1313
# P = pointer vectors, B = bitmap storage, A = value storage
1414
abstract type AbstractGBShallowArray{T, F, O, P, B, A, N} <: AbstractGBArray{T, F, O, N} end
15+
16+
const GBVecOrMat{T, F, O} = Union{AbstractGBVector{T, F, O}, AbstractGBMatrix{T, F, O}}
17+
const GBMatrixOrTranspose{T, F, O} = Union{AbstractGBMatrix{T, F, O}, Transpose{<:Any, <:AbstractGBMatrix{T, F, O}}}
18+
const GBVectorOrTranspose{T, F, O} = Union{AbstractGBVector{T, F, O}, Transpose{<:Any, <:AbstractGBVector{T, F, O}}}
19+
const GBArrayOrTranspose{T, F, O} = Union{AbstractGBArray{T, F, O}, Transpose{<:Any, <:AbstractGBArray{T, F, O}}}
20+
const VecMatOrTrans = Union{DenseVecOrMat, Transpose{<:Any, <:DenseVecOrMat}}

src/constants.jl

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
const GBVecOrMat{T, F, O} = Union{AbstractGBVector{T, F, O}, AbstractGBMatrix{T, F, O}}
2-
const GBMatrixOrTranspose{T, F, O} = Union{AbstractGBMatrix{T, F, O}, Transpose{<:Any, <:AbstractGBMatrix{T, F, O}}}
3-
const GBVectorOrTranspose{T, F, O} = Union{AbstractGBVector{T, F, O}, Transpose{<:Any, <:AbstractGBVector{T, F, O}}}
4-
const GBArrayOrTranspose{T, F, O} = Union{AbstractGBArray{T, F, O}, Transpose{<:Any, <:AbstractGBArray{T, F, O}}}
5-
const VecMatOrTrans = Union{DenseVecOrMat, Transpose{<:Any, <:DenseVecOrMat}}
61
const ptrtogbtype = IdDict{Ptr, GBType}()
72

83
const GrBOp = Union{
@@ -32,4 +27,4 @@ const OperatorUnion = Union{
3227
GrBOp
3328
}
3429

35-
const ALL = GBAllType(C_NULL)
30+
const ALL = GBAllType(C_NULL)

src/gbtypes.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ mutable struct GBType{T} <: AbstractGBType
4646
end
4747

4848

49-
50-
const GBTYPES = IdDict{DataType, GBType}()
49+
const JLTOGBTYPES = IdDict{DataType, GBType}()
5150

5251
"""
5352
gbtype(x)
@@ -57,7 +56,7 @@ Determine the GBType equivalent of a Julia primitive type.
5756
See also: [`juliatype`](@ref)
5857
"""
5958
function gbtype(::Type{T}; builtin = false, loaded = false, typestr = string(T)) where T
60-
(get!(GBTYPES, T) do
59+
(get!(JLTOGBTYPES, T) do
6160
return GBType{T}(builtin, loaded, LibGraphBLAS.GrB_Type(), typestr)
6261
end)::GBType{T}
6362
end
@@ -111,7 +110,7 @@ Base.unsafe_convert(::Type{Ptr{LibGraphBLAS.GrB_Index}}, s::GBAllType) = s.p
111110
Base.length(::GBAllType) = 0 #Allow indexing with ALL
112111

113112
"""
114-
tojuliatype(x::GBType)
113+
juliatype(x::GBType)
115114
116115
Determine the Julia equivalent of a GBType.
117116
@@ -132,4 +131,3 @@ juliatype(::GBType{T}) where {T} = T
132131
@_gbtype Float64 GrB_FP64
133132
@_gbtype ComplexF32 GxB_FC32
134133
@_gbtype ComplexF64 GxB_FC64
135-

src/operations/operationutils.jl

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ inferbinarytype(::Type{X}, ::Type{Y}, op::TypedBinaryOperator{F, X2, Y2, Z}) whe
2626
"""
2727
Complement{T}
2828
29-
The complement of a GraphBLAS mask.
29+
The complement of a GraphBLAS mask.
3030
This wrapper will set the mask argument of a GraphBLAS operation to be the negation of the
3131
original mask.
3232
@@ -47,14 +47,14 @@ struct Structural{T}
4747
end
4848

4949
Complement(A::T) where {
50-
T<:Union{GBArrayOrTranspose,
51-
Structural{<:GBArrayOrTranspose},
50+
T<:Union{GBArrayOrTranspose,
51+
Structural{<:GBArrayOrTranspose},
5252
Complement{<:GBArrayOrTranspose}}
5353
} = Complement{T}(A)
5454

5555
Base.:~(A::T) where {
56-
T<:Union{GBArrayOrTranspose,
57-
Structural{<:GBArrayOrTranspose},
56+
T<:Union{GBArrayOrTranspose,
57+
Structural{<:GBArrayOrTranspose},
5858
Complement}
5959
} = Complement(A)
6060
Base.parent(C::Complement) = C.parent
@@ -116,9 +116,20 @@ _promotefill(x, ::AbstractGBArray{<:Any, Missing}, op) = missing
116116
_promotefill(::AbstractGBArray{<:Any, Missing}, ::AbstractGBArray{<:Any, <:Any}, op) = missing
117117
_promotefill(::AbstractGBArray{<:Any, <:Any}, ::AbstractGBArray{<:Any, Missing}, op) = missing
118118

119+
_promotefill(::AbstractGBArray{<:Any, Nothing}, ::AbstractGBArray{<:Any, Nothing}, op) = nothing
120+
_promotefill(::AbstractGBArray{<:Any, Nothing}, y, op) = nothing
121+
_promotefill(x, ::AbstractGBArray{<:Any, Nothing}, op) = nothing
122+
_promotefill(::AbstractGBArray{<:Any, Nothing}, ::AbstractGBArray{<:Any, <:Any}, op) = nothing
123+
_promotefill(::AbstractGBArray{<:Any, <:Any}, ::AbstractGBArray{<:Any, Nothing}, op) = nothing
124+
119125
_promotefill(x, op) = x
120126

121127
function _promotefill(x::AbstractGBArray{<:Any, T}, y::AbstractGBArray{<:Any, U}, op) where {T, U}
122-
getfill(x) getfill(y) && (return inferbinarytype(T, U, op)(getfill(x)))
123-
return defaultfill(inferbinarytype(T, U, op)) # fallback to defaultfill.
124-
end
128+
V = inferbinarytype(T, U, op)
129+
xfill, yfill = getfill(x), getfill(y)
130+
if (V === T === U) && xfill == yfill
131+
return xfill
132+
else # TODO: in 1.0 handle fills correctly no matter what.
133+
return defaultfill(inferbinarytype(T, U, op)) # fallback to defaultfill.
134+
end
135+
end

src/serialization.jl

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,86 @@ function Serialization.serialize(s::AbstractSerializer, A::GBVecOrMat)
22
Serialization.writetag(s.io, Serialization.OBJECT_TAG)
33
Serialization.serialize(s, typeof(A))
44
Serialization.serialize(s, A.fill)
5-
v = Vector{UInt8}(undef, serialize_sizehint(A))
6-
sz = Ref{LibGraphBLAS.GrB_Index}()
5+
hint = serialize_sizehint(A)
6+
v = Vector{UInt8}(undef, hint)
7+
sz = Ref{LibGraphBLAS.GrB_Index}(hint)
78
@wraperror LibGraphBLAS.GrB_Matrix_serialize(v, sz, A)
89
resize!(v, sz[])
910
serialize(s, v)
1011
return nothing
1112
end
1213

13-
function _gbdeserialize(s::AbstractSerializer, ::Type{T}) where {T} # Only for internal use, we assume we've already got a GB<Something> here.
14-
fill = deserialize(s)
14+
function _gbdeserialize_matrix(v, ::Type{T}) where {T} # Only for internal use, we assume we've already got a GB<Something> here.
1515
refA = Ref{LibGraphBLAS.GrB_Matrix}() # Everything is a GrB_Matrix in the end.
16-
v = deserialize(s)
17-
@wraperror LibGraphBLAS.GrB_Matrix_deserialize(refA, gbtype(T), v, LibGraphBLAS.GrB_Index(length(v)))
18-
return refA[], fill
16+
@wraperror LibGraphBLAS.GrB_Matrix_deserialize(refA, T === Nothing ? C_NULL : gbtype(T), v, LibGraphBLAS.GrB_Index(length(v)))
17+
return refA
18+
end
19+
20+
function _gbdeserialize_fill(s::AbstractSerializer) # Only for internal use, we assume we've already got a GB<Something> here.
21+
return deserialize(s)
1922
end
2023

2124
function Serialization.deserialize(s::AbstractSerializer, ::Type{GBMatrix{T, Tf}}) where {T, Tf}
22-
return GBMatrix{T, Tf}(_gbdeserialize(s, T)...)
25+
fill = _gbdeserialize_fill(s)
26+
v = deserialize(s)
27+
return GBMatrix{T, Tf}(_gbdeserialize_matrix(v, T), fill)
2328
end
2429
function Serialization.deserialize(s::AbstractSerializer, ::Type{GBVector{T, Tf}}) where {T, Tf}
25-
return GBVector{T, Tf}(_gbdeserialize(s, T)...)
30+
fill = _gbdeserialize_fill(s)
31+
v = deserialize(s)
32+
return GBVector{T, Tf}(_gbdeserialize_matrix(v, T), fill)
2633
end
2734

2835
function serialize_sizehint(A::GBVecOrMat)
2936
sz = Ref{LibGraphBLAS.GrB_Index}()
3037
@wraperror LibGraphBLAS.GrB_Matrix_serializeSize(sz, A)
3138
return sz[]
3239
end
40+
41+
gbwrite(filename::AbstractString, A::GBVecOrMat) = open(io->gbwrite(io, A), filename, "w")
42+
43+
function gbwrite(io::IO, A::GBVecOrMat)
44+
hint = serialize_sizehint(A)
45+
v = Vector{UInt8}(undef, hint)
46+
sz = Ref{LibGraphBLAS.GrB_Index}(hint)
47+
@wraperror LibGraphBLAS.GrB_Matrix_serialize(v, sz, A)
48+
resize!(v, sz[])
49+
write(io, v)
50+
end
51+
52+
gbread(filename::AbstractString, ::Type{T}; fill = defaultfill(Tf)) where {Te, Tf, T<:GBVecOrMat{Te, Tf}} =
53+
open(io->gbread(io, T; fill), filename, "r")
54+
55+
# TODO: I don't love how this works with fill. Rewrite for 1.0 with SparseBase
56+
function gbread(io::IO, ::Type{GBMatrix{T, Tf}}; fill = defaultfill(Tf)) where {T, Tf}
57+
v = read(io)
58+
gb = _gbdeserialize_matrix(v, T)
59+
GBMatrix{T, Tf}(gb, fill)
60+
end
61+
function gbread(io::IO, ::Type{GBVector{T, Tf}}; fill = defaultfill(Tf)) where {T, Tf}
62+
v = read(io)
63+
gb = _gbdeserialize_matrix(v, T)
64+
GBVector{T, Tf}(gb, fill)
65+
end
66+
67+
gbread_matrix(filename::AbstractString; fill = Nothing) =
68+
open(io->gbread_matrix(io; fill), filename, "r")
69+
70+
function gbread_matrix(io::IO; fill = Nothing)
71+
v = read(io)
72+
gb = _gbdeserialize_matrix(v, Nothing) # we don't know the eltype pass nothing
73+
type = Ref{LibGraphBLAS.GrB_Type}()
74+
LibGraphBLAS.GxB_Matrix_type(type, gb[])
75+
T = juliatype(ptrtogbtype[type[]])
76+
fill = fill === Nothing ? defaultfill(T) : fill
77+
return GBMatrix{T}(gb; fill)
78+
end
79+
function gbread_vector(io::IO; fill = Nothing)
80+
v = read(io)
81+
gb = _gbdeserialize_matrix(v, Nothing) # we don't know the eltype pass nothing
82+
type = Ref{LibGraphBLAS.GrB_Type}()
83+
LibGraphBLAS.GxB_Matrix_type(type, gb)
84+
T = juliatype(ptrtogbtype[type[]])
85+
fill = fill === Nothing ? defaultfill(T) : fill
86+
return GBVector{T}(gb; fill)
87+
end

src/solvers/cholmod.jl

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using LinearAlgebra
44
import LinearAlgebra: (\),
55
cholesky, cholesky!, det, diag, ishermitian, isposdef,
66
issuccess, issymmetric, ldlt, ldlt!, logdet, Symmetric, Hermitian, lu
7-
using ..SuiteSparseGraphBLAS: AbstractGBMatrix, AbstractGBVector, unsafepack!, unsafeunpack!, GBMatrix,
7+
using ..SuiteSparseGraphBLAS: AbstractGBMatrix, AbstractGBVector, unsafepack!, unsafeunpack!, GBMatrix,
88
GBVector, AbstractGBArray, LibGraphBLAS, ColMajor, sparsitystatus,
99
_sizedjlmalloc, increment!, isshallow, nnz, tempunpack!, storedeltype
1010
using SuiteSparseGraphBLAS
@@ -66,11 +66,11 @@ function CHOLMOD.Dense(A::AbstractGBMatrix)
6666
end
6767
end
6868

69-
function _extract_args(s, ::Type{T}) where {T<:CHOLMOD.VTypes}
70-
ptr = SuiteSparseGraphBLAS._copytoraw(unsafe_wrap(Array, s.p, (s.ncol + 1,), own = false))
69+
function _extract_args(s, ::Type{T}, ::Type{I}) where {T<:CHOLMOD.VTypes, I<:CHOLMOD.ITypes}
70+
ptr = SuiteSparseGraphBLAS._copytoraw(unsafe_wrap(Array, Ptr{I}(s.p), (s.ncol + 1,), own = false))
7171
l = ptr[end] - 1
7272
return s.nrow, s.ncol, ptr,
73-
SuiteSparseGraphBLAS._copytoraw(unsafe_wrap(Array, s.i, (l + 1,), own = false)),
73+
SuiteSparseGraphBLAS._copytoraw(unsafe_wrap(Array, Ptr{I}(s.i), (l + 1,), own = false)),
7474
SuiteSparseGraphBLAS._copytoraw(unsafe_wrap(Array, Ptr{T}(s.x), (l + 1,), own = false))
7575
end
7676

@@ -82,24 +82,24 @@ function GBVector{T, F}(D::CHOLMOD.Dense{T}; fill = defaultfill(F)) where {T, F}
8282
SuiteSparseGraphBLAS.unsafepack!(A, D, false; order = ColMajor())
8383
return A
8484
end
85-
function GBVector{T, F}(S::CHOLMOD.Sparse{T}; fill = defaultfill(F)) where {T, F}
85+
function GBVector{T, F}(S::CHOLMOD.Sparse{T, I}; fill = defaultfill(F)) where {T, F, I}
8686
@assert size(S, 2) == 1
8787
s = unsafe_load(pointer(S))
8888
if s.stype != 0
8989
throw(ArgumentError("matrix has stype != 0. Convert to matrix " *
9090
"with stype == 0 before converting to GBMatrix"))
9191
end
92-
nrow, ncol, ptr, idx, vals = _extract_args(s, T)
92+
nrow, ncol, ptr, idx, vals = _extract_args(s, T, I)
9393
A = GBVector{T}(nrow; fill)
9494
SuiteSparseGraphBLAS.unsafepack!(
95-
A, ptr, idx, vals, false;
95+
A, ptr, idx, vals, false;
9696
order = ColMajor(), jumbled = s.sorted == 0)
9797
return A
9898
end
9999

100-
GBVector{T}(D::Union{CHOLMOD.Sparse{T}, CHOLMOD.Dense{T}}; fill::F = defaultfill(T)) where {T, F} =
100+
GBVector{T}(D::Union{CHOLMOD.Sparse{T}, CHOLMOD.Dense{T}}; fill::F = defaultfill(T)) where {T, F} =
101101
GBVector{T, F}(D; fill)
102-
GBVector(D::Union{CHOLMOD.Sparse{T}, CHOLMOD.Dense{T}}; fill::F = defaultfill(T)) where {T, F} =
102+
GBVector(D::Union{CHOLMOD.Sparse{T}, CHOLMOD.Dense{T}}; fill::F = defaultfill(T)) where {T, F} =
103103
GBVector{T, F}(D; fill)
104104

105105
for Mat [:GBMatrix, :GBMatrixC, :GBMatrixR]
@@ -111,23 +111,23 @@ for Mat ∈ [:GBMatrix, :GBMatrixC, :GBMatrixR]
111111
SuiteSparseGraphBLAS.unsafepack!(A, D, false; order = ColMajor())
112112
return A
113113
end
114-
function $Mat{T, F}(S::CHOLMOD.Sparse{T}; fill = defaultfill(F)) where {T, F}
114+
function $Mat{T, F}(S::CHOLMOD.Sparse{T, I}; fill = defaultfill(F)) where {T, F, I}
115115
s = unsafe_load(pointer(S))
116116
if s.stype != 0
117117
throw(ArgumentError("matrix has stype != 0. Convert to matrix " *
118118
"with stype == 0 before converting to GBMatrix"))
119119
end
120-
nrow, ncol, ptr, idx, vals = _extract_args(s, T)
120+
nrow, ncol, ptr, idx, vals = _extract_args(s, T, I)
121121
A = $Mat{T}(nrow, ncol; fill)
122122
SuiteSparseGraphBLAS.unsafepack!(
123-
A, ptr, idx, vals, false;
123+
A, ptr, idx, vals, false;
124124
order = ColMajor(), jumbled = s.sorted == 0)
125125
return A
126126
end
127127

128-
$Mat{T}(D::Union{CHOLMOD.Sparse{T}, CHOLMOD.Dense{T}}; fill::F = defaultfill(T)) where {T, F} =
128+
$Mat{T}(D::Union{CHOLMOD.Sparse{T}, CHOLMOD.Dense{T}}; fill::F = defaultfill(T)) where {T, F} =
129129
$Mat{T, F}(D; fill)
130-
$Mat(D::Union{CHOLMOD.Sparse{T}, CHOLMOD.Dense{T}}; fill::F = defaultfill(T)) where {T, F} =
130+
$Mat(D::Union{CHOLMOD.Sparse{T}, CHOLMOD.Dense{T}}; fill::F = defaultfill(T)) where {T, F} =
131131
$Mat{T, F}(D; fill)
132132

133133
function LinearAlgebra.Symmetric{Float64,<:$Mat{Float64}}(S::Sparse{Float64})
@@ -137,7 +137,7 @@ for Mat ∈ [:GBMatrix, :GBMatrixC, :GBMatrixR]
137137
Symmetric(A, s.stype > 0 ? :U : :L)
138138
end
139139
convert(T::Type{Symmetric{Float64,<:$Mat{Float64}}}, A::Sparse{Float64}) = T(A)
140-
140+
141141
function LinearAlgebra.Hermitian{Tv,<:$Mat{Tv}}(A::Sparse{Tv}) where Tv<:VTypes
142142
s = unsafe_load(pointer(A))
143143
ishermitian(A) || throw(ArgumentError("matrix is not Hermitian"))
@@ -183,7 +183,7 @@ end
183183
function CHOLMOD.getLd!(S::AbstractGBMatrix)
184184
nz = nnz(S)
185185
colptr, rowvals, nonzeros, repack! = tempunpack!(
186-
S, SuiteSparseGraphBLAS.Sparse();
186+
S, SuiteSparseGraphBLAS.Sparse();
187187
order = ColMajor()
188188
)
189189
d = Vector{eltype(S)}(undef, size(S, 1))
@@ -264,7 +264,7 @@ function LinearAlgebra.lu(A::GBRealHermSymComplexHermF64SSL)
264264
return lu(copy(A))
265265
end
266266

267-
# TODO: Improve these, to use better promotion:
267+
# TODO: Improve these, to use better promotion:
268268
Base.:*(A::Symmetric{Float64,G},
269269
B::AbstractGBArray) where {G<:AbstractGBMatrix} = GBMatrix(Sparse(A)*Sparse(B))
270270
Base.:*(A::Hermitian{ComplexF64,<:GBMatrix},
@@ -278,4 +278,4 @@ Base.:*(A::AbstractGBArray{ComplexF64},
278278
B::Hermitian{ComplexF64,<:AbstractGBMatrix}) = GBMatrix(Sparse(A)*Sparse(B))
279279
Base.:*(A::AbstractGBArray{Float64},
280280
B::Hermitian{Float64,<:AbstractGBMatrix}) = GBMatrix(Sparse(A)*Sparse(B))
281-
end
281+
end

0 commit comments

Comments
 (0)