Skip to content

Commit fbd58ff

Browse files
committed
Move over code from LazyArrays
1 parent 845534a commit fbd58ff

13 files changed

+2168
-0
lines changed

.travis.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Documentation: http://docs.travis-ci.com/user/languages/julia/
2+
language: julia
3+
os:
4+
- linux
5+
- osx
6+
- windows
7+
julia:
8+
- 1.0
9+
- 1.1
10+
- 1.2
11+
- 1.3
12+
- nightly
13+
matrix:
14+
allow_failures:
15+
- julia: nightly
16+
notifications:
17+
email: false
18+
after_success:
19+
- julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())'
20+
21+
# uncomment the following lines to override the default test script
22+
#script:
23+
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
24+
# - julia -e 'Pkg.clone(pwd()); Pkg.build("MyPackage"); Pkg.test("MyPackage"; coverage=true)'
25+
26+
# jobs:
27+
# include:
28+
# - stage: Documentation
29+
# julia: 1.2
30+
# script: julia --project=docs -e '
31+
# using Pkg;
32+
# Pkg.develop(PackageSpec(path=pwd()));
33+
# Pkg.instantiate();
34+
# include("docs/make.jl");'
35+
# after_success: skip

Project.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name = "ArrayLayouts"
2+
uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
3+
authors = ["Sheehan Olver <[email protected]>"]
4+
version = "0.1.0"
5+
6+
[deps]
7+
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
8+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
9+
10+
[compat]
11+
FillArrays = "0.8"
12+
julia = "1"
13+
14+
[extras]
15+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
16+
17+
[targets]
18+
test = ["Test"]

src/ArrayLayouts.jl

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module ArrayLayouts
2+
using Base, Base.Broadcast, LinearAlgebra, FillArrays
3+
import LinearAlgebra.BLAS
4+
5+
import Base: AbstractArray, AbstractMatrix, AbstractVector,
6+
ReinterpretArray, ReshapedArray, AbstractCartesianIndex, Slice,
7+
RangeIndex, BroadcastStyle, copyto!, length, broadcastable, axes,
8+
getindex, eltype, tail, IndexStyle, IndexLinear, getproperty,
9+
*, +, -, /, \, ==, isinf, isfinite, sign, angle, show, isless,
10+
fld, cld, div, min, max, minimum, maximum, mod,
11+
<, , >, , promote_rule, convert, copy,
12+
size, step, isempty, length, first, last, ndims,
13+
getindex, setindex!, intersect, @_inline_meta, inv,
14+
sort, sort!, issorted, sortperm, diff, cumsum, sum, in, broadcast,
15+
eltype, parent, real, imag,
16+
conj, transpose, adjoint, permutedims, vec,
17+
exp, log, sqrt, cos, sin, tan, csc, sec, cot,
18+
cosh, sinh, tanh, csch, sech, coth,
19+
acos, asin, atan, acsc, asec, acot,
20+
acosh, asinh, atanh, acsch, asech, acoth, (:),
21+
AbstractMatrix, AbstractArray, checkindex, unsafe_length, OneTo, one, zero,
22+
to_shape, _sub2ind, print_matrix, print_matrix_row, print_matrix_vdots,
23+
checkindex, Slice, @propagate_inbounds, @_propagate_inbounds_meta,
24+
_in_range, _range, _rangestyle, Ordered,
25+
ArithmeticWraps, floatrange, reverse, unitrange_last,
26+
AbstractArray, AbstractVector, axes, (:), _sub2ind_recurse, broadcast, promote_eltypeof,
27+
similar, @_gc_preserve_end, @_gc_preserve_begin,
28+
@nexprs, @ncall, @ntuple, tuple_type_tail,
29+
all, any, isbitsunion, issubset, replace_in_print_matrix, replace_with_centered_mark
30+
31+
import Base.Broadcast: BroadcastStyle, AbstractArrayStyle, Broadcasted, broadcasted,
32+
combine_eltypes, DefaultArrayStyle, instantiate, materialize,
33+
materialize!, eltypes
34+
35+
import LinearAlgebra: AbstractTriangular, AbstractQ, checksquare, pinv, fill!, tilebufsize, Abuf, Bbuf, Cbuf, dot, factorize, qr, lu, cholesky,
36+
norm2, norm1, normInf, normMinusInf
37+
38+
import LinearAlgebra.BLAS: BlasFloat, BlasReal, BlasComplex
39+
40+
import FillArrays: AbstractFill, getindex_value
41+
42+
if VERSION < v"1.2-"
43+
import Base: has_offset_axes
44+
require_one_based_indexing(A...) = !has_offset_axes(A...) || throw(ArgumentError("offset arrays are not supported but got an array with index other than 1"))
45+
else
46+
import Base: require_one_based_indexing
47+
end
48+
49+
export materialize, materialize!, MulAdd, muladd!, Ldiv, Lmul, Rmul, MemoryLayout
50+
51+
struct ApplyBroadcastStyle <: BroadcastStyle end
52+
@inline function copyto!(dest::AbstractArray, bc::Broadcasted{ApplyBroadcastStyle})
53+
@assert length(bc.args) == 1
54+
copyto!(dest, first(bc.args))
55+
end
56+
57+
include("memorylayout.jl")
58+
include("muladd.jl")
59+
include("lmul.jl")
60+
include("ldiv.jl")
61+
include("diagonal.jl")
62+
include("triangular.jl")
63+
64+
end

