Skip to content

Commit 5a46d24

Browse files
authored
searchsortedfirst and sample (#208)
* searchsortedfirst and sample * Update Project.toml * test with ∞ domains * BiInfMap
1 parent 9f45d82 commit 5a46d24

File tree

6 files changed

+132
-9
lines changed

6 files changed

+132
-9
lines changed

Project.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ContinuumArrays"
22
uuid = "7ae1f121-cc2c-504b-ac30-9b923412ae5c"
3-
version = "0.19.6"
3+
version = "0.20.0"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
@@ -38,17 +38,21 @@ Infinities = "0.1"
3838
IntervalSets = "0.7"
3939
LazyArrays = "2"
4040
Makie = "0.20, 0.21, 0.22, 0.24"
41-
QuasiArrays = "0.12.2"
41+
QuasiArrays = "0.13"
42+
Random = "1.0"
4243
RecipesBase = "1.0"
4344
StaticArrays = "1.0"
45+
StatsBase = "0.34"
4446
julia = "1.10"
4547

4648
[extras]
4749
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
4850
FastTransforms = "057dd010-8810-581a-b7be-e3fc3b93f78c"
4951
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
52+
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
5053
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
54+
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
5155
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
5256

5357
[targets]
54-
test = ["Base64", "FastTransforms", "RecipesBase", "Makie", "Test"]
58+
test = ["Base64", "FastTransforms", "Makie", "Random", "RecipesBase", "StatsBase", "Test"]

src/ContinuumArrays.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import QuasiArrays: cardinality, checkindex, QuasiAdjoint, QuasiTranspose, Inclu
1919
ApplyQuasiArray, ApplyQuasiMatrix, LazyQuasiArrayApplyStyle, AbstractQuasiArrayApplyStyle, AbstractQuasiLazyLayout,
2020
LazyQuasiArray, LazyQuasiVector, LazyQuasiMatrix, LazyLayout, LazyQuasiArrayStyle, _factorize, _cutdim,
2121
AbstractQuasiFill, UnionDomain, sum_size, sum_layout, _cumsum, cumsum_layout, applylayout, equals_layout, layout_broadcasted, PolynomialLayout, dot_size,
22-
diff_layout, diff_size, AbstractQuasiVecOrMat, vec_layout
22+
diff_layout, diff_size, AbstractQuasiVecOrMat, vec_layout, searchsortedfirst_layout
2323
import InfiniteArrays: Infinity, InfAxes
2424
import AbstractFFTs: Plan
2525

@@ -122,4 +122,6 @@ function copy(d::Dot{<:ExpansionLayout,<:ExpansionLayout,<:AbstractQuasiArray,<:
122122
c' * (P'Q) * d
123123
end
124124

125+
include("sort.jl")
126+
125127
end

src/maps.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ Base.union(d::Map) = axes(invmap(d),1)
2222
for find in (:findfirst, :findlast)
2323
@eval function $find(f::Base.Fix2{typeof(isequal)}, d::Map)
2424
f.x in d || return nothing
25-
$find(isequal(invmap(d)[f.x]), union(d))
25+
$find(isequal(invmap(d)[f.x]), axes(d,1))
2626
end
2727
end
2828

2929
@eval function findall(f::Base.Fix2{typeof(isequal)}, d::Map)
3030
f.x in d || return eltype(axes(d,1))[]
31-
findall(isequal(invmap(d)[f.x]), union(d))
31+
findall(isequal(invmap(d)[f.x]), axes(d,1))
3232
end
3333

3434
function Base.getindex(d::Map, x::Inclusion)

src/sort.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# gives a generalization of midpoint for when `a` or `b` is infinite
2+
function genmidpoint(a::T, b::T) where T
3+
if isinf(a) && isinf(b)
4+
zero(T)
5+
elseif isinf(a)
6+
b - 100
7+
elseif isinf(b)
8+
a + 100
9+
else
10+
(a+b)/2
11+
end
12+
end
13+
14+
15+
function searchsortedfirst_layout(::ExpansionLayout, f, x; iterations=47)
16+
d = axes(f,1)
17+
a,b = first(d), last(d)
18+
19+
for k=1:iterations #TODO: decide 47
20+
m= genmidpoint(a,b)
21+
(f[m] x) ? (a = m) : (b = m)
22+
end
23+
(a+b)/2
24+
end
25+
26+

test/test_chebyshev.jl

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,37 @@ Base.getindex(d::InvQuadraticMap, x::Number) = sqrt((x+1)/2)
5858
ContinuumArrays.invmap(::QuadraticMap{T}) where T = InvQuadraticMap{T}()
5959
ContinuumArrays.invmap(::InvQuadraticMap{T}) where T = QuadraticMap{T}()
6060

61+
struct InfMap{T} <: Map{T}
62+
s
63+
end
64+
struct InvInfMap{T} <: Map{T}
65+
s
66+
end
67+
68+
InfMap(s=1) = InfMap{Float64}(s)
69+
InvInfMap(s=1) = InvInfMap{Float64}(s)
70+
71+
Base.getindex(m::InfMap, r::Number) = 1-2/(m.s * r+1)
72+
Base.axes(m::InfMap{T}) where T = (Inclusion(m.s * (0..Inf)),)
73+
Base.axes(::InvInfMap{T}) where T = (Inclusion(-1..1),)
74+
Base.getindex(m::InvInfMap, x::Number) = m.s*( 2/(1-x) - 1)
75+
ContinuumArrays.invmap(m::InfMap{T}) where T = InvInfMap{T}(m.s)
76+
ContinuumArrays.invmap(m::InvInfMap{T}) where T = InfMap{T}(m.s)
77+
78+
struct BiInfMap{T} <: Map{T} end
79+
struct InvBiInfMap{T} <: Map{T} end
80+
81+
BiInfMap() = BiInfMap{Float64}()
82+
InvBiInfMap() = InvBiInfMap{Float64}()
83+
84+
Base.getindex(m::BiInfMap, y::Number) = iszero(y) ? y : (-1 + sqrt(1 + 4y^2))/(2y)
85+
Base.axes(m::BiInfMap{T}) where T = (Inclusion(-Inf..Inf),)
86+
Base.axes(::InvBiInfMap{T}) where T = (Inclusion(-1..1),)
87+
Base.getindex(m::InvBiInfMap, x::Number) = x/(1-x^2)
88+
ContinuumArrays.invmap(m::BiInfMap{T}) where T = InvBiInfMap{T}()
89+
ContinuumArrays.invmap(m::InvBiInfMap{T}) where T = BiInfMap{T}()
90+
91+
6192
struct FooDomain end
6293

6394
struct FooBasis <: Basis{Float64} end
@@ -146,6 +177,52 @@ Base.:(==)(::FooBasis, ::FooBasis) = true
146177
@test x == Inclusion(0..1)
147178
@test M \ exp.(x) T \ exp.(sqrt.((axes(T,1) .+ 1)/2))
148179
end
180+
181+
@testset "InvMap" begin
182+
m = InfMap()
183+
mi = InvInfMap()
184+
@test 0.1 m
185+
@test -0.1 m
186+
@test 2 m
187+
@test 2 mi
188+
@test 0.1 mi
189+
@test -0.1 mi
190+
191+
@test m[findfirst(isequal(0.1), m)] 0.1
192+
@test m[findlast(isequal(0.1), m)] 0.1
193+
@test m[findall(isequal(0.1), m)] [0.1]
194+
195+
@test m[Inclusion(0..Inf)] m
196+
@test_throws BoundsError m[Inclusion(-1..1)]
197+
T = Chebyshev(5)
198+
M = T[m,:]
199+
@test MemoryLayout(M) isa MappedBasisLayout
200+
@test MemoryLayout(M[:,1:3]) isa MappedBasisLayout
201+
@test M[0.1,:] T[1-2/(0.1+1),:]
202+
x = axes(M,1)
203+
@test x == Inclusion(0..Inf)
204+
@test M \ exp.(-x) T \ exp.(-(2 ./ (1 .- axes(T,1)) .- 1))
205+
206+
f = M/M\(1 .- exp.(-x))
207+
@test f[0.1] 1 - exp(-0.1) atol=1E-2
208+
209+
@test f[searchsortedfirst(f, 0.5)] 0.5
210+
211+
M = T[InfMap(-1),:]
212+
@test axes(M,1) == Inclusion(-Inf .. 0)
213+
x = axes(M,1)
214+
f = M/M\(exp.(x))
215+
@test f[-0.1] exp(-0.1) atol=1E-2
216+
@test f[searchsortedfirst(f, 0.5)] 0.5
217+
218+
M = T[BiInfMap(),:]
219+
@test axes(M,1) == Inclusion(-Inf .. Inf)
220+
x = axes(M,1)
221+
f = M/M\(atan.(x))
222+
@test f[-0.1] atan(-0.1) atol=1E-2
223+
@test f[0] 0 atol=1E-10
224+
@test f[searchsortedfirst(f, 0.5)] 0.5
225+
end
149226
end
150227

151228
@testset "Broadcasted" begin
@@ -173,7 +250,7 @@ Base.:(==)(::FooBasis, ::FooBasis) = true
173250
@test (2T)'*(T*(1:5)) T'*(2T*(1:5)) T'BroadcastQuasiMatrix(*, 2, T*(1:5))
174251
@test T' * (a .* (T * (1:5))) T' * ((a .* T) * (1:5))
175252
@test T'BroadcastQuasiMatrix(*, 2, 2T) == 4*(T'T)
176-
253+
177254
@test LazyArrays.simplifiable(*, T', T*(1:5)) == Val(true)
178255
@test LazyArrays.simplifiable(*, T', (a .* (T * (1:5)))) == Val(true)
179256
@test LazyArrays.simplifiable(*, T', a .* T) == Val(true)
@@ -209,6 +286,6 @@ Base.:(==)(::FooBasis, ::FooBasis) = true
209286

210287
@testset "Adjoint*Basis not defined" begin
211288
@test_throws ErrorException Chebyshev(5)'LinearSpline([-1,1])
212-
@test_throws ErrorException FooBasis()'FooBasis()
289+
@test_throws ErrorException FooBasis()'FooBasis()
213290
end
214291
end

test/test_splines.jl

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
using ContinuumArrays, LinearAlgebra, Base64, FillArrays, QuasiArrays, BandedMatrices, BlockArrays, Test
1+
using ContinuumArrays, LinearAlgebra, Base64, FillArrays, QuasiArrays, BandedMatrices, BlockArrays, StatsBase, Random, Test
22
using QuasiArrays: ApplyQuasiArray, ApplyStyle, MemoryLayout, mul, MulQuasiMatrix, Vec
33
import LazyArrays: MulStyle, LdivStyle, arguments, applied, apply, simplifiable
44
import ContinuumArrays: basis, AdjointBasisLayout, ExpansionLayout, BasisLayout, SubBasisLayout, AdjointMappedBasisLayouts, MappedBasisLayout, plan_grid_transform, weaklaplacian
55

6+
Random.seed!(24543)
7+
68
@testset "Splines" begin
79
@testset "HeavisideSpline" begin
810
H = HeavisideSpline([1,2,3])
@@ -671,4 +673,16 @@ import ContinuumArrays: basis, AdjointBasisLayout, ExpansionLayout, BasisLayout,
671673
@test F[:,1:2][0.1,:] F[0.1,1:2]
672674
end
673675
end
676+
677+
@testset "searchsortedfirst" begin
678+
L = LinearSpline(range(-1,1,1000))
679+
f = expand(L, exp)
680+
@test searchsortedfirst(f, 1) 0 atol=1E-6
681+
end
682+
683+
@testset "sample" begin
684+
H = HeavisideSpline(range(0,1,1000))
685+
f = expand(H, exp)
686+
@test mean(sample(f, 1000)) 1/(ℯ-1) atol=1E-1
687+
end
674688
end

0 commit comments

Comments
 (0)