Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More updates for Julia 0.7 #69

Merged
merged 3 commits into from
Aug 26, 2018
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
1 change: 1 addition & 0 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
julia 0.7
Combinatorics 0.2.1
DataStructures 0.4.4
Requires
14 changes: 14 additions & 0 deletions src/NamedArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

module NamedArrays

using Requires
using Random
using Statistics
using SparseArrays
Expand All @@ -34,4 +35,17 @@ include("rearrange.jl")
include("show.jl")
include("convert.jl")


function __init__()
@require KahanSummation="8e2b3108-d4c1-50be-a7a2-16352aec75c3" begin

# NOTE: KahanSummation do not support Julia 0.7 dims keyword argument at the moment

## rename a dimension
function KahanSummation.cumsum_kbn(a::NamedArray, dims::Integer)
NamedArrays.fan(KahanSummation.cumsum_kbn, "cumsum_kbn", a, dims)
end
end
end

end
60 changes: 27 additions & 33 deletions src/arithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -154,40 +154,34 @@ end
LinearAlgebra.tril!(n::NamedMatrix, k::Integer) = (tril!(n.array, k); n)
LinearAlgebra.triu!(n::NamedMatrix, k::Integer) = (triu!(n.array, k); n)

# TODO : ## LU factorization
# TODO : function lu!(n::NamedArray{T, N, AT, DT}, pivot = Val(true); kargs...) where {T, N, AT, DT}
# TODO : luf = lu!(n.array, pivot; kargs...)
# TODO : LU{T,typeof(n),}(n, luf.ipiv, luf.info)
# TODO : end

# TODO : ## after lu.jl, this could be merged at Base.
# TODO : function Base.getindex(A::LU{T,NamedArray{T,2,AT,DT}}, d::Symbol) where {T, AT, DT}
# TODO : m, n = size(A)
# TODO : if d == :L
# TODO : L = tril!(A.factors[1:m, 1:min(m,n)])
# TODO : for i = 1:min(m,n); L[i,i] = one(T); end
# TODO : setnames!(L, defaultnames(L,2), 2)
# TODO : setdimnames!(L, :LU, 2)
# TODO : return L
# TODO : end
# TODO : if d == :U
# TODO : U = triu!(A.factors[1:min(m,n), 1:n])
# TODO : setnames!(U, defaultnames(U,1), 1)
# TODO : setdimnames!(U, :LU, 1)
# TODO : return U
# TODO : end
# TODO : d == :p && return ipiv2perm(A.ipiv, m)
# TODO : if d == :P
# TODO : p = A[:p]
# TODO : P = zeros(T, m, m)
# TODO : for i in 1:m
# TODO : P[i,p[i]] = one(T)
# TODO : end
# TODO : return P
# TODO : end
# TODO : throw(KeyError(d))
# TODO : end
## LU factorization
function LinearAlgebra.lu!(n::NamedArray{T, N, AT, DT}, pivot = Val(true); kargs...) where {T, N, AT, DT}
luf = lu!(n.array, pivot; kargs...)
LU(n, luf.ipiv, luf.info)
end

# From /stdlib/LinearAlgebra/src/lu.jl
function Base.getproperty(A::LU{T,NamedArray{T, N, AT, DT}}, d::Symbol) where {T, N, AT, DT}
m, n = size(A)
if d == :L
L = tril!(getfield(A, :factors)[1:m, 1:min(m,n)])
for i = 1:min(m,n); L[i,i] = one(T); end
setnames!(L, defaultnames(L,2), 2)
setdimnames!(L, :LU, 2)
return L
elseif d == :U
U = triu!(getfield(A, :factors)[1:min(m,n), 1:n])
setnames!(U, defaultnames(U,1), 1)
setdimnames!(U, :LU, 1)
return U
elseif d == :p
return ipiv2perm(getfield(A, :ipiv), m)
elseif d == :P
return Matrix{T}(I, m, m)[:,invperm(A.p)]
else
getfield(F, d)
end
end

# TODO: function cholfact!(n::NamedArray{T}, uplo::Symbol=:U) where T<:LinearAlgebra.BlasFloat
# TODO: ishermitian(n) || LinearAlgebra.non_hermitian_error("cholfact!")
Expand Down
36 changes: 20 additions & 16 deletions src/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,26 @@
## This code is licensed under the MIT license
## See the file LICENSE.md in this distribution

