Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/src/utilities.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
```@docs
setfill
setfill!
getfill
sparsitystatus
format
setstorageorder!
gbset
gbget
SuiteSparseGraphBLAS.jit!
Descriptor
SuiteSparseGraphBLAS.set_lib!
Expand All @@ -15,4 +17,5 @@ SuiteSparseGraphBLAS.xtype
SuiteSparseGraphBLAS.ytype
SuiteSparseGraphBLAS.ztype
gbrand
gbrandn
```
5 changes: 5 additions & 0 deletions src/abstractgbarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,11 @@ function setfill(A::AbstractGBArray, x) # aliasing form.
return B
end

"""
getfill(A::AbstractGBArray)

Return the fill value of `A`, the value of entries that are not stored.
"""
getfill(A::AbstractGBArray) = A.fill
getfill(A::LinearAlgebra.AdjOrTrans{<:Any, <:AbstractGBArray}) = getfill(parent(A))

Expand Down
14 changes: 10 additions & 4 deletions src/mem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@ function _copytoraw(A::DenseVecOrMat{T}) where {T}
return unsafe_wrap(Array, ptr, size(A))
end

function _copytoraw(A::SparseMatrixCSC)
return _copytoraw(getcolptr(A)), _copytoraw(getrowval(A)), _copytoraw(getnzval(A))
# GraphBLAS indices are 64-bit, so narrower index types (e.g. Int32) are widened first.
_int64(v::Vector{Int64}) = v
_int64(v::AbstractVector{<:Integer}) = convert(Vector{Int64}, v)

function _copytoraw(A::SparseMatrixCSC, ::Type{T} = eltype(A)) where {T}
return _copytoraw(_int64(getcolptr(A))), _copytoraw(_int64(getrowval(A))),
_copytoraw(convert(Vector{T}, getnzval(A)))
end

function _copytoraw(v::SparseVector)
return _copytoraw([1, length(v.nzind) + 1]), _copytoraw(v.nzind), _copytoraw(v.nzval)
function _copytoraw(v::SparseVector, ::Type{T} = eltype(v)) where {T}
return _copytoraw([1, length(v.nzind) + 1]), _copytoraw(_int64(v.nzind)),
_copytoraw(convert(Vector{T}, v.nzval))
end
6 changes: 4 additions & 2 deletions src/operations/broadcasts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ mutatingop(::typeof(apply)) = apply!
else
left = first(bc.args)
right = last(bc.args)
f = bc.f
# handle annoyances with the pow operator
if left isa Base.RefValue{typeof(^)}
f = ^
Expand Down Expand Up @@ -204,7 +205,7 @@ mutatingop(::typeof(apply)) = apply!
add = mutatingop(defaultadd(f))
return add(C, left, right, f)
else
return apply!(C, f, left, right; accum=second)
return apply!(f, C, left, right; accum=second)
end
end
end
Expand Down Expand Up @@ -263,6 +264,7 @@ end
else
left = first(bc.args)
right = last(bc.args)
f = bc.f
# handle annoyances with the pow operator
if left isa Base.RefValue{typeof(^)}
f = ^
Expand Down Expand Up @@ -329,7 +331,7 @@ end
add = mutatingop(defaultadd(f))
return add(C, left, right, f)
else
return apply!(C, f, left, right; accum=second)
return apply!(f, C, left, right; accum=second)
end
end
end
Expand Down
21 changes: 15 additions & 6 deletions src/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
gbset(option, value)

Set an option either for a specific GBArray, or globally. The commonly used options are:
- `:format = [RowMajor() | ColMajor()]`: The global default or array specific
column major or row major ordering.
- `:nthreads = [Integer]`: The global number of OpenMP threads to use.
- `:burble = [Bool]`: Print diagnostic output.
- `:sparsity_control = [:full | :bitmap | :sparse | :hypersparse]`: Set the sparsity of a
single GBArray.

- `:format = [RowMajor() | ColMajor()]`: The global default or array specific
column major or row major ordering.
- `:nthreads = [Integer]`: The global number of OpenMP threads to use.
- `:burble = [Bool]`: Print diagnostic output.
- `:sparsity_control = [:full | :bitmap | :sparse | :hypersparse]`: Set the sparsity of a
single GBArray.

