Skip to content

Commit f930625

Browse files
committed
implement cf for (Symmetric)AlphaStable
1 parent c199d9b commit f930625

File tree

2 files changed

+80
-12
lines changed

2 files changed

+80
-12
lines changed

src/AlphaStableDistributions.jl

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ Base.@kwdef struct AlphaStable{T} <: Distributions.ContinuousUnivariateDistribut
1515
end
1616

1717
AlphaStable::Integer, β::Integer, scale::Integer, location::Integer) = AlphaStable(float(α), float(β), float(scale), float(location))
18-
18+
function AlphaStable(α,β,scale,location)
19+
αT,βT,scaleT,locationT = promote(α,β,scale,location)
20+
AlphaStable(αT,βT,scaleT,locationT)
21+
end
22+
Distributions.params(d::AlphaStable) = (d.α, d.β, d.scale, d.location)
1923

2024
# sampler(d::AlphaStable) = error("Not implemented")
2125
# pdf(d::AlphaStable, x::Real) = error("Not implemented")
@@ -33,7 +37,17 @@ Statistics.var(d::AlphaStable) = d.α == 2 ? 2d.scale^2 : Inf
3337
# kurtosis(d::Distribution, ::Bool) = error("Not implemented")
3438
# entropy(d::AlphaStable, ::Real) = error("Not implemented")
3539
# mgf(d::AlphaStable, ::Any) = error("Not implemented")
36-
# cf(d::AlphaStable, ::Any) = error("Not implemented")
40+
41+
function Distributions.cf(d::AlphaStable{S}, t::Real) where {S}
42+
T = float(promote_type(S, typeof(t)))
43+
α,β,c,δ = params(d)
44+
Φ = if α == one(α)
45+
T(-2/π * log(abs(t)))
46+
else
47+
T(tan*α/2))
48+
end
49+
exp(im*t*δ - abs(c*t)^α * (1 - im*β*sign(t)*Φ))
50+
end
3751

3852
# lookup tables from McCulloch (1986)
3953
const _ena = [
@@ -220,6 +234,12 @@ Base.@kwdef struct SymmetricAlphaStable{T} <: Distributions.ContinuousUnivariate
220234
scale::T = one(α)
221235
location::T = zero(α)
222236
end
237+
Distributions.params(d::SymmetricAlphaStable) = (d.α, d.scale, d.location)
238+
Distributions.cf(d::SymmetricAlphaStable, t::Real) = cf(AlphaStable(d), t)
239+
240+
function AlphaStable(d::SymmetricAlphaStable)
241+
AlphaStable=d.α,scale=d.scale,location=d.location)
242+
end
223243

