Skip to content

Commit e74ba97

Browse files
committed
Merge branch 'master' into dw/pairwise
2 parents af79de7 + 837d312 commit e74ba97

File tree

9 files changed

+173
-1
lines changed

9 files changed

+173
-1
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Distributions"
22
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
33
authors = ["JuliaStats"]
4-
version = "0.25.28"
4+
version = "0.25.29"
55

66
[deps]
77
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"

docs/src/univariate.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,13 @@ LogNormal
327327
plotdensity((0, 5), LogNormal, (0, 1)) # hide
328328
```
329329

330+
```@docs
331+
LogUniform
332+
```
333+
```@example plotdensity
334+
plotdensity((0, 11), LogUniform, (1, 10)) # hide
335+
```
336+
330337
```@docs
331338
NoncentralBeta
332339
```

src/Distributions.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export
118118
LocationScale,
119119
Logistic,
120120
LogNormal,
121+
LogUniform,
121122
LogitNormal,
122123
MatrixBeta,
123124
MatrixFDist,

src/truncate.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,4 @@ _use_multline_show(d::Truncated) = _use_multline_show(d.untruncated)
172172
include(joinpath("truncated", "normal.jl"))
173173
include(joinpath("truncated", "exponential.jl"))
174174
include(joinpath("truncated", "uniform.jl"))
175+
include(joinpath("truncated", "loguniform.jl"))

src/truncated/loguniform.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
truncated(d::LogUniform, lo::T, hi::T) where {T<:Real} = LogUniform(max(d.a, lo), min(d.b, hi))
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
LogUniform(a,b)
3+
4+
A positive random variable `X` is log-uniformly with parameters `a` and `b` if the logarithm of `X` is `Uniform(log(a), log(b))`.
5+
The *log uniform* distribution is also known as *reciprocal distribution*.
6+
```julia
7+
LogUniform(1,10)
8+
```
9+
External links
10+
11+
* [Log uniform distribution on Wikipedia](https://en.wikipedia.org/wiki/Reciprocal_distribution)
12+
"""
13+
struct LogUniform{T<:Real} <: ContinuousUnivariateDistribution
14+
a::T
15+
b::T
16+
LogUniform{T}(a::T, b::T) where {T <: Real} = new{T}(a, b)
17+
end
18+
19+
function LogUniform(a::T, b::T; check_args=true) where {T <: Real}
20+
check_args && @check_args(LogUniform, 0 < a < b)
21+
LogUniform{T}(a, b)
22+
end
23+
24+
LogUniform(a::Real, b::Real; kwargs...) = LogUniform(promote(a, b)...; kwargs...)
25+
26+
convert(::Type{LogUniform{T}}, d::LogUniform) where {T<:Real} = LogUniform(T(d.a), T(d.b))
27+
Base.minimum(d::LogUniform) = d.a
28+
Base.maximum(d::LogUniform) = d.b
29+
30+
#### Parameters
31+
params(d::LogUniform) = (d.a, d.b)
32+
partype(::LogUniform{T}) where {T<:Real} = T
33+
34+
#### Statistics
35+
36+
function mean(d::LogUniform)
37+
a, b = params(d)
38+
(b - a) / log(b/a)
39+
end
40+
function var(d::LogUniform)
41+
a, b = params(d)
42+
log_ba = log(b/a)
43+
(b^2 - a^2) / (2*log_ba) - ((b-a)/ log_ba)^2
44+
end
45+
mode(d::LogUniform) = d.a
46+
modes(d::LogUniform) = partype(d)[]
47+
48+
function entropy(d::LogUniform)
49+
a,b = params(d)
50+
log(a * b) / 2 + log(log(b / a))
51+
end
52+
#### Evaluation
53+
function pdf(d::LogUniform, x::Real)
54+
x1, a, b = promote(x, params(d)...) # ensure e.g. pdf(LogUniform(1,2), 1f0)::Float32
55+
res = inv(x1 * log(b / a))
56+
return insupport(d, x1) ? res : zero(res)
57+
end
58+
function cdf(d::LogUniform, x::Real)
59+
x1, a, b = promote(x, params(d)...) # ensure e.g. cdf(LogUniform(1,2), 1f0)::Float32
60+
x1 = clamp(x1, a, b)
61+
return log(x1 / a) / log(b / a)
62+
end
63+
logpdf(d::LogUniform, x::Real) = log(pdf(d,x))
64+
65+
function quantile(d::LogUniform, p::Real)
66+
p1,a,b = promote(p, params(d)...) # ensure e.g. quantile(LogUniform(1,2), 1f0)::Float32
67+
exp(p1 * log(b/a)) * a
68+
end
69+
70+
function kldivergence(p::LogUniform, q::LogUniform)
71+
ap, bp, aq, bq = promote(params(p)..., params(q)...)
72+
finite = aq <= ap < bp <= bq
73+
res = log(log(bq / aq) / log(bp / ap))
74+
return finite ? res : oftype(res, Inf)
75+
end

src/univariates.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,7 @@ const continuous_distributions = [
716716
"triangular",
717717
"triweight",
718718
"uniform",
719+
"loguniform", # depends on Uniform
719720
"vonmises",
720721
"weibull"
721722
]

test/loguniform.jl

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
module TestLogUniform
2+
using Test
3+
using Distributions
4+
import Random
5+
6+
@testset "LogUniform" begin
7+
rng = Random.MersenneTwister(0)
8+
9+
@test pdf(LogUniform(1f0, 2f0), 1) isa Float32
10+
@test pdf(LogUniform(1, 2), 1f0) isa Float32
11+
@test pdf(LogUniform(1, 2), 1) isa Float64
12+
@test quantile(LogUniform(1, 2), 1) isa Float64
13+
@test quantile(LogUniform(1, 2), 1f0) isa Float32
14+
@testset "$f" for f in [pdf, cdf, quantile, logpdf, logcdf]
15+
@test @inferred(f(LogUniform(1,2), 1)) isa Float64
16+
@test @inferred(f(LogUniform(1,2), 1.0)) isa Float64
17+
@test @inferred(f(LogUniform(1.0,2), 1.0)) isa Float64
18+
@test @inferred(f(LogUniform(1.0f0,2), 1)) isa Float32
19+
@test @inferred(f(LogUniform(1.0f0,2), 1f0)) isa Float32
20+
@test @inferred(f(LogUniform(1,2), 1f0)) isa Float32
21+
end
22+
23+
d = LogUniform(1,10)
24+
@test eltype(d) === Float64
25+
@test 1 <= rand(rng, d) <= 10
26+
@test rand(rng, d) isa eltype(d)
27+
@test @inferred(quantile(d, 0)) 1
28+
@test quantile(d, 0.5) sqrt(10) # geomean
29+
@test quantile(d, 1) 10
30+
@test mode(d) 1
31+
@test !insupport(d, 0)
32+
@test @inferred(minimum(d)) === 1
33+
@test @inferred(maximum(d)) === 10
34+
@test partype(d) === Int
35+
@test truncated(d, 2, 14) === LogUniform(2,10)
36+
37+
# numbers obtained by calling scipy.stats.loguniform
38+
@test @inferred(std(d) ) 2.49399867607628
39+
@test @inferred(mean(d) ) 3.908650337129266
40+
@test @inferred(pdf(d, 1.0001)) 0.43425105679757203
41+
@test @inferred(pdf(d, 5 )) 0.08685889638065035
42+
@test @inferred(pdf(d, 9.9999)) 0.04342988248915007
43+
@test @inferred(cdf(d, 1.0001)) 4.342727686266485e-05
44+
@test @inferred(cdf(d, 5 )) 0.6989700043360187
45+
@test @inferred(cdf(d, 9.9999)) 0.999995657033466
46+
@test @inferred(median(d) ) 3.1622776601683795
47+
@test @inferred(logpdf(d, 5) ) -2.443470357682056
48+
49+
for _ in 1:10
50+
lo = rand(rng)
51+
hi = lo + 10*rand(rng)
52+
dist = LogUniform(lo,hi)
53+
q = rand(rng)
54+
@test cdf(dist, quantile(dist, q)) q
55+
56+
u = Uniform(log(lo), log(hi))
57+
@test exp(quantile(u, q)) quantile(dist, q)
58+
@test exp(median(u)) median(dist)
59+
x = rand(rng, dist)
60+
@test cdf(u, log(x)) cdf(dist, x)
61+
62+
@test @inferred(entropy(dist)) Distributions.expectation(dist, x->-logpdf(dist,x))
63+
end
64+
65+
@test kldivergence(LogUniform(1,2), LogUniform(1,2)) 0 atol=100eps(Float64)
66+
@test isfinite(kldivergence(LogUniform(1,2), LogUniform(1,10)))
67+
@test kldivergence(LogUniform(1.1,10), LogUniform(1,2)) === Inf
68+
@test kldivergence(LogUniform(0.1,10), LogUniform(1,2)) === Inf
69+
@test kldivergence(LogUniform(0.1,1), LogUniform(1,2)) === Inf
70+
@test @inferred(kldivergence(LogUniform(0.1f0,1), LogUniform(1,2))) === Inf32
71+
72+
for _ in 1:10
73+
aq = 10*rand(rng)
74+
ap = aq + 10*rand(rng)
75+
bp = ap + 10*rand(rng)
76+
bq = bp + 10*rand(rng)
77+
p = LogUniform(ap, bp)
78+
q = LogUniform(aq, bq)
79+
@test @inferred(kldivergence(p, q))
80+
kldivergence(Uniform(log(ap), log(bp)), Uniform(log(aq), log(bq)))
81+
end
82+
end
83+
84+
85+
end#module

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import JSON
1111
import ForwardDiff
1212

1313
const tests = [
14+
"loguniform",
1415
"arcsine",
1516
"dirac",
1617
"truncate",

0 commit comments

Comments
 (0)