See also: [`gbget`](@ref).
"""
function gbset end
using .LibGraphBLAS: GrB_Descriptor, GrB_Info, GrB_Desc_Field, GrB_Desc_Value, GrB_OUTP, GrB_MASK, GrB_INP0, GrB_INP1,
Expand Down Expand Up @@ -93,6 +96,12 @@ function gbset(option, value)
return nothing
end

"""
gbget(A::GBArray, option)
gbget(option)

Get the value of an option for a specific GBArray, or globally. See [`gbset`](@ref).
"""
function gbget(option)
option = option_toconst(option)
return GxB_Global_Option_get(option)
Expand Down
6 changes: 6 additions & 0 deletions src/pack.jl
Original file line number Diff line number Diff line change
Expand Up @@ -277,14 +277,20 @@ function unsafepack!(
end

function unsafepack!(A::AbstractGBArray, S::SparseMatrixCSC, shallow::Bool = true; decrementindices = true)
_checkindices(S)
unsafepack!(A, getcolptr(S), getrowval(S), getnzval(S), shallow; decrementindices)
end
# GraphBLAS reads indices as 64-bit, so narrower ones can't be shared without a copy.
_checkindices(::Union{SparseMatrixCSC{<:Any, Int64}, SparseVector{<:Any, Int64}}) = nothing
_checkindices(S) = throw(ArgumentError(
"unsafepack! needs Int64 indices, got $(eltype(rowvals(S))). Use the GBMatrix/GBVector constructor to copy instead."))
unsafepack!(
A::AbstractGBArray,
S::Transpose{<:Any, <:SparseMatrixCSC}, shallow; decrementindices = true
) = transpose(unsafepack!(A, parent(S), shallow; decrementindices))

function unsafepack!(A::AbstractGBArray, s::SparseVector, shallow::Bool = true; decrementindices = true)
_checkindices(s)
ptrvec = [1, length(s.nzind) + 1]
ptrvec = shallow ? ptrvec : _copytoraw(ptrvec) # TODO: potential segfault when ptrvec goes out.
unsafepack!(A, ptrvec, s.nzind, s.nzval, shallow; decrementindices)
Expand Down
6 changes: 6 additions & 0 deletions src/random.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ function gbrand(
)
end

"""
gbrandn(type, nrows, ncols, density; kwargs...)::GBMatrix
gbrandn(rng::AbstractRNG, type, nrows, ncols, density; kwargs...)::GBMatrix