224244
"""
225245
fit(d::Type{<:SymmetricAlphaStable}, x; alg=QuickSort)
@@ -465,4 +485,4 @@ function Distributions.fit(d::Type{<:AlphaSubGaussian}, x::AbstractVector{T}, m:
465485
AlphaSubGaussian=α, R=cov, n=length(x))
466486
end
467487

468-
end # module
488+
end # module

test/runtests.jl

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,65 @@
11
using AlphaStableDistributions
22
using Test, Random, Distributions
33

4-
@testset "AlphaStableDistributions.jl" begin
4+
@testset "cf" begin
5+
rng = MersenneTwister(1)
6+
for _ in 1:100
7+
d = AlphaStable(
8+
α=rand(rng,Uniform(0,10)),
9+
β=rand(rng,Uniform(-1,1)),
10+
scale=rand(rng,Uniform(0,10)),
11+
location=rand(rng,Uniform(0,10)),
12+
)
13+
@test cf(d,0) 1
14+
x = rand(rng,Uniform(-10,10))
15+
@test abs(cf(d, x)) <= 1
16+
17+
d32 = AlphaStable(Float32.(Distributions.params(d))...)
18+
@test cf(d32, Float32(x)) isa Complex{Float32}
19+
@test cf(d32, Float32(x)) cf(d,x) atol=100*eps(Float32)
20+
end
21+
xs = range(-1,1,length=100)
22+
d1 = SymmetricAlphaStable=2.0, scale=1/sqrt(2), location=0.0)
23+
d2 = AlphaStable(d1)
24+
d_ref = Normal(0.0,1.0)
25+
@test cf.(Ref(d1),xs) cf.(Ref(d_ref),xs)
26+
@test cf.(Ref(d2),xs) cf.(Ref(d_ref),xs)
27+
28+
xs = range(-10,10,length=100)
29+
d1 = SymmetricAlphaStable=1.0, scale=1.0, location=0.0)
30+
d2 = AlphaStable(d1)
31+
d_ref = Cauchy(0.0,1.0)
32+
@test cf.(Ref(d1),xs) cf.(Ref(d_ref),xs)
33+
@test cf.(Ref(d2),xs) cf.(Ref(d_ref),xs)
34+
35+
d1 = SymmetricAlphaStable=1.0, scale=17.9, location=42.0)
36+
d2 = AlphaStable(d1)
37+
d_ref = Cauchy(42.0,17.9)
38+
@test cf.(Ref(d1),xs) cf.(Ref(d_ref),xs)
39+
@test cf.(Ref(d2),xs) cf.(Ref(d_ref),xs)
40+
41+
d1 = AlphaStable=1/2, β=1.0, scale=12.0, location=-7.2)
42+
d_ref = Levy(-7.2, 12.0)
43+
@test cf.(Ref(d1),xs) cf.(Ref(d_ref),xs)
544

45+
@test @inferred(cf(AlphaStable= 1.0) , 1.0)) isa Complex{Float64}
46+
@test @inferred(cf(AlphaStable= 1 ) , 1 )) isa Complex{Float64}
47+
@test @inferred(cf(AlphaStable= 1.0) , 1f0)) isa Complex{Float64}
48+
@test @inferred(cf(AlphaStable= 1f0) , 1 )) isa Complex{Float32}
49+
@test @inferred(cf(AlphaStable= 1f0) , 1f0)) isa Complex{Float32}
50+
end
51+
52+
53+
@testset "AlphaStableDistributions.jl" begin
54+
rng = MersenneTwister(0)
655
sampletypes = [Float32,Float64]
756
stabletypes = [AlphaStable,SymmetricAlphaStable]
857
αs = [0.6:0.1:2,1:0.1:2]
958
for sampletype sampletypes
1059
for (i, stabletype) in enumerate(stabletypes)
1160
for α in αs[i]
1261
d1 = AlphaStable=sampletype(α))
13-
s = rand(d1, 200000)
62+
s = rand(rng,d1, 200000)
1463
@test eltype(s) == sampletype
1564

1665
d2 = fit(stabletype, s)
@@ -22,14 +71,14 @@ using Test, Random, Distributions
2271
@test d1.location d2.location atol=0.1
2372
end
2473

25-
xnormal = rand(Normal(3.0, 4.0), 96000)
74+
xnormal = rand(rng,Normal(3.0, 4.0), 96000)
2675
d = fit(stabletype, xnormal)
2776
@test d.α 2 rtol=0.2
2877
stabletype != SymmetricAlphaStable && @test d.β 0 atol=0.2
2978
@test d.scale 4/√2 rtol=0.2
3079
@test d.location 3 rtol=0.1
3180

32-
xcauchy = rand(Cauchy(3.0, 4.0), 96000)
81+
xcauchy = rand(rng,Cauchy(3.0, 4.0), 96000)
3382
d = fit(stabletype, xcauchy)
3483
@test d.α 1 rtol=0.2
3584
stabletype != SymmetricAlphaStable && @test d.β 0 atol=0.2
@@ -40,9 +89,9 @@ using Test, Random, Distributions
4089

4190
for α in 1.1:0.1:1.9
4291
d = AlphaSubGaussian=α, n=96000)
43-
x = rand(d)
92+
x = rand(rng,d)
4493
x2 = copy(x)
45-
rand!(d, x2)
94+
rand!(rng,d, x2)
4695
@test x != x2
4796

4897
d3 = fit(AlphaStable, x)
@@ -54,13 +103,12 @@ using Test, Random, Distributions
54103

55104
d4 = AlphaSubGaussian=1.5, n=96000)
56105
m = size(d4.R, 1) - 1
57-
x = rand(d4)
106+
x = rand(rng,d4)
58107
d5 = fit(AlphaSubGaussian, x, m, p=1.0)
59108
@test d4.α d5.α rtol=0.1
60109
@test d4.R d5.R rtol=0.1
61110

62111
end
63-
64112
# 362.499 ms (4620903 allocations: 227.64 MiB)
65113
# 346.520 ms (4621052 allocations: 209.62 MiB) # StaticArrays in outer fun
66114
# 345.925 ms (4225524 allocations: 167.66 MiB) # tempind to tuple
@@ -114,4 +162,4 @@ end
114162
# d1 = AlphaStable(α=1.5)
115163
# s = rand(d1, 100000)
116164
# using ThreadsX
117-
# @btime fit($AlphaStable, $s, $ThreadsX.MergeSort)
165+
# @btime fit($AlphaStable, $s, $ThreadsX.MergeSort)

0 commit comments

Comments
 (0)