From f5cc3021c5a661c66f8ce31249c324350eb5b492 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 24 Oct 2017 12:17:40 +0100 Subject: [PATCH 01/26] add special time for views of Band --- src/Band.jl | 33 +++++++++++++++++++++++ src/BandedMatrices.jl | 5 +++- src/banded/BandedMatrix.jl | 54 +++++++++++++++++++++++++------------- test/test_indexing.jl | 23 ++++++++++++++-- 4 files changed, 94 insertions(+), 21 deletions(-) diff --git a/src/Band.jl b/src/Band.jl index 595017eb..5ad7aae0 100644 --- a/src/Band.jl +++ b/src/Band.jl @@ -3,6 +3,8 @@ struct Band i::Int end +show(io::IO, r::Band) = print(io, "Band(", r.i, ")") + doc""" band(i) @@ -165,3 +167,34 @@ end checkbandmatch(A::AbstractMatrix, V::AbstractMatrix, ::Colon, ::Colon) = checkbandmatch(A, V, 1:size(A,1), 1:size(A,2)) + +""" + BandSlice(band, indices) + +Represent an AbstractUnitRange of indices corresponding to a band. + +Upon calling `to_indices()`, Bands are converted to BandSlice objects to represent +the indices over which the Band spans. + +This mimics the relationship between `Colon` and `Base.Slice`. +""" + + +struct BandSlice <: OrdinalRange{Int,Int} + band::Band + indices::StepRange{Int,Int} +end + +for f in (:indices, :unsafe_indices, :indices1, :first, :last, :size, :length, + :unsafe_length, :start, :step) + @eval $f(S::BandSlice) = $f(S.indices) +end + +getindex(S::BandSlice, i::Int) = getindex(S.indices, i) +show(io::IO, r::BandSlice) = print(io, "BandSlice(", r.band, ",", r.indices, ")") +next(S::BandSlice, s) = next(S.indices, s) +done(S::BandSlice, s) = done(S.indices, s) + +to_index(::Band) = throw(ArgumentError("Block must be converted by to_indices(...)")) + +@inline to_indices(A, I::Tuple{Band}) = (BandSlice(I[1], diagind(A, I[1].i)),) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index 7eab202f..da557624 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -6,7 +6,9 @@ using Base, Compat import Base: getindex, setindex!, *, +, -, ==, <, <=, >, >=, /, ^, \, transpose, showerror, reindex, checkbounds -import Base: convert, size, view +import Base: convert, size, view, indices, unsafe_indices, indices1, + first, last, size, length, unsafe_length, start, next, done, step, + to_indices, to_index, indices, show import Base.BLAS: libblas import Base.LAPACK: liblapack @@ -48,6 +50,7 @@ export BandedMatrix, bandwidth, BandError, band, + Band, BandRange, bandwidths, colrange, diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index c40a9a67..e28e0cc1 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -207,29 +207,46 @@ end @inline getindex(A::BandedMatrix, kr::Colon, jr::Colon) = copy(A) # ~ indexing along a band +# we reduce it to converting a View # scalar - band - colon -@inline function getindex(A::BandedMatrix{T}, b::Band) where {T} - @boundscheck checkband(A, b) - if b.i > 0 - vec(A.data[A.u - b.i + 1, b.i+1:min(size(A,2),size(A,1)+b.i)]) - elseif b.i == 0 - vec(A.data[A.u - b.i + 1, 1:min(size(A,2),size(A,1))]) - else # b.i < 0 - vec(A.data[A.u - b.i + 1, 1:min(size(A,2),size(A,1)+b.i)]) +@inline getindex(A::BandedMatrix{T}, b::Band) where {T} = Vector{T}(view(A, b)) + +# type to represent a view of a band +const BandedMatrixBand{T} = SubArray{T, 1, Base.ReshapedArray{T,1,BandedMatrix{T}, + Tuple{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int}}}, Tuple{BandSlice}, false} + +function convert(::Type{Vector{T}}, V::BandedMatrixBand) where T + A = parent(parent(V)) + bs = parentindexes(V)[1] #BandSlice + b = bs.band.i + if -A.l ≤ b ≤ A.u + m,n = size(A) + if b > 0 + Vector{T}(view(A.data, A.u - b + 1, b+1:min(n,m+b))) + elseif b == 0 + Vector{T}(view(A.data, A.u - b + 1, 1:min(n,m))) + else # b < 0 + Vector{T}(view(A.data, A.u - b + 1, 1:min(n,m+b))) + end + else + zeros(T, length(bs)) end end -@inline function view(A::BandedMatrix{T}, b::Band) where {T} - @boundscheck checkband(A, b) - if b.i > 0 - view(A.data,A.u - b.i + 1, b.i+1:min(size(A,2),size(A,1)+b.i)) - elseif b.i == 0 - view(A.data,A.u - b.i + 1, 1:min(size(A,2),size(A,1))) - else # b.i < 0 - view(A.data,A.u - b.i + 1, 1:min(size(A,2),size(A,1)+b.i)) - end -end +convert(::Type{Array{T}}, A::BandedMatrixBand) where T = convert(Vector{T}, A) +convert(::Type{Array}, A::BandedMatrixBand) = convert(Vector{eltype(A)}, A) +convert(::Type{Vector}, A::BandedMatrixBand)= convert(Vector{eltype(A)}, A) + + +convert(::Type{AbstractArray{T}}, A::BandedMatrixBand{T}) where T = A +convert(::Type{AbstractVector{T}}, A::BandedMatrixBand{T}) where T = A +convert(::Type{AbstractArray}, A::BandedMatrixBand{T}) where T = A +convert(::Type{AbstractVector}, A::BandedMatrixBand{T}) where T = A + +convert(::Type{AbstractArray{T}}, A::BandedMatrixBand) where T = convert(Vector{T}, A) +convert(::Type{AbstractVector{T}}, A::BandedMatrixBand) where T = convert(Vector{T}, A) + # scalar - BandRange - integer -- A[1, BandRange] @inline getindex(A::AbstractMatrix, ::Type{BandRange}, j::Integer) = A[colrange(A, j), j] @@ -238,6 +255,7 @@ end @inline getindex(A::AbstractMatrix, k::Integer, ::Type{BandRange}) = A[k, rowrange(A, k)] + # ~ indexing along a row diff --git a/test/test_indexing.jl b/test/test_indexing.jl index 5a66df95..40c12dce 100644 --- a/test/test_indexing.jl +++ b/test/test_indexing.jl @@ -659,6 +659,25 @@ end let # tests bug a = bzeros(1,1,3,-1) - a[band(-2)] .+= 2 - @test isempty(a[band(-2)]) + @test_throws ArgumentError a[band(-2)] +end + + +# test band views +let + for A in (rand(11,10), brand(11,10,2,3), brand(Float32, 11,10,2,3), + brand(Complex128, 11,10,2,3)) + for k = -5:5 + V = view(A, band(k)) + bs = parentindexes(V)[1] # a bandslice + @test bs.indices == diagind(A, k) + @test bs.band == Band(k) + @test collect(bs) == collect(diagind(A, k)) + @test Vector{eltype(A)}(V) == collect(V) == A[diagind(A,k)] == A[band(k)] + @test Vector{Complex128}(V) == Vector{Complex128}(A[diagind(A,k)]) == + convert(AbstractVector{Complex128}, V) == convert(AbstractArray{Complex128}, V) + @test V ≡ convert(AbstractArray, V) ≡ convert(AbstractArray{eltype(A)}, V) ≡ + convert(AbstractArray, V) ≡ convert(AbstractVector, V) + end + end end From ff27d5dae68862f09a3e1837974d7feca40b590e Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Thu, 26 Oct 2017 16:41:48 +0100 Subject: [PATCH 02/26] export isbanded --- src/BandedMatrices.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index da557624..ea5af833 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -54,7 +54,8 @@ export BandedMatrix, BandRange, bandwidths, colrange, - rowrange + rowrange, + isbanded From 24b63cf104015bb49f8d1e8e6a54c1e4fa75e346 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Fri, 27 Oct 2017 16:46:45 +0100 Subject: [PATCH 03/26] reorganize files, macro for lin alg overrides --- src/BandedMatrices.jl | 11 +- src/banded/BandedMatrix.jl | 32 +- src/banded/linalg.jl | 538 +++++++--------------- src/{ => generic}/AbstractBandedMatrix.jl | 0 src/{ => generic}/Band.jl | 17 +- src/{ => generic}/interface.jl | 0 src/generic/linalg.jl | 241 ++++++++++ src/{ => generic}/utils.jl | 0 8 files changed, 451 insertions(+), 388 deletions(-) rename src/{ => generic}/AbstractBandedMatrix.jl (100%) rename src/{ => generic}/Band.jl (91%) rename src/{ => generic}/interface.jl (100%) create mode 100644 src/generic/linalg.jl rename src/{ => generic}/utils.jl (100%) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index ea5af833..193e37e7 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -4,7 +4,7 @@ module BandedMatrices using Base, Compat import Base: getindex, setindex!, *, +, -, ==, <, <=, >, - >=, /, ^, \, transpose, showerror, reindex, checkbounds + >=, /, ^, \, transpose, showerror, reindex, checkbounds, @propagate_inbounds import Base: convert, size, view, indices, unsafe_indices, indices1, first, last, size, length, unsafe_length, start, next, done, step, @@ -62,9 +62,10 @@ export BandedMatrix, include("blas.jl") include("lapack.jl") -include("AbstractBandedMatrix.jl") -include("Band.jl") -include("utils.jl") +include("generic/AbstractBandedMatrix.jl") +include("generic/Band.jl") +include("generic/utils.jl") +include("generic/linalg.jl") include("banded/BandedMatrix.jl") include("banded/BandedLU.jl") @@ -76,7 +77,7 @@ include("symbanded/SymBandedMatrix.jl") include("symbanded/BandedCholesky.jl") include("symbanded/linalg.jl") -include("interface.jl") +include("generic/interface.jl") include("deprecate.jl") diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index e28e0cc1..c7e54d8d 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -216,21 +216,29 @@ end const BandedMatrixBand{T} = SubArray{T, 1, Base.ReshapedArray{T,1,BandedMatrix{T}, Tuple{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int}}}, Tuple{BandSlice}, false} + +band(V::BandedMatrixBand) = first(parentindexes(V)).band.i + +# gives a view of the parent's data matrix +function dataview(V::BandedMatrixBand) + A = parent(parent(V)) + b = band(V) + m,n = size(A) + if b > 0 + view(A.data, A.u - b + 1, b+1:min(n,m+b)) + elseif b == 0 + view(A.data, A.u - b + 1, 1:min(n,m)) + else # b < 0 + view(A.data, A.u - b + 1, 1:min(n,m+b)) + end +end + function convert(::Type{Vector{T}}, V::BandedMatrixBand) where T A = parent(parent(V)) - bs = parentindexes(V)[1] #BandSlice - b = bs.band.i - if -A.l ≤ b ≤ A.u - m,n = size(A) - if b > 0 - Vector{T}(view(A.data, A.u - b + 1, b+1:min(n,m+b))) - elseif b == 0 - Vector{T}(view(A.data, A.u - b + 1, 1:min(n,m))) - else # b < 0 - Vector{T}(view(A.data, A.u - b + 1, 1:min(n,m+b))) - end + if -A.l ≤ band(V) ≤ A.u + Vector{T}(dataview(V)) else - zeros(T, length(bs)) + zeros(T, length(V)) end end diff --git a/src/banded/linalg.jl b/src/banded/linalg.jl index 307ccb3f..e94e6753 100644 --- a/src/banded/linalg.jl +++ b/src/banded/linalg.jl @@ -1,417 +1,227 @@ -# additions and subtractions -function banded_generic_axpy!(a::Number, X::AbstractMatrix{U}, Y::AbstractMatrix{V}) where {U, V} - n,m = size(X) - if (n,m) ≠ size(Y) - throw(BoundsError()) +macro banded_banded_banded_linalg(Typ1, Typ2, Typ3) + ret = quote + BandedMatrices.positively_banded_matmatmul!(C::$Typ1{T}, tA::Char, tB::Char, A::$Typ2{T}, B::$Typ3{T}) where {T <: BlasFloat} = + BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) end - Xl,Xu = bandwidths(X) - Yl,Yu = bandwidths(Y) - - if Xl > Yl - # test that all entries are zero in extra bands - for j=1:size(X,2),k=max(1,j+Yl+1):min(j+Xl,n) - if inbands_getindex(X,k,j) ≠ 0 - error("X has nonzero entries in bands outside bandrange of Y.") - end - end - end - if Xu > Yu - # test that all entries are zero in extra bands - for j=1:size(X,2),k=max(1,j-Xu):min(j-Yu-1,n) - if inbands_getindex(X,k,j) ≠ 0 - error("X has nonzero entries in bands outside bandrange of Y.") - end - end - end - - l = min(Xl,Yl) - u = min(Xu,Yu) - - @inbounds for j=1:m,k=max(1,j-u):min(n,j+l) - inbands_setindex!(Y,a*inbands_getindex(X,k,j)+inbands_getindex(Y,k,j),k,j) - end - Y + esc(ret) end -function banded_dense_axpy!(a::Number, X::AbstractMatrix ,Y::AbstractMatrix) - if size(X) != size(Y) - throw(DimensionMismatch("+")) - end - @inbounds for j=1:size(X,2),k=colrange(X,j) - Y[k,j]+=a*inbands_getindex(X,k,j) - end - Y -end -banded_axpy!(a::Number, X::BLASBandedMatrix ,Y::BLASBandedMatrix) = banded_generic_axpy!(a, X, Y) -banded_axpy!(a::Number, X::BLASBandedMatrix ,Y::AbstractMatrix) = banded_dense_axpy!(a, X, Y) +# add banded linear algebra routines between Typ1 and Typ2 both implementing +# the BandedMatrix interface +macro banded_banded_linalg(Typ1, Typ2) + ret = quote + BandedMatrices.@banded_banded_banded_linalg($Typ2, $Typ1, $Typ2) # the first argument is the destination -axpy!(a::Number, X::BLASBandedMatrix, Y::BLASBandedMatrix) = banded_axpy!(a, X, Y) -axpy!(a::Number, X::BLASBandedMatrix, Y::AbstractMatrix) = banded_axpy!(a, X, Y) + BandedMatrices.banded_axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_generic_axpy!(a, X, Y) + Base.BLAS.axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_axpy!(a, X, Y) + function Base.:+(A::$Typ1{T}, B::$Typ2{V}) where {T,V} + n, m = size(A) + ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) + axpy!(one(T), A, ret) + axpy!(one(V), B, ret) + ret + end -function +(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T,V} - n, m=size(A) - ret = bzeros(promote_type(T,V),n,m,sumbandwidths(A, B)...) - axpy!(1.,A,ret) - axpy!(1.,B,ret) - ret -end - -function +(A::BLASBandedMatrix{T},B::AbstractMatrix{T}) where {T} - ret = deepcopy(B) - axpy!(one(T),A,ret) - ret -end - -function +(A::BLASBandedMatrix{T},B::AbstractMatrix{V}) where {T,V} - n, m=size(A) - ret = zeros(promote_type(T,V),n,m) - axpy!(one(T),A,ret) - axpy!(one(V),B,ret) - ret -end - -+(A::AbstractMatrix{T},B::BLASBandedMatrix{V}) where {T,V} = B+A + function Base.:-(A::$Typ1{T}, B::$Typ2{V}) where {T,V} + n, m=size(A) + ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) + axpy!(one(T), A, ret) + axpy!(-one(V), B, ret) + ret + end + BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::$Typ1{T}, B::$Typ2{T}) where {T <: BlasFloat} = + BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) -function -(A::BLASBandedMatrix{T}, B::BLASBandedMatrix{V}) where {T,V} - n, m=size(A) - ret = bzeros(promote_type(T,V),n,m,sumbandwidths(A, B)...) - axpy!(one(T),A,ret) - axpy!(-one(V),B,ret) - ret -end + Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = banded_matmatmul!(C, 'N', 'N', A, B) -function -(A::BLASBandedMatrix{T},B::AbstractMatrix{T}) where {T} - ret = deepcopy(B) - Base.scale!(ret,-1) - axpy!(one(T),A,ret) - ret -end + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) + Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) -function -(A::BLASBandedMatrix{T},B::AbstractMatrix{V}) where {T,V} - n, m=size(A) - ret = zeros(promote_type(T,V),n,m) - axpy!(one(T),A,ret) - axpy!(-one(V),B,ret) - ret -end - --(A::AbstractMatrix{T},B::BLASBandedMatrix{V}) where {T,V} = Base.scale!(B-A,-1) - + # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + function Base.:*(A::$Typ1{T}, B::$Typ2{V}) where {T, V} + n, m = size(A,1), size(B,2) + Y = BandedMatrix(promote_type(T,V), n, m, prodbandwidths(A, B)...) + A_mul_B!(Y, A, B) + end -## UniformScaling + Base.LinAlg.Ac_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_B!(BandedMatrices.banded_similar('C', 'N', A, B, promote_type(T, V)), A, B) + Base.LinAlg.A_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bc!(BandedMatrices.banded_similar('N', 'C', A, B, promote_type(T, V)), A, B) + Base.LinAlg.Ac_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_Bc!(BandedMatrices.banded_similar('C', 'C', A, B, promote_type(T, V)), A, B) -function axpy!(a::Number,X::UniformScaling,Y::BLASBandedMatrix{T}) where {T} - checksquare(Y) - α = a * X.λ - @inbounds for k = 1:size(Y,1) - inbands_setindex!(Y, inbands_getindex(Y, k, k) + α, k, k) + Base.LinAlg.At_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'N', A, B, promote_type(T, V)), A, B) + Base.LinAlg.A_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bt!(BandedMatrices.banded_similar('N', 'T', A, B, promote_type(T, V)), A, B) + Base.LinAlg.At_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'T', A, B, promote_type(T, V)), A, B) end - Y + esc(ret) end -function +(A::BLASBandedMatrix, B::UniformScaling) - ret = deepcopy(A) - axpy!(1,B,ret) -end - -+(A::UniformScaling, B::BLASBandedMatrix) = B+A +# add banded linear algebra routines for Typ implementing the BandedMatrix interface +macro banded_linalg(Typ) + ret = quote + BandedMatrices.@banded_banded_linalg($Typ, $Typ) + # default is to use dense axpy! + BandedMatrices.banded_axpy!(a::Number, X::$Typ, Y::AbstractMatrix) = + BandedMatrices.banded_dense_axpy!(a, X, Y) + Base.BLAS.axpy!(a::Number, X::$Typ, Y::AbstractMatrix) = + BandedMatrices.banded_axpy!(a, X, Y) + function Base.:+(A::$Typ{T}, B::AbstractMatrix{T}) where {T} + ret = deepcopy(B) + axpy!(one(T), A, ret) + ret + end + function Base.:+(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} + n, m=size(A) + ret = zeros(promote_type(T,V),n,m) + axpy!(one(T), A,ret) + axpy!(one(V), B,ret) + ret + end + Base.:+(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = B + A -function -(A::BLASBandedMatrix, B::UniformScaling) - ret = deepcopy(A) - axpy!(-1,B,ret) -end + function Base.:-(A::$Typ{T}, B::AbstractMatrix{T}) where {T} + ret = deepcopy(B) + Base.scale!(ret,-1) + Base.BLAS.axpy!(one(T), A, ret) + ret + end + function Base.:-(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} + n, m= size(A) + ret = zeros(promote_type(T,V),n,m) + Base.BLAS.axpy!(one(T), A, ret) + Base.BLAS.axpy!(-one(V), B, ret) + ret + end + Base.:-(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = Base.scale!(B - A, -1) -function -(A::UniformScaling, B::BLASBandedMatrix) - ret = deepcopy(B) - Base.scale!(ret,-1) - axpy!(1,A,ret) -end -# matrix * vector + ## UniformScaling -function _banded_generic_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} - @inbounds c[:] = zero(T) - if tA == 'N' - @inbounds for j = 1:size(A,2), k = colrange(A,j) - c[k] += inbands_getindex(A,k,j)*b[j] - end - elseif tA == 'C' - @inbounds for j = 1:size(A,2), k = colrange(A,j) - c[j] += inbands_getindex(A,k,j)'*b[k] + function Base.BLAS.axpy!(a::Number, X::UniformScaling, Y::$Typ{T}) where {T} + BandedMatrices.checksquare(Y) + α = a * X.λ + @inbounds for k = 1:size(Y,1) + BandedMatrices.inbands_setindex!(Y, BandedMatrices.inbands_getindex(Y, k, k) + α, k, k) + end + Y end - elseif tA == 'T' - @inbounds for j = 1:size(A,2), k = colrange(A,j) - c[j] += inbands_getindex(A,k,j)*b[k] + + function Base.:+(A::$Typ, B::UniformScaling) + ret = deepcopy(A) + Base.BLAS.axpy!(1, B,ret) end - end - c -end -positively_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} = _banded_generic_matvecmul!(c, tA, A, b) -# use BLAS routine for positively banded BLASBandedMatrix -positively_banded_matvecmul!(c::StridedVector{T}, tA::Char, A::BLASBandedMatrix{T}, b::StridedVector{T}) where {T <: BlasFloat} = gbmv!(tA, one(T), A, b, zero(T), c) + Base.:+(A::UniformScaling, B::$Typ) = B + A -function generally_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} - m, n = _size(tA, A) - if length(c) ≠ m || length(b) ≠ n - throw(DimensionMismatch("*")) - end + function Base.:-(A::$Typ, B::UniformScaling) + ret = deepcopy(A) + axpy!(-1, B, ret) + end - l, u = _bandwidths(tA, A) - if -l > u - # no bands - c[:] = zero(T) - elseif l < 0 - banded_matvecmul!(c, tA, _view(tA, A, :, 1-l:n), view(b, 1-l:n)) - elseif u < 0 - c[1:-u] = zero(T) - banded_matvecmul!(view(c, 1-u:m), tA, _view(tA, A, 1-u:m, :), b) - else - positively_banded_matvecmul!(c, tA, A, b) - end - c -end + function Base.:-(A::UniformScaling, B::$Typ) + ret = deepcopy(B) + Base.scale!(ret, -1) + axpy!(1, A, ret) + end -banded_matvecmul!(c::StridedVector{T}, tA::Char, A::BLASBandedMatrix{T}, b::AbstractVector{T}) where {T <: BlasFloat} = generally_banded_matvecmul!(c, tA, A, b) + # use BLAS routine for positively banded BLASBandedMatrix + BandedMatrices.positively_banded_matvecmul!(c::StridedVector{T}, tA::Char, A::$Typ{T}, b::StridedVector{T}) where {T <: BandedMatrices.BlasFloat} = + BandedMatrices.gbmv!(tA, one(T), A, b, zero(T), c) -banded_generic_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} = generally_banded_matvecmul!(c, tA, A, b) -A_mul_B!(c::AbstractVector{T}, A::BLASBandedMatrix{U}, b::AbstractVector{V}) where {T, U, V} = banded_matvecmul!(c, 'N', A, b) -Ac_mul_B!(c::AbstractVector{T}, A::BLASBandedMatrix{U}, b::AbstractVector{V}) where {T, U, V} = banded_matvecmul!(c, 'C', A, b) -Ac_mul_B!(c::AbstractVector{T}, A::BLASBandedMatrix{U}, b::AbstractVector{V}) where {T, U<:Real, V} = banded_matvecmul!(c, 'T', A, b) -At_mul_B!(c::AbstractVector{T}, A::BLASBandedMatrix{U}, b::AbstractVector{V}) where {T, U, V} = banded_matvecmul!(c, 'T', A, b) + BandedMatrices.banded_matvecmul!(c::StridedVector{T}, tA::Char, A::$Typ{T}, b::AbstractVector{T}) where {T <: BlasFloat} = + BandedMatrices.generally_banded_matvecmul!(c, tA, A, b) -*(A::BLASBandedMatrix{U}, b::StridedVector{V}) where {U, V} = - A_mul_B!(Vector{promote_type(U, V)}(size(A, 1)), A, b) + Base.LinAlg.A_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'N', A, b) + Base.LinAlg.Ac_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'C', A, b) + Base.LinAlg.Ac_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U<:Real, V} = BandedMatrices.banded_matvecmul!(c, 'T', A, b) + Base.LinAlg.At_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'T', A, b) + Base.:*(A::$Typ{U}, b::StridedVector{V}) where {U, V} = + Base.LinAlg.A_mul_B!(Vector{promote_type(U, V)}(size(A, 1)), A, b) -# matrix * matrix -function _banded_generic_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} - Am, An = _size(tA, A) - Bm, Bn = _size(tB, B) - Al,Au = _bandwidths(tA, A) - Bl,Bu = _bandwidths(tB, B) - Cl,Cu = prodbandwidths(tA, tB, A, B) + BandedMatrices.positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::$Typ{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = + BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) + BandedMatrices.positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::$Typ{T}) where {T <: BlasFloat} = + BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) - if tA == 'N' && tB == 'N' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) + BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::$Typ{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = + BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) + BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::$Typ{T}) where {T <: BlasFloat} = + BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,ν,j) - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'C' && tB == 'N' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,ν,k)' * inbands_getindex(B,ν,j) - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'N' && tB == 'C' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,j,ν)' - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'C' && tB == 'C' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,ν,k)' * inbands_getindex(B,j,ν)' - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'T' && tB == 'N' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,ν,k) * inbands_getindex(B,ν,j) - end - inbands_setindex!(C,tmp,k,j) - end + Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) + Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) - elseif tA == 'N' && tB == 'T' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,j,ν) - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'T' && tB == 'T' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,ν,k) * inbands_getindex(B,j,ν) - end - inbands_setindex!(C,tmp,k,j) - end - end - C -end -# use BLAS routine for positively banded BLASBandedMatrices -function _positively_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{T}, B::AbstractMatrix{T}) where {T <: BlasFloat} - Al,Au = _bandwidths(tA, A) - Bl,Bu = _bandwidths(tB, B) - # _banded_generic_matmatmul! is faster for sparse matrix - if tA != 'N' || tB != 'N' || (Al + Au < 100 && Bl + Bu < 100) - _banded_generic_matmatmul!(C, tA, tB, A, B) - else - # TODO: implement gbmm! routines for other flags - gbmm!('N', 'N', one(T), A, B, zero(T), C) - end -end + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) -positively_banded_matmatmul!(C::BLASBandedMatrix{T}, tA::Char, tB::Char, A::BLASBandedMatrix{T}, B::BLASBandedMatrix{T}) where {T <: BlasFloat} = _positively_banded_matmatmul!(C, tA, tB, A, B) -positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::BLASBandedMatrix{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = _positively_banded_matmatmul!(C, tA, tB, A, B) -positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::BLASBandedMatrix{T}) where {T <: BlasFloat} = _positively_banded_matmatmul!(C, tA, tB, A, B) -positively_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} = _banded_generic_matmatmul!(C, tA, tB, A, B) + Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) -function generally_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} - Am, An = _size(tA, A) - Bm, Bn = _size(tB, B) - if An != Bm || size(C, 1) != Am || size(C, 2) != Bn - throw(DimensionMismatch("*")) - end - # TODO: checkbandmatch - - Al, Au = _bandwidths(tA, A) - Bl, Bu = _bandwidths(tB, B) - - if (-Al > Au) || (-Bl > Bu) # A or B has empty bands - C[:,:] = zero(T) - elseif Al < 0 - C[max(1,Bn+Al-1):Am, :] = zero(T) - banded_matmatmul!(C, tA, tB, _view(tA, A, :, 1-Al:An), _view(tB, B, 1-Al:An, :)) - elseif Au < 0 - C[1:-Au,:] = zero(T) - banded_matmatmul!(view(C, 1-Au:Am,:), tA, tB, _view(tA, A, 1-Au:Am,:), B) - elseif Bl < 0 - C[:, 1:-Bl] = zero(T) - banded_matmatmul!(view(C, :, 1-Bl:Bn), tA, tB, A, _view(tB, B, :, 1-Bl:Bn)) - elseif Bu < 0 - C[:, max(1,Am+Bu-1):Bn] = zero(T) - banded_matmatmul!(C, tA, tB, _view(tA, A, :, 1-Bu:Bm), _view(tB, B, 1-Bu:Bm, :)) - else - positively_banded_matmatmul!(C, tA::Char, tB::Char, A, B) - end - C -end + function Base.:*(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} + n, m = size(A,1), size(B,2) + A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) + end -banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::BLASBandedMatrix{T}, B::BLASBandedMatrix{T}) where {T <: BlasFloat} = generally_banded_matmatmul!(C, tA, tB, A, B) -banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::BLASBandedMatrix{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = generally_banded_matmatmul!(C, tA, tB, A, B) -banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::BLASBandedMatrix{T}) where {T <: BlasFloat} = generally_banded_matmatmul!(C, tA, tB, A, B) - -banded_generic_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} = generally_banded_matmatmul!(C, tA, tB, A, B) - -A_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) -A_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) -A_mul_B!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) - -Ac_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) -Ac_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) -Ac_mul_B!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) -A_mul_Bc!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'C', A, B) -A_mul_Bc!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'C', A, B) -A_mul_Bc!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'C', A, B) -Ac_mul_Bc!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) -Ac_mul_Bc!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) -Ac_mul_Bc!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) - -At_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) -At_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) -At_mul_B!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) -A_mul_Bt!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) -A_mul_Bt!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) -A_mul_Bt!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) -At_mul_Bt!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) -At_mul_Bt!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) -At_mul_Bt!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) - -# override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values -Ac_mul_B!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V} = banded_matmatmul!(C, 'T', 'N', A, B) -Ac_mul_B!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::AbstractMatrix{V}) where {T, U<:Real, V} = banded_matmatmul!(C, 'T', 'N', A, B) -Ac_mul_B!(C::AbstractMatrix{T} ,A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V} = banded_matmatmul!(C, 'T', 'N', A, B) -A_mul_Bc!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::BLASBandedMatrix{V}) where {T, U, V<:Real} = banded_matmatmul!(C, 'N', 'T', A, B) -A_mul_Bc!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::AbstractMatrix{V}) where {T, U, V<:Real} = banded_matmatmul!(C, 'N', 'T', A, B) -A_mul_Bc!(C::AbstractMatrix{T} ,A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) where {T, U, V<:Real} = banded_matmatmul!(C, 'N', 'T', A, B) -Ac_mul_Bc!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V<:Real} = banded_matmatmul!(C, 'T', 'T', A, B) -Ac_mul_Bc!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::AbstractMatrix{V}) where {T, U<:Real, V<:Real} = banded_matmatmul!(C, 'T', 'T', A, B) -Ac_mul_Bc!(C::AbstractMatrix{T} ,A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V<:Real} = banded_matmatmul!(C, 'T', 'T', A, B) - - - -function *(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} - n, m = size(A,1), size(B,2) - Y = BandedMatrix(promote_type(T,V), n, m, prodbandwidths(A, B)...) - A_mul_B!(Y,A,B) -end + function Base.:*(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} + n, m = size(A,1), size(B,2) + A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) + end -function *(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} - n, m = size(A,1), size(B,2) - A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) + Base.LinAlg.Ac_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.Ac_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.A_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.A_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.Ac_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + Base.LinAlg.Ac_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + + Base.LinAlg.At_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.At_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.A_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.A_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.At_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + Base.LinAlg.At_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + end + esc(ret) end -function *(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} - n, m = size(A,1), size(B,2) - A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) -end +@banded_linalg AbstractBandedMatrix +@banded_linalg BLASBandedMatrix # this supports views of banded matrices -Ac_mul_B(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_B!(banded_similar('C', 'N', A, B, promote_type(T, V)), A, B) -Ac_mul_B(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) -Ac_mul_B(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) -A_mul_Bc(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bc!(banded_similar('N', 'C', A, B, promote_type(T, V)), A, B) -A_mul_Bc(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) -A_mul_Bc(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) -Ac_mul_Bc(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_Bc!(banded_similar('C', 'C', A, B, promote_type(T, V)), A, B) -Ac_mul_Bc(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) -Ac_mul_Bc(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - -At_mul_B(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(banded_similar('T', 'N', A, B, promote_type(T, V)), A, B) -At_mul_B(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) -At_mul_B(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) -A_mul_Bt(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bt!(banded_similar('N', 'T', A, B, promote_type(T, V)), A, B) -A_mul_Bt(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) -A_mul_Bt(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) -At_mul_Bt(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(banded_similar('T', 'T', A, B, promote_type(T, V)), A, B) -At_mul_Bt(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) -At_mul_Bt(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) ## Method definitions for generic eltypes - will make copies diff --git a/src/AbstractBandedMatrix.jl b/src/generic/AbstractBandedMatrix.jl similarity index 100% rename from src/AbstractBandedMatrix.jl rename to src/generic/AbstractBandedMatrix.jl diff --git a/src/Band.jl b/src/generic/Band.jl similarity index 91% rename from src/Band.jl rename to src/generic/Band.jl index 5ad7aae0..9d86849b 100644 --- a/src/Band.jl +++ b/src/generic/Band.jl @@ -66,6 +66,9 @@ struct BandError <: Exception i::Int end +# shorthand to specify k and j without calculating band +BandError(A::AbstractMatrix, kj::Tuple{Int,Int}) = BandError(A, kj[2]-kj[1]) + function showerror(io::IO, e::BandError) A, i = e.A, e.i print(io, "attempt to access $(typeof(A)) with bandwidths " * @@ -102,12 +105,12 @@ checkband(A::AbstractMatrix, kr::AbstractRange, jr::AbstractRange) = function checkbandmatch(A::AbstractMatrix{T}, V::AbstractVector, ::Colon, j::Integer) where {T} for k = 1:colstart(A,j)-1 if V[k] ≠ zero(T) - throw(BandError(A, j-k)) + throw(BandError(A, (k,j))) end end for k = colstop(A,j)+1:size(A,1) if V[k] ≠ zero(T) - throw(BandError(A, j-k)) + throw(BandError(A, (k,j))) end end end @@ -119,7 +122,7 @@ function checkbandmatch(A::AbstractMatrix{T}, V::AbstractVector, kr::AbstractRan for v in V k = kr[i+=1] if (k < a || k > b) && v ≠ zero(T) - throw(BandError(A, j-k)) + throw(BandError(A, (k,j))) end end end @@ -127,12 +130,12 @@ end function checkbandmatch(A::AbstractMatrix{T}, V::AbstractVector, k::Integer, ::Colon) where {T} for j = 1:rowstart(A,k)-1 if V[j] ≠ zero(T) - throw(BandError(A, j-k)) + throw(BandError(A, (k,j))) end end for j = rowstop(A,j)+1:size(A,2) if V[j] ≠ zero(T) - throw(BandError(A, j-k)) + throw(BandError(A, (k,j))) end end end @@ -144,7 +147,7 @@ function checkbandmatch(A::AbstractMatrix{T}, V::AbstractVector, k::Integer, jr: for v in V j = jr[i+=1] if (j < a || j > b) && v ≠ zero(T) - throw(BandError(A, j-k)) + throw(BandError(A, (k,j))) end end end @@ -157,7 +160,7 @@ function checkbandmatch(A::AbstractMatrix{T}, V::AbstractMatrix, kr::AbstractRan for k in kr if !(-l ≤ j - k ≤ u) && V[kk, jj] ≠ zero(T) # we index V manually in column-major order - throw(BandError(A, j-k)) + throw(BandError(A, (k,j))) end kk += 1 end diff --git a/src/interface.jl b/src/generic/interface.jl similarity index 100% rename from src/interface.jl rename to src/generic/interface.jl diff --git a/src/generic/linalg.jl b/src/generic/linalg.jl new file mode 100644 index 00000000..b65f97fd --- /dev/null +++ b/src/generic/linalg.jl @@ -0,0 +1,241 @@ +# some functions + +function banded_axpy! end +function banded_matmatmul! end +function banded_matvecmul! end + + +# additions and subtractions + +@propagate_inbounds function banded_generic_axpy!(a::Number, X::AbstractMatrix{U}, Y::AbstractMatrix{V}) where {U, V} + n,m = size(X) + if (n,m) ≠ size(Y) + throw(BoundsError()) + end + Xl, Xu = bandwidths(X) + Yl, Yu = bandwidths(Y) + + @boundscheck if Xl > Yl + # test that all entries are zero in extra bands + for j=1:size(X,2),k=max(1,j+Yl+1):min(j+Xl,n) + if inbands_getindex(X,k,j) ≠ 0 + throw(BandError(X, (k,j))) + end + end + end + @boundscheck if Xu > Yu + # test that all entries are zero in extra bands + for j=1:size(X,2),k=max(1,j-Xu):min(j-Yu-1,n) + if inbands_getindex(X,k,j) ≠ 0 + throw(BandError(X, (k,j))) + end + end + end + + l = min(Xl,Yl) + u = min(Xu,Yu) + + @inbounds for j=1:m,k=max(1,j-u):min(n,j+l) + inbands_setindex!(Y, a*inbands_getindex(X,k,j) + inbands_getindex(Y,k,j) ,k, j) + end + Y +end + +function banded_dense_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) + if size(X) != size(Y) + throw(DimensionMismatch("+")) + end + @inbounds for j=1:size(X,2),k=colrange(X,j) + Y[k,j] += a*inbands_getindex(X,k,j) + end + Y +end + + +# matrix * vector + +function _banded_generic_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} + @inbounds c[:] = zero(T) + if tA == 'N' + @inbounds for j = 1:size(A,2), k = colrange(A,j) + c[k] += inbands_getindex(A,k,j)*b[j] + end + elseif tA == 'C' + @inbounds for j = 1:size(A,2), k = colrange(A,j) + c[j] += inbands_getindex(A,k,j)'*b[k] + end + elseif tA == 'T' + @inbounds for j = 1:size(A,2), k = colrange(A,j) + c[j] += inbands_getindex(A,k,j)*b[k] + end + end + c +end + + +positively_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} = + _banded_generic_matvecmul!(c, tA, A, b) +positively_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} = + _banded_generic_matmatmul!(C, tA, tB, A, B) + +function generally_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} + m, n = _size(tA, A) + if length(c) ≠ m || length(b) ≠ n + throw(DimensionMismatch("*")) + end + + l, u = _bandwidths(tA, A) + if -l > u + # no bands + c[:] = zero(T) + elseif l < 0 + banded_matvecmul!(c, tA, _view(tA, A, :, 1-l:n), view(b, 1-l:n)) + elseif u < 0 + c[1:-u] = zero(T) + banded_matvecmul!(view(c, 1-u:m), tA, _view(tA, A, 1-u:m, :), b) + else + positively_banded_matvecmul!(c, tA, A, b) + end + c +end + +banded_generic_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} = generally_banded_matvecmul!(c, tA, A, b) + + +# matrix * matrix +function _banded_generic_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} + Am, An = _size(tA, A) + Bm, Bn = _size(tB, B) + Al, Au = _bandwidths(tA, A) + Bl, Bu = _bandwidths(tB, B) + Cl,Cu = prodbandwidths(tA, tB, A, B) + + if tA == 'N' && tB == 'N' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,ν,j) + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'C' && tB == 'N' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,ν,k)' * inbands_getindex(B,ν,j) + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'N' && tB == 'C' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,j,ν)' + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'C' && tB == 'C' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,ν,k)' * inbands_getindex(B,j,ν)' + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'T' && tB == 'N' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,ν,k) * inbands_getindex(B,ν,j) + end + inbands_setindex!(C,tmp,k,j) + end + + elseif tA == 'N' && tB == 'T' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,j,ν) + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'T' && tB == 'T' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,ν,k) * inbands_getindex(B,j,ν) + end + inbands_setindex!(C,tmp,k,j) + end + end + C +end + +# use BLAS routine for positively banded BLASBandedMatrices +function _positively_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{T}, B::AbstractMatrix{T}) where {T <: BlasFloat} + Al, Au = _bandwidths(tA, A) + Bl, Bu = _bandwidths(tB, B) + # _banded_generic_matmatmul! is faster for sparse matrix + if tA != 'N' || tB != 'N' || (Al + Au < 100 && Bl + Bu < 100) + _banded_generic_matmatmul!(C, tA, tB, A, B) + else + # TODO: implement gbmm! routines for other flags + gbmm!('N', 'N', one(T), A, B, zero(T), C) + end +end + + +function generally_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} + Am, An = _size(tA, A) + Bm, Bn = _size(tB, B) + if An != Bm || size(C, 1) != Am || size(C, 2) != Bn + throw(DimensionMismatch("*")) + end + # TODO: checkbandmatch + + Al, Au = _bandwidths(tA, A) + Bl, Bu = _bandwidths(tB, B) + + if (-Al > Au) || (-Bl > Bu) # A or B has empty bands + C[:,:] = zero(T) + elseif Al < 0 + C[max(1,Bn+Al-1):Am, :] = zero(T) + banded_matmatmul!(C, tA, tB, _view(tA, A, :, 1-Al:An), _view(tB, B, 1-Al:An, :)) + elseif Au < 0 + C[1:-Au,:] = zero(T) + banded_matmatmul!(view(C, 1-Au:Am,:), tA, tB, _view(tA, A, 1-Au:Am,:), B) + elseif Bl < 0 + C[:, 1:-Bl] = zero(T) + banded_matmatmul!(view(C, :, 1-Bl:Bn), tA, tB, A, _view(tB, B, :, 1-Bl:Bn)) + elseif Bu < 0 + C[:, max(1,Am+Bu-1):Bn] = zero(T) + banded_matmatmul!(C, tA, tB, _view(tA, A, :, 1-Bu:Bm), _view(tB, B, 1-Bu:Bm, :)) + else + positively_banded_matmatmul!(C, tA::Char, tB::Char, A, B) + end + C +end + + +banded_generic_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} = generally_banded_matmatmul!(C, tA, tB, A, B) diff --git a/src/utils.jl b/src/generic/utils.jl similarity index 100% rename from src/utils.jl rename to src/generic/utils.jl From 98e12adc704a29ef8ae671737677cb965975ccb1 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 30 Oct 2017 07:32:43 +0000 Subject: [PATCH 04/26] move macro to generic --- src/banded/linalg.jl | 220 --------------------------------------- src/generic/linalg.jl | 237 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+), 220 deletions(-) diff --git a/src/banded/linalg.jl b/src/banded/linalg.jl index e94e6753..b91189b3 100644 --- a/src/banded/linalg.jl +++ b/src/banded/linalg.jl @@ -1,223 +1,3 @@ - -macro banded_banded_banded_linalg(Typ1, Typ2, Typ3) - ret = quote - BandedMatrices.positively_banded_matmatmul!(C::$Typ1{T}, tA::Char, tB::Char, A::$Typ2{T}, B::$Typ3{T}) where {T <: BlasFloat} = - BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) - end - esc(ret) -end - - -# add banded linear algebra routines between Typ1 and Typ2 both implementing -# the BandedMatrix interface -macro banded_banded_linalg(Typ1, Typ2) - ret = quote - BandedMatrices.@banded_banded_banded_linalg($Typ2, $Typ1, $Typ2) # the first argument is the destination - - BandedMatrices.banded_axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_generic_axpy!(a, X, Y) - Base.BLAS.axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_axpy!(a, X, Y) - - function Base.:+(A::$Typ1{T}, B::$Typ2{V}) where {T,V} - n, m = size(A) - ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) - axpy!(one(T), A, ret) - axpy!(one(V), B, ret) - ret - end - - function Base.:-(A::$Typ1{T}, B::$Typ2{V}) where {T,V} - n, m=size(A) - ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) - axpy!(one(T), A, ret) - axpy!(-one(V), B, ret) - ret - end - - BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::$Typ1{T}, B::$Typ2{T}) where {T <: BlasFloat} = - BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) - - Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = banded_matmatmul!(C, 'N', 'N', A, B) - - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) - - Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - - # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - - function Base.:*(A::$Typ1{T}, B::$Typ2{V}) where {T, V} - n, m = size(A,1), size(B,2) - Y = BandedMatrix(promote_type(T,V), n, m, prodbandwidths(A, B)...) - A_mul_B!(Y, A, B) - end - - Base.LinAlg.Ac_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_B!(BandedMatrices.banded_similar('C', 'N', A, B, promote_type(T, V)), A, B) - Base.LinAlg.A_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bc!(BandedMatrices.banded_similar('N', 'C', A, B, promote_type(T, V)), A, B) - Base.LinAlg.Ac_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_Bc!(BandedMatrices.banded_similar('C', 'C', A, B, promote_type(T, V)), A, B) - - Base.LinAlg.At_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'N', A, B, promote_type(T, V)), A, B) - Base.LinAlg.A_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bt!(BandedMatrices.banded_similar('N', 'T', A, B, promote_type(T, V)), A, B) - Base.LinAlg.At_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'T', A, B, promote_type(T, V)), A, B) - end - esc(ret) -end - -# add banded linear algebra routines for Typ implementing the BandedMatrix interface -macro banded_linalg(Typ) - ret = quote - BandedMatrices.@banded_banded_linalg($Typ, $Typ) - # default is to use dense axpy! - BandedMatrices.banded_axpy!(a::Number, X::$Typ, Y::AbstractMatrix) = - BandedMatrices.banded_dense_axpy!(a, X, Y) - Base.BLAS.axpy!(a::Number, X::$Typ, Y::AbstractMatrix) = - BandedMatrices.banded_axpy!(a, X, Y) - function Base.:+(A::$Typ{T}, B::AbstractMatrix{T}) where {T} - ret = deepcopy(B) - axpy!(one(T), A, ret) - ret - end - function Base.:+(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} - n, m=size(A) - ret = zeros(promote_type(T,V),n,m) - axpy!(one(T), A,ret) - axpy!(one(V), B,ret) - ret - end - Base.:+(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = B + A - - function Base.:-(A::$Typ{T}, B::AbstractMatrix{T}) where {T} - ret = deepcopy(B) - Base.scale!(ret,-1) - Base.BLAS.axpy!(one(T), A, ret) - ret - end - function Base.:-(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} - n, m= size(A) - ret = zeros(promote_type(T,V),n,m) - Base.BLAS.axpy!(one(T), A, ret) - Base.BLAS.axpy!(-one(V), B, ret) - ret - end - Base.:-(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = Base.scale!(B - A, -1) - - - - ## UniformScaling - - function Base.BLAS.axpy!(a::Number, X::UniformScaling, Y::$Typ{T}) where {T} - BandedMatrices.checksquare(Y) - α = a * X.λ - @inbounds for k = 1:size(Y,1) - BandedMatrices.inbands_setindex!(Y, BandedMatrices.inbands_getindex(Y, k, k) + α, k, k) - end - Y - end - - function Base.:+(A::$Typ, B::UniformScaling) - ret = deepcopy(A) - Base.BLAS.axpy!(1, B,ret) - end - - Base.:+(A::UniformScaling, B::$Typ) = B + A - - function Base.:-(A::$Typ, B::UniformScaling) - ret = deepcopy(A) - axpy!(-1, B, ret) - end - - function Base.:-(A::UniformScaling, B::$Typ) - ret = deepcopy(B) - Base.scale!(ret, -1) - axpy!(1, A, ret) - end - - # use BLAS routine for positively banded BLASBandedMatrix - BandedMatrices.positively_banded_matvecmul!(c::StridedVector{T}, tA::Char, A::$Typ{T}, b::StridedVector{T}) where {T <: BandedMatrices.BlasFloat} = - BandedMatrices.gbmv!(tA, one(T), A, b, zero(T), c) - - - BandedMatrices.banded_matvecmul!(c::StridedVector{T}, tA::Char, A::$Typ{T}, b::AbstractVector{T}) where {T <: BlasFloat} = - BandedMatrices.generally_banded_matvecmul!(c, tA, A, b) - - Base.LinAlg.A_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'N', A, b) - Base.LinAlg.Ac_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'C', A, b) - Base.LinAlg.Ac_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U<:Real, V} = BandedMatrices.banded_matvecmul!(c, 'T', A, b) - Base.LinAlg.At_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'T', A, b) - - Base.:*(A::$Typ{U}, b::StridedVector{V}) where {U, V} = - Base.LinAlg.A_mul_B!(Vector{promote_type(U, V)}(size(A, 1)), A, b) - - BandedMatrices.positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::$Typ{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = - BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) - BandedMatrices.positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::$Typ{T}) where {T <: BlasFloat} = - BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) - - BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::$Typ{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = - BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) - BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::$Typ{T}) where {T <: BlasFloat} = - BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) - - Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) - Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) - - - - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) - - Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - - # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - - - function Base.:*(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} - n, m = size(A,1), size(B,2) - A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) - end - - function Base.:*(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} - n, m = size(A,1), size(B,2) - A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) - end - - Base.LinAlg.Ac_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) - Base.LinAlg.Ac_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) - Base.LinAlg.A_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) - Base.LinAlg.A_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) - Base.LinAlg.Ac_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - Base.LinAlg.Ac_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - - Base.LinAlg.At_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) - Base.LinAlg.At_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) - Base.LinAlg.A_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) - Base.LinAlg.A_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) - Base.LinAlg.At_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - Base.LinAlg.At_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - end - esc(ret) -end - @banded_linalg AbstractBandedMatrix @banded_linalg BLASBandedMatrix # this supports views of banded matrices diff --git a/src/generic/linalg.jl b/src/generic/linalg.jl index b65f97fd..7baff489 100644 --- a/src/generic/linalg.jl +++ b/src/generic/linalg.jl @@ -239,3 +239,240 @@ end banded_generic_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} = generally_banded_matmatmul!(C, tA, tB, A, B) + + + + +macro banded_banded_banded_linalg(Typ1, Typ2, Typ3) + ret = quote + BandedMatrices.positively_banded_matmatmul!(C::$Typ1{T}, tA::Char, tB::Char, A::$Typ2{T}, B::$Typ3{T}) where {T <: BlasFloat} = + BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) + end + esc(ret) +end + + +# add banded linear algebra routines between Typ1 and Typ2 both implementing +# the BandedMatrix interface +macro _banded_banded_linalg(Typ1, Typ2) + ret = quote + BandedMatrices.@banded_banded_banded_linalg($Typ2, $Typ1, $Typ2) # the first argument is the destination + + BandedMatrices.banded_axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_generic_axpy!(a, X, Y) + Base.BLAS.axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_axpy!(a, X, Y) + + function Base.:+(A::$Typ1{T}, B::$Typ2{V}) where {T,V} + n, m = size(A) + ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) + axpy!(one(T), A, ret) + axpy!(one(V), B, ret) + ret + end + + function Base.:-(A::$Typ1{T}, B::$Typ2{V}) where {T,V} + n, m=size(A) + ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) + axpy!(one(T), A, ret) + axpy!(-one(V), B, ret) + ret + end + + BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::$Typ1{T}, B::$Typ2{T}) where {T <: BlasFloat} = + BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) + + Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = banded_matmatmul!(C, 'N', 'N', A, B) + + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) + + Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + + # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + + function Base.:*(A::$Typ1{T}, B::$Typ2{V}) where {T, V} + n, m = size(A,1), size(B,2) + Y = BandedMatrix(promote_type(T,V), n, m, prodbandwidths(A, B)...) + A_mul_B!(Y, A, B) + end + + Base.LinAlg.Ac_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_B!(BandedMatrices.banded_similar('C', 'N', A, B, promote_type(T, V)), A, B) + Base.LinAlg.A_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bc!(BandedMatrices.banded_similar('N', 'C', A, B, promote_type(T, V)), A, B) + Base.LinAlg.Ac_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_Bc!(BandedMatrices.banded_similar('C', 'C', A, B, promote_type(T, V)), A, B) + + Base.LinAlg.At_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'N', A, B, promote_type(T, V)), A, B) + Base.LinAlg.A_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bt!(BandedMatrices.banded_similar('N', 'T', A, B, promote_type(T, V)), A, B) + Base.LinAlg.At_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'T', A, B, promote_type(T, V)), A, B) + end + esc(ret) +end + +macro banded_banded_linalg(Typ1, Typ2) + ret = quote + BandedMatrices.@_banded_banded_linalg($Typ1, $Typ2) + end + if Typ1 ≠ Typ2 + ret = quote + $ret + BandedMatrices.@_banded_banded_linalg($Typ2, $Typ1) + BandedMatrices.@banded_banded_banded_linalg($Typ1, $Typ1, $Typ2) + BandedMatrices.@banded_banded_banded_linalg($Typ2, $Typ2, $Typ1) + end + end + esc(ret) +end + +# add banded linear algebra routines for Typ implementing the BandedMatrix interface +macro banded_linalg(Typ) + ret = quote + BandedMatrices.@banded_banded_linalg($Typ, $Typ) + # default is to use dense axpy! + BandedMatrices.banded_axpy!(a::Number, X::$Typ, Y::AbstractMatrix) = + BandedMatrices.banded_dense_axpy!(a, X, Y) + Base.BLAS.axpy!(a::Number, X::$Typ, Y::AbstractMatrix) = + BandedMatrices.banded_axpy!(a, X, Y) + function Base.:+(A::$Typ{T}, B::AbstractMatrix{T}) where {T} + ret = deepcopy(B) + axpy!(one(T), A, ret) + ret + end + function Base.:+(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} + n, m=size(A) + ret = zeros(promote_type(T,V),n,m) + axpy!(one(T), A,ret) + axpy!(one(V), B,ret) + ret + end + Base.:+(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = B + A + + function Base.:-(A::$Typ{T}, B::AbstractMatrix{T}) where {T} + ret = deepcopy(B) + Base.scale!(ret,-1) + Base.BLAS.axpy!(one(T), A, ret) + ret + end + function Base.:-(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} + n, m= size(A) + ret = zeros(promote_type(T,V),n,m) + Base.BLAS.axpy!(one(T), A, ret) + Base.BLAS.axpy!(-one(V), B, ret) + ret + end + Base.:-(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = Base.scale!(B - A, -1) + + + + ## UniformScaling + + function Base.BLAS.axpy!(a::Number, X::UniformScaling, Y::$Typ{T}) where {T} + BandedMatrices.checksquare(Y) + α = a * X.λ + @inbounds for k = 1:size(Y,1) + BandedMatrices.inbands_setindex!(Y, BandedMatrices.inbands_getindex(Y, k, k) + α, k, k) + end + Y + end + + function Base.:+(A::$Typ, B::UniformScaling) + ret = deepcopy(A) + Base.BLAS.axpy!(1, B,ret) + end + + Base.:+(A::UniformScaling, B::$Typ) = B + A + + function Base.:-(A::$Typ, B::UniformScaling) + ret = deepcopy(A) + axpy!(-1, B, ret) + end + + function Base.:-(A::UniformScaling, B::$Typ) + ret = deepcopy(B) + Base.scale!(ret, -1) + axpy!(1, A, ret) + end + + # use BLAS routine for positively banded BLASBandedMatrix + BandedMatrices.positively_banded_matvecmul!(c::StridedVector{T}, tA::Char, A::$Typ{T}, b::StridedVector{T}) where {T <: BandedMatrices.BlasFloat} = + BandedMatrices.gbmv!(tA, one(T), A, b, zero(T), c) + + + BandedMatrices.banded_matvecmul!(c::StridedVector{T}, tA::Char, A::$Typ{T}, b::AbstractVector{T}) where {T <: BlasFloat} = + BandedMatrices.generally_banded_matvecmul!(c, tA, A, b) + + Base.LinAlg.A_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'N', A, b) + Base.LinAlg.Ac_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'C', A, b) + Base.LinAlg.Ac_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U<:Real, V} = BandedMatrices.banded_matvecmul!(c, 'T', A, b) + Base.LinAlg.At_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'T', A, b) + + Base.:*(A::$Typ{U}, b::StridedVector{V}) where {U, V} = + Base.LinAlg.A_mul_B!(Vector{promote_type(U, V)}(size(A, 1)), A, b) + + BandedMatrices.positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::$Typ{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = + BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) + BandedMatrices.positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::$Typ{T}) where {T <: BlasFloat} = + BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) + + BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::$Typ{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = + BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) + BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::$Typ{T}) where {T <: BlasFloat} = + BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) + + Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) + Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) + + + + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) + + Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + + # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + + + function Base.:*(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} + n, m = size(A,1), size(B,2) + A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) + end + + function Base.:*(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} + n, m = size(A,1), size(B,2) + A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) + end + + Base.LinAlg.Ac_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.Ac_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.A_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.A_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.Ac_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + Base.LinAlg.Ac_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + + Base.LinAlg.At_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.At_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.A_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.A_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.At_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + Base.LinAlg.At_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + end + esc(ret) +end From 32417c0a69abdba7284f06f8f0653b1c8c99db65 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sat, 4 Nov 2017 22:06:23 +0000 Subject: [PATCH 05/26] add BlasBanded, BlasSymBanded and BlasStrided traits to dispatch linalg --- src/BandedMatrices.jl | 3 +- src/banded/BandedMatrix.jl | 17 +- src/banded/gbmm.jl | 22 +- src/banded/linalg.jl | 10 +- src/generic/interface.jl | 529 ++++++++++++++++++++++++++++++- src/generic/linalg.jl | 478 ---------------------------- src/symbanded/SymBandedMatrix.jl | 5 +- 7 files changed, 556 insertions(+), 508 deletions(-) delete mode 100644 src/generic/linalg.jl diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index 193e37e7..c1b49b5a 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -65,7 +65,7 @@ include("lapack.jl") include("generic/AbstractBandedMatrix.jl") include("generic/Band.jl") include("generic/utils.jl") -include("generic/linalg.jl") +include("generic/interface.jl") include("banded/BandedMatrix.jl") include("banded/BandedLU.jl") @@ -77,7 +77,6 @@ include("symbanded/SymBandedMatrix.jl") include("symbanded/BandedCholesky.jl") include("symbanded/linalg.jl") -include("generic/interface.jl") include("deprecate.jl") diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index c7e54d8d..edc804c2 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -24,20 +24,17 @@ mutable struct BandedMatrix{T} <: AbstractBandedMatrix{T} end end +blasstructure(::Type{BandedMatrix{<:BlasFloat}}) = BlasStrided() + # BandedMatrix with unit range indexes is also banded const BandedSubBandedMatrix{T} = SubArray{T,2,BandedMatrix{T},I} where I<:Tuple{Vararg{AbstractUnitRange}} - -# these are the banded matrices that are ameniable to BLAS routines -const BLASBandedMatrix{T} = Union{ - BandedMatrix{T}, - BandedSubBandedMatrix{T} - } - +@banded_linalg BandedSubBandedMatrix isbanded(::BandedSubBandedMatrix{T}) where {T} = true +blasstructure(::Type{BandedSubBandedMatrix{<:BlasFloat}}) = BlasStrided() ## Constructors @@ -50,11 +47,11 @@ returns an unitialized `n`×`m` banded matrix of type `T` with bandwidths `(l,u) """ # Use zeros to avoid unallocated entries for bigfloat -BandedMatrix(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T<:BlasFloat} = +BandedMatrix(::Type{T}, n::Integer, m::Integer, a::Integer, b::Integer) where {T<:BlasFloat} = BandedMatrix{T}(Matrix{T}(max(0,b+a+1),m),n,a,b) -BandedMatrix(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T<:Number} = +BandedMatrix(::Type{T}, n::Integer, m::Integer, a::Integer, b::Integer) where {T<:Number} = BandedMatrix{T}(zeros(T,max(0,b+a+1),m),n,a,b) -BandedMatrix(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} = +BandedMatrix(::Type{T}, n::Integer, m::Integer, a::Integer, b::Integer) where {T} = BandedMatrix{T}(Matrix{T}(max(0,b+a+1),m),n,a,b) diff --git a/src/banded/gbmm.jl b/src/banded/gbmm.jl index 60922fdf..211b04df 100644 --- a/src/banded/gbmm.jl +++ b/src/banded/gbmm.jl @@ -317,8 +317,20 @@ function gbmm!(tA::Char, tB::Char, α::T, A::StridedMatrix{T}, B::AbstractMatrix C end -αA_mul_B_plus_βC!(α,A::BLASBandedMatrix{T},x,β,y) where {T} = gbmv!('N',α,A,x,β,y) -αA_mul_B_plus_βC!(α,A::StridedMatrix,x,β,y) = BLAS.gemv!('N',α,A,x,β,y) -αA_mul_B_plus_βC!(α,A,x,β,y) = (y .= α*A*x + β*y) -αA_mul_B_plus_βC!(α,A::BLASBandedMatrix{T},B::BLASBandedMatrix{U},β,C::BLASBandedMatrix{V}) where {T,U,V} = gbmm!(α,A,B,β,C) -αA_mul_B_plus_βC!(α,A::StridedMatrix,B::StridedMatrix,β,C::StridedMatrix) = BLAS.gemm!('N','N',α,A,B,β,C) +αA_mul_B_plus_βC!(α, A, x, β, y) = + _αA_mul_B_plus_βC!(α, A, x, β, y, + blasstructure(A), blasstructure(x), blasstructure(y)) +_αA_mul_B_plus_βC!(α, A, x, β, y, blasA, blasx, blasy) = (y .= α*A*x + β*y) +_αA_mul_B_plus_βC!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, + ::BlasStrided, ::BlasBanded, ::BlasStrided) where {T<:BlasFloat} = + gbmv!('N', α, A, x, β, y) +_αA_mul_B_plus_βC!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, + ::BlasStrided, ::BlasStrided, ::BlasStrided) where {T<:BlasFloat} = + BLAS.gemv!('N', α, A, x, β, y) + +_αA_mul_B_plus_βC!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, + ::BlasBanded, ::BlasBanded, ::BlasBanded) where {T<:BlasFloat} = + gbmm!(α, A, B, β, C) +_αA_mul_B_plus_βC!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, + ::BlasStrided, ::BlasStrided, ::BlasStrided) where {T<:BlasFloat} = + BLAS.gemm!('N', 'N', α, A, B, β, C) diff --git a/src/banded/linalg.jl b/src/banded/linalg.jl index b91189b3..e8ba22ec 100644 --- a/src/banded/linalg.jl +++ b/src/banded/linalg.jl @@ -1,8 +1,4 @@ -@banded_linalg AbstractBandedMatrix -@banded_linalg BLASBandedMatrix # this supports views of banded matrices - - - +@_banded_linalg AbstractBandedMatrix ## Method definitions for generic eltypes - will make copies @@ -16,11 +12,11 @@ for typ in [BandedMatrix, BandedLU] end end # \ is different because it needs a copy, but we have to avoid ambiguity - @eval function (\)(A::$typ{T}, B::VecOrMat{Complex{T}}) where {T<:BlasReal} + @eval function \(A::$typ{T}, B::VecOrMat{Complex{T}}) where {T<:BlasReal} checksquare(A) A_ldiv_B!(convert($typ{Complex{T}}, A), copy(B)) # goes to BlasFloat call end - @eval function (\)(A::$typ{T}, B::StridedVecOrMat{S}) where {T<:Number, S<:Number} + @eval function \(A::$typ{T}, B::StridedVecOrMat{S}) where {T<:Number, S<:Number} checksquare(A) TS = _promote_to_blas_type(T, S) A_ldiv_B!(convert($typ{TS}, A), copy_oftype(B, TS)) # goes to BlasFloat call diff --git a/src/generic/interface.jl b/src/generic/interface.jl index f1aec62f..a3d8546e 100644 --- a/src/generic/interface.jl +++ b/src/generic/interface.jl @@ -1,19 +1,69 @@ +#### +# BandedMatrix traiut +# an abstract matrix returns IsBanded if it is banded +#### + +struct BandedInterface{truefalse} end +bandedinterface(_) = BandedInterface{false}() +bandedinterface(::AbstractBandedMatrix) = BandedInterface{true}() + + +#### +# BLAS Banded traits +# +# if blasstructure(A) returns BlasBanded, you must override +# pointer and leadingdimension +# in addition to the banded matrix interface +#### + +struct NotBlas end +struct BlasStrided end +struct BlasBanded end +struct BLASSymBanded end + + +blasstructure(::Type{<:AbstractArray}) = NotBlas() +blasstructure(::Type{SM}) where SM <: StridedMatrix{T} where T <: BlasFloat = BlasStrided() +blasstructure(A::AbstractArray) = blasstructure(typeof(A)) + + + # these are the routines of the banded interface of other AbstractMatrices +banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) = _banded_axpy!(a, X, Y, bandedinterface(X), bandedinterface(Y)) +_banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix, ::BandedInterface{true}, ::BandedInterface{true}) = + banded_generic_axpy!(a, X, Y) +_banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix, notbandedX, notbandedY) = + banded_dense_axpy!(a, X, Y) -banded_axpy!(a::Number, X::AbstractMatrix{U}, Y::AbstractMatrix{V}) where {U, V} = banded_generic_axpy!(a, X, Y) # matrix * vector +banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector) = + _banded_matvecmul!(c, tA, A, b, blasstructure(c), blasstructure(A), blasstructure(b)) +_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{T}, b::AbstractVector{T}, + ::BlasStrided, ::BlasBanded, ::BlasStrided) where {T <: BlasFloat} = + generally_banded_matvecmul!(c, tA, A, b) +_banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector, + notblasc, notblasA, notblasb) = + banded_generic_matvecmul!(c, tA, A, b) + -# for AbstractMatrix, uses the generic version of multiplication -banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} = banded_generic_matvecmul!(c, tA, A, b) banded_A_mul_B!(c::AbstractVector, A::AbstractMatrix, b::AbstractVector) = banded_matvecmul!(c, 'N', A, b) banded_Ac_mul_B!(c::AbstractVector, A::AbstractMatrix, b::AbstractVector) = banded_matvecmul!(c, 'C', A, b) banded_At_mul_B!(c::AbstractVector, A::AbstractMatrix, b::AbstractVector) = banded_matvecmul!(c, 'T', A, b) # matrix * matrix +banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix) = + banded_matmatmul!(C, tA, tB, A, B, blasstructure(A), blasstructure(B)) +banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, + notblasA, notblasB) = + banded_generic_matmatmul!(C, tA, tB, A, B) +banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, + ::BlasBanded, ::BlasBanded) = + generally_banded_matmatmul!(C, tA, tB, A, B) + + -banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} = banded_generic_matmatmul!(C, tA, tB, A, B) banded_A_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) banded_Ac_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) banded_At_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) @@ -21,3 +71,474 @@ banded_A_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = band banded_A_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) banded_Ac_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) banded_At_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) + + + +# some default functions + + + +# additions and subtractions + + +@propagate_inbounds function banded_generic_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) + n,m = size(X) + if (n,m) ≠ size(Y) + throw(BoundsError()) + end + Xl, Xu = bandwidths(X) + Yl, Yu = bandwidths(Y) + + @boundscheck if Xl > Yl + # test that all entries are zero in extra bands + for j=1:size(X,2),k=max(1,j+Yl+1):min(j+Xl,n) + if inbands_getindex(X, k, j) ≠ 0 + throw(BandError(X, (k,j))) + end + end + end + @boundscheck if Xu > Yu + # test that all entries are zero in extra bands + for j=1:size(X,2),k=max(1,j-Xu):min(j-Yu-1,n) + if inbands_getindex(X, k, j) ≠ 0 + throw(BandError(X, (k,j))) + end + end + end + + l = min(Xl,Yl) + u = min(Xu,Yu) + + @inbounds for j=1:m,k=max(1,j-u):min(n,j+l) + inbands_setindex!(Y, a*inbands_getindex(X,k,j) + inbands_getindex(Y,k,j) ,k, j) + end + Y +end + +function banded_dense_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) + if size(X) != size(Y) + throw(DimensionMismatch("+")) + end + @inbounds for j=1:size(X,2),k=colrange(X,j) + Y[k,j] += a*inbands_getindex(X,k,j) + end + Y +end + + +# matrix * vector + +function _banded_generic_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} + @inbounds c[:] = zero(T) + if tA == 'N' + @inbounds for j = 1:size(A,2), k = colrange(A,j) + c[k] += inbands_getindex(A,k,j)*b[j] + end + elseif tA == 'C' + @inbounds for j = 1:size(A,2), k = colrange(A,j) + c[j] += inbands_getindex(A,k,j)'*b[k] + end + elseif tA == 'T' + @inbounds for j = 1:size(A,2), k = colrange(A,j) + c[j] += inbands_getindex(A,k,j)*b[k] + end + end + c +end + + +positively_banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector) = + _positively_banded_matvecmul!(c, tA, A, b, blasstructure(c), blasstructure(A), blasstructure(b)) +_positively_banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector, + notblasc, notblasA, notblasb) = + _banded_generic_matvecmul!(c, tA, A, b) + +# use BLAS routine for positively banded BlasBanded +_positively_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{T}, b::AbstractVector{T}, + ::BlasStrided, ::BlasBanded, ::BlasStrided) where {T <: BlasFloat} = + gbmv!(tA, one(T), A, b, zero(T), c) + +positively_banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix) = + _positively_banded_matmatmul!(C, tA, tB, A, B, blasstructure(C), blasstructure(A), blasstructure(B)) +_positively_banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, + notblasC, notblasA, notblasb) = + _banded_generic_matmatmul!(C, tA, tB, A, B) + +function generally_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} + m, n = _size(tA, A) + if length(c) ≠ m || length(b) ≠ n + throw(DimensionMismatch("*")) + end + + l, u = _bandwidths(tA, A) + if -l > u + # no bands + c[:] = zero(T) + elseif l < 0 + banded_matvecmul!(c, tA, _view(tA, A, :, 1-l:n), view(b, 1-l:n)) + elseif u < 0 + c[1:-u] = zero(T) + banded_matvecmul!(view(c, 1-u:m), tA, _view(tA, A, 1-u:m, :), b) + else + positively_banded_matvecmul!(c, tA, A, b) + end + c +end + +banded_generic_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector) = + generally_banded_matvecmul!(c, tA, A, b) + + + +# matrix * matrix +function _banded_generic_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} + Am, An = _size(tA, A) + Bm, Bn = _size(tB, B) + Al, Au = _bandwidths(tA, A) + Bl, Bu = _bandwidths(tB, B) + Cl,Cu = prodbandwidths(tA, tB, A, B) + + if tA == 'N' && tB == 'N' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,ν,j) + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'C' && tB == 'N' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,ν,k)' * inbands_getindex(B,ν,j) + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'N' && tB == 'C' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,j,ν)' + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'C' && tB == 'C' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,ν,k)' * inbands_getindex(B,j,ν)' + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'T' && tB == 'N' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,ν,k) * inbands_getindex(B,ν,j) + end + inbands_setindex!(C,tmp,k,j) + end + + elseif tA == 'N' && tB == 'T' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,j,ν) + end + inbands_setindex!(C,tmp,k,j) + end + elseif tA == 'T' && tB == 'T' + @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) + νmin = max(1,k-Al,j-Bu) + νmax = min(An,k+Au,j+Bl) + + tmp = zero(T) + for ν=νmin:νmax + tmp = tmp + inbands_getindex(A,ν,k) * inbands_getindex(B,j,ν) + end + inbands_setindex!(C,tmp,k,j) + end + end + C +end + +# use BLAS routine for positively banded BlasBandedMatrices +function _positively_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{T}, B::AbstractMatrix{T}, + ::BlasBanded, ::BlasBanded, ::BlasBanded) where {T} + Al, Au = _bandwidths(tA, A) + Bl, Bu = _bandwidths(tB, B) + # _banded_generic_matmatmul! is faster for sparse matrix + if tA != 'N' || tB != 'N' || (Al + Au < 100 && Bl + Bu < 100) + _banded_generic_matmatmul!(C, tA, tB, A, B) + else + # TODO: implement gbmm! routines for other flags + gbmm!('N', 'N', one(T), A, B, zero(T), C) + end +end + + +function generally_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} + Am, An = _size(tA, A) + Bm, Bn = _size(tB, B) + if An != Bm || size(C, 1) != Am || size(C, 2) != Bn + throw(DimensionMismatch("*")) + end + # TODO: checkbandmatch + + Al, Au = _bandwidths(tA, A) + Bl, Bu = _bandwidths(tB, B) + + if (-Al > Au) || (-Bl > Bu) # A or B has empty bands + C[:,:] = zero(T) + elseif Al < 0 + C[max(1,Bn+Al-1):Am, :] = zero(T) + banded_matmatmul!(C, tA, tB, _view(tA, A, :, 1-Al:An), _view(tB, B, 1-Al:An, :)) + elseif Au < 0 + C[1:-Au,:] = zero(T) + banded_matmatmul!(view(C, 1-Au:Am,:), tA, tB, _view(tA, A, 1-Au:Am,:), B) + elseif Bl < 0 + C[:, 1:-Bl] = zero(T) + banded_matmatmul!(view(C, :, 1-Bl:Bn), tA, tB, A, _view(tB, B, :, 1-Bl:Bn)) + elseif Bu < 0 + C[:, max(1,Am+Bu-1):Bn] = zero(T) + banded_matmatmul!(C, tA, tB, _view(tA, A, :, 1-Bu:Bm), _view(tB, B, 1-Bu:Bm, :)) + else + positively_banded_matmatmul!(C, tA::Char, tB::Char, A, B) + end + C +end + + +banded_generic_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix) = + generally_banded_matmatmul!(C, tA, tB, A, B) + + + +# add banded linear algebra routines between Typ1 and Typ2 both implementing +# the BandedMatrix interface +macro _banded_banded_linalg(Typ1, Typ2) + ret = quote + Base.BLAS.axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_axpy!(a, X, Y) + + function Base.:+(A::$Typ1{T}, B::$Typ2{V}) where {T,V} + n, m = size(A) + ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) + axpy!(one(T), A, ret) + axpy!(one(V), B, ret) + ret + end + + function Base.:-(A::$Typ1{T}, B::$Typ2{V}) where {T,V} + n, m=size(A) + ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) + axpy!(one(T), A, ret) + axpy!(-one(V), B, ret) + ret + end + + + Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = banded_matmatmul!(C, 'N', 'N', A, B) + + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) + + Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + + # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + + function Base.:*(A::$Typ1{T}, B::$Typ2{V}) where {T, V} + n, m = size(A,1), size(B,2) + Y = BandedMatrix(promote_type(T,V), n, m, prodbandwidths(A, B)...) + A_mul_B!(Y, A, B) + end + + Base.LinAlg.Ac_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_B!(BandedMatrices.banded_similar('C', 'N', A, B, promote_type(T, V)), A, B) + Base.LinAlg.A_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bc!(BandedMatrices.banded_similar('N', 'C', A, B, promote_type(T, V)), A, B) + Base.LinAlg.Ac_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_Bc!(BandedMatrices.banded_similar('C', 'C', A, B, promote_type(T, V)), A, B) + + Base.LinAlg.At_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'N', A, B, promote_type(T, V)), A, B) + Base.LinAlg.A_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bt!(BandedMatrices.banded_similar('N', 'T', A, B, promote_type(T, V)), A, B) + Base.LinAlg.At_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'T', A, B, promote_type(T, V)), A, B) + end + esc(ret) +end + +macro banded_banded_linalg(Typ1, Typ2) + ret = quote + BandedMatrices.@_banded_banded_linalg($Typ1, $Typ2) + end + if Typ1 ≠ Typ2 + ret = quote + $ret + BandedMatrices.@_banded_banded_linalg($Typ2, $Typ1) + end + end + esc(ret) +end + +# add banded linear algebra routines for Typ implementing the BandedMatrix interface +macro _banded_linalg(Typ) + ret = quote + BandedMatrices.@banded_banded_linalg($Typ, $Typ) + + Base.BLAS.axpy!(a::Number, X::$Typ, Y::AbstractMatrix) = + BandedMatrices.banded_axpy!(a, X, Y) + function Base.:+(A::$Typ{T}, B::AbstractMatrix{T}) where {T} + ret = deepcopy(B) + axpy!(one(T), A, ret) + ret + end + function Base.:+(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} + n, m=size(A) + ret = zeros(promote_type(T,V),n,m) + axpy!(one(T), A,ret) + axpy!(one(V), B,ret) + ret + end + Base.:+(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = B + A + + function Base.:-(A::$Typ{T}, B::AbstractMatrix{T}) where {T} + ret = deepcopy(B) + Base.scale!(ret, -one(T)) + Base.BLAS.axpy!(one(T), A, ret) + ret + end + function Base.:-(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} + n, m= size(A) + ret = zeros(promote_type(T,V),n,m) + Base.BLAS.axpy!( one(T), A, ret) + Base.BLAS.axpy!(-one(V), B, ret) + ret + end + Base.:-(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = Base.scale!(B - A, -1) + + + + ## UniformScaling + + function Base.BLAS.axpy!(a::Number, X::UniformScaling, Y::$Typ{T}) where {T} + BandedMatrices.checksquare(Y) + α = a * X.λ + @inbounds for k = 1:size(Y,1) + BandedMatrices.inbands_setindex!(Y, BandedMatrices.inbands_getindex(Y, k, k) + α, k, k) + end + Y + end + + function Base.:+(A::$Typ, B::UniformScaling) + ret = deepcopy(A) + Base.BLAS.axpy!(1, B,ret) + end + + Base.:+(A::UniformScaling, B::$Typ) = B + A + + function Base.:-(A::$Typ, B::UniformScaling) + ret = deepcopy(A) + axpy!(-1, B, ret) + end + + function Base.:-(A::UniformScaling, B::$Typ) + ret = deepcopy(B) + Base.scale!(ret, -1) + axpy!(1, A, ret) + end + + Base.LinAlg.A_mul_B!(c::AbstractVector, A::$Typ, b::AbstractVector) = + BandedMatrices.banded_matvecmul!(c, 'N', A, b) + Base.LinAlg.Ac_mul_B!(c::AbstractVector, A::$Typ, b::AbstractVector) = + BandedMatrices.banded_matvecmul!(c, 'C', A, b) + Base.LinAlg.Ac_mul_B!(c::AbstractVector, A::$Typ{<:Real}, b::AbstractVector) = + BandedMatrices.banded_matvecmul!(c, 'T', A, b) + Base.LinAlg.At_mul_B!(c::AbstractVector, A::$Typ, b::AbstractVector) = + BandedMatrices.banded_matvecmul!(c, 'T', A, b) + + Base.:*(A::$Typ{U}, b::StridedVector{V}) where {U, V} = + Base.LinAlg.A_mul_B!(Vector{promote_type(U, V)}(size(A, 1)), A, b) + + + Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) + Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) + + + + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) + + Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + + # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) + + + function Base.:*(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} + n, m = size(A,1), size(B,2) + A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) + end + + function Base.:*(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} + n, m = size(A,1), size(B,2) + A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) + end + + Base.LinAlg.Ac_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.Ac_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.A_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.A_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.Ac_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + Base.LinAlg.Ac_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + + Base.LinAlg.At_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.At_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) + Base.LinAlg.A_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.A_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) + Base.LinAlg.At_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + Base.LinAlg.At_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + end + esc(ret) +end + +macro banded_linalg(Typ) + ret = quote + BandedMatrices.@_banded_linalg($Typ) + BandedMatrices.@banded_banded_linalg($Typ, BandedMatrices.AbstractBandedMatrix) + end + esc(ret) +end diff --git a/src/generic/linalg.jl b/src/generic/linalg.jl deleted file mode 100644 index 7baff489..00000000 --- a/src/generic/linalg.jl +++ /dev/null @@ -1,478 +0,0 @@ -# some functions - -function banded_axpy! end -function banded_matmatmul! end -function banded_matvecmul! end - - -# additions and subtractions - -@propagate_inbounds function banded_generic_axpy!(a::Number, X::AbstractMatrix{U}, Y::AbstractMatrix{V}) where {U, V} - n,m = size(X) - if (n,m) ≠ size(Y) - throw(BoundsError()) - end - Xl, Xu = bandwidths(X) - Yl, Yu = bandwidths(Y) - - @boundscheck if Xl > Yl - # test that all entries are zero in extra bands - for j=1:size(X,2),k=max(1,j+Yl+1):min(j+Xl,n) - if inbands_getindex(X,k,j) ≠ 0 - throw(BandError(X, (k,j))) - end - end - end - @boundscheck if Xu > Yu - # test that all entries are zero in extra bands - for j=1:size(X,2),k=max(1,j-Xu):min(j-Yu-1,n) - if inbands_getindex(X,k,j) ≠ 0 - throw(BandError(X, (k,j))) - end - end - end - - l = min(Xl,Yl) - u = min(Xu,Yu) - - @inbounds for j=1:m,k=max(1,j-u):min(n,j+l) - inbands_setindex!(Y, a*inbands_getindex(X,k,j) + inbands_getindex(Y,k,j) ,k, j) - end - Y -end - -function banded_dense_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) - if size(X) != size(Y) - throw(DimensionMismatch("+")) - end - @inbounds for j=1:size(X,2),k=colrange(X,j) - Y[k,j] += a*inbands_getindex(X,k,j) - end - Y -end - - -# matrix * vector - -function _banded_generic_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} - @inbounds c[:] = zero(T) - if tA == 'N' - @inbounds for j = 1:size(A,2), k = colrange(A,j) - c[k] += inbands_getindex(A,k,j)*b[j] - end - elseif tA == 'C' - @inbounds for j = 1:size(A,2), k = colrange(A,j) - c[j] += inbands_getindex(A,k,j)'*b[k] - end - elseif tA == 'T' - @inbounds for j = 1:size(A,2), k = colrange(A,j) - c[j] += inbands_getindex(A,k,j)*b[k] - end - end - c -end - - -positively_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} = - _banded_generic_matvecmul!(c, tA, A, b) -positively_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} = - _banded_generic_matmatmul!(C, tA, tB, A, B) - -function generally_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} - m, n = _size(tA, A) - if length(c) ≠ m || length(b) ≠ n - throw(DimensionMismatch("*")) - end - - l, u = _bandwidths(tA, A) - if -l > u - # no bands - c[:] = zero(T) - elseif l < 0 - banded_matvecmul!(c, tA, _view(tA, A, :, 1-l:n), view(b, 1-l:n)) - elseif u < 0 - c[1:-u] = zero(T) - banded_matvecmul!(view(c, 1-u:m), tA, _view(tA, A, 1-u:m, :), b) - else - positively_banded_matvecmul!(c, tA, A, b) - end - c -end - -banded_generic_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{U}, b::AbstractVector{V}) where {T, U, V} = generally_banded_matvecmul!(c, tA, A, b) - - -# matrix * matrix -function _banded_generic_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} - Am, An = _size(tA, A) - Bm, Bn = _size(tB, B) - Al, Au = _bandwidths(tA, A) - Bl, Bu = _bandwidths(tB, B) - Cl,Cu = prodbandwidths(tA, tB, A, B) - - if tA == 'N' && tB == 'N' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,ν,j) - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'C' && tB == 'N' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,ν,k)' * inbands_getindex(B,ν,j) - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'N' && tB == 'C' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,j,ν)' - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'C' && tB == 'C' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,ν,k)' * inbands_getindex(B,j,ν)' - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'T' && tB == 'N' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,ν,k) * inbands_getindex(B,ν,j) - end - inbands_setindex!(C,tmp,k,j) - end - - elseif tA == 'N' && tB == 'T' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,k,ν) * inbands_getindex(B,j,ν) - end - inbands_setindex!(C,tmp,k,j) - end - elseif tA == 'T' && tB == 'T' - @inbounds for j = 1:Bn, k = max(j-Cu, 1):max(min(j+Cl, Am), 0) - νmin = max(1,k-Al,j-Bu) - νmax = min(An,k+Au,j+Bl) - - tmp = zero(T) - for ν=νmin:νmax - tmp = tmp + inbands_getindex(A,ν,k) * inbands_getindex(B,j,ν) - end - inbands_setindex!(C,tmp,k,j) - end - end - C -end - -# use BLAS routine for positively banded BLASBandedMatrices -function _positively_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{T}, B::AbstractMatrix{T}) where {T <: BlasFloat} - Al, Au = _bandwidths(tA, A) - Bl, Bu = _bandwidths(tB, B) - # _banded_generic_matmatmul! is faster for sparse matrix - if tA != 'N' || tB != 'N' || (Al + Au < 100 && Bl + Bu < 100) - _banded_generic_matmatmul!(C, tA, tB, A, B) - else - # TODO: implement gbmm! routines for other flags - gbmm!('N', 'N', one(T), A, B, zero(T), C) - end -end - - -function generally_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} - Am, An = _size(tA, A) - Bm, Bn = _size(tB, B) - if An != Bm || size(C, 1) != Am || size(C, 2) != Bn - throw(DimensionMismatch("*")) - end - # TODO: checkbandmatch - - Al, Au = _bandwidths(tA, A) - Bl, Bu = _bandwidths(tB, B) - - if (-Al > Au) || (-Bl > Bu) # A or B has empty bands - C[:,:] = zero(T) - elseif Al < 0 - C[max(1,Bn+Al-1):Am, :] = zero(T) - banded_matmatmul!(C, tA, tB, _view(tA, A, :, 1-Al:An), _view(tB, B, 1-Al:An, :)) - elseif Au < 0 - C[1:-Au,:] = zero(T) - banded_matmatmul!(view(C, 1-Au:Am,:), tA, tB, _view(tA, A, 1-Au:Am,:), B) - elseif Bl < 0 - C[:, 1:-Bl] = zero(T) - banded_matmatmul!(view(C, :, 1-Bl:Bn), tA, tB, A, _view(tB, B, :, 1-Bl:Bn)) - elseif Bu < 0 - C[:, max(1,Am+Bu-1):Bn] = zero(T) - banded_matmatmul!(C, tA, tB, _view(tA, A, :, 1-Bu:Bm), _view(tB, B, 1-Bu:Bm, :)) - else - positively_banded_matmatmul!(C, tA::Char, tB::Char, A, B) - end - C -end - - -banded_generic_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} = generally_banded_matmatmul!(C, tA, tB, A, B) - - - - -macro banded_banded_banded_linalg(Typ1, Typ2, Typ3) - ret = quote - BandedMatrices.positively_banded_matmatmul!(C::$Typ1{T}, tA::Char, tB::Char, A::$Typ2{T}, B::$Typ3{T}) where {T <: BlasFloat} = - BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) - end - esc(ret) -end - - -# add banded linear algebra routines between Typ1 and Typ2 both implementing -# the BandedMatrix interface -macro _banded_banded_linalg(Typ1, Typ2) - ret = quote - BandedMatrices.@banded_banded_banded_linalg($Typ2, $Typ1, $Typ2) # the first argument is the destination - - BandedMatrices.banded_axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_generic_axpy!(a, X, Y) - Base.BLAS.axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_axpy!(a, X, Y) - - function Base.:+(A::$Typ1{T}, B::$Typ2{V}) where {T,V} - n, m = size(A) - ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) - axpy!(one(T), A, ret) - axpy!(one(V), B, ret) - ret - end - - function Base.:-(A::$Typ1{T}, B::$Typ2{V}) where {T,V} - n, m=size(A) - ret = BandedMatrices.bzeros(promote_type(T,V), n, m, BandedMatrices.sumbandwidths(A, B)...) - axpy!(one(T), A, ret) - axpy!(-one(V), B, ret) - ret - end - - BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::$Typ1{T}, B::$Typ2{T}) where {T <: BlasFloat} = - BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) - - Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = banded_matmatmul!(C, 'N', 'N', A, B) - - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) - - Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ1, B::$Typ2) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - - # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ1{U}, B::$Typ2{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - - function Base.:*(A::$Typ1{T}, B::$Typ2{V}) where {T, V} - n, m = size(A,1), size(B,2) - Y = BandedMatrix(promote_type(T,V), n, m, prodbandwidths(A, B)...) - A_mul_B!(Y, A, B) - end - - Base.LinAlg.Ac_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_B!(BandedMatrices.banded_similar('C', 'N', A, B, promote_type(T, V)), A, B) - Base.LinAlg.A_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bc!(BandedMatrices.banded_similar('N', 'C', A, B, promote_type(T, V)), A, B) - Base.LinAlg.Ac_mul_Bc(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = Ac_mul_Bc!(BandedMatrices.banded_similar('C', 'C', A, B, promote_type(T, V)), A, B) - - Base.LinAlg.At_mul_B(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'N', A, B, promote_type(T, V)), A, B) - Base.LinAlg.A_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = A_mul_Bt!(BandedMatrices.banded_similar('N', 'T', A, B, promote_type(T, V)), A, B) - Base.LinAlg.At_mul_Bt(A::$Typ1{T}, B::$Typ2{V}) where {T, V} = At_mul_B!(BandedMatrices.banded_similar('T', 'T', A, B, promote_type(T, V)), A, B) - end - esc(ret) -end - -macro banded_banded_linalg(Typ1, Typ2) - ret = quote - BandedMatrices.@_banded_banded_linalg($Typ1, $Typ2) - end - if Typ1 ≠ Typ2 - ret = quote - $ret - BandedMatrices.@_banded_banded_linalg($Typ2, $Typ1) - BandedMatrices.@banded_banded_banded_linalg($Typ1, $Typ1, $Typ2) - BandedMatrices.@banded_banded_banded_linalg($Typ2, $Typ2, $Typ1) - end - end - esc(ret) -end - -# add banded linear algebra routines for Typ implementing the BandedMatrix interface -macro banded_linalg(Typ) - ret = quote - BandedMatrices.@banded_banded_linalg($Typ, $Typ) - # default is to use dense axpy! - BandedMatrices.banded_axpy!(a::Number, X::$Typ, Y::AbstractMatrix) = - BandedMatrices.banded_dense_axpy!(a, X, Y) - Base.BLAS.axpy!(a::Number, X::$Typ, Y::AbstractMatrix) = - BandedMatrices.banded_axpy!(a, X, Y) - function Base.:+(A::$Typ{T}, B::AbstractMatrix{T}) where {T} - ret = deepcopy(B) - axpy!(one(T), A, ret) - ret - end - function Base.:+(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} - n, m=size(A) - ret = zeros(promote_type(T,V),n,m) - axpy!(one(T), A,ret) - axpy!(one(V), B,ret) - ret - end - Base.:+(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = B + A - - function Base.:-(A::$Typ{T}, B::AbstractMatrix{T}) where {T} - ret = deepcopy(B) - Base.scale!(ret,-1) - Base.BLAS.axpy!(one(T), A, ret) - ret - end - function Base.:-(A::$Typ{T}, B::AbstractMatrix{V}) where {T,V} - n, m= size(A) - ret = zeros(promote_type(T,V),n,m) - Base.BLAS.axpy!(one(T), A, ret) - Base.BLAS.axpy!(-one(V), B, ret) - ret - end - Base.:-(A::AbstractMatrix{T}, B::$Typ{V}) where {T,V} = Base.scale!(B - A, -1) - - - - ## UniformScaling - - function Base.BLAS.axpy!(a::Number, X::UniformScaling, Y::$Typ{T}) where {T} - BandedMatrices.checksquare(Y) - α = a * X.λ - @inbounds for k = 1:size(Y,1) - BandedMatrices.inbands_setindex!(Y, BandedMatrices.inbands_getindex(Y, k, k) + α, k, k) - end - Y - end - - function Base.:+(A::$Typ, B::UniformScaling) - ret = deepcopy(A) - Base.BLAS.axpy!(1, B,ret) - end - - Base.:+(A::UniformScaling, B::$Typ) = B + A - - function Base.:-(A::$Typ, B::UniformScaling) - ret = deepcopy(A) - axpy!(-1, B, ret) - end - - function Base.:-(A::UniformScaling, B::$Typ) - ret = deepcopy(B) - Base.scale!(ret, -1) - axpy!(1, A, ret) - end - - # use BLAS routine for positively banded BLASBandedMatrix - BandedMatrices.positively_banded_matvecmul!(c::StridedVector{T}, tA::Char, A::$Typ{T}, b::StridedVector{T}) where {T <: BandedMatrices.BlasFloat} = - BandedMatrices.gbmv!(tA, one(T), A, b, zero(T), c) - - - BandedMatrices.banded_matvecmul!(c::StridedVector{T}, tA::Char, A::$Typ{T}, b::AbstractVector{T}) where {T <: BlasFloat} = - BandedMatrices.generally_banded_matvecmul!(c, tA, A, b) - - Base.LinAlg.A_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'N', A, b) - Base.LinAlg.Ac_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'C', A, b) - Base.LinAlg.Ac_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U<:Real, V} = BandedMatrices.banded_matvecmul!(c, 'T', A, b) - Base.LinAlg.At_mul_B!(c::AbstractVector{T}, A::$Typ{U}, b::AbstractVector{V}) where {T, U, V} = BandedMatrices.banded_matvecmul!(c, 'T', A, b) - - Base.:*(A::$Typ{U}, b::StridedVector{V}) where {U, V} = - Base.LinAlg.A_mul_B!(Vector{promote_type(U, V)}(size(A, 1)), A, b) - - BandedMatrices.positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::$Typ{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = - BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) - BandedMatrices.positively_banded_matmatmul!(C::StridedMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::$Typ{T}) where {T <: BlasFloat} = - BandedMatrices._positively_banded_matmatmul!(C, tA, tB, A, B) - - BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::$Typ{T}, B::StridedMatrix{T}) where {T <: BlasFloat} = - BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) - BandedMatrices.banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, B::$Typ{T}) where {T <: BlasFloat} = - BandedMatrices.generally_banded_matmatmul!(C, tA, tB, A, B) - - Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) - Base.LinAlg.A_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'N', A, B) - - - - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'N', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'C', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'C', 'C', A, B) - - Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.At_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.A_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::$Typ, B::AbstractMatrix) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - Base.LinAlg.At_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::$Typ) = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - - # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.Ac_mul_B!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V} = BandedMatrices.banded_matmatmul!(C, 'T', 'N', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.A_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'N', 'T', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::$Typ{U}, B::AbstractMatrix{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - Base.LinAlg.Ac_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::$Typ{V}) where {T, U<:Real, V<:Real} = BandedMatrices.banded_matmatmul!(C, 'T', 'T', A, B) - - - function Base.:*(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} - n, m = size(A,1), size(B,2) - A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) - end - - function Base.:*(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} - n, m = size(A,1), size(B,2) - A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) - end - - Base.LinAlg.Ac_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) - Base.LinAlg.Ac_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) - Base.LinAlg.A_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) - Base.LinAlg.A_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) - Base.LinAlg.Ac_mul_Bc(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - Base.LinAlg.Ac_mul_Bc(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - - Base.LinAlg.At_mul_B(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) - Base.LinAlg.At_mul_B(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) - Base.LinAlg.A_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) - Base.LinAlg.A_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) - Base.LinAlg.At_mul_Bt(A::$Typ{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - Base.LinAlg.At_mul_Bt(A::StridedMatrix{T}, B::$Typ{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - end - esc(ret) -end diff --git a/src/symbanded/SymBandedMatrix.jl b/src/symbanded/SymBandedMatrix.jl index 919df954..274e0456 100644 --- a/src/symbanded/SymBandedMatrix.jl +++ b/src/symbanded/SymBandedMatrix.jl @@ -23,6 +23,7 @@ mutable struct SymBandedMatrix{T} <: AbstractBandedMatrix{T} end end +blasstructure(::Type{SymBandedMatrix{<:BlasFloat}}) = BlasSymBanded() SymBandedMatrix(data::Matrix,k::Integer) = SymBandedMatrix{eltype(data)}(data,k) @@ -42,8 +43,8 @@ SymBandedMatrix(::Type{T},n::Integer,k::Integer) where {T} = for MAT in (:SymBandedMatrix, :AbstractBandedMatrix, :AbstractMatrix, :AbstractArray) - @eval Base.convert(::Type{$MAT{V}},M::SymBandedMatrix) where {V} = - SymBandedMatrix{V}(convert(Matrix{V},M.data),M.k) + @eval Base.convert(::Type{$MAT{V}}, M::SymBandedMatrix) where {V} = + SymBandedMatrix{V}(convert(Matrix{V},M.data), M.k) end Base.copy(B::SymBandedMatrix) = SymBandedMatrix(copy(B.data),B.k) From f80767f8b2de0a587ef638db74587b7fc5eca3f4 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 12 Nov 2017 18:24:17 +0000 Subject: [PATCH 06/26] using Test in 0.7 --- test/test_indexing.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/test_indexing.jl b/test/test_indexing.jl index 6bcc8f65..913df127 100644 --- a/test/test_indexing.jl +++ b/test/test_indexing.jl @@ -1,4 +1,10 @@ -using Base.Test, BandedMatrices +using BandedMatrices +if VERSION < v"0.7-" + using Base.Test +else + using Test +end + import BandedMatrices: rowstart, rowstop, colstart, From 96b95ac828d7a191129f30b8dad821bbd426bc94 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 13 Nov 2017 19:30:49 +0000 Subject: [PATCH 07/26] Add @banded and @banded_interface macros for adding new banded matrices that are not <: AbstractBandedMatrix --- src/banded/BandedMatrix.jl | 3 +-- src/generic/interface.jl | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 8277f014..103a87fc 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -31,9 +31,8 @@ blasstructure(::Type{BandedMatrix{<:BlasFloat}}) = BlasStrided() const BandedSubBandedMatrix{T} = SubArray{T,2,BandedMatrix{T},I} where I<:Tuple{Vararg{AbstractUnitRange}} -@banded_linalg BandedSubBandedMatrix +@banded BandedSubBandedMatrix -isbanded(::BandedSubBandedMatrix{T}) where {T} = true blasstructure(::Type{BandedSubBandedMatrix{<:BlasFloat}}) = BlasStrided() ## Constructors diff --git a/src/generic/interface.jl b/src/generic/interface.jl index a3d8546e..ed36d70d 100644 --- a/src/generic/interface.jl +++ b/src/generic/interface.jl @@ -542,3 +542,20 @@ macro banded_linalg(Typ) end esc(ret) end + +# add routines for banded interface +macro banded_interface(Typ) + ret = quote + BandedMatrices.bandedinterface(::$Typ) = BandedMatrices.BandedInterface{true}() + BandedMatrices.isbanded(::$Typ) = true + end + esc(ret) +end + +macro banded(Typ) + ret = quote + BandedMatrices.@banded_interface($Typ) + BandedMatrices.@banded_linalg($Typ) + end + esc(ret) +end From acb5b84fc3fbdb5c25108e5da3d8564f211816e5 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 20 Nov 2017 16:11:28 +0000 Subject: [PATCH 08/26] start using Zeros and Eye --- README.md | 8 +++---- docs/src/index.md | 15 ------------ src/BandedMatrices.jl | 7 ++++-- src/banded/BandedMatrix.jl | 30 ++++++++++++++++++++---- src/banded/BandedQR.jl | 2 +- src/banded/linalg.jl | 4 ++-- src/deprecate.jl | 40 ++++++++++++++++++++++++++++++++ src/symbanded/SymBandedMatrix.jl | 23 +++++++++++++++--- test/test_banded.jl | 7 +++++- test/test_indexing.jl | 8 +++---- test/test_miscs.jl | 4 ++-- test/test_symbanded.jl | 4 ++-- 12 files changed, 112 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index fe01d309..5b9f8188 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A Julia package for representing banded matrices [![Build Status](https://travis-ci.org/JuliaMatrices/BandedMatrices.jl.svg?branch=master)](https://travis-ci.org/JuliaMatrices/BandedMatrices.jl) -[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaMatrices.github.io/BandedMatrices.jl/stable) +[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaMatrices.github.io/BandedMatrices.jl/stable) [![](https://img.shields.io/badge/docs-latest-blue.svg)](https://JuliaMatrices.github.io/BandedMatrices.jl/latest) @@ -14,10 +14,10 @@ bands. One can create banded matrices of type `BandedMatrix` as follows: ```julia -bzeros(m,n,l,u) # creates a banded matrix of zeros, with l sub-diagonals and u super-diagonals +BandedMatrix(Zeros(m,n), l, u) # creates a banded matrix of zeros, with l sub-diagonals and u super-diagonals brand(m,n,l,u) # creates a random banded matrix, with l sub-diagonals and u super-diagonals -bones(m,n,l,u) # creates a banded matrix of ones, with l sub-diagonals and u super-diagonals -beye(n,l,u) # creates a banded n x n identity matrix, with l sub-diagonals and u super-diagonals +BandedMatrix(Ones(m,n), l, u) # creates a banded matrix of ones, with l sub-diagonals and u super-diagonals +BandedMatrix(Eye(n),l,u) # creates a banded n x n identity matrix, with l sub-diagonals and u super-diagonals ``` Specialized algebra routines are overriden, include `*` and `\`: diff --git a/docs/src/index.md b/docs/src/index.md index c8f725f4..0ef376eb 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -7,10 +7,6 @@ BandedMatrix ``` -```@docs -beye -``` - ```@docs bones ``` @@ -19,10 +15,6 @@ bones brand ``` -```@docs -bzeros -``` - ## Accessing banded matrices @@ -54,9 +46,6 @@ BandRange SymBandedMatrix ``` -```@docs -sbeye -``` ```@docs sbones @@ -66,10 +55,6 @@ sbones sbrand ``` -```@docs -sbzeros -``` - ## Banded matrix interface diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index 7eab202f..27591485 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -1,7 +1,7 @@ __precompile__() module BandedMatrices -using Base, Compat +using Base, Compat, FillArrays import Base: getindex, setindex!, *, +, -, ==, <, <=, >, >=, /, ^, \, transpose, showerror, reindex, checkbounds @@ -51,7 +51,10 @@ export BandedMatrix, BandRange, bandwidths, colrange, - rowrange + rowrange, + Zeros, + Fill, + Ones diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 1f6247c5..f0365ec5 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -89,10 +89,9 @@ Base.promote_rule(::Type{BandedMatrix{T}},::Type{BandedMatrix{V}}) where {T,V} = for (op,bop) in ((:(Base.rand),:brand),(:(Base.zeros),:bzeros),(:(Base.ones),:bones)) - name_str = "bzeros" @eval begin $bop(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} = - BandedMatrix($op(T,max(0,b+a+1),m),n,a,b) + BandedMatrix{T}($op(T,max(0,b+a+1),m),n,a,b) $bop(::Type{T},n::Integer,a::Integer,b::Integer) where {T} = $bop(T,n,n,a,b) $bop(::Type{T},n::Integer,::Colon,a::Integer,b::Integer) where {T} = $bop(T,n,n+b,a,b) $bop(::Type{T},::Colon,m::Integer,a::Integer,b::Integer) where {T} = $bop(T,m+a,m,a,b) @@ -111,6 +110,26 @@ for (op,bop) in ((:(Base.rand),:brand),(:(Base.zeros),:bzeros),(:(Base.ones),:bo end end + +## Conversions from FillArrays + +BandedMatrix{V}(Z::Zeros{T,2}, lu::NTuple{2,Int}) where {T,V} = + BandedMatrix{V}(zeros(V,max(0,sum(lu)+1),size(Z,2)),size(Z,1),lu...) + +BandedMatrix(Z::Zeros{T,2}, lu::NTuple{2,Int}) where T = BandedMatrix{T}(Z, lu) + + +BandedMatrix(E::Eye{T}, lu::NTuple{2,Int}) where T = BandedMatrix{T}(E, lu) +function BandedMatrix{T}(E::Eye, lu::NTuple{2,Int}) where T + ret=BandedMatrix(Zeros{T}(E), lu) + ret[band(0)] = one(T) + ret +end + +BandedMatrix(E::Eye) = BandedMatrix(E, (0,0)) + + + doc""" bzeros(T,n,m,l,u) @@ -133,6 +152,7 @@ Creates an `n×m` banded matrix with random numbers in the bandwidth of type `T brand + """ beye(T,n,l,u) @@ -145,6 +165,8 @@ function beye(::Type{T},n::Integer,a...) where {T} end ret end + + beye(::Type{T},n::Integer) where {T} = beye(T,n,0,0) beye(n::Integer) = beye(n,0,0) beye(n::Integer,a...) = beye(Float64,n,a...) @@ -593,7 +615,7 @@ function Base.scale!(A::BandedMatrix, α::Number) end function Base.transpose(B::BandedMatrix) - Bt=bzeros(eltype(B),size(B,2),size(B,1),B.u,B.l) + Bt = BandedMatrix(Zeros{eltype(B)}(size(B,2),size(B,1)), (B.u,B.l)) for j = 1:size(B,2), k = colrange(B,j) Bt[j,k]=B[k,j] end @@ -601,7 +623,7 @@ function Base.transpose(B::BandedMatrix) end function Base.ctranspose(B::BandedMatrix) - Bt=bzeros(eltype(B),size(B,2),size(B,1),B.u,B.l) + Bt=BandedMatrix(Zeros{eltype(B)}(size(B,2),size(B,1)), (B.u,B.l)) for j = 1:size(B,2), k = colrange(B,j) Bt[j,k]=conj(B[k,j]) end diff --git a/src/banded/BandedQR.jl b/src/banded/BandedQR.jl index e02ca506..c3fc4d68 100644 --- a/src/banded/BandedQR.jl +++ b/src/banded/BandedQR.jl @@ -147,7 +147,7 @@ function Base.qr(A::BandedMatrix) end function Base.qrfact(A::BandedMatrix) - R=bzeros(eltype(A),size(A,1),size(A,2),A.l,A.l+A.u) + R=BandedMatrix(Zeros{eltype(A)}(size(A)), (A.l,A.l+A.u)) R.data[A.l+1:end,:]=A.data banded_qrfact!(R) end diff --git a/src/banded/linalg.jl b/src/banded/linalg.jl index 307ccb3f..22be0c62 100644 --- a/src/banded/linalg.jl +++ b/src/banded/linalg.jl @@ -53,7 +53,7 @@ axpy!(a::Number, X::BLASBandedMatrix, Y::AbstractMatrix) = banded_axpy!(a, X, Y) function +(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T,V} n, m=size(A) - ret = bzeros(promote_type(T,V),n,m,sumbandwidths(A, B)...) + ret = BandedMatrix(Zeros{promote_type(T,V)}(n,m), sumbandwidths(A, B)) axpy!(1.,A,ret) axpy!(1.,B,ret) ret @@ -78,7 +78,7 @@ end function -(A::BLASBandedMatrix{T}, B::BLASBandedMatrix{V}) where {T,V} n, m=size(A) - ret = bzeros(promote_type(T,V),n,m,sumbandwidths(A, B)...) + ret = BandedMatrix(Zeros{promote_type(T,V)}(n,m), sumbandwidths(A, B)) axpy!(one(T),A,ret) axpy!(-one(V),B,ret) ret diff --git a/src/deprecate.jl b/src/deprecate.jl index 11f79242..42764a87 100644 --- a/src/deprecate.jl +++ b/src/deprecate.jl @@ -1 +1,41 @@ @deprecate gbmm!(α::T, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β::T, C::AbstractMatrix{T}) where {T<:BlasFloat} gbmm!('N', 'N', α, A, B, β, C) + + +@deprecate BandedMatrix(data::Matrix,m::Int,a) BandedMatrix(data,m,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Int,m::Int,a) where {T} BandedMatrix(T,n,m,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Int,::Colon,a) where {T} BandedMatrix(T,n,:,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Int,a) where {T} BandedMatrix(T,n,-a[1],a[end]) + + + + +@deprecate bzeros(::Type{T},n::Int,m::Int,a::Int,b::Int) where {T} BandedMatrix(Zeros{T}(n,m), (a,b)) +@deprecate bzeros(::Type{T},n::Int,a::Int,b::Int) where {T} BandedMatrix(Zeros{T}(n,n), (a,b)) +@deprecate bzeros(::Type{T},n::Int,::Colon,a::Int,b::Int) where {T} BandedMatrix(Zeros{T}(n,n+b), (a,b)) +@deprecate bzeros(::Type{T},::Colon,m::Int,a::Int,b::Int) where {T} BandedMatrix(Zeros{T}(m+a,m), (a,b)) +@deprecate bzeros(n::Int,m::Int,a::Int,b::Int) BandedMatrix(Zeros(n,m), (a,b)) +@deprecate bzeros(n::Int,a::Int,b::Int) BandedMatrix(Zeros(n,n), (a,b)) + +@deprecate bzeros(::Type{T},n::Int,m::Int,a) where {T} BandedMatrix(Zeros(n,m),(-a[1],a[2])) +@deprecate bzeros(::Type{T},n::Number,::Colon,a) where {T} BandedMatrix(Zeros(n,n+a[2]),(-a[1],a[end])) +@deprecate bzeros(::Type{T},::Colon,m::Int,a) where {T} BandedMatrix(Zeros(m-a[1],m),(-a[1],a[end])) +@deprecate bzeros(::Type{T},n::Int,a) where {T} BandedMatrix(Zeros{T}(n,n),(-a[1],a[end])) +@deprecate bzeros(n::Int,m::Int,a) BandedMatrix(Zeros(n,m),(-a[1],a[end])) +@deprecate bzeros(n::Int,a) BandedMatrix(Zeros(n,n),(-a[1],a[end])) + +@deprecate bzeros(B::AbstractMatrix) BandedMatrix(Zeros(B),bandwidths(B)) + + + +@deprecate beye(::Type{T},n::Int,a) where {T} BandedMatrix(Eye{T}(n), (-a[1],a[2])) +@deprecate beye(::Type{T},n::Int) where {T} BandedMatrix(Eye{T}(n)) +@deprecate beye(n::Int) BandedMatrix(Eye(n)) +@deprecate beye(n::Int,a) BandedMatrix(Eye(n),(-a[1],a[2])) + +@deprecate BandedMatrix(data::Matrix,n::Int,l::Int,u::Int) BandedMatrix{eltype(data)}(data,n,l,u) +@deprecate SymBandedMatrix(data::Matrix,k::Int) SymBandedMatrix{eltype(data)}(data,k) + +@deprecate sbzeros(::Type{T},n::Int,a::Int) where {T} SymBandedMatrix(Zeros{T}(n,n),a) +@deprecate sbzeros(n::Int,a::Int) SymBandedMatrix(Zeros(n,n),a) + +# @deprecate sbzeros(B::AbstractMatrix) SymBandedMatrix(Zeros(B), bandwidths(B)) diff --git a/src/symbanded/SymBandedMatrix.jl b/src/symbanded/SymBandedMatrix.jl index 0e44ec4d..fda5d037 100644 --- a/src/symbanded/SymBandedMatrix.jl +++ b/src/symbanded/SymBandedMatrix.jl @@ -23,9 +23,6 @@ mutable struct SymBandedMatrix{T} <: AbstractBandedMatrix{T} end end - -SymBandedMatrix(data::Matrix,k::Integer) = SymBandedMatrix{eltype(data)}(data,k) - doc""" SymBandedMatrix(T, n, k) @@ -62,6 +59,26 @@ for (op,bop) in ((:(Base.rand),:sbrand),(:(Base.zeros),:sbzeros),(:(Base.ones),: end end +function SymBandedMatrix{V}(Z::Zeros{T,2}, a::Int) where {T,V} + n,m = size(Z) + @boundscheck n == m || throw(BoundsError()) + SymBandedMatrix{V}(zeros(V,a+1,n),a) +end + +SymBandedMatrix(Z::Zeros{T,2}, a::Int) where T = SymBandedMatrix{T}(Z, a) + + +function SymBandedMatrix{T}(E::Eye, a::Int) where T + n,m = size(E) + @boundscheck n == m || throw(BoundsError()) + ret = SymBandedMatrix(Zeros{T}(E), a) + ret[band(0)] = one(T) + ret +end + +SymBandedMatrix(Z::Eye{T}, a::Int) where T = SymBandedMatrix{T}(Z, a) +SymBandedMatrix(Z::Eye) = SymBandedMatrix(Z, 0) + doc""" sbzeros(T,n,k) diff --git a/test/test_banded.jl b/test/test_banded.jl index 7b06337d..49d640d9 100644 --- a/test/test_banded.jl +++ b/test/test_banded.jl @@ -1,5 +1,10 @@ # some basic operations +@test BandedMatrix(Zeros(5,5), (1,1)) == BandedMatrix{Float64}(zeros(3,5), 5, 1, 1) +@test BandedMatrix(Zeros{Int}(5,5), (1,1)) == BandedMatrix{Int}(zeros(Int,3,5), 5, 1, 1) +@test BandedMatrix{Int}(Zeros(5,5), (1,1)) == BandedMatrix{Int}(zeros(Int,3,5), 5, 1, 1) + + let A = brand(10,12,2,3),B = brand(10,12,3,4) @test Matrix(sparse(A)) ≈ Matrix(A) @@ -94,7 +99,7 @@ end ## BigFloat -let A = brand(5, 5, 1, 2), B = bzeros(BigFloat,5,5,2,3), D = rand(5, 5) +let A = brand(5, 5, 1, 2), B = BandedMatrix(Zeros{BigFloat}(5,5),(2,3)), D = rand(5, 5) for j = 1:size(B,2), k = colrange(B,j) B[k,j]=randn() end diff --git a/test/test_indexing.jl b/test/test_indexing.jl index d7496701..dc091783 100644 --- a/test/test_indexing.jl +++ b/test/test_indexing.jl @@ -501,7 +501,7 @@ end # indexing along a band let - a = bzeros(5, 4, 2, 1) + a = BandedMatrix(Zeros(5, 4), (2, 1)) # 5x4 BandedMatrices.BandedMatrix{Float64}: # 0.0 0.0 # 0.0 0.0 0.0 @@ -543,7 +543,7 @@ end let - a = bzeros(5, 4, 2, 2) + a = BandedMatrix(Zeros(5, 4), (2, 2)) # 5x4 BandedMatrices.BandedMatrix{Float64}: # 0.0 0.0 0.0 # 0.0 0.0 0.0 0.0 @@ -620,7 +620,7 @@ end # replace a block in the band let - a = bzeros(5, 4, 2, 1) + a = BandedMatrix(Zeros(5, 4), (2, 1)) # 5x4 BandedMatrices.BandedMatrix{Float64}: # 0.0 0.0 # 0.0 0.0 0.0 @@ -658,7 +658,7 @@ end let # tests bug - a = bzeros(1,1,3,-1) + a = BandedMatrix(Zeros(1,1), (3,-1)) a[band(-2)] .+= 2 @test isempty(a[band(-2)]) end diff --git a/test/test_miscs.jl b/test/test_miscs.jl index 3e679ff6..2054a590 100644 --- a/test/test_miscs.jl +++ b/test/test_miscs.jl @@ -6,12 +6,12 @@ Base.zero(::Type{BandedMatrixWithZero}) = 0*I A=BandedMatrix(BandedMatrixWithZero,1,2,0,1) A[1,1]=beye(1,1,0,1) -A[1,2]=bzeros(1,2,0,1) +A[1,2]=BandedMatrix(Zeros(1,2),(0,1)) A[1,2][1,1]=-1/3 A[1,2][1,2]=1/3 B=BandedMatrix(BandedMatrixWithZero,2,1,1,1) B[1,1]=0.2beye(1,1,0,1) -B[2,1]=bzeros(2,1,1,0) +B[2,1]=BandedMatrix(Zeros(2,1), (1,0)) B[2,1][1,1]=-2/30 B[2,1][2,1]=1/3 diff --git a/test/test_symbanded.jl b/test/test_symbanded.jl index 804afc24..9adba6f8 100644 --- a/test/test_symbanded.jl +++ b/test/test_symbanded.jl @@ -19,7 +19,7 @@ A = sbrand(Float64, 100, 4) # generalized eigvals function An(::Type{T}, N::Int) where {T} - A = sbzeros(T, N, 2) + A = SymBandedMatrix(Zeros{T}(N,N), 2) for n = 0:N-1 A.data[3,n+1] = T((n+1)*(n+2)) end @@ -27,7 +27,7 @@ function An(::Type{T}, N::Int) where {T} end function Bn(::Type{T}, N::Int) where {T} - B = sbzeros(T, N, 2) + B = SymBandedMatrix(Zeros{T}(N,N), 2) for n = 0:N-1 B.data[3,n+1] = T(2*(n+1)*(n+2))/T((2n+1)*(2n+5)) end From 35ca2205663acaea901ee185bb808f222b832320 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 20 Nov 2017 16:37:29 +0000 Subject: [PATCH 09/26] Deprecate BandedMatrix(data,...) for BandedMatrix{T}(data,...). --- src/BandedMatrices.jl | 5 +- src/banded/BandedMatrix.jl | 102 ++++++++++++------------------- src/banded/linalg.jl | 2 +- src/deprecate.jl | 71 +++++++++++++-------- src/symbanded/SymBandedMatrix.jl | 26 ++------ src/utils.jl | 2 +- test/test_bandedlu.jl | 12 ++-- test/test_miscs.jl | 10 +-- 8 files changed, 107 insertions(+), 123 deletions(-) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index 27591485..d4bbf771 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -36,7 +36,7 @@ import Base.LinAlg: BlasInt, copy_oftype, checksquare -import Base: lufact, cholfact, cholfact! +import Base: lufact, cholfact, cholfact!, promote_op export BandedMatrix, SymBandedMatrix, @@ -54,7 +54,8 @@ export BandedMatrix, rowrange, Zeros, Fill, - Ones + Ones, + Eye diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index f0365ec5..b3feec76 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -41,32 +41,30 @@ isbanded(::BandedSubBandedMatrix{T}) where {T} = true ## Constructors -BandedMatrix(data::Matrix,m::Integer,a::Integer,b::Integer) = BandedMatrix{eltype(data)}(data,m,a,b) - doc""" - BandedMatrix(T, n, m, l, u) + BandedMatrix{T}(n, m, l, u) returns an unitialized `n`×`m` banded matrix of type `T` with bandwidths `(l,u)`. """ -# Use zeros to avoid unallocated entries for bigfloat -BandedMatrix(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T<:BlasFloat} = + + +BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T<:BlasFloat} = BandedMatrix{T}(Matrix{T}(max(0,b+a+1),m),n,a,b) -BandedMatrix(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T<:Number} = +BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T<:Number} = BandedMatrix{T}(zeros(T,max(0,b+a+1),m),n,a,b) -BandedMatrix(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} = +BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T} = BandedMatrix{T}(Matrix{T}(max(0,b+a+1),m),n,a,b) -BandedMatrix(::Type{T},n::Integer,a::Integer,b::Integer) where {T} = BandedMatrix(T,n,n,a,b) -BandedMatrix(::Type{T},n::Integer,::Colon,a::Integer,b::Integer) where {T} = BandedMatrix(T,n,n+b,a,b) +BandedMatrix{T}(n::Integer,a::Integer,b::Integer) where {T} = BandedMatrix{T}(n,n,a,b) +BandedMatrix{T}(n::Integer,::Colon,a::Integer,b::Integer) where {T} = BandedMatrix{T}(n,n+b,a,b) +BandedMatrix{T}(n::Integer,m::Integer,a) where {T} = BandedMatrix{T}(n,m,-a[1],a[end]) +BandedMatrix{T}(n::Integer,::Colon,a) where {T} = BandedMatrix{T}(n,:,-a[1],a[end]) +BandedMatrix{T}(n::Integer,a) where {T} = BandedMatrix{T}(n,-a[1],a[end]) -BandedMatrix(data::Matrix,m::Integer,a) = BandedMatrix(data,m,-a[1],a[end]) -BandedMatrix(::Type{T},n::Integer,m::Integer,a) where {T} = BandedMatrix(T,n,m,-a[1],a[end]) -BandedMatrix(::Type{T},n::Integer,::Colon,a) where {T} = BandedMatrix(T,n,:,-a[1],a[end]) -BandedMatrix(::Type{T},n::Integer,a) where {T} = BandedMatrix(T,n,-a[1],a[end]) for MAT in (:BandedMatrix, :AbstractBandedMatrix, :AbstractMatrix, :AbstractArray) @@ -82,13 +80,13 @@ function Base.convert(::Type{BM},M::Matrix) where {BM<:BandedMatrix} ret end -Base.copy(B::BandedMatrix) = BandedMatrix(copy(B.data),B.m,B.l,B.u) +Base.copy(B::BandedMatrix) = BandedMatrix{eltype(B)}(copy(B.data),B.m,B.l,B.u) Base.promote_rule(::Type{BandedMatrix{T}},::Type{BandedMatrix{V}}) where {T,V} = BandedMatrix{promote_type(T,V)} -for (op,bop) in ((:(Base.rand),:brand),(:(Base.zeros),:bzeros),(:(Base.ones),:bones)) +for (op,bop) in ((:(Base.rand),:brand),(:(Base.ones),:bones)) @eval begin $bop(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} = BandedMatrix{T}($op(T,max(0,b+a+1),m),n,a,b) @@ -111,32 +109,6 @@ for (op,bop) in ((:(Base.rand),:brand),(:(Base.zeros),:bzeros),(:(Base.ones),:bo end -## Conversions from FillArrays - -BandedMatrix{V}(Z::Zeros{T,2}, lu::NTuple{2,Int}) where {T,V} = - BandedMatrix{V}(zeros(V,max(0,sum(lu)+1),size(Z,2)),size(Z,1),lu...) - -BandedMatrix(Z::Zeros{T,2}, lu::NTuple{2,Int}) where T = BandedMatrix{T}(Z, lu) - - -BandedMatrix(E::Eye{T}, lu::NTuple{2,Int}) where T = BandedMatrix{T}(E, lu) -function BandedMatrix{T}(E::Eye, lu::NTuple{2,Int}) where T - ret=BandedMatrix(Zeros{T}(E), lu) - ret[band(0)] = one(T) - ret -end - -BandedMatrix(E::Eye) = BandedMatrix(E, (0,0)) - - - -doc""" - bzeros(T,n,m,l,u) - -Creates an `n×m` banded matrix of all zeros of type `T` with bandwidths `(l,u)` -""" -bzeros - doc""" bones(T,n,m,l,u) @@ -153,23 +125,24 @@ brand -""" - beye(T,n,l,u) +## Conversions from FillArrays -`n×n` banded identity matrix of type `T` with bandwidths `(l,u)` -""" -function beye(::Type{T},n::Integer,a...) where {T} - ret=bzeros(T,n,a...) - for k=1:n - ret[k,k]=one(T) - end +BandedMatrix{V}(Z::Zeros{T,2}, lu::NTuple{2,Int}) where {T,V} = + BandedMatrix{V}(zeros(V,max(0,sum(lu)+1),size(Z,2)),size(Z,1),lu...) + +BandedMatrix(Z::Zeros{T,2}, lu::NTuple{2,Int}) where T = BandedMatrix{T}(Z, lu) + + +BandedMatrix(E::Eye{T}, lu::NTuple{2,Int}) where T = BandedMatrix{T}(E, lu) +function BandedMatrix{T}(E::Eye, lu::NTuple{2,Int}) where T + ret=BandedMatrix(Zeros{T}(E), lu) + ret[band(0)] = one(T) ret end +BandedMatrix(E::Eye) = BandedMatrix(E, (0,0)) + -beye(::Type{T},n::Integer) where {T} = beye(T,n,0,0) -beye(n::Integer) = beye(n,0,0) -beye(n::Integer,a...) = beye(Float64,n,a...) Base.similar(B::BandedMatrix) = BandedMatrix(eltype(B),size(B,1),size(B,2),bandwidth(B,1),bandwidth(B,2)) @@ -661,16 +634,21 @@ end ## numbers for OP in (:*,:/) @eval begin - $OP(A::BandedMatrix, b::Number) = BandedMatrix($OP(A.data,b),A.m,A.l,A.u) + $OP(A::BandedMatrix, b::Number) = + BandedMatrix{promote_op($OP,eltype(A),typeof(b))}($OP(A.data,b),A.m,A.l,A.u) broadcast(::typeof($OP), A::BandedMatrix, b::Number) = - BandedMatrix($OP.(A.data,b),A.m,A.l,A.u) + BandedMatrix{promote_op($OP,eltype(A),typeof(b))}($OP.(A.data,b),A.m,A.l,A.u) end end - -*(a::Number,B::BandedMatrix) = BandedMatrix(a*B.data,B.m,B.l,B.u) -broadcast(::typeof(*), a::Number, B::BandedMatrix) = BandedMatrix(a.*B.data,B.m,B.l,B.u) - +for OP in (:*,:\) + @eval begin + $OP(a::Number, B::BandedMatrix) = + BandedMatrix{promote_op($OP,typeof(a),eltype(B))}($OP(a,B.data),B.m,B.l,B.u) + broadcast(::typeof($OP), a::Number, B::BandedMatrix) = + BandedMatrix{promote_op($OP,typeof(a),eltype(B))}($OP.(a,B.data),B.m,B.l,B.u) + end +end #implements fliplr(flipud(A)) @@ -719,17 +697,17 @@ function Base.convert(::Type{BandedMatrix},S::BandedSubBandedMatrix{T}) where {T shft=kr[1]-jr[1] l,u=bandwidths(A) if -u ≤ shft ≤ l - BandedMatrix(A.data[:,jr],length(kr),l-shft,u+shft) + BandedMatrix{T}(A.data[:,jr],length(kr),l-shft,u+shft) elseif shft > l # need to add extra zeros at top since negative bandwidths not supported # new bandwidths = (0,u+shft) dat = zeros(T,u+shft+1,length(jr)) dat[1:l+u+1,:] = A.data[:,jr] - BandedMatrix(dat,length(kr),0,u+shft) + BandedMatrix{T}(dat,length(kr),0,u+shft) else # shft < -u dat = zeros(T,l-shft+1,length(jr)) dat[-shft-u+1:end,:] = A.data[:,jr] # l-shft+1 - (-shft-u) == l+u+1 - BandedMatrix(dat,length(kr),l-shft,0) + BandedMatrix{T}(dat,length(kr),l-shft,0) end end diff --git a/src/banded/linalg.jl b/src/banded/linalg.jl index 22be0c62..ed73082b 100644 --- a/src/banded/linalg.jl +++ b/src/banded/linalg.jl @@ -378,7 +378,7 @@ Ac_mul_Bc!(C::AbstractMatrix{T} ,A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) w function *(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} n, m = size(A,1), size(B,2) - Y = BandedMatrix(promote_type(T,V), n, m, prodbandwidths(A, B)...) + Y = BandedMatrix{promote_type(T,V)}(n, m, prodbandwidths(A, B)...) A_mul_B!(Y,A,B) end diff --git a/src/deprecate.jl b/src/deprecate.jl index 42764a87..e89057c5 100644 --- a/src/deprecate.jl +++ b/src/deprecate.jl @@ -1,41 +1,64 @@ @deprecate gbmm!(α::T, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β::T, C::AbstractMatrix{T}) where {T<:BlasFloat} gbmm!('N', 'N', α, A, B, β, C) -@deprecate BandedMatrix(data::Matrix,m::Int,a) BandedMatrix(data,m,-a[1],a[end]) -@deprecate BandedMatrix(::Type{T},n::Int,m::Int,a) where {T} BandedMatrix(T,n,m,-a[1],a[end]) -@deprecate BandedMatrix(::Type{T},n::Int,::Colon,a) where {T} BandedMatrix(T,n,:,-a[1],a[end]) -@deprecate BandedMatrix(::Type{T},n::Int,a) where {T} BandedMatrix(T,n,-a[1],a[end]) +@deprecate BandedMatrix(data::Matrix,m::Integer,a) BandedMatrix{eltype(data)}(data,m,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Integer,m::Integer,a) where {T} BandedMatrix{T}(n,m,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Integer,::Colon,a) where {T} BandedMatrix{T}(n,:,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Integer,a) where {T} BandedMatrix{T}(n,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix{T}(n,m,a,b) +@deprecate BandedMatrix(::Type{T},n::Integer,a::Integer,b::Integer) where {T} BandedMatrix{T}(n,a,b) +@deprecate BandedMatrix(::Type{T},n::Integer,::Colon,a::Integer,b::Integer) where {T} BandedMatrix{T}(n,:,a,b) -@deprecate bzeros(::Type{T},n::Int,m::Int,a::Int,b::Int) where {T} BandedMatrix(Zeros{T}(n,m), (a,b)) -@deprecate bzeros(::Type{T},n::Int,a::Int,b::Int) where {T} BandedMatrix(Zeros{T}(n,n), (a,b)) -@deprecate bzeros(::Type{T},n::Int,::Colon,a::Int,b::Int) where {T} BandedMatrix(Zeros{T}(n,n+b), (a,b)) -@deprecate bzeros(::Type{T},::Colon,m::Int,a::Int,b::Int) where {T} BandedMatrix(Zeros{T}(m+a,m), (a,b)) -@deprecate bzeros(n::Int,m::Int,a::Int,b::Int) BandedMatrix(Zeros(n,m), (a,b)) -@deprecate bzeros(n::Int,a::Int,b::Int) BandedMatrix(Zeros(n,n), (a,b)) +@deprecate BandedMatrix(::Type{T},n::Integer,m::Integer,a) where {T} BandedMatrix{T}(T,n,m,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Integer,::Colon,a) where {T} BandedMatrix{T}(n,:,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Integer,a) where {T} BandedMatrix{T}(T,n,-a[1],a[end]) -@deprecate bzeros(::Type{T},n::Int,m::Int,a) where {T} BandedMatrix(Zeros(n,m),(-a[1],a[2])) + + +@deprecate bzeros(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Zeros{T}(n,m), (a,b)) +@deprecate bzeros(::Type{T},n::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Zeros{T}(n,n), (a,b)) +@deprecate bzeros(::Type{T},n::Integer,::Colon,a::Integer,b::Integer) where {T} BandedMatrix(Zeros{T}(n,n+b), (a,b)) +@deprecate bzeros(::Type{T},::Colon,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Zeros{T}(m+a,m), (a,b)) +@deprecate bzeros(n::Integer,m::Integer,a::Integer,b::Integer) BandedMatrix(Zeros(n,m), (a,b)) +@deprecate bzeros(n::Integer,a::Integer,b::Integer) BandedMatrix(Zeros(n,n), (a,b)) + +@deprecate bzeros(::Type{T},n::Integer,m::Integer,a) where {T} BandedMatrix(Zeros(n,m),(-a[1],a[2])) @deprecate bzeros(::Type{T},n::Number,::Colon,a) where {T} BandedMatrix(Zeros(n,n+a[2]),(-a[1],a[end])) -@deprecate bzeros(::Type{T},::Colon,m::Int,a) where {T} BandedMatrix(Zeros(m-a[1],m),(-a[1],a[end])) -@deprecate bzeros(::Type{T},n::Int,a) where {T} BandedMatrix(Zeros{T}(n,n),(-a[1],a[end])) -@deprecate bzeros(n::Int,m::Int,a) BandedMatrix(Zeros(n,m),(-a[1],a[end])) -@deprecate bzeros(n::Int,a) BandedMatrix(Zeros(n,n),(-a[1],a[end])) +@deprecate bzeros(::Type{T},::Colon,m::Integer,a) where {T} BandedMatrix(Zeros(m-a[1],m),(-a[1],a[end])) +@deprecate bzeros(::Type{T},n::Integer,a) where {T} BandedMatrix(Zeros{T}(n,n),(-a[1],a[end])) +@deprecate bzeros(n::Integer,m::Integer,a) BandedMatrix(Zeros(n,m),(-a[1],a[end])) +@deprecate bzeros(n::Integer,a) BandedMatrix(Zeros(n,n),(-a[1],a[end])) @deprecate bzeros(B::AbstractMatrix) BandedMatrix(Zeros(B),bandwidths(B)) -@deprecate beye(::Type{T},n::Int,a) where {T} BandedMatrix(Eye{T}(n), (-a[1],a[2])) -@deprecate beye(::Type{T},n::Int) where {T} BandedMatrix(Eye{T}(n)) -@deprecate beye(n::Int) BandedMatrix(Eye(n)) -@deprecate beye(n::Int,a) BandedMatrix(Eye(n),(-a[1],a[2])) -@deprecate BandedMatrix(data::Matrix,n::Int,l::Int,u::Int) BandedMatrix{eltype(data)}(data,n,l,u) -@deprecate SymBandedMatrix(data::Matrix,k::Int) SymBandedMatrix{eltype(data)}(data,k) -@deprecate sbzeros(::Type{T},n::Int,a::Int) where {T} SymBandedMatrix(Zeros{T}(n,n),a) -@deprecate sbzeros(n::Int,a::Int) SymBandedMatrix(Zeros(n,n),a) -# @deprecate sbzeros(B::AbstractMatrix) SymBandedMatrix(Zeros(B), bandwidths(B)) +@deprecate beye(::Type{T},n::Integer,a) where {T} BandedMatrix(Eye{T}(n), (-a[1],a[2])) +@deprecate beye(::Type{T},n::Integer) where {T} BandedMatrix(Eye{T}(n)) +@deprecate beye(n::Integer,m::Integer,a::Integer,b::Integer) BandedMatrix(Eye(n,m),(a,b)) +@deprecate beye(n::Integer) BandedMatrix(Eye(n)) +@deprecate beye(n::Integer,a) BandedMatrix(Eye(n),(-a[1],a[2])) + + +@deprecate BandedMatrix(data::Matrix,n::Integer,l::Integer,u::Integer) BandedMatrix{eltype(data)}(data,n,l,u) +@deprecate SymBandedMatrix(data::Matrix,k::Integer) SymBandedMatrix{eltype(data)}(data,k) + +@deprecate SymBandedMatrix(::Type{T},n::Integer,k::Integer) where {T} SymBandedMatrix{T}(n,k) + + +@deprecate sbzeros(::Type{T},n::Integer,a::Integer) where {T} SymBandedMatrix(Zeros{T}(n,n),a) +@deprecate sbzeros(n::Integer,a::Integer) SymBandedMatrix(Zeros(n,n),a) + +@deprecate sbzeros(B::AbstractMatrix) SymBandedMatrix(Zeros(B), bandwidths(B)) + + + + +@deprecate sbeye(::Type{T},n::Integer,a) where {T} SymBandedMatrix(Eye(n),a) +@deprecate sbeye(n::Integer) SymBandedMatrix(Eye(n)) diff --git a/src/symbanded/SymBandedMatrix.jl b/src/symbanded/SymBandedMatrix.jl index fda5d037..1bea1d2c 100644 --- a/src/symbanded/SymBandedMatrix.jl +++ b/src/symbanded/SymBandedMatrix.jl @@ -30,11 +30,11 @@ returns an unitialized `n`×`n` symmetric banded matrix of type `T` with bandwid """ # Use zeros to avoid unallocated entries for bigfloat -SymBandedMatrix(::Type{T},n::Integer,k::Integer) where {T<:BlasFloat} = +SymBandedMatrix{T}(n::Integer,k::Integer) where {T<:BlasFloat} = SymBandedMatrix{T}(Matrix{T}(k+1,n),k) -SymBandedMatrix(::Type{T},n::Integer,k::Integer) where {T<:Number} = +SymBandedMatrix{T}(n::Integer,k::Integer) where {T<:Number} = SymBandedMatrix{T}(zeros(T,k+1,n),k) -SymBandedMatrix(::Type{T},n::Integer,k::Integer) where {T} = +SymBandedMatrix{T}(n::Integer,k::Integer) where {T} = SymBandedMatrix{T}(Matrix{T}(k+1,n),k) @@ -50,7 +50,7 @@ Base.promote_rule(::Type{SymBandedMatrix{T}},::Type{SymBandedMatrix{V}}) where { -for (op,bop) in ((:(Base.rand),:sbrand),(:(Base.zeros),:sbzeros),(:(Base.ones),:sbones)) +for (op,bop) in ((:(Base.rand),:sbrand),(:(Base.ones),:sbones)) @eval begin $bop(::Type{T},n::Integer,a::Integer) where {T} = SymBandedMatrix($op(T,a+1,n),a) $bop(n::Integer,a::Integer) = $bop(Float64,n,a) @@ -79,12 +79,6 @@ end SymBandedMatrix(Z::Eye{T}, a::Int) where T = SymBandedMatrix{T}(Z, a) SymBandedMatrix(Z::Eye) = SymBandedMatrix(Z, 0) -doc""" - sbzeros(T,n,k) - -Creates an `n×n` symmetric banded matrix of all zeros of type `T` with bandwidths `(k,k)` -""" -sbzeros doc""" sbones(T,n,k) @@ -101,18 +95,6 @@ Creates an `n×n` symmetric banded matrix with random numbers in the bandwidth sbrand -""" - sbeye(T,n,l,u) - -`n×n` banded identity matrix of type `T` with bandwidths `(l,u)` -""" -function sbeye(::Type{T},n::Integer,a=0) where {T} - ret=sbzeros(T,n,a) - ret[band(0)] = one(T) - ret -end -sbeye(n::Integer,a...) = sbeye(Float64,n,a...) - Base.similar(B::SymBandedMatrix) = SymBandedMatrix(eltype(B),size(B,1),bandwidth(B,1)) diff --git a/src/utils.jl b/src/utils.jl index 370e15b1..75ff0943 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -52,7 +52,7 @@ end prodbandwidths(A::AbstractMatrix, B::AbstractMatrix) = prodbandwidths('N', 'N', A, B) function banded_similar(tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, T::DataType) - BandedMatrix(T, _size(tA, A, 1), _size(tB, B, 2), prodbandwidths(tA, tB, A, B)...) + BandedMatrix{T}(_size(tA, A, 1), _size(tB, B, 2), prodbandwidths(tA, tB, A, B)...) end # helper functions in matrix addition routines diff --git a/test/test_bandedlu.jl b/test/test_bandedlu.jl index ae418013..4027250c 100644 --- a/test/test_bandedlu.jl +++ b/test/test_bandedlu.jl @@ -30,9 +30,9 @@ end # conversion of inputs to appropriate blas type let - As = Any[BandedMatrix(rand(1:10, 3, 5), 5, 1, 1), - BandedMatrix(rand(3, 5)*im, 5, 1, 1), - BandedMatrix(rand(3, 5), 5, 1, 1) + As = Any[BandedMatrix{Float64}(rand(1:10, 3, 5), 5, 1, 1), + BandedMatrix{Complex128}(rand(3, 5)*im, 5, 1, 1), + BandedMatrix{Float64}(rand(3, 5), 5, 1, 1) ] bs = Any[rand(1:10, 5), rand(1:10, 5), @@ -92,15 +92,15 @@ end # conversion of inputs if needed let # factorisation performs conversion - Ai = BandedMatrix(rand(1:10, 3, 5), 5, 1, 1) + Ai = BandedMatrix{Float64}(rand(1:10, 3, 5), 5, 1, 1) @test eltype(lufact(Ai)) == Float64 # no op - Af = BandedMatrix(rand(Float32, 3, 5), 5, 1, 1) + Af = BandedMatrix{Float32}(rand(Float32, 3, 5), 5, 1, 1) @test eltype(lufact(Af)) == Float32 # linear systems of integer data imply promotion - Ai = BandedMatrix(rand(1:10, 3, 5), 5, 1, 1) + Ai = BandedMatrix{Int}(rand(1:10, 3, 5), 5, 1, 1) bi = collect(1:5) @test eltype(Ai\bi) == Float64 # this code ≈ julia base diff --git a/test/test_miscs.jl b/test/test_miscs.jl index 2054a590..25457ba9 100644 --- a/test/test_miscs.jl +++ b/test/test_miscs.jl @@ -4,13 +4,13 @@ BandedMatrixWithZero = Union{BandedMatrix{Float64}, UniformScaling} # need to define the concept of zero Base.zero(::Type{BandedMatrixWithZero}) = 0*I -A=BandedMatrix(BandedMatrixWithZero,1,2,0,1) -A[1,1]=beye(1,1,0,1) +A=BandedMatrix{BandedMatrixWithZero}(1,2,0,1) +A[1,1]=BandedMatrix(Eye(1),(0,1)) A[1,2]=BandedMatrix(Zeros(1,2),(0,1)) A[1,2][1,1]=-1/3 A[1,2][1,2]=1/3 -B=BandedMatrix(BandedMatrixWithZero,2,1,1,1) -B[1,1]=0.2beye(1,1,0,1) +B=BandedMatrix{BandedMatrixWithZero}(2,1,1,1) +B[1,1]=0.2BandedMatrix(Eye(1),(0,1)) B[2,1]=BandedMatrix(Zeros(2,1), (1,0)) B[2,1][1,1]=-2/30 B[2,1][2,1]=1/3 @@ -48,7 +48,7 @@ A = brand(3,4,1,2) end, "10×10 BandedMatrices.BandedMatrix{Float64}") @test contains(sprint() do io - show(io, beye(3, 1, 1)) + show(io, BandedMatrix(Eye(3),(1,1))) end, "1.0 0.0 \n 0.0 1.0 0.0\n 0.0 1.0") From a8d34565ff4b98b0f31ae78a34d408321ff77e32 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 20 Nov 2017 16:52:54 +0000 Subject: [PATCH 10/26] Fix deprecation warnings --- src/banded/BandedQR.jl | 5 ++--- src/deprecate.jl | 4 ---- src/symbanded/SymBandedMatrix.jl | 4 ++-- test/test_bandedlu.jl | 6 +++--- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/banded/BandedQR.jl b/src/banded/BandedQR.jl index c3fc4d68..ad931ccf 100644 --- a/src/banded/BandedQR.jl +++ b/src/banded/BandedQR.jl @@ -156,8 +156,7 @@ flipsign(x,y) = Base.flipsign(x,y) flipsign(x::BigFloat,y::BigFloat) = sign(y)==1 ? x : (-x) flipsign(x,y::Complex) = y==0 ? x : x*sign(y) -function banded_qrfact!(R::BandedMatrix) - T=eltype(R) +function banded_qrfact!(R::BandedMatrix{T}) where T M=R.l+1 # number of diag+subdiagonal bands m,n=size(R) W=Matrix{T}(M,(n Date: Tue, 21 Nov 2017 21:50:41 +0000 Subject: [PATCH 11/26] =?UTF-8?q?=E2=80=A2=20BandedMatrix{T}(data,...)=20-?= =?UTF-8?q?>=20=5FBandedMatrix(data,...)=20=E2=80=A2=20SymBandedMatrix{T}(?= =?UTF-8?q?data,...)=20->=20=5FSymBandedMatrix(data,...)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These changes avoid confusion between converting a matrix and specifying the data of a matrix. --- src/banded/BandedMatrix.jl | 41 +++++++++++++++----------------- src/deprecate.jl | 4 +++- src/symbanded/SymBandedMatrix.jl | 14 ++++++----- test/test_banded.jl | 8 ++++--- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index b3feec76..7ede3076 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -10,12 +10,15 @@ # a_21 a_32 a_43 * # a_31 a_42 * * ] ### + +function _BandedMatrix end + mutable struct BandedMatrix{T} <: AbstractBandedMatrix{T} data::Matrix{T} # l+u+1 x n (# of columns) m::Int #Number of rows l::Int # lower bandwidth ≥0 u::Int # upper bandwidth ≥0 - function BandedMatrix{T}(data::Matrix{T},m,l,u) where {T} + global function _BandedMatrix(data::Matrix{T},m,l,u) where {T} if size(data,1) ≠ l+u+1 && !(size(data,1) == 0 && -l > u) error("Data matrix must have number rows equal to number of bands") else @@ -50,26 +53,20 @@ returns an unitialized `n`×`m` banded matrix of type `T` with bandwidths `(l,u) BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T<:BlasFloat} = - BandedMatrix{T}(Matrix{T}(max(0,b+a+1),m),n,a,b) + _BandedMatrix(Matrix{T}(max(0,b+a+1),m),n,a,b) BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T<:Number} = - BandedMatrix{T}(zeros(T,max(0,b+a+1),m),n,a,b) + _BandedMatrix(zeros(T,max(0,b+a+1),m),n,a,b) BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T} = - BandedMatrix{T}(Matrix{T}(max(0,b+a+1),m),n,a,b) + _BandedMatrix(Matrix{T}(max(0,b+a+1),m),n,a,b) BandedMatrix{T}(n::Integer,a::Integer,b::Integer) where {T} = BandedMatrix{T}(n,n,a,b) BandedMatrix{T}(n::Integer,::Colon,a::Integer,b::Integer) where {T} = BandedMatrix{T}(n,n+b,a,b) -BandedMatrix{T}(n::Integer,m::Integer,a) where {T} = BandedMatrix{T}(n,m,-a[1],a[end]) -BandedMatrix{T}(n::Integer,::Colon,a) where {T} = BandedMatrix{T}(n,:,-a[1],a[end]) -BandedMatrix{T}(n::Integer,a) where {T} = BandedMatrix{T}(n,-a[1],a[end]) - - - for MAT in (:BandedMatrix, :AbstractBandedMatrix, :AbstractMatrix, :AbstractArray) @eval Base.convert(::Type{$MAT{V}},M::BandedMatrix) where {V} = - BandedMatrix{V}(convert(Matrix{V},M.data),M.m,M.l,M.u) + _BandedMatrix(convert(Matrix{V},M.data),M.m,M.l,M.u) end function Base.convert(::Type{BM},M::Matrix) where {BM<:BandedMatrix} ret = BandedMatrix(eltype(BM)==Any ? eltype(M) : @@ -80,7 +77,7 @@ function Base.convert(::Type{BM},M::Matrix) where {BM<:BandedMatrix} ret end -Base.copy(B::BandedMatrix) = BandedMatrix{eltype(B)}(copy(B.data),B.m,B.l,B.u) +Base.copy(B::BandedMatrix) = _BandedMatrix(copy(B.data),B.m,B.l,B.u) Base.promote_rule(::Type{BandedMatrix{T}},::Type{BandedMatrix{V}}) where {T,V} = BandedMatrix{promote_type(T,V)} @@ -89,7 +86,7 @@ Base.promote_rule(::Type{BandedMatrix{T}},::Type{BandedMatrix{V}}) where {T,V} = for (op,bop) in ((:(Base.rand),:brand),(:(Base.ones),:bones)) @eval begin $bop(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} = - BandedMatrix{T}($op(T,max(0,b+a+1),m),n,a,b) + _BandedMatrix($op(T,max(0,b+a+1),m),n,a,b) $bop(::Type{T},n::Integer,a::Integer,b::Integer) where {T} = $bop(T,n,n,a,b) $bop(::Type{T},n::Integer,::Colon,a::Integer,b::Integer) where {T} = $bop(T,n,n+b,a,b) $bop(::Type{T},::Colon,m::Integer,a::Integer,b::Integer) where {T} = $bop(T,m+a,m,a,b) @@ -128,7 +125,7 @@ brand ## Conversions from FillArrays BandedMatrix{V}(Z::Zeros{T,2}, lu::NTuple{2,Int}) where {T,V} = - BandedMatrix{V}(zeros(V,max(0,sum(lu)+1),size(Z,2)),size(Z,1),lu...) + _BandedMatrix(zeros(V,max(0,sum(lu)+1),size(Z,2)),size(Z,1),lu...) BandedMatrix(Z::Zeros{T,2}, lu::NTuple{2,Int}) where T = BandedMatrix{T}(Z, lu) @@ -145,7 +142,7 @@ BandedMatrix(E::Eye) = BandedMatrix(E, (0,0)) Base.similar(B::BandedMatrix) = - BandedMatrix(eltype(B),size(B,1),size(B,2),bandwidth(B,1),bandwidth(B,2)) + BandedMatrix{eltype(B)}(size(B,1),size(B,2),bandwidth(B,1),bandwidth(B,2)) ## Abstract Array Interface @@ -635,18 +632,18 @@ end for OP in (:*,:/) @eval begin $OP(A::BandedMatrix, b::Number) = - BandedMatrix{promote_op($OP,eltype(A),typeof(b))}($OP(A.data,b),A.m,A.l,A.u) + _BandedMatrix($OP(A.data,b),A.m,A.l,A.u) broadcast(::typeof($OP), A::BandedMatrix, b::Number) = - BandedMatrix{promote_op($OP,eltype(A),typeof(b))}($OP.(A.data,b),A.m,A.l,A.u) + _BandedMatrix($OP.(A.data,b),A.m,A.l,A.u) end end for OP in (:*,:\) @eval begin $OP(a::Number, B::BandedMatrix) = - BandedMatrix{promote_op($OP,typeof(a),eltype(B))}($OP(a,B.data),B.m,B.l,B.u) + _BandedMatrix($OP(a,B.data),B.m,B.l,B.u) broadcast(::typeof($OP), a::Number, B::BandedMatrix) = - BandedMatrix{promote_op($OP,typeof(a),eltype(B))}($OP.(a,B.data),B.m,B.l,B.u) + _BandedMatrix($OP.(a,B.data),B.m,B.l,B.u) end end @@ -697,17 +694,17 @@ function Base.convert(::Type{BandedMatrix},S::BandedSubBandedMatrix{T}) where {T shft=kr[1]-jr[1] l,u=bandwidths(A) if -u ≤ shft ≤ l - BandedMatrix{T}(A.data[:,jr],length(kr),l-shft,u+shft) + _BandedMatrix(A.data[:,jr],length(kr),l-shft,u+shft) elseif shft > l # need to add extra zeros at top since negative bandwidths not supported # new bandwidths = (0,u+shft) dat = zeros(T,u+shft+1,length(jr)) dat[1:l+u+1,:] = A.data[:,jr] - BandedMatrix{T}(dat,length(kr),0,u+shft) + _BandedMatrix(dat,length(kr),0,u+shft) else # shft < -u dat = zeros(T,l-shft+1,length(jr)) dat[-shft-u+1:end,:] = A.data[:,jr] # l-shft+1 - (-shft-u) == l+u+1 - BandedMatrix{T}(dat,length(kr),l-shft,0) + _BandedMatrix(dat,length(kr),l-shft,0) end end diff --git a/src/deprecate.jl b/src/deprecate.jl index df175e4c..0bad0a9b 100644 --- a/src/deprecate.jl +++ b/src/deprecate.jl @@ -12,7 +12,9 @@ @deprecate BandedMatrix(::Type{T},n::Integer,a::Integer,b::Integer) where {T} BandedMatrix{T}(n,a,b) @deprecate BandedMatrix(::Type{T},n::Integer,::Colon,a::Integer,b::Integer) where {T} BandedMatrix{T}(n,:,a,b) - +@deprecate BandedMatrix{T}(n::Integer,m::Integer,a) where {T} BandedMatrix{T}(n,m,-a[1],a[end]) +@deprecate BandedMatrix{T}(n::Integer,::Colon,a) where {T} BandedMatrix{T}(n,:,-a[1],a[end]) +@deprecate BandedMatrix{T}(n::Integer,a) where {T} BandedMatrix{T}(n,-a[1],a[end]) @deprecate bzeros(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Zeros{T}(n,m), (a,b)) @deprecate bzeros(::Type{T},n::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Zeros{T}(n,n), (a,b)) diff --git a/src/symbanded/SymBandedMatrix.jl b/src/symbanded/SymBandedMatrix.jl index cb0af89d..3dc705ed 100644 --- a/src/symbanded/SymBandedMatrix.jl +++ b/src/symbanded/SymBandedMatrix.jl @@ -11,10 +11,12 @@ export sbrand, sbeye, sbzeros # * a_12 a_23 a_34 # a_11 a_22 a_33 a_44 ] ### +function _SymBandedMatrix end + mutable struct SymBandedMatrix{T} <: AbstractBandedMatrix{T} data::Matrix{T} # k+1 x n (# of columns) k::Int # bandwidth ≥ 0 - function SymBandedMatrix{T}(data::Matrix{T},k) where {T} + global function _SymBandedMatrix(data::Matrix{T},k) where {T} if size(data,1) != k+1 error("Data matrix must have number rows equal to number of superdiagonals") else @@ -31,11 +33,11 @@ returns an unitialized `n`×`n` symmetric banded matrix of type `T` with bandwid # Use zeros to avoid unallocated entries for bigfloat SymBandedMatrix{T}(n::Integer,k::Integer) where {T<:BlasFloat} = - SymBandedMatrix{T}(Matrix{T}(k+1,n),k) + _SymBandedMatrix(Matrix{T}(k+1,n),k) SymBandedMatrix{T}(n::Integer,k::Integer) where {T<:Number} = - SymBandedMatrix{T}(zeros(T,k+1,n),k) + _SymBandedMatrix(zeros(T,k+1,n),k) SymBandedMatrix{T}(n::Integer,k::Integer) where {T} = - SymBandedMatrix{T}(Matrix{T}(k+1,n),k) + _SymBandedMatrix(Matrix{T}(k+1,n),k) for MAT in (:SymBandedMatrix, :AbstractBandedMatrix, :AbstractMatrix, :AbstractArray) @@ -43,7 +45,7 @@ for MAT in (:SymBandedMatrix, :AbstractBandedMatrix, :AbstractMatrix, :Abstract SymBandedMatrix{V}(convert(Matrix{V},M.data),M.k) end -Base.copy(B::SymBandedMatrix{T}) where T = SymBandedMatrix{T}(copy(B.data),B.k) +Base.copy(B::SymBandedMatrix{T}) where T = _SymBandedMatrix(copy(B.data),B.k) Base.promote_rule(::Type{SymBandedMatrix{T}},::Type{SymBandedMatrix{V}}) where {T,V} = SymBandedMatrix{promote_type(T,V)} @@ -52,7 +54,7 @@ Base.promote_rule(::Type{SymBandedMatrix{T}},::Type{SymBandedMatrix{V}}) where { for (op,bop) in ((:(Base.rand),:sbrand),(:(Base.ones),:sbones)) @eval begin - $bop(::Type{T},n::Integer,a::Integer) where {T} = SymBandedMatrix{T}($op(T,a+1,n),a) + $bop(::Type{T},n::Integer,a::Integer) where {T} = _SymBandedMatrix($op(T,a+1,n),a) $bop(n::Integer,a::Integer) = $bop(Float64,n,a) $bop(B::AbstractMatrix) = $bop(eltype(B),size(B,1),bandwidth(B,2)) diff --git a/test/test_banded.jl b/test/test_banded.jl index 49d640d9..01420697 100644 --- a/test/test_banded.jl +++ b/test/test_banded.jl @@ -1,8 +1,10 @@ +import BandedMatrices: _BandedMatrix + # some basic operations -@test BandedMatrix(Zeros(5,5), (1,1)) == BandedMatrix{Float64}(zeros(3,5), 5, 1, 1) -@test BandedMatrix(Zeros{Int}(5,5), (1,1)) == BandedMatrix{Int}(zeros(Int,3,5), 5, 1, 1) -@test BandedMatrix{Int}(Zeros(5,5), (1,1)) == BandedMatrix{Int}(zeros(Int,3,5), 5, 1, 1) +@test BandedMatrix(Zeros(5,5), (1,1)) == _BandedMatrix(zeros(3,5), 5, 1, 1) +@test BandedMatrix(Zeros{Int}(5,5), (1,1)) == _BandedMatrix(zeros(Int,3,5), 5, 1, 1) +@test BandedMatrix{Int}(Zeros(5,5), (1,1)) == _BandedMatrix(zeros(Int,3,5), 5, 1, 1) let A = brand(10,12,2,3),B = brand(10,12,3,4) From c20884e776a33d46b4ea33186e25ff8da7fe311c Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 21 Nov 2017 22:27:14 +0000 Subject: [PATCH 12/26] Straggler changes to _BandedMatrix --- src/banded/BandedQR.jl | 2 +- src/deprecate.jl | 8 ++++++-- src/symbanded/SymBandedMatrix.jl | 2 +- test/runtests.jl | 6 +----- test/test_bandedlu.jl | 16 +++++++++------- test/test_symbanded.jl | 3 ++- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/banded/BandedQR.jl b/src/banded/BandedQR.jl index ad931ccf..cd22f57d 100644 --- a/src/banded/BandedQR.jl +++ b/src/banded/BandedQR.jl @@ -195,5 +195,5 @@ function banded_qrfact!(R::BandedMatrix{T}) where T end end - BandedQR(W,BandedMatrix{T}(R.data[1:R.u+1,:],m,0,R.u)) + BandedQR(W, _BandedMatrix(R.data[1:R.u+1,:],m,0,R.u)) end diff --git a/src/deprecate.jl b/src/deprecate.jl index 0bad0a9b..e0b8dd4f 100644 --- a/src/deprecate.jl +++ b/src/deprecate.jl @@ -44,8 +44,12 @@ @deprecate beye(n::Integer,a) BandedMatrix(Eye(n),(-a[1],a[2])) -@deprecate BandedMatrix(data::Matrix,n::Integer,l::Integer,u::Integer) BandedMatrix{eltype(data)}(data,n,l,u) -@deprecate SymBandedMatrix(data::Matrix,k::Integer) SymBandedMatrix{eltype(data)}(data,k) + +@deprecate BandedMatrix{T}(data::Matrix{T},m::Integer,l::Int,u::Int) where T BandedMatrices._BandedMatrix(data,m,l,u) +@deprecate BandedMatrix(data::Matrix,m::Integer,l::Int,u::Int) BandedMatrices._BandedMatrix(data,m,l,u) + +@deprecate SymBandedMatrix{T}(data::Matrix{T},k::Integer) where T BandedMatrices._SymBandedMatrix(data,k) +@deprecate SymBandedMatrix(data::Matrix,k::Integer) BandedMatrices._SymBandedMatrix(data,k) @deprecate SymBandedMatrix(::Type{T},n::Integer,k::Integer) where {T} SymBandedMatrix{T}(n,k) diff --git a/src/symbanded/SymBandedMatrix.jl b/src/symbanded/SymBandedMatrix.jl index 3dc705ed..78e9dbbc 100644 --- a/src/symbanded/SymBandedMatrix.jl +++ b/src/symbanded/SymBandedMatrix.jl @@ -64,7 +64,7 @@ end function SymBandedMatrix{V}(Z::Zeros{T,2}, a::Int) where {T,V} n,m = size(Z) @boundscheck n == m || throw(BoundsError()) - SymBandedMatrix{V}(zeros(V,a+1,n),a) + _SymBandedMatrix(zeros(V,a+1,n),a) end SymBandedMatrix(Z::Zeros{T,2}, a::Int) where T = SymBandedMatrix{T}(Z, a) diff --git a/test/runtests.jl b/test/runtests.jl index 88b5727a..7c4b6c8b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,10 +1,6 @@ using BandedMatrices, Compat +using Compat.Test -if VERSION < v"0.7-" - using Base.Test -else - using Test -end println("Banded matrix tests") include("test_banded.jl") diff --git a/test/test_bandedlu.jl b/test/test_bandedlu.jl index 210c1dd1..589196c9 100644 --- a/test/test_bandedlu.jl +++ b/test/test_bandedlu.jl @@ -1,3 +1,5 @@ +import BandedMatrices: _BandedMatrix + # set prng to some value that avoids test failure srand(0) @@ -30,9 +32,9 @@ end # conversion of inputs to appropriate blas type let - As = Any[BandedMatrix{Int}(rand(1:10, 3, 5), 5, 1, 1), - BandedMatrix{Complex128}(rand(3, 5)*im, 5, 1, 1), - BandedMatrix{Float64}(rand(3, 5), 5, 1, 1) + As = Any[_BandedMatrix(rand(1:10, 3, 5), 5, 1, 1), + _BandedMatrix(rand(3, 5)*im, 5, 1, 1), + _BandedMatrix(rand(3, 5), 5, 1, 1) ] bs = Any[rand(1:10, 5), rand(1:10, 5), @@ -92,15 +94,15 @@ end # conversion of inputs if needed let # factorisation performs conversion - Ai = BandedMatrix{Int}(rand(1:10, 3, 5), 5, 1, 1) + Ai = _BandedMatrix(rand(1:10, 3, 5), 5, 1, 1) @test eltype(lufact(Ai)) == Float64 # no op - Af = BandedMatrix{Float32}(rand(Float32, 3, 5), 5, 1, 1) + Af = _BandedMatrix(rand(Float32, 3, 5), 5, 1, 1) @test eltype(lufact(Af)) == Float32 # linear systems of integer data imply promotion - Ai = BandedMatrix{Int}(rand(1:10, 3, 5), 5, 1, 1) + Ai = _BandedMatrix(rand(1:10, 3, 5), 5, 1, 1) bi = collect(1:5) @test eltype(Ai\bi) == Float64 # this code ≈ julia base @@ -110,7 +112,7 @@ let @test A_ldiv_B!(lufact(Ai), bi) ≈ Matrix(Ai)\copy(bi) # check A\b makes a copy of b - Ai = BandedMatrix{Int}(rand(1:10, 3, 5), 5, 1, 1) + Ai = _BandedMatrix(rand(1:10, 3, 5), 5, 1, 1) bi = collect(1:5) Ai\bi @test bi == [1, 2, 3, 4, 5] diff --git a/test/test_symbanded.jl b/test/test_symbanded.jl index 9adba6f8..e2283a6e 100644 --- a/test/test_symbanded.jl +++ b/test/test_symbanded.jl @@ -1,4 +1,5 @@ -using BandedMatrices, Base.Test +using Compat +using BandedMatrices, Compat.Test A = sbrand(10,2) From 94735b47a32b01cf2a110336421a16194f5db692 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sat, 25 Nov 2017 15:51:04 +0000 Subject: [PATCH 13/26] REQUIRE FillArrays v0.0.1 --- REQUIRE | 1 + 1 file changed, 1 insertion(+) diff --git a/REQUIRE b/REQUIRE index cdbbe78e..f50eace8 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,2 +1,3 @@ julia 0.6 Compat 0.32 +FillArrays 0.0.1 From 13018230295619b7a4987efba25d3f964d687a7f Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 27 Nov 2017 21:21:20 +0000 Subject: [PATCH 14/26] At BandedMatrix(A::AbstractMatrix, bnds) that projects, and implement banded matrix interface for Base types --- src/banded/BandedMatrix.jl | 33 ++++++++++++++++++++++----------- src/interface.jl | 23 +++++++++++++++++++++++ test/test_interface.jl | 31 ++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 7ede3076..d9d9db8a 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -4,7 +4,7 @@ # a_21 a_22 a_23 # a_31 a_32 a_33 a_34 # a_42 a_43 a_44 ] -# ordering the data like (columns first) +# ordering the data like (cobbndsmns first) # [ * a_12 a_23 a_34 # a_11 a_22 a_33 a_44 # a_21 a_32 a_43 * @@ -122,24 +122,35 @@ brand -## Conversions from FillArrays +## Conversions from AbstractArrays, we include FillArrays in case `zeros` is ever faster +function BandedMatrix{T}(A::AbstractMatrix, bnds::Tuple{Int,Int}) where T + (n,m) = size(A) + (l,u) = bnds + ret = BandedMatrix{T}((n,m), bnds) + @inbounds for j = 1:m, k = max(1,j-u):min(n,j+l) + ret[k,j] = A[k,j] + end + ret +end -BandedMatrix{V}(Z::Zeros{T,2}, lu::NTuple{2,Int}) where {T,V} = - _BandedMatrix(zeros(V,max(0,sum(lu)+1),size(Z,2)),size(Z,1),lu...) +BandedMatrix(A::AbstractMatrix{T}, bnds::NTuple{2,Int}) where T = + BandedMatrix{T}(A, bnds) -BandedMatrix(Z::Zeros{T,2}, lu::NTuple{2,Int}) where T = BandedMatrix{T}(Z, lu) +BandedMatrix{V}(Z::Zeros{T,2}, bnds::NTuple{2,Int}) where {T,V} = + _BandedMatrix(zeros(V,max(0,sum(bnds)+1),size(Z,2)),size(Z,1),bnds...) +BandedMatrix(Z::Zeros{T,2}, bnds::NTuple{2,Int}) where T = BandedMatrix{T}(Z, bnds) -BandedMatrix(E::Eye{T}, lu::NTuple{2,Int}) where T = BandedMatrix{T}(E, lu) -function BandedMatrix{T}(E::Eye, lu::NTuple{2,Int}) where T - ret=BandedMatrix(Zeros{T}(E), lu) + +BandedMatrix(E::Eye{T}, bnds::NTuple{2,Int}) where T = BandedMatrix{T}(E, bnds) +function BandedMatrix{T}(E::Eye, bnds::NTuple{2,Int}) where T + ret=BandedMatrix(Zeros{T}(E), bnds) ret[band(0)] = one(T) ret end -BandedMatrix(E::Eye) = BandedMatrix(E, (0,0)) - - +BandedMatrix(A::AbstractMatrix) = + BandedMatrix(A, bandwidths(A)) Base.similar(B::BandedMatrix) = BandedMatrix{eltype(B)}(size(B,1),size(B,2),bandwidth(B,1),bandwidth(B,2)) diff --git a/src/interface.jl b/src/interface.jl index f1aec62f..d5e644a6 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -21,3 +21,26 @@ banded_A_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = band banded_A_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) banded_Ac_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) banded_At_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) + + + +# Here we implement the banded matrix interface for some key examples +isbanded(::Zeros) = true +bandwidth(::Zeros, k::Integer) = 0 +inbands_getindex(::Zeros{T}, k::Integer, j::Integer) where T = zero(T) + +isbanded(::Eye) = true +bandwidth(::Eye, k::Integer) = 0 +inbands_getindex(::Eye{T}, k::Integer, j::Integer) where T = one(T) + +isbanded(::Diagonal) = true +bandwidth(::Diagonal, k::Integer) = 0 +inbands_getindex(D::Diagonal, k::Integer, j::Integer) = D.diag[k] +inbands_setindex!(D::Diagonal, v, k::Integer, j::Integer) = (D.diag[k] = v) + +isbanded(::SymTridiagonal) = true +bandwidth(::SymTridiagonal, k::Integer) = 1 +inbands_getindex(J::SymTridiagonal, k::Integer, j::Integer) = + k == j ? J.dv[k] : J.ev[k] +inbands_setindex!(J::SymTridiagonal, v, k::Integer, j::Integer) = + k == j ? (J.dv[k] = v) : (J.ev[k] = v) diff --git a/test/test_interface.jl b/test/test_interface.jl index e03ef8aa..093a9874 100644 --- a/test/test_interface.jl +++ b/test/test_interface.jl @@ -1,4 +1,33 @@ -import BandedMatrices: banded_axpy!, banded_A_mul_B! +using BandedMatrices, Compat.Test + +import BandedMatrices: banded_axpy!, banded_A_mul_B!, isbanded + + + +## test intervface +@test isbanded(Zeros(5,6)) +@test bandwidths(Zeros(5,6)) == (0,0) +@test BandedMatrices.inbands_getindex(Zeros(5,6), 1,2) == 0 + +@test isbanded(Eye(5)) +@test bandwidths(Eye(5)) == (0,0) +@test BandedMatrices.inbands_getindex(Eye(5), 1,1) == 1 + +A = Diagonal(ones(5,5)) +@test isbanded(A) +@test bandwidths(A) == (0,0) +@test BandedMatrices.inbands_getindex(A, 1,1) == 1 +BandedMatrices.inbands_setindex!(A, 2, 1,1) +@test A[1,1] == 2 + +A = SymTridiagonal([1,2,3],[4,5]) +@test isbanded(A) +@test bandwidths(A) == (1,1) +@test BandedMatrices.inbands_getindex(A, 1,1) == 1 +BandedMatrices.inbands_setindex!(A, 2, 1,1) +@test A[1,1] == 2 + + struct SimpleBandedMatrix{T} <: AbstractMatrix{T} data::Array{T} From e191ddb79fbf47181b88cb5fd06f42597442adb6 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 27 Nov 2017 21:40:14 +0000 Subject: [PATCH 15/26] tests pass again --- src/banded/BandedMatrix.jl | 9 +-------- test/test_interface.jl | 1 + 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index d9d9db8a..3680c0cb 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -106,13 +106,6 @@ for (op,bop) in ((:(Base.rand),:brand),(:(Base.ones),:bones)) end -doc""" - bones(T,n,m,l,u) - -Creates an `n×m` banded matrix with ones in the bandwidth of type `T` with bandwidths `(l,u)` -""" -bones - doc""" brand(T,n,m,l,u) @@ -126,7 +119,7 @@ brand function BandedMatrix{T}(A::AbstractMatrix, bnds::Tuple{Int,Int}) where T (n,m) = size(A) (l,u) = bnds - ret = BandedMatrix{T}((n,m), bnds) + ret = BandedMatrix{T}(n,m, bnds...) @inbounds for j = 1:m, k = max(1,j-u):min(n,j+l) ret[k,j] = A[k,j] end diff --git a/test/test_interface.jl b/test/test_interface.jl index 093a9874..76e30869 100644 --- a/test/test_interface.jl +++ b/test/test_interface.jl @@ -29,6 +29,7 @@ BandedMatrices.inbands_setindex!(A, 2, 1,1) + struct SimpleBandedMatrix{T} <: AbstractMatrix{T} data::Array{T} l::Int From 93cdcacfaae6f030c6516ef130ad96ee3ae7a0f7 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Thu, 30 Nov 2017 10:53:20 +0000 Subject: [PATCH 16/26] REQUIRE Compat 0.38 --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index f50eace8..112a71f3 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,3 +1,3 @@ julia 0.6 -Compat 0.32 +Compat 0.38 FillArrays 0.0.1 From a6391cb52e05d0dc76d03da3f5ff4d0eb48e957a Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Thu, 30 Nov 2017 21:45:33 +0000 Subject: [PATCH 17/26] Add constructor BandedMatrix{T}((n,m), (l,u)) --- src/BandedMatrices.jl | 3 --- src/banded/BandedMatrix.jl | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index 78c4c680..07f107f6 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -43,10 +43,7 @@ import Base: lufact, cholfact, cholfact!, promote_op export BandedMatrix, SymBandedMatrix, bandrange, - bzeros, - beye, brand, - bones, bandwidth, BandError, band, diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 80be9f2e..ebccc5b3 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -54,6 +54,8 @@ BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T<:Number} BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T} = _BandedMatrix(Matrix{T}(max(0,b+a+1),m),n,a,b) +BandedMatrix{T}(nm::NTuple{2,Integer}, ab::NTuple{2,Integer}) where T = + BandedMatrix{T}(nm..., ab...) BandedMatrix{T}(n::Integer,a::Integer,b::Integer) where {T} = BandedMatrix{T}(n,n,a,b) From 7bbeb5047886e8307eaf83b29e6e6928e054025b Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sat, 2 Dec 2017 20:31:29 +0000 Subject: [PATCH 18/26] BandedMatrix{T}(n,m,a,b) -> BandedMatrix{T}(uninitialized,n,m,a,b) SymBandedMatrix{T}(n,m,a,b) -> SymBandedMatrix{T}(uninitialized,n,m,a,b) --- REQUIRE | 2 +- src/BandedMatrices.jl | 2 + src/banded/BandedMatrix.jl | 41 ++++++----- src/banded/linalg.jl | 116 +++++++++++++++---------------- src/deprecate.jl | 49 ++++++++++--- src/symbanded/SymBandedMatrix.jl | 65 ++++++++++------- src/utils.jl | 2 +- test/runtests.jl | 2 +- test/test_indexing.jl | 38 +++++----- test/test_miscs.jl | 4 +- 10 files changed, 181 insertions(+), 140 deletions(-) diff --git a/REQUIRE b/REQUIRE index 112a71f3..f7ae3d68 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,3 +1,3 @@ julia 0.6 -Compat 0.38 +Compat 0.39 FillArrays 0.0.1 diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index d4bbf771..e9c7325f 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -38,6 +38,8 @@ import Base.LinAlg: BlasInt, import Base: lufact, cholfact, cholfact!, promote_op +import FillArrays: AbstractFill + export BandedMatrix, SymBandedMatrix, bandrange, diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 3680c0cb..dc46f4d0 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -51,39 +51,38 @@ returns an unitialized `n`×`m` banded matrix of type `T` with bandwidths `(l,u) """ - -BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T<:BlasFloat} = - _BandedMatrix(Matrix{T}(max(0,b+a+1),m),n,a,b) -BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T<:Number} = +BandedMatrix{T}(::Uninitialized, n::Integer, m::Integer, a::Integer, b::Integer) where {T<:BlasFloat} = + _BandedMatrix(Matrix{T}(max(0,b+a+1),m), n, a, b) +BandedMatrix{T}(::Uninitialized, n::Integer, m::Integer, a::Integer, b::Integer) where {T<:Number} = _BandedMatrix(zeros(T,max(0,b+a+1),m),n,a,b) -BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T} = +BandedMatrix{T}(::Uninitialized, n::Integer, m::Integer, a::Integer, b::Integer) where {T} = _BandedMatrix(Matrix{T}(max(0,b+a+1),m),n,a,b) - - -BandedMatrix{T}(n::Integer,a::Integer,b::Integer) where {T} = BandedMatrix{T}(n,n,a,b) -BandedMatrix{T}(n::Integer,::Colon,a::Integer,b::Integer) where {T} = BandedMatrix{T}(n,n+b,a,b) +BandedMatrix{T}(::Uninitialized, n::Integer, ::Colon, a::Integer, b::Integer) where {T} = + BandedMatrix{T}(uninitialized,n,n+b,a,b) for MAT in (:BandedMatrix, :AbstractBandedMatrix, :AbstractMatrix, :AbstractArray) - @eval Base.convert(::Type{$MAT{V}},M::BandedMatrix) where {V} = - _BandedMatrix(convert(Matrix{V},M.data),M.m,M.l,M.u) + @eval Base.convert(::Type{$MAT{V}}, M::BandedMatrix) where {V} = + _BandedMatrix(convert(Matrix{V}, M.data), M.m, M.l, M.u) end -function Base.convert(::Type{BM},M::Matrix) where {BM<:BandedMatrix} - ret = BandedMatrix(eltype(BM)==Any ? eltype(M) : - promote_type(eltype(BM),eltype(M)),size(M,1),size(M,2),size(M,1)-1,size(M,2)-1) + +#TODO: Add test +function Base.convert(::Type{BM}, M::Matrix) where {BM<:BandedMatrix} + ret = BandedMatrix{eltype(BM) == Any ? eltype(M) : + promote_type(eltype(BM),eltype(M))}(uninitialized, size(M,1),size(M,2),size(M,1)-1,size(M,2)-1) for k=1:size(M,1),j=1:size(M,2) ret[k,j] = M[k,j] end ret end -Base.copy(B::BandedMatrix) = _BandedMatrix(copy(B.data),B.m,B.l,B.u) +Base.copy(B::BandedMatrix) = _BandedMatrix(copy(B.data), B.m, B.l, B.u) -Base.promote_rule(::Type{BandedMatrix{T}},::Type{BandedMatrix{V}}) where {T,V} = BandedMatrix{promote_type(T,V)} +Base.promote_rule(::Type{BandedMatrix{T}}, ::Type{BandedMatrix{V}}) where {T,V} = BandedMatrix{promote_type(T,V)} -for (op,bop) in ((:(Base.rand),:brand),(:(Base.ones),:bones)) +for (op,bop) in ((:(Base.rand),:brand),) @eval begin $bop(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} = _BandedMatrix($op(T,max(0,b+a+1),m),n,a,b) @@ -116,12 +115,12 @@ brand ## Conversions from AbstractArrays, we include FillArrays in case `zeros` is ever faster -function BandedMatrix{T}(A::AbstractMatrix, bnds::Tuple{Int,Int}) where T +function BandedMatrix{T}(A::AbstractMatrix, bnds::NTuple{2,Int}) where T (n,m) = size(A) (l,u) = bnds - ret = BandedMatrix{T}(n,m, bnds...) + ret = BandedMatrix{T}(uninitialized, n, m, bnds...) @inbounds for j = 1:m, k = max(1,j-u):min(n,j+l) - ret[k,j] = A[k,j] + inbands_setindex!(ret, A[k,j], k, j) end ret end @@ -146,7 +145,7 @@ BandedMatrix(A::AbstractMatrix) = BandedMatrix(A, bandwidths(A)) Base.similar(B::BandedMatrix) = - BandedMatrix{eltype(B)}(size(B,1),size(B,2),bandwidth(B,1),bandwidth(B,2)) + BandedMatrix{eltype(B)}(size(B,1), size(B,2), bandwidth(B,1), bandwidth(B,2)) ## Abstract Array Interface diff --git a/src/banded/linalg.jl b/src/banded/linalg.jl index ed73082b..f8909193 100644 --- a/src/banded/linalg.jl +++ b/src/banded/linalg.jl @@ -34,7 +34,7 @@ function banded_generic_axpy!(a::Number, X::AbstractMatrix{U}, Y::AbstractMatrix Y end -function banded_dense_axpy!(a::Number, X::AbstractMatrix ,Y::AbstractMatrix) +function banded_dense_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) if size(X) != size(Y) throw(DimensionMismatch("+")) end @@ -44,8 +44,8 @@ function banded_dense_axpy!(a::Number, X::AbstractMatrix ,Y::AbstractMatrix) Y end -banded_axpy!(a::Number, X::BLASBandedMatrix ,Y::BLASBandedMatrix) = banded_generic_axpy!(a, X, Y) -banded_axpy!(a::Number, X::BLASBandedMatrix ,Y::AbstractMatrix) = banded_dense_axpy!(a, X, Y) +banded_axpy!(a::Number, X::BLASBandedMatrix, Y::BLASBandedMatrix) = banded_generic_axpy!(a, X, Y) +banded_axpy!(a::Number, X::BLASBandedMatrix, Y::AbstractMatrix) = banded_dense_axpy!(a, X, Y) axpy!(a::Number, X::BLASBandedMatrix, Y::BLASBandedMatrix) = banded_axpy!(a, X, Y) axpy!(a::Number, X::BLASBandedMatrix, Y::AbstractMatrix) = banded_axpy!(a, X, Y) @@ -339,79 +339,79 @@ banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::StridedMatrix{T}, banded_generic_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{U}, B::AbstractMatrix{V}) where {T, U, V} = generally_banded_matmatmul!(C, tA, tB, A, B) -A_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) -A_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) -A_mul_B!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) - -Ac_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) -Ac_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) -Ac_mul_B!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) -A_mul_Bc!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'C', A, B) -A_mul_Bc!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'C', A, B) -A_mul_Bc!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'C', A, B) -Ac_mul_Bc!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) -Ac_mul_Bc!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) -Ac_mul_Bc!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) - -At_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) -At_mul_B!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) -At_mul_B!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) -A_mul_Bt!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) -A_mul_Bt!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) -A_mul_Bt!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) -At_mul_Bt!(C::AbstractMatrix ,A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) -At_mul_Bt!(C::AbstractMatrix ,A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) -At_mul_Bt!(C::AbstractMatrix ,A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) +A_mul_B!(C::AbstractMatrix, A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) +A_mul_B!(C::AbstractMatrix, A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) +A_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'N', A, B) + +Ac_mul_B!(C::AbstractMatrix, A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) +Ac_mul_B!(C::AbstractMatrix, A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) +Ac_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'N', A, B) +A_mul_Bc!(C::AbstractMatrix, A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'C', A, B) +A_mul_Bc!(C::AbstractMatrix, A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'C', A, B) +A_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'C', A, B) +Ac_mul_Bc!(C::AbstractMatrix, A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) +Ac_mul_Bc!(C::AbstractMatrix, A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) +Ac_mul_Bc!(C::AbstractMatrix, A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'C', 'C', A, B) + +At_mul_B!(C::AbstractMatrix, A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) +At_mul_B!(C::AbstractMatrix, A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) +At_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'N', A, B) +A_mul_Bt!(C::AbstractMatrix, A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) +A_mul_Bt!(C::AbstractMatrix, A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) +A_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'N', 'T', A, B) +At_mul_Bt!(C::AbstractMatrix, A::BLASBandedMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) +At_mul_Bt!(C::AbstractMatrix, A::BLASBandedMatrix, B::AbstractMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) +At_mul_Bt!(C::AbstractMatrix, A::AbstractMatrix, B::BLASBandedMatrix) = banded_matmatmul!(C, 'T', 'T', A, B) # override the Ac_mul_B, A_mul_Bc and Ac_mul_c for real values -Ac_mul_B!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V} = banded_matmatmul!(C, 'T', 'N', A, B) -Ac_mul_B!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::AbstractMatrix{V}) where {T, U<:Real, V} = banded_matmatmul!(C, 'T', 'N', A, B) -Ac_mul_B!(C::AbstractMatrix{T} ,A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V} = banded_matmatmul!(C, 'T', 'N', A, B) -A_mul_Bc!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::BLASBandedMatrix{V}) where {T, U, V<:Real} = banded_matmatmul!(C, 'N', 'T', A, B) -A_mul_Bc!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::AbstractMatrix{V}) where {T, U, V<:Real} = banded_matmatmul!(C, 'N', 'T', A, B) -A_mul_Bc!(C::AbstractMatrix{T} ,A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) where {T, U, V<:Real} = banded_matmatmul!(C, 'N', 'T', A, B) -Ac_mul_Bc!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V<:Real} = banded_matmatmul!(C, 'T', 'T', A, B) -Ac_mul_Bc!(C::AbstractMatrix{T} ,A::BLASBandedMatrix{U}, B::AbstractMatrix{V}) where {T, U<:Real, V<:Real} = banded_matmatmul!(C, 'T', 'T', A, B) -Ac_mul_Bc!(C::AbstractMatrix{T} ,A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V<:Real} = banded_matmatmul!(C, 'T', 'T', A, B) +Ac_mul_B!(C::AbstractMatrix{T}, A::BLASBandedMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V} = banded_matmatmul!(C, 'T', 'N', A, B) +Ac_mul_B!(C::AbstractMatrix{T}, A::BLASBandedMatrix{U}, B::AbstractMatrix{V}) where {T, U<:Real, V} = banded_matmatmul!(C, 'T', 'N', A, B) +Ac_mul_B!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V} = banded_matmatmul!(C, 'T', 'N', A, B) +A_mul_Bc!(C::AbstractMatrix{T}, A::BLASBandedMatrix{U}, B::BLASBandedMatrix{V}) where {T, U, V<:Real} = banded_matmatmul!(C, 'N', 'T', A, B) +A_mul_Bc!(C::AbstractMatrix{T}, A::BLASBandedMatrix{U}, B::AbstractMatrix{V}) where {T, U, V<:Real} = banded_matmatmul!(C, 'N', 'T', A, B) +A_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) where {T, U, V<:Real} = banded_matmatmul!(C, 'N', 'T', A, B) +Ac_mul_Bc!(C::AbstractMatrix{T}, A::BLASBandedMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V<:Real} = banded_matmatmul!(C, 'T', 'T', A, B) +Ac_mul_Bc!(C::AbstractMatrix{T}, A::BLASBandedMatrix{U}, B::AbstractMatrix{V}) where {T, U<:Real, V<:Real} = banded_matmatmul!(C, 'T', 'T', A, B) +Ac_mul_Bc!(C::AbstractMatrix{T}, A::AbstractMatrix{U}, B::BLASBandedMatrix{V}) where {T, U<:Real, V<:Real} = banded_matmatmul!(C, 'T', 'T', A, B) -function *(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} +function *(A::BLASBandedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} n, m = size(A,1), size(B,2) - Y = BandedMatrix{promote_type(T,V)}(n, m, prodbandwidths(A, B)...) + Y = BandedMatrix{promote_type(T,V)}(uninitialized, n, m, prodbandwidths(A, B)...) A_mul_B!(Y,A,B) end -function *(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} +function *(A::BLASBandedMatrix{T}, B::StridedMatrix{V}) where {T, V} n, m = size(A,1), size(B,2) A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) end -function *(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} +function *(A::StridedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} n, m = size(A,1), size(B,2) A_mul_B!(Matrix{promote_type(T,V)}(n, m), A, B) end -Ac_mul_B(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_B!(banded_similar('C', 'N', A, B, promote_type(T, V)), A, B) -Ac_mul_B(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) -Ac_mul_B(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) -A_mul_Bc(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bc!(banded_similar('N', 'C', A, B, promote_type(T, V)), A, B) -A_mul_Bc(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) -A_mul_Bc(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) -Ac_mul_Bc(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_Bc!(banded_similar('C', 'C', A, B, promote_type(T, V)), A, B) -Ac_mul_Bc(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) -Ac_mul_Bc(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) - -At_mul_B(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(banded_similar('T', 'N', A, B, promote_type(T, V)), A, B) -At_mul_B(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) -At_mul_B(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) -A_mul_Bt(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bt!(banded_similar('N', 'T', A, B, promote_type(T, V)), A, B) -A_mul_Bt(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) -A_mul_Bt(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) -At_mul_Bt(A::BLASBandedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(banded_similar('T', 'T', A, B, promote_type(T, V)), A, B) -At_mul_Bt(A::BLASBandedMatrix{T},B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) -At_mul_Bt(A::StridedMatrix{T},B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) +Ac_mul_B(A::BLASBandedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_B!(banded_similar('C', 'N', A, B, promote_type(T, V)), A, B) +Ac_mul_B(A::BLASBandedMatrix{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) +Ac_mul_B(A::StridedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) +A_mul_Bc(A::BLASBandedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bc!(banded_similar('N', 'C', A, B, promote_type(T, V)), A, B) +A_mul_Bc(A::BLASBandedMatrix{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) +A_mul_Bc(A::StridedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) +Ac_mul_Bc(A::BLASBandedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_Bc!(banded_similar('C', 'C', A, B, promote_type(T, V)), A, B) +Ac_mul_Bc(A::BLASBandedMatrix{T}, B::StridedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) +Ac_mul_Bc(A::StridedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = Ac_mul_Bc!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) + +At_mul_B(A::BLASBandedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(banded_similar('T', 'N', A, B, promote_type(T, V)), A, B) +At_mul_B(A::BLASBandedMatrix{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) +At_mul_B(A::StridedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 2)), A, B) +A_mul_Bt(A::BLASBandedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bt!(banded_similar('N', 'T', A, B, promote_type(T, V)), A, B) +A_mul_Bt(A::BLASBandedMatrix{T}, B::StridedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) +A_mul_Bt(A::StridedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = A_mul_Bt!(Matrix{promote_type(T,V)}(size(A, 1), size(B, 1)), A, B) +At_mul_Bt(A::BLASBandedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(banded_similar('T', 'T', A, B, promote_type(T, V)), A, B) +At_mul_Bt(A::BLASBandedMatrix{T}, B::StridedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) +At_mul_Bt(A::StridedMatrix{T}, B::BLASBandedMatrix{V}) where {T, V} = At_mul_B!(Matrix{promote_type(T,V)}(size(A, 2), size(B, 1)), A, B) ## Method definitions for generic eltypes - will make copies diff --git a/src/deprecate.jl b/src/deprecate.jl index e0b8dd4f..44d99a80 100644 --- a/src/deprecate.jl +++ b/src/deprecate.jl @@ -1,20 +1,25 @@ @deprecate gbmm!(α::T, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β::T, C::AbstractMatrix{T}) where {T<:BlasFloat} gbmm!('N', 'N', α, A, B, β, C) -@deprecate BandedMatrix(data::Matrix,m::Integer,a) BandedMatrix{eltype(data)}(data,m,-a[1],a[end]) -@deprecate BandedMatrix(::Type{T},n::Integer,m::Integer,a) where {T} BandedMatrix{T}(n,m,-a[1],a[end]) -@deprecate BandedMatrix(::Type{T},n::Integer,::Colon,a) where {T} BandedMatrix{T}(n,:,-a[1],a[end]) -@deprecate BandedMatrix(::Type{T},n::Integer,a) where {T} BandedMatrix{T}(n,-a[1],a[end]) +@deprecate BandedMatrix{T}(n::Integer,::Colon,a::Integer,b::Integer) where {T} BandedMatrix{T}(uninitialized,n,:,a,b) +@deprecate BandedMatrix{T}(n::Integer,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix{T}(uninitialized, n, m, a, b) +@deprecate BandedMatrix{T}(n::Integer,a::Integer,b::Integer) where {T} BandedMatrix{T}(uninitialized, n, n, a, b) -@deprecate BandedMatrix(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix{T}(n,m,a,b) +@deprecate BandedMatrix(data::Matrix,m::Integer,a) BandedMatrices._BandedMatrix(data,m,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Integer,m::Integer,a) where {T} BandedMatrix{T}(uninitialized, n,m,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Integer,::Colon,a) where {T} BandedMatrix{T}(uninitialized, n,:,-a[1],a[end]) +@deprecate BandedMatrix(::Type{T},n::Integer,a) where {T} BandedMatrix{T}(uninitialized, n,-a[1],a[end]) -@deprecate BandedMatrix(::Type{T},n::Integer,a::Integer,b::Integer) where {T} BandedMatrix{T}(n,a,b) -@deprecate BandedMatrix(::Type{T},n::Integer,::Colon,a::Integer,b::Integer) where {T} BandedMatrix{T}(n,:,a,b) +@deprecate BandedMatrix(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix{T}(uninitialized, n,m,a,b) -@deprecate BandedMatrix{T}(n::Integer,m::Integer,a) where {T} BandedMatrix{T}(n,m,-a[1],a[end]) -@deprecate BandedMatrix{T}(n::Integer,::Colon,a) where {T} BandedMatrix{T}(n,:,-a[1],a[end]) -@deprecate BandedMatrix{T}(n::Integer,a) where {T} BandedMatrix{T}(n,-a[1],a[end]) + +@deprecate BandedMatrix(::Type{T},n::Integer,a::Integer,b::Integer) where {T} BandedMatrix{T}(uninitialized, n,a,b) +@deprecate BandedMatrix(::Type{T},n::Integer,::Colon,a::Integer,b::Integer) where {T} BandedMatrix{T}(uninitialized, n,:,a,b) + +@deprecate BandedMatrix{T}(n::Integer,m::Integer,a) where {T} BandedMatrix{T}(uninitialized, n,m,-a[1],a[end]) +@deprecate BandedMatrix{T}(n::Integer,::Colon,a) where {T} BandedMatrix{T}(uninitialized, n,:,-a[1],a[end]) +@deprecate BandedMatrix{T}(n::Integer,a) where {T} BandedMatrix{T}(uninitialized, n,-a[1],a[end]) @deprecate bzeros(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Zeros{T}(n,m), (a,b)) @deprecate bzeros(::Type{T},n::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Zeros{T}(n,n), (a,b)) @@ -33,7 +38,21 @@ @deprecate bzeros(B::AbstractMatrix) BandedMatrix(Zeros(B),bandwidths(B)) +@deprecate bones(::Type{T},n::Integer,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Ones{T}(n,m), (a,b)) +@deprecate bones(::Type{T},n::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Ones{T}(n,n), (a,b)) +@deprecate bones(::Type{T},n::Integer,::Colon,a::Integer,b::Integer) where {T} BandedMatrix(Ones{T}(n,n+b), (a,b)) +@deprecate bones(::Type{T},::Colon,m::Integer,a::Integer,b::Integer) where {T} BandedMatrix(Ones{T}(m+a,m), (a,b)) +@deprecate bones(n::Integer,m::Integer,a::Integer,b::Integer) BandedMatrix(Ones(n,m), (a,b)) +@deprecate bones(n::Integer,a::Integer,b::Integer) BandedMatrix(Ones(n,n), (a,b)) +@deprecate bones(::Type{T},n::Integer,m::Integer,a) where {T} BandedMatrix(Ones(n,m),(-a[1],a[2])) +@deprecate bones(::Type{T},n::Number,::Colon,a) where {T} BandedMatrix(Ones(n,n+a[2]),(-a[1],a[end])) +@deprecate bones(::Type{T},::Colon,m::Integer,a) where {T} BandedMatrix(Ones(m-a[1],m),(-a[1],a[end])) +@deprecate bones(::Type{T},n::Integer,a) where {T} BandedMatrix(Ones{T}(n,n),(-a[1],a[end])) +@deprecate bones(n::Integer,m::Integer,a) BandedMatrix(Ones(n,m),(-a[1],a[end])) +@deprecate bones(n::Integer,a) BandedMatrix(Ones(n,n),(-a[1],a[end])) + +@deprecate bones(B::AbstractMatrix) BandedMatrix(Ones(B),bandwidths(B)) @@ -48,10 +67,12 @@ @deprecate BandedMatrix{T}(data::Matrix{T},m::Integer,l::Int,u::Int) where T BandedMatrices._BandedMatrix(data,m,l,u) @deprecate BandedMatrix(data::Matrix,m::Integer,l::Int,u::Int) BandedMatrices._BandedMatrix(data,m,l,u) +@deprecate SymBandedMatrix{T}(n::Integer,k::Integer) where {T} SymBandedMatrix{T}(uninitialized,n::Integer,k::Integer) + @deprecate SymBandedMatrix{T}(data::Matrix{T},k::Integer) where T BandedMatrices._SymBandedMatrix(data,k) @deprecate SymBandedMatrix(data::Matrix,k::Integer) BandedMatrices._SymBandedMatrix(data,k) -@deprecate SymBandedMatrix(::Type{T},n::Integer,k::Integer) where {T} SymBandedMatrix{T}(n,k) +@deprecate SymBandedMatrix(::Type{T},n::Integer,k::Integer) where {T} SymBandedMatrix{T}(uninitialized,n,k) @deprecate sbzeros(::Type{T},n::Integer,a::Integer) where {T} SymBandedMatrix(Zeros{T}(n,n),a) @@ -60,6 +81,12 @@ @deprecate sbzeros(B::AbstractMatrix) SymBandedMatrix(Zeros(B), bandwidths(B)) +@deprecate sbones(::Type{T},n::Integer,a::Integer) where {T} SymBandedMatrix(Ones{T}(n,n),a) +@deprecate sbones(n::Integer,a::Integer) SymBandedMatrix(Ones(n,n),a) + +@deprecate sbones(B::AbstractMatrix) SymBandedMatrix(Ones(B), bandwidths(B)) + + @deprecate sbeye(::Type{T},n::Integer,a) where {T} SymBandedMatrix(Eye(n),a) diff --git a/src/symbanded/SymBandedMatrix.jl b/src/symbanded/SymBandedMatrix.jl index 78e9dbbc..b19b8efd 100644 --- a/src/symbanded/SymBandedMatrix.jl +++ b/src/symbanded/SymBandedMatrix.jl @@ -16,7 +16,7 @@ function _SymBandedMatrix end mutable struct SymBandedMatrix{T} <: AbstractBandedMatrix{T} data::Matrix{T} # k+1 x n (# of columns) k::Int # bandwidth ≥ 0 - global function _SymBandedMatrix(data::Matrix{T},k) where {T} + global function _SymBandedMatrix(data::Matrix{T}, k) where {T} if size(data,1) != k+1 error("Data matrix must have number rows equal to number of superdiagonals") else @@ -32,17 +32,16 @@ returns an unitialized `n`×`n` symmetric banded matrix of type `T` with bandwid """ # Use zeros to avoid unallocated entries for bigfloat -SymBandedMatrix{T}(n::Integer,k::Integer) where {T<:BlasFloat} = - _SymBandedMatrix(Matrix{T}(k+1,n),k) -SymBandedMatrix{T}(n::Integer,k::Integer) where {T<:Number} = - _SymBandedMatrix(zeros(T,k+1,n),k) -SymBandedMatrix{T}(n::Integer,k::Integer) where {T} = - _SymBandedMatrix(Matrix{T}(k+1,n),k) - - -for MAT in (:SymBandedMatrix, :AbstractBandedMatrix, :AbstractMatrix, :AbstractArray) - @eval Base.convert(::Type{$MAT{V}},M::SymBandedMatrix) where {V} = - SymBandedMatrix{V}(convert(Matrix{V},M.data),M.k) +SymBandedMatrix{T}(::Uninitialized, n::Integer, k::Integer) where {T<:BlasFloat} = + _SymBandedMatrix(Matrix{T}(uninitialized, k+1, n), k) +SymBandedMatrix{T}(::Uninitialized, n::Integer, k::Integer) where {T<:Number} = + _SymBandedMatrix(zeros(T, k+1, n), k) +SymBandedMatrix{T}(::Uninitialized, n::Integer, k::Integer) where {T} = + _SymBandedMatrix(Matrix{T}(uninitialized, k+1, n), k) + +for MAT in (:SymBandedMatrix, :AbstractBandedMatrix, :AbstractMatrix, :AbstractArray) + @eval Base.convert(::Type{$MAT{V}}, M::SymBandedMatrix) where {V} = + SymBandedMatrix{V}(uninitialized, convert(Matrix{V}, M.data), M.k) end Base.copy(B::SymBandedMatrix{T}) where T = _SymBandedMatrix(copy(B.data),B.k) @@ -52,22 +51,43 @@ Base.promote_rule(::Type{SymBandedMatrix{T}},::Type{SymBandedMatrix{V}}) where { -for (op,bop) in ((:(Base.rand),:sbrand),(:(Base.ones),:sbones)) +for (op,bop) in ((:(Base.rand),:sbrand),) @eval begin - $bop(::Type{T},n::Integer,a::Integer) where {T} = _SymBandedMatrix($op(T,a+1,n),a) - $bop(n::Integer,a::Integer) = $bop(Float64,n,a) + $bop(::Type{T}, n::Integer, a::Integer) where {T} = _SymBandedMatrix($op(T,a+1,n),a) + $bop(n::Integer, a::Integer) = $bop(Float64,n,a) - $bop(B::AbstractMatrix) = $bop(eltype(B),size(B,1),bandwidth(B,2)) + $bop(B::AbstractMatrix) = $bop(eltype(B), size(B,1), bandwidth(B,2)) end end +##### +# Convert abstract matrix +##### +# TODO: uncomment: this is commented out because of + +# function BandedMatrix{T}(A::AbstractMatrix, a::Int) where T +# (n,m) = size(A) +# @boundscheck n == m || throw(BoundsError()) +# ret = SymBandedMatrix{T}(uninitialized, n, a) +# @inbounds for j = 1:m, k = max(1,j-u):min(n,j+l) +# syminbands_setindex!(ret, A[k,j], k, j) +# end +# ret +# end + +function SymBandedMatrix{V}(Z::Ones{T,2}, a::Int) where {T,V} + n,m = size(Z) + @boundscheck n == m || throw(BoundsError()) + _SymBandedMatrix(ones(V, a+1, n),a) +end + function SymBandedMatrix{V}(Z::Zeros{T,2}, a::Int) where {T,V} n,m = size(Z) @boundscheck n == m || throw(BoundsError()) _SymBandedMatrix(zeros(V,a+1,n),a) end -SymBandedMatrix(Z::Zeros{T,2}, a::Int) where T = SymBandedMatrix{T}(Z, a) +SymBandedMatrix(Z::AbstractFill{T,2}, a::Int) where T = SymBandedMatrix{T}(Z, a) function SymBandedMatrix{T}(E::Eye, a::Int) where T @@ -82,13 +102,6 @@ SymBandedMatrix(Z::Eye{T}, a::Int) where T = SymBandedMatrix{T}(Z, a) SymBandedMatrix(Z::Eye) = SymBandedMatrix(Z, 0) -doc""" - sbones(T,n,k) - -Creates an `n×n` symmetric banded matrix with ones in the bandwidth of type `T` with bandwidths `(k,k)` -""" -sbones - doc""" sbrand(T,n,k) @@ -192,7 +205,7 @@ function setindex!(A::SymBandedMatrix{T}, v, ::Colon, ::Colon) where {T} end end -function Base.convert(::Type{Matrix},A::SymBandedMatrix) +function Base.convert(::Type{Matrix}, A::SymBandedMatrix) ret=zeros(eltype(A),size(A,1),size(A,2)) for j = 1:size(ret,2), k = colrange(ret,j) @inbounds ret[k,j] = A[k,j] @@ -205,7 +218,7 @@ Base.full(A::SymBandedMatrix) = convert(Matrix, A) # algebra -function +(A::SymBandedMatrix{T},B::SymBandedMatrix{V}) where {T,V} +function +(A::SymBandedMatrix{T}, B::SymBandedMatrix{V}) where {T,V} if size(A) != size(B) throw(DimensionMismatch("+")) end diff --git a/src/utils.jl b/src/utils.jl index 75ff0943..b266d26e 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -52,7 +52,7 @@ end prodbandwidths(A::AbstractMatrix, B::AbstractMatrix) = prodbandwidths('N', 'N', A, B) function banded_similar(tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, T::DataType) - BandedMatrix{T}(_size(tA, A, 1), _size(tB, B, 2), prodbandwidths(tA, tB, A, B)...) + BandedMatrix{T}(uninitialized, _size(tA, A, 1), _size(tB, B, 2), prodbandwidths(tA, tB, A, B)...) end # helper functions in matrix addition routines diff --git a/test/runtests.jl b/test/runtests.jl index 7c4b6c8b..a359824c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,7 +14,7 @@ println("LU tests") include("test_bandedlu.jl") println("QR tests") include("test_bandedqr.jl") -println("Symetrix banded matrix tests") +println("Symmetric banded matrix tests") include("test_symbanded.jl") println("Banded matrix interface tests") include("test_interface.jl") diff --git a/test/test_indexing.jl b/test/test_indexing.jl index dc091783..7ef44156 100644 --- a/test/test_indexing.jl +++ b/test/test_indexing.jl @@ -18,7 +18,7 @@ end # rowstart/rowstop business let - A = bones(7, 5, 1, 2) + A = BandedMatrix(Ones(7, 5), (1, 2)) # 1.0 1.0 1.0 0.0 0.0 # 1.0 1.0 1.0 1.0 0.0 # 0.0 1.0 1.0 1.0 1.0 @@ -39,7 +39,7 @@ let @test (colstart(A, 4), colstop(A, 4), collength(A, 4)) == (2, 5, 4) @test (colstart(A, 5), colstop(A, 5), collength(A, 5)) == (3, 6, 4) - A = bones(3, 6, 1, 2) + A = BandedMatrix(Ones(3, 6), (1, 2)) # 1.0 1.0 1.0 0.0 0.0 0.0 # 1.0 1.0 1.0 1.0 0.0 0.0 # 0.0 1.0 1.0 1.0 1.0 0.0 @@ -53,7 +53,7 @@ let @test (colstart(A, 5), colstop(A, 5), collength(A, 5)) == (3, 3, 1) @test (colstart(A, 6), colstop(A, 6), collength(A, 6)) == (4, 3, 0) # zero length - A = bones(3, 4, -1, 2) + A = BandedMatrix(Ones(3, 4), (-1, 2)) # 0.0 1.0 1.0 0.0 # 0.0 0.0 1.0 1.0 # 0.0 0.0 0.0 1.0 @@ -68,7 +68,7 @@ end # test length of diagonal let - A = bones(4, 6, 2, 3) + A = BandedMatrix(Ones(4, 6), (2, 3)) # 4x6 BandedMatrices.BandedMatrix{Float64}: # 1.0 1.0 1.0 1.0 # 1.0 1.0 1.0 1.0 1.0 @@ -81,7 +81,7 @@ let @test diaglength(A, 2) == 4 @test diaglength(A, 3) == 3 - A = bones(6, 5, 2, 1) + A = BandedMatrix(Ones(6, 5), (2, 1)) # 6x5 BandedMatrices.BandedMatrix{Float64}: # 1.0 1.0 # 1.0 1.0 1.0 @@ -94,7 +94,7 @@ let @test diaglength(A, 0) == 5 @test diaglength(A, 1) == 4 - A = bones(4, 4, 1, 1) + A = BandedMatrix(Ones(4, 4), (1, 1)) # 4x4 BandedMatrices.BandedMatrix{Float64}: # 1.0 1.0 # 1.0 1.0 1.0 @@ -110,7 +110,7 @@ end # _firstdiagrow/_firstdiagcol let - A = bones(6, 5, 2, 1) + A = BandedMatrix(Ones(6, 5), (2, 1)) # 6x5 BandedMatrices.BandedMatrix{Float64}: # 1.0 1.0 # 1.0 1.0 1.0 @@ -135,7 +135,7 @@ end # scalar - integer - integer let - a = bones(5, 5, 1, 1) + a = BandedMatrix(Ones(5, 5), (1, 1)) # 1.0 1.0 0.0 0.0 0.0 # 1.0 1.0 1.0 0.0 0.0 # 0.0 1.0 1.0 1.0 0.0 @@ -157,7 +157,7 @@ let @test_throws BoundsError a[6, 5] = 1 @test_throws BoundsError a[6, 6] = 1 - a = bones(5, 5, -1, 1) + a = BandedMatrix(Ones(5, 5), (-1, 1)) a[1, 2] = 2 @test a[1, 2] == 2 @test_throws BandError a[1, 1] = 1 @@ -168,7 +168,7 @@ end # scalar - BandRange/Colon - integer let - a = bones(5, 5, 1, 1) + a = BandedMatrix(Ones(5, 5), (1, 1)) # 1.0 1.0 0.0 0.0 0.0 # 1.0 1.0 1.0 0.0 0.0 # 0.0 1.0 1.0 1.0 0.0 @@ -198,7 +198,7 @@ let @test_throws BoundsError a[BandRange, 0] = 1 @test_throws BoundsError a[BandRange, 6] = 1 - a = bones(3, 5, -1, 2) + a = BandedMatrix(Ones(3, 5), (-1, 2)) @test isempty(a[BandRange,1]) a[BandRange,2] = [1] a[BandRange,3] = [2, 2] @@ -213,7 +213,7 @@ end # vector - BandRange/Colon - integer let - a = bones(Int, 5, 7, 2, 1) + a = BandedMatrix(Ones{Int}(5, 7), (2, 1)) # 5x7 BandedMatrices.BandedMatrix{Float64}: # 1.0 1.0 0 0 0 0 0 0 # 1.0 1.0 1.0 0 0 0 0 0 @@ -252,7 +252,7 @@ end # scalar - range - integer let - a = bones(3, 4, 2, 1) + a = BandedMatrix(Ones(3, 4), (2, 1)) # 1.0 1.0 0.0 0.0 # 1.0 1.0 1.0 0.0 # 1.0 1.0 1.0 1.0 @@ -292,7 +292,7 @@ end # vector - range - integer let - a = bones(5, 4, 1, 2) + a = BandedMatrix(Ones(5, 4), (1, 2)) # 1.0 1.0 1.0 0.0 # 1.0 1.0 1.0 1.0 # 0.0 1.0 1.0 1.0 @@ -345,7 +345,7 @@ end # scalar - integer - BandRange/colon let - a = bones(5, 5, 1, 1) + a = BandedMatrix(Ones(5, 5), (1, 1)) # 1.0 1.0 0.0 0.0 0.0 # 1.0 1.0 1.0 0.0 0.0 # 0.0 1.0 1.0 1.0 0.0 @@ -379,7 +379,7 @@ end # vector - integer - BandRange/colon let - a = bones(7, 5, 1, 2) + a = BandedMatrix(Ones(7, 5), (1, 2)) # 7x5 BandedMatrices.BandedMatrix{Float64}: # 1.0 1.0 1.0 0.0 0.0 # 1.0 1.0 1.0 1.0 0.0 @@ -417,7 +417,7 @@ end # scalar - integer - range let - a = bones(7, 5, 1, 2) + a = BandedMatrix(Ones(7, 5), (1, 2)) # 7x5 BandedMatrices.BandedMatrix{Float64}: # 1.0 1.0 1.0 0.0 0.0 # 1.0 1.0 1.0 1.0 0.0 @@ -463,7 +463,7 @@ end # vector - integer - range let - a = bones(7, 5, 1, 2) + a = BandedMatrix(Ones(7, 5), (1, 2)) # 7x5 BandedMatrices.BandedMatrix{Float64}: # 1.0 1.0 1.0 0.0 0.0 # 1.0 1.0 1.0 1.0 0.0 @@ -592,7 +592,7 @@ end # other special methods let # all elements - a = bones(3, 3, 1, 1) + a = BandedMatrix(Ones(3, 3), (1, 1)) a[:] = 0 @test a == [0 0 0; 0 0 0; diff --git a/test/test_miscs.jl b/test/test_miscs.jl index 25457ba9..ada647f7 100644 --- a/test/test_miscs.jl +++ b/test/test_miscs.jl @@ -4,12 +4,12 @@ BandedMatrixWithZero = Union{BandedMatrix{Float64}, UniformScaling} # need to define the concept of zero Base.zero(::Type{BandedMatrixWithZero}) = 0*I -A=BandedMatrix{BandedMatrixWithZero}(1,2,0,1) +A=BandedMatrix{BandedMatrixWithZero}(uninitialized, 1, 2, 0, 1) A[1,1]=BandedMatrix(Eye(1),(0,1)) A[1,2]=BandedMatrix(Zeros(1,2),(0,1)) A[1,2][1,1]=-1/3 A[1,2][1,2]=1/3 -B=BandedMatrix{BandedMatrixWithZero}(2,1,1,1) +B=BandedMatrix{BandedMatrixWithZero}(uninitialized, 2, 1, 1, 1) B[1,1]=0.2BandedMatrix(Eye(1),(0,1)) B[2,1]=BandedMatrix(Zeros(2,1), (1,0)) B[2,1][1,1]=-2/30 From fab2e25249cd4a3660b18ba5a74dc3869d5bbda7 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sat, 2 Dec 2017 20:56:01 +0000 Subject: [PATCH 19/26] test BBandedMatrix{T}(uninitialized, (n,m), (a,b)) constructor --- src/banded/BandedMatrix.jl | 2 +- test/test_banded.jl | 2 ++ test/test_symbanded.jl | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 60d6ff26..5084c89b 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -55,7 +55,7 @@ BandedMatrix{T}(::Uninitialized, n::Integer, m::Integer, a::Integer, b::Integer) BandedMatrix{T}(::Uninitialized, n::Integer, m::Integer, a::Integer, b::Integer) where {T} = _BandedMatrix(Matrix{T}(max(0,b+a+1),m),n,a,b) BandedMatrix{T}(::Uninitialized, nm::NTuple{2,Integer}, ab::NTuple{2,Integer}) where T = - BandedMatrix{T}(nm..., ab...) + BandedMatrix{T}(uninitialized, nm..., ab...) BandedMatrix{T}(::Uninitialized, n::Integer, ::Colon, a::Integer, b::Integer) where {T} = BandedMatrix{T}(uninitialized,n,n+b,a,b) diff --git a/test/test_banded.jl b/test/test_banded.jl index 01420697..118a6f44 100644 --- a/test/test_banded.jl +++ b/test/test_banded.jl @@ -6,6 +6,8 @@ import BandedMatrices: _BandedMatrix @test BandedMatrix(Zeros{Int}(5,5), (1,1)) == _BandedMatrix(zeros(Int,3,5), 5, 1, 1) @test BandedMatrix{Int}(Zeros(5,5), (1,1)) == _BandedMatrix(zeros(Int,3,5), 5, 1, 1) +@test_throws UndefRefError BandedMatrix{Vector{Float64}}(uninitialized, (5,5), (1,1))[1,1] + let A = brand(10,12,2,3),B = brand(10,12,3,4) @test Matrix(sparse(A)) ≈ Matrix(A) diff --git a/test/test_symbanded.jl b/test/test_symbanded.jl index e2283a6e..6c7df512 100644 --- a/test/test_symbanded.jl +++ b/test/test_symbanded.jl @@ -1,6 +1,8 @@ using Compat using BandedMatrices, Compat.Test +@test_throws UndefRefError SymBandedMatrix{Vector{Float64}}(uninitialized, 5, 1)[1,1] + A = sbrand(10,2) From 8685b81345eaa3996b2b843a1b7229082d103cb7 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sat, 23 Dec 2017 18:37:15 +0000 Subject: [PATCH 20/26] blasstructure -> memorylayout --- src/banded/BandedMatrix.jl | 4 ++-- src/banded/gbmm.jl | 2 +- src/generic/interface.jl | 18 +++++++++--------- src/symbanded/SymBandedMatrix.jl | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 5084c89b..7fd3590b 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -27,7 +27,7 @@ mutable struct BandedMatrix{T} <: AbstractBandedMatrix{T} end end -blasstructure(::Type{BandedMatrix{<:BlasFloat}}) = BlasStrided() +memorylayout(::Type{BandedMatrix{<:BlasFloat}}) = BlasStrided() # BandedMatrix with unit range indexes is also banded @@ -36,7 +36,7 @@ const BandedSubBandedMatrix{T} = @banded BandedSubBandedMatrix -blasstructure(::Type{BandedSubBandedMatrix{<:BlasFloat}}) = BlasStrided() +memorylayout(::Type{BandedSubBandedMatrix{<:BlasFloat}}) = BlasStrided() ## Constructors diff --git a/src/banded/gbmm.jl b/src/banded/gbmm.jl index 211b04df..d3728464 100644 --- a/src/banded/gbmm.jl +++ b/src/banded/gbmm.jl @@ -319,7 +319,7 @@ end αA_mul_B_plus_βC!(α, A, x, β, y) = _αA_mul_B_plus_βC!(α, A, x, β, y, - blasstructure(A), blasstructure(x), blasstructure(y)) + memorylayout(A), memorylayout(x), memorylayout(y)) _αA_mul_B_plus_βC!(α, A, x, β, y, blasA, blasx, blasy) = (y .= α*A*x + β*y) _αA_mul_B_plus_βC!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, ::BlasStrided, ::BlasBanded, ::BlasStrided) where {T<:BlasFloat} = diff --git a/src/generic/interface.jl b/src/generic/interface.jl index b4df74ee..67637dc6 100644 --- a/src/generic/interface.jl +++ b/src/generic/interface.jl @@ -11,7 +11,7 @@ bandedinterface(::AbstractBandedMatrix) = BandedInterface{true}() #### # BLAS Banded traits # -# if blasstructure(A) returns BlasBanded, you must override +# if memorylayout(A) returns BlasBanded, you must override # pointer and leadingdimension # in addition to the banded matrix interface #### @@ -19,12 +19,12 @@ bandedinterface(::AbstractBandedMatrix) = BandedInterface{true}() struct NotBlas end struct BlasStrided end struct BlasBanded end -struct BLASSymBanded end +struct BlasSymBanded end -blasstructure(::Type{<:AbstractArray}) = NotBlas() -blasstructure(::Type{SM}) where SM <: StridedMatrix{T} where T <: BlasFloat = BlasStrided() -blasstructure(A::AbstractArray) = blasstructure(typeof(A)) +memorylayout(::Type{<:AbstractArray}) = NotBlas() +memorylayout(::Type{SM}) where SM <: StridedMatrix{T} where T <: BlasFloat = BlasStrided() +memorylayout(A::AbstractArray) = memorylayout(typeof(A)) @@ -38,7 +38,7 @@ _banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix, notbandedX, notba # matrix * vector banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector) = - _banded_matvecmul!(c, tA, A, b, blasstructure(c), blasstructure(A), blasstructure(b)) + _banded_matvecmul!(c, tA, A, b, memorylayout(c), memorylayout(A), memorylayout(b)) _banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{T}, b::AbstractVector{T}, ::BlasStrided, ::BlasBanded, ::BlasStrided) where {T <: BlasFloat} = generally_banded_matvecmul!(c, tA, A, b) @@ -54,7 +54,7 @@ banded_At_mul_B!(c::AbstractVector, A::AbstractMatrix, b::AbstractVector) = band # matrix * matrix banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix) = - banded_matmatmul!(C, tA, tB, A, B, blasstructure(A), blasstructure(B)) + banded_matmatmul!(C, tA, tB, A, B, memorylayout(A), memorylayout(B)) banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, notblasA, notblasB) = banded_generic_matmatmul!(C, tA, tB, A, B) @@ -148,7 +148,7 @@ end positively_banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector) = - _positively_banded_matvecmul!(c, tA, A, b, blasstructure(c), blasstructure(A), blasstructure(b)) + _positively_banded_matvecmul!(c, tA, A, b, memorylayout(c), memorylayout(A), memorylayout(b)) _positively_banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector, notblasc, notblasA, notblasb) = _banded_generic_matvecmul!(c, tA, A, b) @@ -159,7 +159,7 @@ _positively_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{ gbmv!(tA, one(T), A, b, zero(T), c) positively_banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix) = - _positively_banded_matmatmul!(C, tA, tB, A, B, blasstructure(C), blasstructure(A), blasstructure(B)) + _positively_banded_matmatmul!(C, tA, tB, A, B, memorylayout(C), memorylayout(A), memorylayout(B)) _positively_banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, notblasC, notblasA, notblasb) = _banded_generic_matmatmul!(C, tA, tB, A, B) diff --git a/src/symbanded/SymBandedMatrix.jl b/src/symbanded/SymBandedMatrix.jl index 21b12cf7..5fef7af9 100644 --- a/src/symbanded/SymBandedMatrix.jl +++ b/src/symbanded/SymBandedMatrix.jl @@ -26,7 +26,7 @@ mutable struct SymBandedMatrix{T} <: AbstractBandedMatrix{T} end -blasstructure(::Type{SymBandedMatrix{<:BlasFloat}}) = BlasSymBanded() +memorylayout(::Type{SymBandedMatrix{<:BlasFloat}}) = BlasSymBanded() doc""" From fcc4ccf6927e13b43fd22bb91a817bb107e6b949 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 26 Dec 2017 17:38:59 +0000 Subject: [PATCH 21/26] =?UTF-8?q?=E2=80=A2=20=CE=B1A=5Fmul=5FB=5Fplus=5F?= =?UTF-8?q?=CE=B2C!=20->=20scalemul!=20=E2=80=A2=20fix=20BlasStrided=20->?= =?UTF-8?q?=20BandedLayout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/banded/BandedMatrix.jl | 4 ++-- src/banded/gbmm.jl | 24 +++++++++++------------- src/generic/interface.jl | 25 +++++++++++++------------ 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 7fd3590b..94cde749 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -27,7 +27,7 @@ mutable struct BandedMatrix{T} <: AbstractBandedMatrix{T} end end -memorylayout(::Type{BandedMatrix{<:BlasFloat}}) = BlasStrided() +memorylayout(::Type{BandedMatrix{T}}) where T = BandedLayout{T}() # BandedMatrix with unit range indexes is also banded @@ -36,7 +36,7 @@ const BandedSubBandedMatrix{T} = @banded BandedSubBandedMatrix -memorylayout(::Type{BandedSubBandedMatrix{<:BlasFloat}}) = BlasStrided() +memorylayout(::Type{BandedSubBandedMatrix{<:BlasFloat}}) = BandedLayout{T}() ## Constructors diff --git a/src/banded/gbmm.jl b/src/banded/gbmm.jl index d3728464..05ec82d4 100644 --- a/src/banded/gbmm.jl +++ b/src/banded/gbmm.jl @@ -317,20 +317,18 @@ function gbmm!(tA::Char, tB::Char, α::T, A::StridedMatrix{T}, B::AbstractMatrix C end -αA_mul_B_plus_βC!(α, A, x, β, y) = - _αA_mul_B_plus_βC!(α, A, x, β, y, - memorylayout(A), memorylayout(x), memorylayout(y)) -_αA_mul_B_plus_βC!(α, A, x, β, y, blasA, blasx, blasy) = (y .= α*A*x + β*y) -_αA_mul_B_plus_βC!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, - ::BlasStrided, ::BlasBanded, ::BlasStrided) where {T<:BlasFloat} = +scalemul!(α, A, x, β, y) = _scalemul!(α, A, x, β, y, memorylayout(A), memorylayout(x), memorylayout(y)) +_scalemul!(α, A, x, β, y, blasA, blasx, blasy) = (y .= α .* A*x .+ β.*y) +_scalemul!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, + ::StridedLayout{T}, ::BandedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = gbmv!('N', α, A, x, β, y) -_αA_mul_B_plus_βC!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, - ::BlasStrided, ::BlasStrided, ::BlasStrided) where {T<:BlasFloat} = +_scalemul!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, + ::StridedLayout{T}, ::StridedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = BLAS.gemv!('N', α, A, x, β, y) -_αA_mul_B_plus_βC!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, - ::BlasBanded, ::BlasBanded, ::BlasBanded) where {T<:BlasFloat} = - gbmm!(α, A, B, β, C) -_αA_mul_B_plus_βC!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, - ::BlasStrided, ::BlasStrided, ::BlasStrided) where {T<:BlasFloat} = +_scalemul!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, + ::BandedLayout{T}, ::BandedLayout{T}, ::BandedLayout{T}) where {T<:BlasFloat} = + gbmm!('N', 'N', α, A, B, β, C) +_scalemul!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, + ::StridedLayout{T}, ::StridedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = BLAS.gemm!('N', 'N', α, A, B, β, C) diff --git a/src/generic/interface.jl b/src/generic/interface.jl index 67637dc6..a96a3122 100644 --- a/src/generic/interface.jl +++ b/src/generic/interface.jl @@ -9,25 +9,26 @@ bandedinterface(::AbstractBandedMatrix) = BandedInterface{true}() #### -# BLAS Banded traits +# Matrix memory layout traits # -# if memorylayout(A) returns BlasBanded, you must override +# if memorylayout(A) returns BandedLayout, you must override # pointer and leadingdimension # in addition to the banded matrix interface #### -struct NotBlas end -struct BlasStrided end -struct BlasBanded end -struct BlasSymBanded end +struct UnknownLayout{T} end +struct StridedLayout{T} end +struct BandedLayout{T} end +struct SymBandedLayout{T} end -memorylayout(::Type{<:AbstractArray}) = NotBlas() -memorylayout(::Type{SM}) where SM <: StridedMatrix{T} where T <: BlasFloat = BlasStrided() +memorylayout(::Type{A}) where A <: AbstractArray{T} where T = UnknownLayout{T}() +memorylayout(::Type{SM}) where SM <: StridedMatrix{T} where T = StridedLayout{T}() memorylayout(A::AbstractArray) = memorylayout(typeof(A)) + # these are the routines of the banded interface of other AbstractMatrices banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) = _banded_axpy!(a, X, Y, bandedinterface(X), bandedinterface(Y)) _banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix, ::BandedInterface{true}, ::BandedInterface{true}) = @@ -40,7 +41,7 @@ _banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix, notbandedX, notba banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector) = _banded_matvecmul!(c, tA, A, b, memorylayout(c), memorylayout(A), memorylayout(b)) _banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{T}, b::AbstractVector{T}, - ::BlasStrided, ::BlasBanded, ::BlasStrided) where {T <: BlasFloat} = + ::StridedLayout{T}, ::BandedLayout{T}, ::StridedLayout{T}) where {T <: BlasFloat} = generally_banded_matvecmul!(c, tA, A, b) _banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector, notblasc, notblasA, notblasb) = @@ -59,7 +60,7 @@ banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::A notblasA, notblasB) = banded_generic_matmatmul!(C, tA, tB, A, B) banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, - ::BlasBanded, ::BlasBanded) = + ::BandedLayout, ::BandedLayout) = generally_banded_matmatmul!(C, tA, tB, A, B) @@ -155,7 +156,7 @@ _positively_banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b: # use BLAS routine for positively banded BlasBanded _positively_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{T}, b::AbstractVector{T}, - ::BlasStrided, ::BlasBanded, ::BlasStrided) where {T <: BlasFloat} = + ::StridedLayout{T}, ::BandedLayout{T}, ::StridedLayout{T}) where {T <: BlasFloat} = gbmv!(tA, one(T), A, b, zero(T), c) positively_banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix) = @@ -282,7 +283,7 @@ end # use BLAS routine for positively banded BlasBandedMatrices function _positively_banded_matmatmul!(C::AbstractMatrix{T}, tA::Char, tB::Char, A::AbstractMatrix{T}, B::AbstractMatrix{T}, - ::BlasBanded, ::BlasBanded, ::BlasBanded) where {T} + ::BandedLayout{T}, ::BandedLayout{T}, ::BandedLayout{T}) where {T} Al, Au = _bandwidths(tA, A) Bl, Bu = _bandwidths(tB, B) # _banded_generic_matmatmul! is faster for sparse matrix From 60ced52f5d03d1071671059f6f562899f1d6390a Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Wed, 3 Jan 2018 09:05:37 +0000 Subject: [PATCH 22/26] Add fill! and shorthand BandError --- src/BandedMatrices.jl | 2 +- src/banded/BandedMatrix.jl | 6 ++++++ src/generic/Band.jl | 1 + test/test_banded.jl | 12 +++++++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index c10f719d..4fff0947 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -8,7 +8,7 @@ import Base: getindex, setindex!, *, +, -, ==, <, <=, >, import Base: convert, size, view, indices, unsafe_indices, indices1, first, last, size, length, unsafe_length, start, next, done, step, - to_indices, to_index, indices, show + to_indices, to_index, indices, show, fill! import Base.BLAS: libblas import Base.LAPACK: liblapack diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 94cde749..c7bc0a81 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -601,6 +601,12 @@ Base.norm(B::BandedMatrix,opts...) = norm(Matrix(B),opts...) ## ALgebra and other functions +function fill!(A::BandedMatrix{T}, x) where T + x == zero(T) || throw(BandError(A)) + fill!(A.data, x) + A +end + function Base.scale!(α::Number, A::BandedMatrix) Base.scale!(α, A.data) A diff --git a/src/generic/Band.jl b/src/generic/Band.jl index 9d86849b..7cab3a71 100644 --- a/src/generic/Band.jl +++ b/src/generic/Band.jl @@ -68,6 +68,7 @@ end # shorthand to specify k and j without calculating band BandError(A::AbstractMatrix, kj::Tuple{Int,Int}) = BandError(A, kj[2]-kj[1]) +BandError(A::AbstractMatrix) = BandError(A, max(size(A)...)-1) function showerror(io::IO, e::BandError) A, i = e.A, e.i diff --git a/test/test_banded.jl b/test/test_banded.jl index 118a6f44..17952494 100644 --- a/test/test_banded.jl +++ b/test/test_banded.jl @@ -1,3 +1,4 @@ +using BandedMatrices import BandedMatrices: _BandedMatrix # some basic operations @@ -185,6 +186,15 @@ end # Test for errors in collect -let B=brand(10,10,0,4) +let B = brand(10,10,0,4) @test B*[collect(1.0:10) collect(1.0:10)] ≈ Matrix(B)*[collect(1.0:10) collect(1.0:10)] end + +# Test fill! + +let B = brand(10,10,1,4) + @test_throws BandError fill!(B, 1.0) + @test_throws BandError fill!(B, 1) + fill!(B, 0) + @test Matrix(B) == zeros(10,10) +end From 422c71d429b3919d801c4a9f62b2b72a08a5b348 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 8 Jan 2018 12:58:36 +0100 Subject: [PATCH 23/26] add banded_copy! --- src/BandedMatrices.jl | 2 +- src/banded/BandedMatrix.jl | 2 +- src/generic/interface.jl | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index 4fff0947..767b039b 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -8,7 +8,7 @@ import Base: getindex, setindex!, *, +, -, ==, <, <=, >, import Base: convert, size, view, indices, unsafe_indices, indices1, first, last, size, length, unsafe_length, start, next, done, step, - to_indices, to_index, indices, show, fill! + to_indices, to_index, indices, show, fill!, copy! import Base.BLAS: libblas import Base.LAPACK: liblapack diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index c7bc0a81..ddf84d4e 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -721,7 +721,7 @@ end end -function Base.convert(::Type{BandedMatrix},S::BandedSubBandedMatrix{T}) where {T} +function Base.convert(::Type{BandedMatrix}, S::BandedSubBandedMatrix{T}) where {T} A=parent(S) kr,jr=parentindexes(S) shft=kr[1]-jr[1] diff --git a/src/generic/interface.jl b/src/generic/interface.jl index a96a3122..540c9fd9 100644 --- a/src/generic/interface.jl +++ b/src/generic/interface.jl @@ -28,6 +28,28 @@ memorylayout(A::AbstractArray) = memorylayout(typeof(A)) +# copy! + +function banded_copy!(dest::AbstractMatrix{T}, src::AbstractMatrix) where T + m,n = size(dest) + (m,n) == size(src) || throw(DimensionMismatch()) + + d_l, d_u = bandwidths(dest) + s_l, s_u = bandwidths(src) + (d_l ≥ s_l && d_u ≥ s_u) || throw(BandError(dest)) + for j=1:n + for k = max(1,j-d_u):min(j-s_u-1,m) + inbands_setindex!(dest, zero(T), k, j) + end + for k = max(1,j-s_u):min(j+s_l,m) + inbands_setindex!(dest, inbands_getindex(src, k, j), k, j) + end + for k = max(1,j+s_l+1):min(j+d_l,m) + inbands_setindex!(dest, zero(T), k, j) + end + end + dest +end # these are the routines of the banded interface of other AbstractMatrices banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) = _banded_axpy!(a, X, Y, bandedinterface(X), bandedinterface(Y)) @@ -337,6 +359,7 @@ banded_generic_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatr # the BandedMatrix interface macro _banded_banded_linalg(Typ1, Typ2) ret = quote + Base.copy!(dest::$Typ1, src::$Typ2) = BandedMatrices.banded_copy!(dest,src) Base.BLAS.axpy!(a::Number, X::$Typ1, Y::$Typ2) = BandedMatrices.banded_axpy!(a, X, Y) function Base.:+(A::$Typ1{T}, B::$Typ2{V}) where {T,V} From ca26051e19830a00dc402e8601ac858dee418f0f Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 19 Feb 2018 14:09:24 +0000 Subject: [PATCH 24/26] scalemul! -> mul! --- src/banded/gbmm.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/banded/gbmm.jl b/src/banded/gbmm.jl index 05ec82d4..ccdd771d 100644 --- a/src/banded/gbmm.jl +++ b/src/banded/gbmm.jl @@ -317,18 +317,18 @@ function gbmm!(tA::Char, tB::Char, α::T, A::StridedMatrix{T}, B::AbstractMatrix C end -scalemul!(α, A, x, β, y) = _scalemul!(α, A, x, β, y, memorylayout(A), memorylayout(x), memorylayout(y)) -_scalemul!(α, A, x, β, y, blasA, blasx, blasy) = (y .= α .* A*x .+ β.*y) -_scalemul!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, +mul!(α, A, x, β, y) = _mul!(α, A, x, β, y, memorylayout(A), memorylayout(x), memorylayout(y)) +_mul!(α, A, x, β, y, blasA, blasx, blasy) = (y .= α .* A*x .+ β.*y) +_mul!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, ::StridedLayout{T}, ::BandedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = gbmv!('N', α, A, x, β, y) -_scalemul!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, +_mul!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, ::StridedLayout{T}, ::StridedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = BLAS.gemv!('N', α, A, x, β, y) -_scalemul!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, +_mul!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, ::BandedLayout{T}, ::BandedLayout{T}, ::BandedLayout{T}) where {T<:BlasFloat} = gbmm!('N', 'N', α, A, B, β, C) -_scalemul!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, +_mul!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, ::StridedLayout{T}, ::StridedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = BLAS.gemm!('N', 'N', α, A, B, β, C) From 05292453450d49a2f6514d5168b319402c1fc0a4 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 20 Feb 2018 14:03:19 +0000 Subject: [PATCH 25/26] reorder mul! arguments --- src/banded/gbmm.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/banded/gbmm.jl b/src/banded/gbmm.jl index ccdd771d..bf0bd9ba 100644 --- a/src/banded/gbmm.jl +++ b/src/banded/gbmm.jl @@ -317,18 +317,18 @@ function gbmm!(tA::Char, tB::Char, α::T, A::StridedMatrix{T}, B::AbstractMatrix C end -mul!(α, A, x, β, y) = _mul!(α, A, x, β, y, memorylayout(A), memorylayout(x), memorylayout(y)) -_mul!(α, A, x, β, y, blasA, blasx, blasy) = (y .= α .* A*x .+ β.*y) -_mul!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, +mul!(y, A, x, α, β) = _mul!(y, A, x, α, β, memorylayout(A), memorylayout(x), memorylayout(y)) +_mul!(y, A, x, α, β, blasA, blasx, blasy) = (y .= α .* A*x .+ β.*y) +_mul!(y::AbstractVector{T}, A::AbstractMatrix{T}, x::AbstractVector{T}, α, β, ::StridedLayout{T}, ::BandedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = gbmv!('N', α, A, x, β, y) -_mul!(α, A::AbstractMatrix{T}, x::AbstractVector{T}, β, y::AbstractVector{T}, +_mul!(y::AbstractVector{T}, A::AbstractMatrix{T}, x::AbstractVector{T}, α, β, ::StridedLayout{T}, ::StridedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = BLAS.gemv!('N', α, A, x, β, y) -_mul!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, +_mul!(C::AbstractMatrix{T}, A::AbstractMatrix{T}, B::AbstractMatrix{T}, α, β, ::BandedLayout{T}, ::BandedLayout{T}, ::BandedLayout{T}) where {T<:BlasFloat} = gbmm!('N', 'N', α, A, B, β, C) -_mul!(α, A::AbstractMatrix{T}, B::AbstractMatrix{T}, β, C::AbstractMatrix{T}, +_mul!(C::AbstractMatrix{T}, A::AbstractMatrix{T}, B::AbstractMatrix{T}, α, β, ::StridedLayout{T}, ::StridedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = BLAS.gemm!('N', 'N', α, A, B, β, C) From c31613237e2b8eb185f17767cd246d9df1a467ac Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 20 Feb 2018 14:58:10 +0000 Subject: [PATCH 26/26] Update MemoryLayout --- src/banded/BandedMatrix.jl | 4 +- src/banded/gbmm.jl | 8 ++-- src/generic/interface.jl | 81 ++++++++++++++++++++++---------- src/symbanded/SymBandedMatrix.jl | 2 +- 4 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index ddf84d4e..6ccacefe 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -27,7 +27,7 @@ mutable struct BandedMatrix{T} <: AbstractBandedMatrix{T} end end -memorylayout(::Type{BandedMatrix{T}}) where T = BandedLayout{T}() +MemoryLayout(::BandedMatrix{T}) where T = BandedLayout{T}() # BandedMatrix with unit range indexes is also banded @@ -36,8 +36,6 @@ const BandedSubBandedMatrix{T} = @banded BandedSubBandedMatrix -memorylayout(::Type{BandedSubBandedMatrix{<:BlasFloat}}) = BandedLayout{T}() - ## Constructors doc""" diff --git a/src/banded/gbmm.jl b/src/banded/gbmm.jl index bf0bd9ba..a302a6c7 100644 --- a/src/banded/gbmm.jl +++ b/src/banded/gbmm.jl @@ -317,18 +317,18 @@ function gbmm!(tA::Char, tB::Char, α::T, A::StridedMatrix{T}, B::AbstractMatrix C end -mul!(y, A, x, α, β) = _mul!(y, A, x, α, β, memorylayout(A), memorylayout(x), memorylayout(y)) +mul!(y, A, x, α, β) = _mul!(y, A, x, α, β, MemoryLayout(x), MemoryLayout(A), MemoryLayout(y)) _mul!(y, A, x, α, β, blasA, blasx, blasy) = (y .= α .* A*x .+ β.*y) _mul!(y::AbstractVector{T}, A::AbstractMatrix{T}, x::AbstractVector{T}, α, β, - ::StridedLayout{T}, ::BandedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = + ::AbstractStridedLayout{T}, ::BandedLayout{T}, ::AbstractStridedLayout{T}) where {T<:BlasFloat} = gbmv!('N', α, A, x, β, y) _mul!(y::AbstractVector{T}, A::AbstractMatrix{T}, x::AbstractVector{T}, α, β, - ::StridedLayout{T}, ::StridedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = + ::AbstractStridedLayout{T}, ::AbstractColumnMajor{T}, ::AbstractStridedLayout{T}) where {T<:BlasFloat} = BLAS.gemv!('N', α, A, x, β, y) _mul!(C::AbstractMatrix{T}, A::AbstractMatrix{T}, B::AbstractMatrix{T}, α, β, ::BandedLayout{T}, ::BandedLayout{T}, ::BandedLayout{T}) where {T<:BlasFloat} = gbmm!('N', 'N', α, A, B, β, C) _mul!(C::AbstractMatrix{T}, A::AbstractMatrix{T}, B::AbstractMatrix{T}, α, β, - ::StridedLayout{T}, ::StridedLayout{T}, ::StridedLayout{T}) where {T<:BlasFloat} = + ::AbstractColumnMajor{T}, ::AbstractColumnMajor{T}, ::AbstractColumnMajor{T}) where {T<:BlasFloat} = BLAS.gemm!('N', 'N', α, A, B, β, C) diff --git a/src/generic/interface.jl b/src/generic/interface.jl index 540c9fd9..3be19540 100644 --- a/src/generic/interface.jl +++ b/src/generic/interface.jl @@ -1,30 +1,59 @@ -#### -# BandedMatrix traiut -# an abstract matrix returns IsBanded if it is banded -#### - -struct BandedInterface{truefalse} end -bandedinterface(_) = BandedInterface{false}() -bandedinterface(::AbstractBandedMatrix) = BandedInterface{true}() - #### # Matrix memory layout traits # -# if memorylayout(A) returns BandedLayout, you must override +# if MemoryLayout(A) returns BandedLayout, you must override # pointer and leadingdimension # in addition to the banded matrix interface #### -struct UnknownLayout{T} end -struct StridedLayout{T} end -struct BandedLayout{T} end -struct SymBandedLayout{T} end - - -memorylayout(::Type{A}) where A <: AbstractArray{T} where T = UnknownLayout{T}() -memorylayout(::Type{SM}) where SM <: StridedMatrix{T} where T = StridedLayout{T}() -memorylayout(A::AbstractArray) = memorylayout(typeof(A)) +abstract type MemoryLayout{T} end +struct UnknownLayout{T} <: MemoryLayout{T} end +abstract type AbstractStridedLayout{T} <: MemoryLayout{T} end +abstract type AbstractColumnMajor{T} <: AbstractStridedLayout{T} end +struct DenseColumnMajor{T} <: AbstractColumnMajor{T} end +struct ColumnMajor{T} <: AbstractColumnMajor{T} end +abstract type AbstractRowMajor{T} <: AbstractStridedLayout{T} end +struct DenseRowMajor{T} <: AbstractRowMajor{T} end +struct RowMajor{T} <: AbstractRowMajor{T} end +struct StridedLayout{T} <: AbstractStridedLayout{T} end + + +struct BandedLayout{T} <: MemoryLayout{T} end +struct SymBandedLayout{T} <: MemoryLayout{T} end + +MemoryLayout(A::AbstractArray{T}) where T = UnknownLayout{T}() +MemoryLayout(A::Vector{T}) where T = DenseColumnMajor{T}() +MemoryLayout(A::Matrix{T}) where T = DenseColumnMajor{T}() + +import Base: AbstractCartesianIndex, Slice + +MemoryLayout(A::SubArray) = submemorylayout(MemoryLayout(parent(A)), parentindexes(A)) +submemorylayout(::MemoryLayout{T}, _) where T = UnknownLayout{T}() +submemorylayout(::AbstractColumnMajor{T}, ::Tuple{I}) where {T,I<:Union{AbstractUnitRange{Int},Int,AbstractCartesianIndex}} = + DenseColumnMajor{T}() +submemorylayout(::AbstractStridedLayout{T}, ::Tuple{I}) where {T,I<:Union{RangeIndex,AbstractCartesianIndex}} = + StridedLayout{T}() +submemorylayout(::AbstractColumnMajor{T}, ::Tuple{I,Int}) where {T,I<:Union{AbstractUnitRange{Int},Int,AbstractCartesianIndex}} = + DenseColumnMajor{T}() +submemorylayout(::AbstractColumnMajor{T}, ::Tuple{I,Int}) where {T,I<:Slice} = + DenseColumnMajor{T}() +submemorylayout(::AbstractRowMajor{T}, ::Tuple{Int,I}) where {T,I<:Union{AbstractUnitRange{Int},Int,AbstractCartesianIndex}} = + DenseColumnMajor{T}() +submemorylayout(::AbstractRowMajor{T}, ::Tuple{Int,I}) where {T,I<:Slice} = + DenseColumnMajor{T}() +submemorylayout(::DenseColumnMajor{T}, ::Tuple{I1,I2}) where {T,I1<:Slice,I2<:AbstractUnitRange{Int}} = + DenseColumnMajor{T}() +submemorylayout(::DenseColumnMajor{T}, ::Tuple{I1,I2}) where {T,I1<:AbstractUnitRange{Int},I2<:AbstractUnitRange{Int}} = + ColumnMajor{T}() +submemorylayout(::AbstractColumnMajor{T}, ::Tuple{I1,I2}) where {T,I1<:AbstractUnitRange{Int},I2<:AbstractUnitRange{Int}} = + ColumnMajor{T}() +submemorylayout(::AbstractRowMajor{T}, ::Tuple{I1,I2}) where {T,I1<:AbstractUnitRange{Int},I2<:Slice} = + DenseRowMajor{T}() +submemorylayout(::AbstractRowMajor{T}, ::Tuple{I1,I2}) where {T,I1<:AbstractUnitRange{Int},I2<:AbstractUnitRange{Int}} = + RowMajor{T}() +submemorylayout(::AbstractStridedLayout{T}, ::Tuple{I1,I2}) where {T,I1<:Union{RangeIndex,AbstractCartesianIndex},I2<:Union{RangeIndex,AbstractCartesianIndex}} = + StridedLayout{T}() @@ -52,8 +81,8 @@ function banded_copy!(dest::AbstractMatrix{T}, src::AbstractMatrix) where T end # these are the routines of the banded interface of other AbstractMatrices -banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) = _banded_axpy!(a, X, Y, bandedinterface(X), bandedinterface(Y)) -_banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix, ::BandedInterface{true}, ::BandedInterface{true}) = +banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix) = _banded_axpy!(a, X, Y, MemoryLayout(X), MemoryLayout(Y)) +_banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix, ::BandedLayout, ::BandedLayout) = banded_generic_axpy!(a, X, Y) _banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix, notbandedX, notbandedY) = banded_dense_axpy!(a, X, Y) @@ -61,7 +90,7 @@ _banded_axpy!(a::Number, X::AbstractMatrix, Y::AbstractMatrix, notbandedX, notba # matrix * vector banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector) = - _banded_matvecmul!(c, tA, A, b, memorylayout(c), memorylayout(A), memorylayout(b)) + _banded_matvecmul!(c, tA, A, b, MemoryLayout(c), MemoryLayout(A), MemoryLayout(b)) _banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{T}, b::AbstractVector{T}, ::StridedLayout{T}, ::BandedLayout{T}, ::StridedLayout{T}) where {T <: BlasFloat} = generally_banded_matvecmul!(c, tA, A, b) @@ -77,7 +106,7 @@ banded_At_mul_B!(c::AbstractVector, A::AbstractMatrix, b::AbstractVector) = band # matrix * matrix banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix) = - banded_matmatmul!(C, tA, tB, A, B, memorylayout(A), memorylayout(B)) + banded_matmatmul!(C, tA, tB, A, B, MemoryLayout(A), MemoryLayout(B)) banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, notblasA, notblasB) = banded_generic_matmatmul!(C, tA, tB, A, B) @@ -171,7 +200,7 @@ end positively_banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector) = - _positively_banded_matvecmul!(c, tA, A, b, memorylayout(c), memorylayout(A), memorylayout(b)) + _positively_banded_matvecmul!(c, tA, A, b, MemoryLayout(c), MemoryLayout(A), MemoryLayout(b)) _positively_banded_matvecmul!(c::AbstractVector, tA::Char, A::AbstractMatrix, b::AbstractVector, notblasc, notblasA, notblasb) = _banded_generic_matvecmul!(c, tA, A, b) @@ -182,7 +211,7 @@ _positively_banded_matvecmul!(c::AbstractVector{T}, tA::Char, A::AbstractMatrix{ gbmv!(tA, one(T), A, b, zero(T), c) positively_banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix) = - _positively_banded_matmatmul!(C, tA, tB, A, B, memorylayout(C), memorylayout(A), memorylayout(B)) + _positively_banded_matmatmul!(C, tA, tB, A, B, MemoryLayout(C), MemoryLayout(A), MemoryLayout(B)) _positively_banded_matmatmul!(C::AbstractMatrix, tA::Char, tB::Char, A::AbstractMatrix, B::AbstractMatrix, notblasC, notblasA, notblasb) = _banded_generic_matmatmul!(C, tA, tB, A, B) @@ -570,7 +599,7 @@ end # add routines for banded interface macro banded_interface(Typ) ret = quote - BandedMatrices.bandedinterface(::$Typ) = BandedMatrices.BandedInterface{true}() + BandedMatrices.MemoryLayout(A::$Typ) = BandedMatrices.BandedLayout{eltype(A)}() BandedMatrices.isbanded(::$Typ) = true end esc(ret) diff --git a/src/symbanded/SymBandedMatrix.jl b/src/symbanded/SymBandedMatrix.jl index 5fef7af9..9906c5f7 100644 --- a/src/symbanded/SymBandedMatrix.jl +++ b/src/symbanded/SymBandedMatrix.jl @@ -26,7 +26,7 @@ mutable struct SymBandedMatrix{T} <: AbstractBandedMatrix{T} end -memorylayout(::Type{SymBandedMatrix{<:BlasFloat}}) = BlasSymBanded() +MemoryLayout(::SymBandedMatrix{T}) where T = BlasSymBanded{T}() doc"""