# ## copy
# import Base: copy, copy!
# copy{T,N,AT,DT}(a::NamedArray{T,N,AT,DT}) = NamedArray{T,N,AT,DT}(copy(a.array), deepcopy(a.dicts), identity(a.dimnames))
#
# ## from array.jl
# function copy!{T}(dest::NamedArray{T}, dsto::Integer, src::ArrayOrNamed{T}, so::Integer, N::
# Integer)
# if so+N-1 > length(src) || dsto+N-1 > length(dest) || dsto < 1 || so < 1
# throw(BoundsError())
# end
# if isa(src, NamedArray)
# unsafe_copy!(dest.array, dsto, src.array, so, N)
# else
# unsafe_copy!(dest.array, dsto, src, so, N)
# end
# end
## copy
function Base.copy(a::NamedArray{T,N,AT,DT}) where {T,N,AT,DT}
NamedArray{T,N,AT,DT}(copy(a.array),deepcopy(a.dicts), identity(a.dimnames))
end

## from array.jl
function Base.copy!(dest::NamedArray{T},
dsto::Integer,
src::ArrayOrNamed{T},
so::Integer,
N::Integer) where {T}
if so+N-1 > length(src) || dsto+N-1 > length(dest) || dsto < 1 || so < 1
throw(BoundsError())
end
if isa(src, NamedArray)
unsafe_copy!(dest.array, dsto, src.array, so, N)
else
unsafe_copy!(dest.array, dsto, src, so, N)
end
end

Base.size(a::NamedArray) = size(a.array)
# Base.size(a::NamedArray, d) = size(a.array, d)
Expand Down
1 change: 0 additions & 1 deletion src/changingnames.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ function fan(f::Function, fname::AbstractString, a::NamedArray{T,N}, dim::Int) w
end

## rename a dimension
# cumsum_kbn has been moved to the package KahanSummation.jl
for f in (:cumprod, :cumsum)
@eval Base.$f(a::NamedArray, d::Integer) = fan($f, string($f), a, d)
end
4 changes: 3 additions & 1 deletion src/convert.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ convert(::Type{NamedVector}, a::AbstractArray) = NamedArray(a)
## convert{T,N}(::Type{AbstractArray}, a::NamedArray{T,N}) = a.array

## to other type
convert(::Type{NamedArray{T}}, n::NamedArray) where {T} = NamedArray(convert(Array{T}, n.array), n.dicts, n.dimnames)
convert(::Type{NamedArray{T}}, n::NamedArray) where {T} = NamedArray(T.(n.array), n.dicts, n.dimnames)

@inline convert(::Type{NamedArray}, n::NamedArray) = n
12 changes: 4 additions & 8 deletions src/keepnames.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,8 @@ sort(v::NamedVector; kws...) = sort!(copy(v); kws...)
## Note: I can't think of a sensible way to define sort!(a::NamedArray, dim>1)

## drop name of sorted dimension, as each index along that dimension is sorted individually
function sort(n::NamedArray, dim::Integer; kws...)
if ndims(n)==1 && dim==1
return sort(n; kws...)
else
nms = names(n)
nms[dim] = [string(i) for i in 1:size(n, dim)]
return NamedArray(sort(n.array, dim; kws...), tuple(nms...), n.dimnames)
end
function sort(n::NamedArray; dims::Integer, kws...)
nms = names(n)
nms[dims] = [string(i) for i in 1:size(n, dims)]
NamedArray(sort(n.array; dims=dims, kws...), tuple(nms...), n.dimnames)
end
2 changes: 1 addition & 1 deletion src/names.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ setdimnames!(n::NamedArray, dn::Vector) = setdimnames!(n, tuple(dn...))

function setdimnames!(n::NamedArray{T,N}, v, d::Integer) where {T,N}
1 <= d <= N || throw(BoundsError(size(n), d))
vdimnames = Array{Any}(N)
vdimnames = Array{Any}(undef, N)
for i=1:N
if i==d
vdimnames[i] = v
Expand Down
1 change: 1 addition & 0 deletions test/REQUIRE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
KahanSummation
22 changes: 11 additions & 11 deletions test/arithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,17 @@ c = copy(m)
triu!(c)
@test triu(m).array == triu(m.array) == c.array

# TODO : ## lufact!
# TODO : lufn = lu(n)
# TODO : lufa = lu(n.array)
# TODO : @test lufn[:U].array == lufa[:U]
# TODO : @test lufn[:L].array == lufa[:L]
# TODO : @test names(lufn[:U], 2) == names(n, 2)
# TODO : @test dimnames(lufn[:U], 2) == dimnames(n, 2)
# TODO : @test names(lufn[:L], 1) == names(n, 1)
# TODO : @test dimnames(lufn[:L], 1) == dimnames(n, 1)
# TODO : @test lufn[:p] == lufa[:p]
# TODO : @test lufn[:P] == lufa[:P]
## lufact!
lufn = lu(n)
lufa = lu(n.array)
@test lufn.U == lufa.U
@test lufn.L == lufa.L
@test names(lufn.U, 2) == names(n, 2) # lu doesn't return NamedArrays now
@test dimnames(lufn.U, 2) == dimnames(n, 2)
@test names(lufn.L, 1) == names(n, 1)
@test dimnames(lufn.L, 1) == dimnames(n, 1)
@test lufn.p == lufa.p
@test lufn.P == lufa.P

