Skip to content

Commit 139872d

Browse files
committed
Refactor truncation names
1 parent b37a9fd commit 139872d

4 files changed

Lines changed: 96 additions & 115 deletions

File tree

src/MatrixAlgebraKit.jl

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,14 @@ export left_polar!, right_polar!
2828
export left_orth, right_orth, left_null, right_null
2929
export left_orth!, right_orth!, left_null!, right_null!
3030

31-
export LAPACK_HouseholderQR, LAPACK_HouseholderLQ,
32-
LAPACK_Simple, LAPACK_Expert,
33-
LAPACK_QRIteration, LAPACK_Bisection, LAPACK_MultipleRelativelyRobustRepresentations,
34-
LAPACK_DivideAndConquer, LAPACK_Jacobi,
35-
LQViaTransposedQR,
36-
CUSOLVER_Simple,
37-
CUSOLVER_HouseholderQR, CUSOLVER_QRIteration, CUSOLVER_SVDPolar, CUSOLVER_Jacobi, CUSOLVER_Randomized, CUSOLVER_DivideAndConquer,
38-
ROCSOLVER_HouseholderQR, ROCSOLVER_QRIteration, ROCSOLVER_Jacobi, ROCSOLVER_DivideAndConquer, ROCSOLVER_Bisection,
39-
DiagonalAlgorithm
40-
export truncrank, trunctol, truncabove, TruncationKeepSorted, TruncationKeepFiltered, truncerror
31+
export LAPACK_HouseholderQR, LAPACK_HouseholderLQ, LAPACK_Simple, LAPACK_Expert, LAPACK_QRIteration, LAPACK_Bisection, LAPACK_MultipleRelativelyRobustRepresentations, LAPACK_DivideAndConquer, LAPACK_Jacobi
32+
export LQViaTransposedQR
33+
export DiagonalAlgorithm
34+
export CUSOLVER_Simple, CUSOLVER_HouseholderQR, CUSOLVER_QRIteration, CUSOLVER_SVDPolar, CUSOLVER_Jacobi, CUSOLVER_Randomized, CUSOLVER_DivideAndConquer
35+
export ROCSOLVER_HouseholderQR, ROCSOLVER_QRIteration, ROCSOLVER_Jacobi,
36+
ROCSOLVER_DivideAndConquer, ROCSOLVER_Bisection
37+
38+
export notrunc, truncrank, trunctol, truncerror, truncfilter
4139