src/diagonal.jl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
rowsupport(::DiagonalLayout, _, k) = minimum(k):maximum(k)
3+
colsupport(::DiagonalLayout, _, j) = minimum(j):maximum(j)
4+
5+
###
6+
# Lmul
7+
####
8+
9+
# Diagonal multiplication never changes structure
10+
similar(M::Lmul{<:DiagonalLayout}, ::Type{T}, axes) where T = similar(M.B, T, axes)
11+
# equivalent to rescaling
12+
function materialize!(M::Lmul{<:DiagonalLayout{<:AbstractFillLayout}})
13+
M.B .= getindex_value(M.A.diag) .* M.B
14+
M.B
15+
end
16+
17+
copy(M::Lmul{<:DiagonalLayout,<:DiagonalLayout}) = Diagonal(M.A.diag .* M.B.diag)
18+
copy(M::Lmul{<:DiagonalLayout}) = M.A.diag .* M.B
19+
copy(M::Lmul{<:DiagonalLayout{<:AbstractFillLayout}}) = getindex_value(M.A.diag) .* M.B
20+
copy(M::Lmul{<:DiagonalLayout{<:AbstractFillLayout},<:DiagonalLayout}) = Diagonal(getindex_value(M.A.diag) .* M.B.diag)
21+
22+
# Diagonal multiplication never changes structure
23+
similar(M::Rmul{<:Any,<:DiagonalLayout}, ::Type{T}, axes) where T = similar(M.A, T, axes)
24+
# equivalent to rescaling
25+
function materialize!(M::Rmul{<:Any,<:DiagonalLayout{<:AbstractFillLayout}})
26+
M.A .= M.A .* getindex_value(M.B.diag)
27+
M.A
28+
end
29+
30+
copy(M::Rmul{<:Any,<:DiagonalLayout}) = M.A .* permutedims(M.B.diag)
31+
copy(M::Rmul{<:Any,<:DiagonalLayout{<:AbstractFillLayout}}) = M.A .* getindex_value(M.B.diag)