a = randn(1000,10); s = NamedArray(a'a)

Expand Down
18 changes: 12 additions & 6 deletions test/convert.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@ print("convert, ")
n = NamedArray(randn(5, 10))

@test convert(Array, n) == n.array
# TODO: @test convert(NamedArray, n) == n
@test convert(NamedArray, n) == n

for T in [Float32, Float16]
# TODO: for m in (map(T, n), convert(NamedArray{T}, n))
# TODO: @test m.array == map(T, n.array)
# TODO: @test names(m) == names(n)
# TODO: @test dimnames(m) == dimnames(n)
# TODO: end
for matrix in (map(T, n), convert(NamedArray{T}, n))
@test matrix.array == map(T, n.array)
@test names(matrix) == names(n)
@test dimnames(matrix) == dimnames(n)
end
end

# issue 43

x = @inferred NamedArray(Array([1 2; 3 4]), (["a","b"], [10,11]), (:rows,:cols))
@test convert(Array, x) == x.array

# Test convert don't change array type

n_sparray = NamedArray(SparseArrays.sprand(Int, 5, 5, 0.5))
@test isa(n_sparray.array, SparseMatrixCSC{Int,Int})
@test isa(convert(NamedArray{Float64}, n_sparray).array, SparseMatrixCSC{Float64,Int})
2 changes: 2 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ using DelimitedFiles
using Statistics
using Random

using KahanSummation

include("test.jl")
1 change: 0 additions & 1 deletion test/speed.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ for _ = 1:2
end
println("Timing named index: ", t1, ", array index: ", t2, ", named key: ", t3)

# TODO: It is too slow now
s = sparse(rand(1:1000, 10), rand(1:1000, 10), true)
n = @inferred NamedArray(s)
for _ = 1:2
Expand Down
40 changes: 22 additions & 18 deletions test/test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,23 @@ for f = (:sum, :prod, :maximum, :minimum, :mean, :std, :var)
println(" ", f)
for dim in 1:2
@eval @test ($f)(n.array, dims=$dim) == ($f)(n, dims=$dim).array
# TODO: @eval @inferred ($f)(n, dims=$dim)
# for maximum Base._mapreduce_dim is inferred as AbstractArray
@eval @inferred ($f)(n, dims=$dim)
end
end

for f in (:cumprod, :cumsum) # , :cumsum_kbn)
for f in (:cumprod, :cumsum)
for dim in 1:2
@eval @test ($f)(n.array, dims=$dim) == ($f)(n, dims=$dim).array
@eval @inferred ($f)(n, dims=$dim)
end
end

# NOTE: KahanSummation do not support Julia 0.7 dims keyword argument at the moment
@test cumsum_kbn(n.array, 1) == cumsum_kbn(n, 1).array
@test cumsum_kbn(n.array, 2) == cumsum_kbn(n, 2).array
@inferred cumsum_kbn(n, 1)
@inferred cumsum_kbn(n, 2)

print("multi-dimensional, ")
#multidimensional
m = NamedArray(rand(2,3,4,3,2,3))
Expand Down Expand Up @@ -94,23 +99,22 @@ m = NamedArray(rand(4), ([4, 3, 2, 1],), ("reverse confusion",))

print("sort, ")
m = NamedArray(rand(100))
# TODO: for rev in [false, true]
# TODO: ms = sort(m, rev=rev)
# TODO: @test ms.array == sort(m.array, rev=rev)
# TODO: @test names(ms, 1) == names(m, 1)[sortperm(m.array, rev=rev)]
# TODO: end
# TODO: m = NamedArray(rand(10,10))
# TODO: for rev in [false, true]
# TODO: for dim in 1:2
# TODO: ms = sort(m, dim, rev=rev)
# TODO: @test ms.array == sort(m.array, dim, rev=rev)
# TODO: @test names(ms, dim) == [string(i) for i in 1:size(ms, dim)]
# TODO: end
# TODO: end
for rev in [false, true]
ms = sort(m, rev=rev)
@test ms.array == sort(m.array, rev=rev)
@test names(ms, 1) == names(m, 1)[sortperm(m.array, rev=rev)]
end
m = NamedArray(rand(10,10))
for rev in [false, true]
for dim in 1:2
ms = sort(m, dims=dim, rev=rev)
@test ms.array == sort(m.array, dims=dim, rev=rev)
@test names(ms, dim) == [string(i) for i in 1:size(ms, dim)]
end
end

print("broadcast, ")
# TODO: @test broadcast(-, n, mean(n, dims=1)).array == broadcast(-, n.array, mean(n.array, dims=1))
# Array has no field array
@test broadcast(-, n, mean(n, dims=1)).array == broadcast(-, n.array, mean(n.array, dims=1))

print("vectorized, ")

Expand Down