4240
VERSION >= v"1.11.0-DEV.469" &&
4341
eval(Expr(:public, :default_algorithm, :findtruncated, :findtruncated_sorted,

src/implementations/orthnull.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ function null_truncation_strategy(; atol=nothing, rtol=nothing, maxnullity=nothi
207207
end
208208
atol = @something atol 0
209209
rtol = @something rtol 0
210-
trunc = TruncationKeepBelow(atol, rtol)
210+
trunc = trunctol(; atol, rtol, rev=false)
211211
return !isnothing(maxnullity) ? trunc & truncrank(maxnullity; rev=false) : trunc
212212
end
213213

src/implementations/truncation.jl

Lines changed: 41 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -28,82 +28,78 @@ end
2828

2929
# findtruncated
3030
# -------------
31+
# Generic fallback
32+
function findtruncated_sorted(values::AbstractVector, strategy::TruncationStrategy)
33+
return findtruncated(values, strategy)
34+
end
35+
3136
# specific implementations for finding truncated values
3237
findtruncated(values::AbstractVector, ::NoTruncation) = Colon()
3338

34-
function findtruncated(values::AbstractVector, strategy::TruncationKeepSorted)
39+
function findtruncated(values::AbstractVector, strategy::TruncationByOrder)
3540
howmany = min(strategy.howmany, length(values))
36-
return partialsortperm(values, 1:howmany; by=strategy.by, rev=strategy.rev)
41+
return partialsortperm(values, 1:howmany; strategy.by, strategy.rev)
3742
end
38-
function findtruncated_sorted(values::AbstractVector, strategy::TruncationKeepSorted)
43+
function findtruncated_sorted(values::AbstractVector, strategy::TruncationByOrder)
3944
howmany = min(strategy.howmany, length(values))
4045
return 1:howmany
4146
end
4247

43-
# TODO: consider if worth using that values are sorted when filter is `<` or `>`.
44-
function findtruncated(values::AbstractVector, strategy::TruncationKeepFiltered)
48+
function findtruncated(values::AbstractVector, strategy::TruncationByFilter)
4549
ind = findall(strategy.filter, values)
4650
return ind
4751
end
4852

49-
function findtruncated(values::AbstractVector, strategy::TruncationKeepBelow)
50-
atol = max(strategy.atol, strategy.rtol * norm(values, strategy.p))
51-
return findall((atol) strategy.by, values)
52-
end
53-
function findtruncated_sorted(values::AbstractVector, strategy::TruncationKeepBelow)
54-
atol = max(strategy.atol, strategy.rtol * norm(values, strategy.p))
55-
i = searchsortedfirst(values, atol; by=strategy.by, rev=true)
56-
return i:length(values)
57-
end
58-
59-
function findtruncated(values::AbstractVector, strategy::TruncationKeepAbove)
53+
function findtruncated(values::AbstractVector, strategy::TruncationByValue)
6054
atol = max(strategy.atol, strategy.rtol * norm(values, strategy.p))
61-
return findall((atol) strategy.by, values)
55+
filter = (strategy.rev ? (atol) : (atol)) strategy.by
56+
return findall(filter, values)
6257
end
63-
function findtruncated_sorted(values::AbstractVector, strategy::TruncationKeepAbove)
58+
function findtruncated_sorted(values::AbstractVector, strategy::TruncationByValue)
6459
atol = max(strategy.atol, strategy.rtol * norm(values, strategy.p))
65-
i = searchsortedlast(values, atol; by=strategy.by, rev=true)
66-
return 1:i
67-
end
68-
69-
function findtruncated(values::AbstractVector, strategy::TruncationIntersection)
70-
inds = map(Base.Fix1(findtruncated, values), strategy.components)
71-
return intersect(inds...)
72-
end
73-
function findtruncated_sorted(values::AbstractVector, strategy::TruncationIntersection)
74-
inds = map(Base.Fix1(findtruncated_sorted, values), strategy.components)
75-
return intersect(inds...)
60+
if strategy.rev
61+
i = searchsortedlast(values, atol; by=strategy.by, rev=true)
62+
return 1:i
63+
else
64+
i = searchsortedfirst(values, atol; by=strategy.by, rev=true)
65+
return i:length(values)
66+
end
7667
end
7768

78-
function findtruncated(values::AbstractVector, strategy::TruncationError)
69+
function findtruncated(values::AbstractVector, strategy::TruncationByError)
7970
I = sortperm(values; by=abs, rev=true)
80-
I′ = _truncerr_impl(values, I, strategy)
71+
I′ = _truncerr_impl(values, I; strategy.atol, strategy.rtol, strategy.p)
8172
return I[I′]
8273
end
83-
function findtruncated_sorted(values::AbstractVector, strategy::TruncationError)
74+
function findtruncated_sorted(values::AbstractVector, strategy::TruncationByError)
8475
I = eachindex(values)
85-
I′ = _truncerr_impl(values, I, strategy)
76+
I′ = _truncerr_impl(values, I; strategy.atol, strategy.rtol, strategy.p)
8677
return I[I′]
8778
end
88-
function _truncerr_impl(values::AbstractVector, I, strategy::TruncationError)
89-
Nᵖ = sum(Base.Fix2(^, strategy.p) abs, values)
90-
ϵᵖ = max(strategy.atol^strategy.p, strategy.rtol^strategy.p * Nᵖ)
79+
function _truncerr_impl(values::AbstractVector, I; atol::Real=0, rtol::Real=0, p::Real=2)
80+
by = Base.Fix2(^, p) abs
81+
Nᵖ = sum(by, values)
82+
ϵᵖ = max(atol^p, rtol^p * Nᵖ)
83+
84+
# fast path to avoid checking all values
9185
ϵᵖ Nᵖ && return Base.OneTo(0)
9286

9387
truncerrᵖ = zero(real(eltype(values)))
9488
rank = length(values)
9589
for i in reverse(I)
96-
truncerrᵖ += abs(values[i])^strategy.p
97-
if truncerrᵖ ϵᵖ
98-
break
99-
else
100-
rank -= 1
101-
end
90+
truncerrᵖ += by(values[i])
91+
truncerrᵖ ϵᵖ && break
92+
rank -= 1
10293
end
94+
10395
return Base.OneTo(rank)
10496
end
10597

106-
# Generic fallback
107-
function findtruncated_sorted(values::AbstractVector, strategy::TruncationStrategy)
108-
return findtruncated(values, strategy)
98+
function findtruncated(values::AbstractVector, strategy::TruncationIntersection)
99+
inds = map(Base.Fix1(findtruncated, values), strategy.components)
100+
return intersect(inds...)
101+
end
102+
function findtruncated_sorted(values::AbstractVector, strategy::TruncationIntersection)
103+
inds = map(Base.Fix1(findtruncated_sorted, values), strategy.components)
104+
return intersect(inds...)
109105
end

src/interface/truncation.jl

Lines changed: 46 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ function TruncationStrategy(; atol=nothing, rtol=nothing, maxrank=nothing)
1414
elseif isnothing(maxrank)
1515
atol = @something atol 0
1616
rtol = @something rtol 0
17-
return TruncationKeepAbove(atol, rtol)
17+
return trunctol(; atol, rtol)
1818
else
1919
if isnothing(atol) && isnothing(rtol)
2020
return truncrank(maxrank)
2121
else
2222
atol = @something atol 0
2323
rtol = @something rtol 0
24-
return truncrank(maxrank) & TruncationKeepAbove(atol, rtol)
24+
return truncrank(maxrank) & trunctol(; atol, rtol)
2525
end
2626
end
2727
end
@@ -42,87 +42,102 @@ Truncation strategy that does nothing, and keeps all the values.
4242
notrunc() = NoTruncation()
4343

4444
"""
45-
TruncationKeepSorted(howmany::Int, by::Function, rev::Bool)
45+
TruncationByOrder(howmany::Int, by::Function, rev::Bool)
4646
4747
Truncation strategy to keep the first `howmany` values when sorted according to `by` in increasing (decreasing) order if `rev` is false (true).
48+
4849
See also [`truncrank`](@ref).
4950
"""
50-
struct TruncationKeepSorted{F} <: TruncationStrategy
51+
struct TruncationByOrder{F} <: TruncationStrategy
5152
howmany::Int
5253
by::F
5354
rev::Bool
5455
end
5556

5657
"""
57-
truncrank(howmany::Int; by=abs, rev=true)
58+
truncrank(howmany::Integer; by=abs, rev::Bool=true)
5859
5960
Truncation strategy to keep the first `howmany` values when sorted according to `by` or the last `howmany` if `rev` is true.
6061
"""
61-
truncrank(howmany::Int; by=abs, rev=true) = TruncationKeepSorted(howmany, by, rev)
62+
truncrank(howmany::Integer; by=abs, rev::Bool=true) = TruncationByOrder(howmany, by, rev)
6263

6364
"""
64-
TruncationKeepFiltered(filter::Function)
65+
TruncationByFilter(filter::Function)
6566
6667
Truncation strategy to keep the values for which `filter` returns true.
68+
69+
See also [`truncfilter`](@ref).
6770
"""
68-
struct TruncationKeepFiltered{F} <: TruncationStrategy
71+
struct TruncationByFilter{F} <: TruncationStrategy
6972
filter::F
7073
end
7174

7275
"""
73-
truncabove(val::Real; by=abs)
76+
truncfilter(filter)
77+
78+
Truncation strategy to keep the values for which `filter` returns true.
79+
"""
80+
truncfilter(f) = TruncationByFilter(f)
7481

75-
Truncation strategy to discard the values that are larger than `val` according to `by`.
7682
"""
77-
truncabove(val::Real; by=abs) = TruncationKeepFiltered((val) by)
83+
TruncationByValue(atol::Real, rtol::Real, p::Real, by, rev::Bool=true)
7884
79-
struct TruncationKeepAbove{T<:Real,P<:Real,F} <: TruncationStrategy
85+
Truncation strategy to keep the values that satisfy `by(val) < max(atol, rtol * norm(values, p)`
86+
if `rev = true`, or discard them when `rev = false`.
87+
See also [`trunctol`](@ref)
88+
"""
89+
struct TruncationByValue{T<:Real,P<:Real,F} <: TruncationStrategy
8090
atol::T
8191
rtol::T
8292
p::P
8393
by::F
94+
rev::Bool
8495
end
85-
function TruncationKeepAbove(; atol::Real, rtol::Real, p::Real=2, by=abs)
86-
return TruncationKeepAbove(atol, rtol, p, by)
96+
function TruncationByValue(atol::Real, rtol::Real, p::Real=2, by=abs, rev::Bool=true)
97+
return TruncationByValue(promote(atol, rtol)..., p, by, rev)
8798
end
88-
function TruncationKeepAbove(atol::Real, rtol::Real, p::Real=2, by=abs)
89-
return TruncationKeepAbove(promote(atol, rtol)..., p, by)
99+
100+
"""
101+
trunctol(; atol::Real=0, rtol::Real=0, p::Real=2, by=abs, )
102+
103+
Truncation strategy to keep the values that satisfy `by(val) < max(atol, rtol * norm(values, p)`
104+
if `rev = true`, or discard them when `rev = false`.
105+
"""
106+
function trunctol(; atol::Real=0, rtol::Real=0, p::Real=2, by=abs, rev::Bool=true)
107+
return TruncationByValue(atol, rtol, p, by, rev)
90108
end
91109

92110
"""
93-
TruncationKeepBelow(; atol::Real, rtol::Real, p=2, by=abs)
111+
TruncationByError(; atol::Real, rtol::Real, p::Real)
94112
95-
Truncation strategy to discard the values that are smaller than the norm of the values.
113+
Truncation strategy to discard values until the error caused by the discarded values exceeds some tolerances.
114+
See also [`truncerror`](@ref).
96115
"""
97-
struct TruncationKeepBelow{T<:Real,P<:Real,F} <: TruncationStrategy
116+
struct TruncationByError{T<:Real,P<:Real} <: TruncationStrategy
98117
atol::T
99118
rtol::T
100119
p::P
101-
by::F
102-
end
103-
function TruncationKeepBelow(; atol::Real, rtol::Real, p::Real=2, by=abs)
104-
return TruncationKeepBelow(atol, rtol, p, by)
105120
end
106-
function TruncationKeepBelow(atol::Real, rtol::Real, p::Real=2, by=abs)
107-
return TruncationKeepBelow(promote(atol, rtol)..., p, by)
121+
function TruncationError(atol::Real, rtol::Real, p::Real=2)
122+
return TruncationError(promote(atol, rtol)..., p)
108123
end
109124

110125
"""
111-
trunctol(; atol::Real, rtol::Real, p::Real=2, by=abs)
126+
truncerror(; atol::Real=0, rtol::Real=0, p::Real=2)
112127
113-
Truncation strategy to discard all values that satisfy `by(val) < max(atol, rtol * norm(values))`.
128+
Create a truncation strategy for truncating such that the error in the factorization
129+
is smaller than `max(atol, rtol * norm)`, where the error is determined using the `p`-norm.
114130
"""
115-
function trunctol(; atol::Real=0, rtol::Real=0, p::Real=2, by=abs)
116-
return TruncationKeepBelow(; atol, rtol, p, by)
131+
function truncerror(; atol::Real=0, rtol::Real=0, p::Real=2)
132+
return TruncationByError(promote(atol, rtol)..., p)
117133
end
118134

119135
"""
120136
TruncationIntersection(trunc::TruncationStrategy, truncs::TruncationStrategy...)
121137
122138
Composition of multiple truncation strategies, keeping values common between them.
123139
"""
124-
struct TruncationIntersection{T<:Tuple{Vararg{TruncationStrategy}}} <:
125-
TruncationStrategy
140+
struct TruncationIntersection{T<:Tuple{Vararg{TruncationStrategy}}} <: TruncationStrategy
126141
components::T
127142
end
128143
function TruncationIntersection(trunc::TruncationStrategy, truncs::TruncationStrategy...)
@@ -141,31 +156,3 @@ end
141156
function Base.:&(trunc1::TruncationStrategy, trunc2::TruncationIntersection)
142157
return TruncationIntersection((trunc1, trunc2.components...))
143158
end
144-
145-
"""
146-
TruncationError(; atol::Real, rtol::Real, p::Real)
147-
148-
Truncation strategy to discard values until the error caused by the discarded values exceeds some tolerances.
149-
See also [`truncerror`](@ref).
150-
"""
151-
struct TruncationError{T<:Real,P<:Real} <: TruncationStrategy
152-
atol::T
153-
rtol::T
154-
p::P
155-
end
156-
function TruncationError(; atol::Real, rtol::Real, p::Real=2)
157-
return TruncationError(atol, rtol, p)
158-
end
159-
function TruncationError(atol::Real, rtol::Real, p::Real=2)
160-
return TruncationError(promote(atol, rtol)..., p)
161-
end
162-
163-
"""
164-
truncerror(; atol::Real=0, rtol::Real=0, p::Real=2)
165-
166-
Create a truncation strategy for truncating such that the error in the factorization
167-
is smaller than `max(atol, rtol * norm)`, where the error is determined using the `p`-norm.
168-
"""
169-
function truncerror(; atol::Real=0, rtol::Real=0, p::Real=2)
170-
return TruncationError(promote(atol, rtol)..., p)
171-
end

0 commit comments

Comments
 (0)