Skip to content

Commit 7363170

Browse files
authored
Julia v1.6+ overhaul (#163)
1 parent e05375f commit 7363170

13 files changed

+106
-147
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
strategy:
1515
matrix:
1616
version:
17-
- '1.0'
17+
- '1.6'
1818
- '1'
1919
- 'nightly'
2020
os:

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
77
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
88

99
[compat]
10-
julia = "1"
10+
julia = "1.6"
1111

1212
[extras]
1313
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"

src/LinearMaps.jl

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@ using LinearAlgebra
88
import LinearAlgebra: mul!
99
using SparseArrays
1010

11-
if VERSION < v"1.2-"
12-
import Base: has_offset_axes
13-
require_one_based_indexing(A...) = !has_offset_axes(A...) || throw(ArgumentError("offset arrays are not supported but got an array with index other than 1"))
14-
else
15-
import Base: require_one_based_indexing
16-
end
11+
using Base: require_one_based_indexing
1712

1813
abstract type LinearMap{T} end
1914

@@ -33,11 +28,7 @@ MulStyle(::ThreeArg, ::FiveArg) = ThreeArg()
3328
MulStyle(::FiveArg, ::ThreeArg) = ThreeArg()
3429
MulStyle(::ThreeArg, ::ThreeArg) = ThreeArg()
3530
MulStyle(::LinearMap) = ThreeArg() # default
36-
@static if VERSION v"1.3.0-alpha.115"
37-
MulStyle(::AbstractVecOrMat) = FiveArg()
38-
else
39-
MulStyle(::AbstractVecOrMat) = ThreeArg()
40-
end
31+
MulStyle(::AbstractVecOrMat) = FiveArg()
4132
MulStyle(A::LinearMap, As::LinearMap...) = MulStyle(MulStyle(A), MulStyle(As...))
4233

4334
Base.isreal(A::LinearMap) = eltype(A) <: Real
@@ -117,9 +108,8 @@ function Base.:(*)(A::LinearMap, x::AbstractVector)
117108
y = similar(x, T, axes(A)[1])
118109
return mul!(y, A, x)
119110
end
120-
if VERSION v"1.3"
121-
(L::LinearMap)(x::AbstractVector) = L*x
122-
end
111+
112+
(L::LinearMap)(x::AbstractVector) = L*x
123113

124114
"""
125115
mul!(Y::AbstractVecOrMat, A::LinearMap, B::AbstractVector) -> Y
@@ -225,13 +215,9 @@ function mul!(Y::AbstractMatrix, A::LinearMap, X::AbstractMatrix, α::Number, β
225215
end
226216

227217
function _generic_mapmat_mul!(Y, A, X, α=true, β=false)
228-
@views for i in 1:size(X, 2)
229-
_unsafe_mul!(Y[:, i], A, X[:, i], α, β)
218+
for (Xi, Yi) in zip(eachcol(X), eachcol(Y))
219+
mul!(Yi, A, Xi, α, β)
230220
end
231-
# starting from Julia v1.1, we could use the `eachcol` iterator
232-
# for (Xi, Yi) in zip(eachcol(X), eachcol(Y))
233-
# mul!(Yi, A, Xi, α, β)
234-
# end
235221
return Y
236222
end
237223

src/blockmap.jl

Lines changed: 38 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ BlockMap{T}(maps::As, rows::Rs) where {T, As<:LinearMapTuple, Rs} =
2424

2525
MulStyle(A::BlockMap) = MulStyle(A.maps...)
2626

27+
function _getranges(maps, dim, inds=ntuple(identity, Val(length(maps))))
28+
sizes = map(i -> size(maps[i], dim)::Int, inds)
29+
ends = cumsum(sizes)
30+
starts = (1, (1 .+ Base.front(ends))...)
31+
return UnitRange.(starts, ends)
32+
end
33+
2734
"""
2835
rowcolranges(maps, rows)
2936
@@ -32,24 +39,20 @@ map in `maps`, according to its position in a virtual matrix representation of t
3239
block linear map obtained from `hvcat(rows, maps...)`.
3340
"""
3441
function rowcolranges(maps, rows)
35-
rowranges = ntuple(n->1:0, Val(length(rows)))
36-
colranges = ntuple(n->1:0, Val(length(maps)))
37-
mapind = 0
38-
rowstart = 1
39-
for (i, row) in enumerate(rows)
40-
mapind += 1
41-
rowend = rowstart + Int(size(maps[mapind], 1))::Int - 1
42-
rowranges = Base.setindex(rowranges, rowstart:rowend, i)
43-
colstart = 1
44-
colend = Int(size(maps[mapind], 2))::Int
45-
colranges = Base.setindex(colranges, colstart:colend, mapind)
46-
for colind in 2:row
47-
mapind += 1
48-
colstart = colend + 1
49-
colend += Int(size(maps[mapind], 2))::Int
50-
colranges = Base.setindex(colranges, colstart:colend, mapind)
51-
end
52-
rowstart = rowend + 1
42+
# find indices of the row-wise first maps
43+
firstmapinds = cumsum((1, Base.front(rows)...))
44+
# compute rowranges from first dimension of the row-wise first maps
45+
rowranges = _getranges(maps, 1, firstmapinds)
46+
47+
# compute ranges from second dimension as if all in one row
48+
temp = _getranges(maps, 2)
49+
# introduce "line breaks"
50+
colranges = ntuple(Val(length(maps))) do i
51+
# for each map find the index of the respective row-wise first map
52+
# something-trick just to assure the compiler that the index is an Int
53+
@inbounds firstmapind = firstmapinds[something(findlast(<=(i), firstmapinds), 1)]
54+
# shift ranges by the first col-index of the row-wise first map
55+
return @inbounds temp[i] .- first(temp[firstmapind]) .+ 1
5356
end
5457
return rowranges, colranges
5558
end
@@ -82,17 +85,13 @@ function Base.hcat(As::Union{LinearMap, UniformScaling, AbstractVecOrMat}...)
8285
T = promote_type(map(eltype, As)...)
8386
nbc = length(As)
8487

85-
nrows = -1
8688
# find first non-UniformScaling to detect number of rows
87-
for A in As
88-
if !(A isa UniformScaling)
89-
nrows = size(A, 1)
90-
break
91-
end
92-
end
93-
@assert nrows != -1
89+
j = findfirst(A -> !isa(A, UniformScaling), As)
9490
# this should not happen, function should only be called with at least one LinearMap
95-
return BlockMap{T}(promote_to_lmaps(ntuple(i->nrows, nbc), 1, 1, As...), (nbc,))
91+
@assert !isnothing(j)
92+
@inbounds nrows = size(As[j], 1)::Int
93+
94+
return BlockMap{T}(promote_to_lmaps(ntuple(_ -> nrows, Val(nbc)), 1, 1, As...), (nbc,))
9695
end
9796

9897
############
@@ -124,18 +123,14 @@ function Base.vcat(As::Union{LinearMap,UniformScaling,AbstractVecOrMat}...)
124123
T = promote_type(map(eltype, As)...)
125124
nbr = length(As)
126125

127-
ncols = -1
128-
# find first non-UniformScaling to detect number of columns
129-
for A in As
130-
if !(A isa UniformScaling)
131-
ncols = size(A, 2)
132-
break
133-
end
134-
end
135-
@assert ncols != -1
126+
# find first non-UniformScaling to detect number of rows
127+
j = findfirst(A -> !isa(A, UniformScaling), As)
136128
# this should not happen, function should only be called with at least one LinearMap
137-
rows = ntuple(i->1, nbr)
138-
return BlockMap{T}(promote_to_lmaps(ntuple(i->ncols, nbr), 1, 2, As...), rows)
129+
@assert !isnothing(j)
130+
@inbounds ncols = size(As[j], 2)::Int
131+
132+
rows = ntuple(_ -> 1, Val(nbr))
133+
return BlockMap{T}(promote_to_lmaps(ntuple(_ -> ncols, Val(nbr)), 1, 2, As...), rows)
139134
end
140135

141136
############
@@ -181,7 +176,7 @@ function Base.hvcat(rows::Tuple{Vararg{Int}},
181176
ni = -1 # number of rows in this block-row, -1 indicates unknown
182177
for k in 1:rows[i]
183178
if !isa(As[j+k], UniformScaling)
184-
na = size(As[j+k], 1)
179+
na = size(As[j+k], 1)::Int
185180
ni >= 0 && ni != na &&
186181
throw(DimensionMismatch("mismatch in number of rows"))
187182
ni = na
@@ -199,7 +194,7 @@ function Base.hvcat(rows::Tuple{Vararg{Int}},
199194
nci = 0
200195
rows[i] > 0 && n[j+1] == -1 && (j += rows[i]; continue)
201196
for k = 1:rows[i]
202-
nci += isa(As[j+k], UniformScaling) ? n[j+k] : size(As[j+k], 2)
197+
nci += isa(As[j+k], UniformScaling) ? n[j+k] : size(As[j+k], 2)::Int
203198
end
204199
nc >= 0 && nc != nci && throw(DimensionMismatch("mismatch in number of columns"))
205200
nc = nci
@@ -412,14 +407,8 @@ struct BlockDiagonalMap{T,
412407
promote_type(T, TA) == T ||
413408
error("eltype $TA cannot be promoted to $T in BlockDiagonalMap constructor")
414409
end
415-
# row ranges
416-
inds = vcat(1, size.(maps, 1)...)
417-
cumsum!(inds, inds)
418-
rowranges = ntuple(i -> inds[i]:inds[i+1]-1, Val(length(maps)))
419-
# column ranges
420-
inds[2:end] .= size.(maps, 2)
421-
cumsum!(inds, inds)
422-
colranges = ntuple(i -> inds[i]:inds[i+1]-1, Val(length(maps)))
410+
rowranges = _getranges(maps, 1)
411+
colranges = _getranges(maps, 2)
423412
return new{T, As, typeof(rowranges)}(maps, rowranges, colranges)
424413
end
425414
end
@@ -476,7 +465,7 @@ object among the first 8 arguments.
476465
"""
477466
Base.cat
478467

479-
Base.size(A::BlockDiagonalMap) = (last(A.rowranges[end]), last(A.colranges[end]))
468+
Base.size(A::BlockDiagonalMap) = (last(last(A.rowranges)), last(last(A.colranges)))
480469

481470
MulStyle(A::BlockDiagonalMap) = MulStyle(A.maps...)
482471

src/composition.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ struct CompositeMap{T, As<:LinearMapTuple} <: LinearMap{T}
55
for n in 2:N
66
check_dim_mul(maps[n], maps[n-1])
77
end
8-
for TA in Base.Generator(eltype, maps)
9-
# like lazy map; could use Base.Iterators.map in Julia >= 1.6
8+
for TA in Base.Iterators.map(eltype, maps)
109
promote_type(T, TA) == T ||
1110
error("eltype $TA cannot be promoted to $T in CompositeMap constructor")
1211
end

src/kronecker.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
struct KroneckerMap{T, As<:LinearMapTuple} <: LinearMap{T}
22
maps::As
33
function KroneckerMap{T}(maps::LinearMapTuple) where {T}
4-
for TA in Base.Generator(eltype, maps)
4+
for TA in Base.Iterators.map(eltype, maps)
55
promote_type(T, TA) == T ||
66
error("eltype $TA cannot be promoted to $T in KroneckerMap constructor")
77
end
@@ -221,7 +221,7 @@ struct KroneckerSumMap{T, As<:Tuple{LinearMap, LinearMap}} <: LinearMap{T}
221221
A1, A2 = maps
222222
(size(A1, 1) == size(A1, 2) && size(A2, 1) == size(A2, 2)) ||
223223
throw(ArgumentError("operators need to be square in Kronecker sums"))
224-
for TA in Base.Generator(eltype, maps)
224+
for TA in Base.Iterators.map(eltype, maps)
225225
promote_type(T, TA) == T ||
226226
error("eltype $TA cannot be promoted to $T in KroneckerSumMap constructor")
227227
end

src/linearcombination.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ MulStyle(A::LinearCombination) = MulStyle(A.maps...)
1818

1919
# basic methods
2020
Base.size(A::LinearCombination) = size(A.maps[1])
21-
Base.axes(A::LinearMaps.LinearCombination) = axes(A.maps[1])
21+
Base.axes(A::LinearCombination) = axes(A.maps[1])
2222
# following conditions are sufficient but not necessary
2323
LinearAlgebra.issymmetric(A::LinearCombination) = all(issymmetric, A.maps)
2424
LinearAlgebra.ishermitian(A::LinearCombination) = all(ishermitian, A.maps)

src/wrappedmap.jl

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -87,40 +87,38 @@ mul!(Y::AbstractMatrix, X::AbstractMatrix, A::VecOrMatMap) = mul!(Y, X, A.lmap)
8787
# the following method is needed for disambiguation with left-multiplication
8888
mul!(Y::AbstractMatrix, X::TransposeAbsVecOrMat, A::VecOrMatMap) = mul!(Y, X, A.lmap)
8989

90-
if VERSION v"1.3.0-alpha.115"
91-
for (In, Out) in ((AbstractVector, AbstractVecOrMat), (AbstractMatrix, AbstractMatrix))
92-
@eval begin
93-
function _unsafe_mul!(y::$Out, A::WrappedMap, x::$In, α::Number, β::Number)
94-
return _unsafe_mul!(y, A.lmap, x, α, β)
95-
end
96-
function _unsafe_mul!(y::$Out, At::TransposeMap{<:Any,<:WrappedMap}, x::$In,
97-
α::Number, β::Number)
98-
A = At.lmap
99-
return (issymmetric(A) || (isreal(A) && ishermitian(A))) ?
100-
_unsafe_mul!(y, A.lmap, x, α, β) :
101-
_unsafe_mul!(y, transpose(A.lmap), x, α, β)
102-
end
103-
function _unsafe_mul!(y::$Out, Ac::AdjointMap{<:Any,<:WrappedMap}, x::$In, α::Number, β::Number)
104-
A = Ac.lmap
105-
return ishermitian(A) ?
106-
_unsafe_mul!(y, A.lmap, x, α, β) :
107-
_unsafe_mul!(y, adjoint(A.lmap), x, α, β)
108-
end
90+
for (In, Out) in ((AbstractVector, AbstractVecOrMat), (AbstractMatrix, AbstractMatrix))
91+
@eval begin
92+
function _unsafe_mul!(y::$Out, A::WrappedMap, x::$In, α::Number, β::Number)
93+
return _unsafe_mul!(y, A.lmap, x, α, β)
94+
end
95+
function _unsafe_mul!(y::$Out, At::TransposeMap{<:Any,<:WrappedMap}, x::$In,
96+
α::Number, β::Number)
97+
A = At.lmap
98+
return (issymmetric(A) || (isreal(A) && ishermitian(A))) ?
99+
_unsafe_mul!(y, A.lmap, x, α, β) :
100+
_unsafe_mul!(y, transpose(A.lmap), x, α, β)
101+
end
102+
function _unsafe_mul!(y::$Out, Ac::AdjointMap{<:Any,<:WrappedMap}, x::$In, α::Number, β::Number)
103+
A = Ac.lmap
104+
return ishermitian(A) ?
105+
_unsafe_mul!(y, A.lmap, x, α, β) :
106+
_unsafe_mul!(y, adjoint(A.lmap), x, α, β)
109107
end
110108
end
109+
end
111110

112-
mul!(X::AbstractMatrix, Y::AbstractMatrix, A::VecOrMatMap, α::Number, β::Number) =
113-
mul!(X, Y, A.lmap, α, β)
114-
# the following method is needed for disambiguation with left-multiplication
115-
function mul!(Y::AbstractMatrix{<:RealOrComplex}, X::AbstractMatrix{<:RealOrComplex}, A::VecOrMatMap{<:RealOrComplex},
116-
α::RealOrComplex, β::RealOrComplex)
117-
return mul!(Y, X, A.lmap, α, β)
118-
end
119-
function mul!(Y::AbstractMatrix{<:RealOrComplex}, X::TransposeAbsVecOrMat{<:RealOrComplex}, A::VecOrMatMap{<:RealOrComplex},
120-
α::RealOrComplex, β::RealOrComplex)
121-
return mul!(Y, X, A.lmap, α, β)
122-
end
123-
end # VERSION
111+
mul!(X::AbstractMatrix, Y::AbstractMatrix, A::VecOrMatMap, α::Number, β::Number) =
112+
mul!(X, Y, A.lmap, α, β)
113+
# the following 2 methods are needed for disambiguation with left-multiplication
114+
function mul!(Y::AbstractMatrix{<:RealOrComplex}, X::AbstractMatrix{<:RealOrComplex}, A::VecOrMatMap{<:RealOrComplex},
115+
α::RealOrComplex, β::RealOrComplex)
116+
return mul!(Y, X, A.lmap, α, β)
117+
end
118+
function mul!(Y::AbstractMatrix{<:RealOrComplex}, X::TransposeAbsVecOrMat{<:RealOrComplex}, A::VecOrMatMap{<:RealOrComplex},
119+
α::RealOrComplex, β::RealOrComplex)
120+
return mul!(Y, X, A.lmap, α, β)
121+
end
124122

125123
# combine LinearMap and Matrix objects: linear combinations and map composition
126124
Base.:(+)(A₁::LinearMap, A₂::AbstractMatrix) = +(A₁, WrappedMap(A₂))

test/blockmap.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Test, LinearMaps, LinearAlgebra, SparseArrays, BenchmarkTools, InteractiveUtils
2+
using LinearMaps: FiveArg, ThreeArg
23

34
@testset "block maps" begin
45
@testset "hcat" begin
@@ -8,7 +9,7 @@ using Test, LinearMaps, LinearAlgebra, SparseArrays, BenchmarkTools, Interactive
89
v = rand(elty, 10)
910
L = @inferred hcat(LinearMap(A11), LinearMap(A12))
1011
@test occursin("10×$(10+n2) LinearMaps.BlockMap{$elty}", sprint((t, s) -> show(t, "text/plain", s), L))
11-
@test @inferred(LinearMaps.MulStyle(L)) === matrixstyle
12+
@test @inferred(LinearMaps.MulStyle(L)) === FiveArg()
1213
@test L isa LinearMaps.BlockMap{elty}
1314
if elty <: Complex
1415
@test_throws ErrorException LinearMaps.BlockMap{Float64}((LinearMap(A11), LinearMap(A12)), (2,))
@@ -54,7 +55,7 @@ using Test, LinearMaps, LinearAlgebra, SparseArrays, BenchmarkTools, Interactive
5455
L = @inferred vcat(LinearMap(A11), LinearMap(A21))
5556
@test occursin("30×10 LinearMaps.BlockMap{$elty}", sprint((t, s) -> show(t, "text/plain", s), L))
5657
@test L isa LinearMaps.BlockMap{elty}
57-
@test @inferred(LinearMaps.MulStyle(L)) === matrixstyle
58+
@test @inferred(LinearMaps.MulStyle(L)) === FiveArg()
5859
@test (@which [A11; A21]).module != LinearMaps
5960
A = [A11; A21]
6061
x = rand(10)
@@ -84,7 +85,7 @@ using Test, LinearMaps, LinearAlgebra, SparseArrays, BenchmarkTools, Interactive
8485
@test (@which [A11 A12; A21 A22]).module != LinearMaps
8586
@inferred hvcat((2,2), LinearMap(A11), LinearMap(A12), LinearMap(A21), LinearMap(A22))
8687
L = [LinearMap(A11) LinearMap(A12); LinearMap(A21) LinearMap(A22)]
87-
@test @inferred(LinearMaps.MulStyle(L)) === matrixstyle
88+
@test @inferred(LinearMaps.MulStyle(L)) === FiveArg()
8889
@test @inferred !issymmetric(L)
8990
@test @inferred !ishermitian(L)
9091
x = rand(30)
@@ -142,7 +143,7 @@ using Test, LinearMaps, LinearAlgebra, SparseArrays, BenchmarkTools, Interactive
142143
A12 = rand(elty, 10, 10)
143144
A = [I A12; transform(A12) I]
144145
L = [I LinearMap(A12); transform(LinearMap(A12)) I]
145-
@test @inferred(LinearMaps.MulStyle(L)) === matrixstyle
146+
@test @inferred(LinearMaps.MulStyle(L)) === FiveArg()
146147
if elty <: Complex
147148
if transform == transpose
148149
@test @inferred issymmetric(L)
@@ -201,7 +202,7 @@ using Test, LinearMaps, LinearAlgebra, SparseArrays, BenchmarkTools, Interactive
201202
@test (@which cat(M1, M2, M3, M2, M1; dims=(1,2))).module != LinearMaps
202203
x = randn(elty, size(Md, 2))
203204
Bd = @inferred blockdiag(L1, L2, L3, L2, L1)
204-
@test @inferred(LinearMaps.MulStyle(Bd)) === matrixstyle
205+
@test @inferred(LinearMaps.MulStyle(Bd)) === FiveArg()
205206
@test occursin("25×39 LinearMaps.BlockDiagonalMap{$elty}", sprint((t, s) -> show(t, "text/plain", s), Bd))
206207
@test Matrix(Bd) == Md
207208
@test convert(AbstractMatrix, Bd) isa SparseMatrixCSC

0 commit comments

Comments
 (0)