Skip to content

Commit 373f3ef

Browse files
committed
make mean work stably
1 parent e4334cb commit 373f3ef

File tree

5 files changed

+28
-4
lines changed

5 files changed

+28
-4
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "LinearMaps"
22
uuid = "7a12625a-238d-50fd-b39a-03d52299707e"
3-
version = "3.5.2"
3+
version = "3.6.0"
44

55
[deps]
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

docs/src/history.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Version history
22

3+
## What's new in v3.6
4+
5+
* Support for Julia versions below v1.6 has been dropped.
6+
* `Block[Diagonal]Map`, `CompositeMap`, `KroneckerMap` and `LinearCombination` type objects
7+
can now be backed by a `Vector` of `LinearMap`-type elements. This can be beneficial in
8+
cases where these higher-order `LinearMap`s are constructed from many maps where a tuple
9+
backend may get inefficient or impose hard work for the compiler at construction.
10+
The default behavior, however, does not change, and construction of vector-based
11+
`LinearMap`s requires usage of the unexported constructors ("expert usage").
12+
313
## What's new in v3.5
414

515
* `WrappedMap`, `ScaledMap`, `LinearCombination`, `AdjointMap`, `TransposeMap` and
@@ -24,7 +34,7 @@
2434
## What's new in v3.3
2535

2636
* `AbstractVector`s can now be wrapped by a `LinearMap` just like `AbstractMatrix``
27-
typed objects. Upon wrapping, there are not implicitly reshaped to matrices. This
37+
typed objects. Upon wrapping, they are not implicitly reshaped to matrices. This
2838
feature might be helpful, for instance, in the lazy representation of rank-1
2939
operators `kron(LinearMap(u), v') == ⊗(u, v') == u ⊗ v'` for vectors `u` and `v`.
3040
The action on vectors,`(u⊗v')*x`, is implemented optimally via `u*(v'x)`.

src/linearcombination.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,18 @@ end
1414

1515
LinearCombination{T}(maps::As) where {T, As} = LinearCombination{T, As}(maps)
1616

17+
# this method avoids the afoldl-mechanism even for LinearMapTuple
1718
Base.mapreduce(::typeof(identity), ::typeof(Base.add_sum), maps::LinearMapTupleOrVector) =
1819
LinearCombination{promote_type(map(eltype, maps)...)}(maps)
20+
# this method is required for type stability in the mixed-map-equal-eltype case
1921
Base.mapreduce(::typeof(identity), ::typeof(Base.add_sum), maps::AbstractVector{<:LinearMap{T}}) where {T} =
2022
LinearCombination{T}(maps)
23+
# the following two methods are needed to make e.g. `mean` work,
24+
# for which `f` is some sort of promotion function
25+
Base.mapreduce(f::F, ::typeof(Base.add_sum), maps::LinearMapTupleOrVector) where {F} =
26+
LinearCombination{promote_type(map(eltype, maps)...)}(f.(maps))
27+
Base.mapreduce(f::F, ::typeof(Base.add_sum), maps::AbstractVector{<:LinearMap{T}}) where {F,T} =
28+
LinearCombination{T}(f.(maps))
2129

2230
MulStyle(A::LinearCombination) = MulStyle(A.maps...)
2331

test/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
77
Quaternions = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0"
88
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
9+
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
910
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1011

1112
[compat]

test/linearcombination.jl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Test, LinearMaps, LinearAlgebra, SparseArrays, BenchmarkTools
1+
using Test, LinearMaps, LinearAlgebra, SparseArrays, BenchmarkTools, Statistics
22
using LinearMaps: FiveArg, LinearMapTuple, LinearMapVector
33

44
@testset "linear combinations" begin
@@ -14,10 +14,15 @@ using LinearMaps: FiveArg, LinearMapTuple, LinearMapVector
1414
@test (@inferred sum(L.maps::LinearMapTuple)) == L
1515
Lv = @inferred LinearMaps.LinearCombination{ComplexF64}(fill(CS!, n))
1616
@test (@inferred sum(Lv.maps::LinearMapVector)) == Lv
17+
@test isa((@inferred mean(Lv.maps)),
18+
LinearMaps.ScaledMap{ComplexF64,Float64,<:LinearMaps.LinearCombination{ComplexF64,<:LinearMapVector}})
19+
@test (@inferred mean(x -> x*x, Lv.maps)) == (@inferred sum(x -> x*x, Lv.maps)/n)
1720
@test L == Lv
1821
@test isa((@inferred sum([CS!, LinearMap(randn(eltype(CS!), size(CS!)))])),
1922
LinearMaps.LinearCombination{<:ComplexF64,<:LinearMapVector})
20-
@test isa(sum([CS!, LinearMap(randn(real(eltype(CS!)), size(CS!)))]),
23+
A = randn(eltype(CS!), size(CS!))
24+
@test (@inferred mean([CS!, LinearMap(A)])) == (@inferred sum([CS!, LinearMap(A)])/2)
25+
@test isa(sum([CS!, LinearMap(real(A))]),
2126
LinearMaps.LinearCombination{<:ComplexF64,<:LinearMapVector})
2227
for sum1 in (CS!, L, Lv), sum2 in (CS!, L, Lv)
2328
m1 = sum1 == CS! ? 1 : 10

0 commit comments

Comments
 (0)