Like [`gbrand`](@ref), but with normally distributed values drawn by `randn`.
"""
function gbrandn(
rng::AbstractRNG, type::DataType, nrows::Integer, ncols::Integer, density::AbstractFloat;
symmetric=false, pattern=false, skewsymmetric=false, hermitian=false, nodiagonal=false
Expand Down
49 changes: 30 additions & 19 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ macro gbmatrixtype(typename)
$typename{T}(dims::Dims{2}, x; fill::F = defaultfill(T)) where {T, F} =
$typename{T, F}(dims, x; fill)
$typename(dims::Dims{2}, x::T; fill = defaultfill(T)) where T =
$typename{T}(dims, x, fill)
$typename{T}(dims, x; fill)

$typename{T}(nrows, ncols, x; fill::F = defaultfill(T)) where {T, F} =
$typename{T, F}((nrows, ncols), x; fill)
Expand Down Expand Up @@ -527,7 +527,7 @@ macro gbmatrixtype(typename)
fill = defaultfill(F)
) where {T, F}
C = $typename{T, F}(size(A, 1), 1; fill)
return unsafepack!(C, _copytoraw(A)..., false)
return unsafepack!(C, _copytoraw(A, T)..., false)
end
$typename{T}(
A::SparseVector;
Expand All @@ -543,7 +543,7 @@ macro gbmatrixtype(typename)
fill = defaultfill(F)
) where {T, F}
C = $typename{T, F}(size(A)...; fill)
return unsafepack!(C, _copytoraw(A)..., false)
return unsafepack!(C, _copytoraw(A, T)..., false)
end
$typename{T}(
A::SparseMatrixCSC;
Expand Down Expand Up @@ -683,7 +683,7 @@ macro gbvectortype(typename)
function $typename(
I::AbstractVector, x::T, n;
fill = defaultfill(T)) where {T}
$typename{T}(I, J, x, n; fill)
$typename{T}(I, x, n; fill)
end
$typename(I::AbstractVector, x::T; fill = defaultfill(T)) where T =
$typename{T}(I, x, maximum(I); fill)
Expand All @@ -696,7 +696,7 @@ macro gbvectortype(typename)
$typename{T}(dims::Dims{1}, x; fill::F = defaultfill(T)) where {T, F} =
$typename{T, F}(dims, x; fill)
$typename(dims::Dims{1}, x::T; fill = defaultfill(T)) where T =
$typename{T}(dims, x, fill)
$typename{T}(dims, x; fill)

$typename{T}(nrows, x; fill = defaultfill(T)) where T =
$typename{T}((nrows,), x; fill)
Expand Down Expand Up @@ -739,7 +739,7 @@ macro gbvectortype(typename)
fill = defaultfill(F)
) where {T, F}
C = $typename{T, F}(size(A, 1); fill)
return unsafepack!(C, _copytoraw(A)..., false)
return unsafepack!(C, _copytoraw(A, T)..., false)
end
$typename{T}(
A::SparseVector;
Expand Down Expand Up @@ -772,19 +772,24 @@ end
GBVector{T, F} <: AbstractSparseArray{T, UInt64, 1}

One-dimensional GraphBLAS array with elements of type T. `F` is the type of the fill-value,
which is typically `Missing` or `T`.
which is typically `Nothing`, `Missing`, or `T`.
Internal representation is specified as opaque, but may be either a dense vector, bitmap vector, or
compressed sparse vector.

See also: [`GBMatrix`](@ref).

# Construction Signatures
# Constructors

GBVector{T, F}(n::Integer; fill = defaultfill(F))
GBVector{T}(n::Integer; fill = defaultfill(T))
GBVector(I::AbstractVector, X::AbstractVector{T}, n; fill=defaultfill(T), combine=+)
GBVector(I::AbstractVector, x::T, n; fill=defaultfill(T), combine=+)
GBVector(v::Union{<:AbstractGBVector, <:AbstractVector}; fill = defaultfill(eltype(v)))
GBVector(v::AbstractVector; fill = defaultfill(eltype(v)))
GBVector(I::AbstractVector, X::AbstractVector{T}, n; fill = defaultfill(T), combine = +)
GBVector(I::AbstractVector, x::T, n; fill = defaultfill(T))

The first two create an empty vector. `v` may be a dense `Vector`, a `SparseVector`, or
another `GBVector`. The coordinate forms store `X[k]` (or the scalar `x`) at `I[k]`,
merging duplicates with `combine`; `n` defaults to `maximum(I)`. `fill` is the value of
entries that are not stored, `zero(T)` by default.

All constructors, no matter their input, may specify parameters for
element type `T` as well as a fill type `F`, conversions are handled internally.
Expand Down Expand Up @@ -812,7 +817,7 @@ GBVector{T}(
GBMatrix{T, F} <: AbstractSparseArray{T, UInt64, 2}

Two-dimensional GraphBLAS array with elements of type `T`. `F` is the type of the fill-value,
which is typically `Missing` or `T`.
which is typically `Nothing`, `Missing`, or `T`.
Internal representation is specified as opaque, but in this implementation is stored as one of
the following in either row or column orientation:

Expand All @@ -823,13 +828,19 @@ the following in either row or column orientation:

The storage type is automatically determined by the library.

#Signatures
# Constructors

GBMatrix{T, F}(nrows::Integer, ncols::Integer; fill = defaultfill(F))
GBMatrix{T}(nrows::Integer, ncols::Integer; fill = defaultfill(T))
GBMatrix(I::AbstractVector, J::AbstractVector, X::AbstractVector{T}, dims...; fill=defaultfill(T), combine=+)
GBMatrix(I::AbstractVector, J::AbstractVector, x::T, dims...; fill=defaultfill(T), combine=+)
GBMatrix(A::Union{<:AbstractGBArray, <:AbstractMatrix}; fill = defaultfill(eltype(A)))
GBMatrix(A::AbstractMatrix; fill = defaultfill(eltype(A)))
GBMatrix(I::AbstractVector, J::AbstractVector, X::AbstractVector{T}, nrows, ncols; fill = defaultfill(T), combine = +)
GBMatrix(I::AbstractVector, J::AbstractVector, x::T, nrows, ncols; fill = defaultfill(T))

The first two create an empty matrix. `A` may be a dense `Matrix`, a `SparseMatrixCSC`, or
another GraphBLAS array. The coordinate (COO) forms store `X[k]` (or the scalar `x`) at
`(I[k], J[k])`, merging duplicates with `combine`; `nrows` and `ncols` default to
`maximum(I)` and `maximum(J)`. `fill` is the value of entries that are not stored,
`zero(T)` by default.

All constructors, no matter their input, may specify an element type `T`
as well as a fill type `F`, conversions are handled internally.
Expand Down Expand Up @@ -861,18 +872,18 @@ GBMatrix{T}(
OrientedGBMatrix{T, F, O} <: AbstractSparseArray{T, UInt64, 2}

Two-dimensional GraphBLAS array with elements of type `T`. `F` is the type of the fill-value,
which is typically `Missing` or `T`.
which is typically `Nothing`, `Missing`, or `T`.
Exactly the same as [`GBMatrix`](@ref), except the memory orientation is static: either
`StorageOrders.RowMajor()` (default) or `StorageOrders.ColMajor()`.

The aliases `GBMatrixC` and `GBMatrixR` are the preferred construction methods.

#Signatures
# Constructors

GBMatrix[R | C]{T, F}(nrows::Integer, ncols::Integer; fill = defaultfill(F))
GBMatrix[R | C]{T}(nrows::Integer, ncols::Integer; fill = defaultfill(T))
GBMatrix[R | C](I::AbstractVector, J::AbstractVector, X::AbstractVector{T}, dims...; fill=defaultfill(T), combine=+)
GBMatrix[R | C](I::AbstractVector, J::AbstractVector, x::T, dims...; fill=defaultfill(T), combine=+)
GBMatrix[R | C](I::AbstractVector, J::AbstractVector, x::T, dims...; fill=defaultfill(T))
GBMatrix[R | C](A::Union{<:AbstractGBArray, <:AbstractMatrix}; fill = defaultfill(eltype(A)))

All constructors, no matter their input, may specify an element type `T`
Expand Down
13 changes: 13 additions & 0 deletions test/gbarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@
vnz = findnz(v)
xnz = findnz(x)
@test vnz == xnz

# narrower indices and eltype conversion (#144)
S = SparseMatrixCSC{Float64, Int32}(sparse([1, 3], [1, 2], [1.0, 2.0], 3, 3))
@test SparseMatrixCSC(GBMatrix(S)) == S
@test eltype(GBMatrix{Float32}(S)) == Float32 && SparseMatrixCSC(GBMatrix{Float32}(S)) == S
s = SparseVector{Float64, Int32}(5, Int32[2, 4], [1.0, 2.0])
@test SparseVector(GBVector(s)) == s
@test_throws ArgumentError SuiteSparseGraphBLAS.unsafepack!(GBMatrix{Float64}(3, 3), S)

# scalar-valued constructors
@test Vector(GBVector([1, 3], 2.0, 4)) == [2.0, 0, 2, 0]
@test Vector(GBVector((3,), 1.0)) == ones(3)
@test Matrix(GBMatrix((2, 2), 1.0)) == ones(2, 2)
end
end

Expand Down
8 changes: 8 additions & 0 deletions test/operations/broadcasting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
B .= sqrt.(A .^ 2)
@test B == A

# C .= A .op B where C is neither operand (#124)
C = GBVector(zeros(3))
C .= GBVector([1.0, 2, 3]) .+ GBVector([4.0, 5, 6])
@test Vector(C) == [5.0, 7, 9]
D = GBMatrix(zeros(2, 2))
D .= A .- 1
@test Matrix(D) == [0 2; 1 3]

u = rand(1000)
v = GBVector(u)
@test sin.(u) ≈ Vector(sin.(v))
Expand Down
Loading