src/ldiv.jl

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
2+
3+
4+
5+
struct Ldiv{StyleA, StyleB, AType, BType}
6+
A::AType
7+
B::BType
8+
end
9+
10+
Ldiv{StyleA, StyleB}(A::AType, B::BType) where {StyleA,StyleB,AType,BType} =
11+
Ldiv{StyleA,StyleB,AType,BType}(A,B)
12+
13+
Ldiv(A::AType, B::BType) where {AType,BType} =
14+
Ldiv{typeof(MemoryLayout(AType)),typeof(MemoryLayout(BType)),AType,BType}(A, B)
15+
16+
struct LdivBroadcastStyle <: BroadcastStyle end
17+
18+
size(L::Ldiv{<:Any,<:Any,<:Any,<:AbstractMatrix}) = (size(L.A, 2),size(L.B,2))
19+
size(L::Ldiv{<:Any,<:Any,<:Any,<:AbstractVector}) = (size(L.A, 2),)
20+
axes(L::Ldiv{<:Any,<:Any,<:Any,<:AbstractMatrix}) = (axes(L.A, 2),axes(L.B,2))
21+
axes(L::Ldiv{<:Any,<:Any,<:Any,<:AbstractVector}) = (axes(L.A, 2),)
22+
length(L::Ldiv{<:Any,<:Any,<:Any,<:AbstractVector}) =size(L.A, 2)
23+
24+
_ldivaxes(::Tuple{}, ::Tuple{}) = ()
25+
_ldivaxes(::Tuple{}, Bax::Tuple) = Bax
26+
_ldivaxes(::Tuple{<:Any}, ::Tuple{<:Any}) = ()
27+
_ldivaxes(::Tuple{<:Any}, Bax::Tuple{<:Any,<:Any}) = (OneTo(1),last(Bax))
28+
_ldivaxes(Aax::Tuple{<:Any,<:Any}, ::Tuple{<:Any}) = (last(Aax),)
29+
_ldivaxes(Aax::Tuple{<:Any,<:Any}, Bax::Tuple{<:Any,<:Any}) = (last(Aax),last(Bax))
30+
31+
@inline ldivaxes(A, B) = _ldivaxes(axes(A), axes(B))
32+
33+
ndims(L::Ldiv) = ndims(last(L.args))
34+
eltype(M::Ldiv) = promote_type(Base.promote_op(inv, eltype(M.A)), eltype(M.B))
35+
36+
BroadcastStyle(::Type{<:Ldiv}) = ApplyBroadcastStyle()
37+
broadcastable(M::Ldiv) = M
38+
39+
similar(A::Ldiv, ::Type{T}) where T = similar(Array{T}, axes(A))
40+
similar(A::Ldiv) = similar(A, eltype(A))
41+
42+
function instantiate(L::Ldiv)
43+
check_ldiv_axes(L.A, L.B)
44+
Ldiv(instantiate(L.A), instantiate(L.B))
45+
end
46+
47+
48+
check_ldiv_axes(A, B) =
49+
axes(A,1) == axes(B,1) || throw(DimensionMismatch("First axis of A, $(axes(A,1)), and first axis of B, $(axes(B,1)) must match"))
50+
51+
52+
53+
copy(M::Ldiv) = copyto!(similar(M), M)
54+
materialize(M::Ldiv) = copy(instantiate(M))
55+
56+
_ldiv!(A, B) = ldiv!(factorize(A), B)
57+
_ldiv!(A::Factorization, B) = ldiv!(A, B)
58+
59+
_ldiv!(dest, A, B) = ldiv!(dest, factorize(A), B)
60+
_ldiv!(dest, A::Factorization, B) = ldiv!(dest, A, B)
61+
62+
63+
materialize!(M::Ldiv) = _ldiv!(M.A, M.B)
64+
if VERSION v"1.1-pre"
65+
copyto!(dest::AbstractArray, M::Ldiv) = _ldiv!(dest, M.A, M.B)
66+
else
67+
copyto!(dest::AbstractArray, M::Ldiv) = _ldiv!(dest, M.A, copy(M.B))
68+
end
69+
70+
const MatLdivVec{styleA, styleB, T, V} = Ldiv{styleA, styleB, <:AbstractMatrix{T}, <:AbstractVector{V}}
71+
const MatLdivMat{styleA, styleB, T, V} = Ldiv{styleA, styleB, <:AbstractMatrix{T}, <:AbstractMatrix{V}}
72+
const BlasMatLdivVec{styleA, styleB, T<:BlasFloat} = MatLdivVec{styleA, styleB, T, T}
73+
const BlasMatLdivMat{styleA, styleB, T<:BlasFloat} = MatLdivMat{styleA, styleB, T, T}

src/lmul.jl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
for Typ in (:Lmul, :Rmul)
2+
@eval begin
3+
struct $Typ{StyleA, StyleB, TypeA, TypeB}
4+
A::TypeA
5+
B::TypeB
6+
end
7+
8+
$Typ(A::TypeA, B::TypeB) where {TypeA,TypeB} = $Typ{typeof(MemoryLayout(TypeA)),typeof(MemoryLayout(TypeB)),TypeA,TypeB}(A,B)
9+
10+
BroadcastStyle(::Type{<:$Typ}) = ApplyBroadcastStyle()
11+
broadcastable(M::$Typ) = M
12+
13+
eltype(::$Typ{<:Any,<:Any,A,B}) where {A,B} = promote_type(eltype(A), eltype(B))
14+
size(M::$Typ, p::Int) = size(M)[p]
15+
axes(M::$Typ, p::Int) = axes(M)[p]
16+
length(M::$Typ) = prod(size(M))
17+
size(M::$Typ) = map(length,axes(M))
18+
axes(M::$Typ) = (axes(M.A,1),axes(M.B,2))
19+
20+
similar(M::$Typ, ::Type{T}, axes) where {T,N} = similar(Array{T}, axes)
21+
similar(M::$Typ, ::Type{T}) where T = similar(M, T, axes(M))
22+
similar(M::$Typ) = similar(M, eltype(M))
23+
end
24+
end
25+
26+
27+
28+
const MatLmulVec{StyleA,StyleB} = Lmul{StyleA,StyleB,<:AbstractMatrix,<:AbstractVector}
29+
const MatLmulMat{StyleA,StyleB} = Lmul{StyleA,StyleB,<:AbstractMatrix,<:AbstractMatrix}
30+
31+
const BlasMatLmulVec{StyleA,StyleB,T<:BlasFloat} = Lmul{StyleA,StyleB,<:AbstractMatrix{T},<:AbstractVector{T}}
32+
const BlasMatLmulMat{StyleA,StyleB,T<:BlasFloat} = Lmul{StyleA,StyleB,<:AbstractMatrix{T},<:AbstractMatrix{T}}
33+
34+
const MatRmulMat{StyleA,StyleB} = Rmul{StyleA,StyleB,<:AbstractMatrix,<:AbstractMatrix}
35+
const BlasMatRmulMat{StyleA,StyleB,T<:BlasFloat} = Rmul{StyleA,StyleB,<:AbstractMatrix{T},<:AbstractMatrix{T}}
36+
37+
38+
####
39+
# LMul materialize
40+
####
41+
42+
axes(M::MatLmulVec) = (axes(M.A,1),)
43+
44+
45+
copy(M::Lmul) = materialize!(Lmul(M.A,copy(M.B)))
46+
copy(M::Rmul) = materialize!(Rmul(copy(M.A),M.B))
47+
48+
@inline function copyto!(dest::AbstractArray, M::Lmul)
49+
M.B dest || copyto!(dest, M.B)
50+
materialize!(Lmul(M.A,dest))
51+
end
52+
53+
@inline function copyto!(dest::AbstractArray, M::Rmul)
54+
M.A dest || copyto!(dest, M.A)
55+
materialize!(Rmul(dest,M.B))
56+
end
57+
58+
materialize!(M::Lmul) = lmul!(M.A,M.B)
59+
materialize!(M::Rmul) = rmul!(M.A,M.B)
60+

0 commit comments

Comments
 (0)