Skip to content

Commit 8345f1c

Browse files
authored
Merge branch 'master' into dw/quantile_types
2 parents 74d0feb + a1010e4 commit 8345f1c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+749
-399
lines changed

.github/workflows/CI.yml

+14-21
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ name: CI
22

33
on:
44
pull_request:
5-
branches:
6-
- master
75
push:
86
branches:
97
- master
108
tags: '*'
9+
workflow_dispatch:
10+
merge_group:
1111

1212
concurrency:
1313
# Skip intermediate builds: always.
@@ -17,38 +17,28 @@ concurrency:
1717

1818
jobs:
1919
test:
20-
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
20+
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ github.event_name }}
2121
runs-on: ${{ matrix.os }}
22-
continue-on-error: ${{ matrix.version == 'nightly' }}
2322
strategy:
2423
fail-fast: false
2524
matrix:
2625
version:
2726
- '1.3'
2827
- '1'
29-
- 'nightly'
28+
- pre
3029
os:
3130
- ubuntu-latest
3231
- macos-latest
3332
- windows-latest
34-
arch:
35-
- x64
3633
steps:
3734
- uses: actions/checkout@v4
38-
- uses: julia-actions/setup-julia@v1
35+
- uses: julia-actions/setup-julia@v2
3936
with:
4037
version: ${{ matrix.version }}
41-
arch: ${{ matrix.arch }}
42-
- uses: actions/cache@v3
43-
env:
44-
cache-name: cache-artifacts
45-
with:
46-
path: ~/.julia/artifacts
47-
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
48-
restore-keys: |
49-
${{ runner.os }}-test-${{ env.cache-name }}-
50-
${{ runner.os }}-test-
51-
${{ runner.os }}-
38+
# ARM64 on macos-latest is neither supported by older Julia versions nor setup-julia
39+
arch: ${{ matrix.os == 'macos-latest' && matrix.version != '1.3' && 'aarch64' || 'x64' }}
40+
show-versioninfo: true
41+
- uses: julia-actions/cache@v2
5242
- uses: julia-actions/julia-buildpkg@v1
5343
- uses: julia-actions/julia-runtest@v1
5444
- run: |
@@ -57,17 +47,20 @@ jobs:
5747
Pkg.instantiate()'
5848
- run: julia --project=perf perf/samplers.jl
5949
- uses: julia-actions/julia-processcoverage@v1
60-
- uses: codecov/codecov-action@v3
50+
- uses: codecov/codecov-action@v4
6151
with:
52+
token: ${{ secrets.CODECOV_TOKEN }} # required
53+
fail_ci_if_error: true
6254
files: lcov.info
6355
docs:
6456
name: Documentation
6557
runs-on: ubuntu-latest
6658
steps:
6759
- uses: actions/checkout@v4
68-
- uses: julia-actions/setup-julia@v1
60+
- uses: julia-actions/setup-julia@v2
6961
with:
7062
version: '1'
63+
show-versioninfo: true
7164
- run: |
7265
julia --project=docs -e '
7366
using Pkg

.github/workflows/IntegrationTest.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232

3333
steps:
3434
- uses: actions/checkout@v4
35-
- uses: julia-actions/setup-julia@v1
35+
- uses: julia-actions/setup-julia@v2
3636
with:
3737
version: 1
3838
arch: x64

Project.toml

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
name = "Distributions"
22
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
33
authors = ["JuliaStats"]
4-
version = "0.25.103"
4+
version = "0.25.112"
55

66
[deps]
7+
AliasTables = "66dad0bd-aa9a-41b7-9441-69ab47430ed8"
78
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
89
DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
910
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
@@ -30,15 +31,27 @@ DistributionsDensityInterfaceExt = "DensityInterface"
3031
DistributionsTestExt = "Test"
3132

3233
[compat]
34+
AliasTables = "1"
35+
Aqua = "0.8"
36+
Calculus = "0.5"
3337
ChainRulesCore = "1"
38+
ChainRulesTestUtils = "1"
3439
DensityInterface = "0.4"
40+
Distributed = "<0.0.1, 1"
3541
FillArrays = "0.9, 0.10, 0.11, 0.12, 0.13, 1"
42+
FiniteDifferences = "0.12"
43+
ForwardDiff = "0.10"
44+
JSON = "0.21"
3645
LinearAlgebra = "<0.0.1, 1"
46+
OffsetArrays = "1"
3747
PDMats = "0.10, 0.11"
3848
Printf = "<0.0.1, 1"
3949
QuadGK = "2"
4050
Random = "<0.0.1, 1"
51+
SparseArrays = "<0.0.1, 1"
4152
SpecialFunctions = "1.2, 2"
53+
StableRNGs = "1"
54+
StaticArrays = "1"
4255
Statistics = "1"
4356
StatsAPI = "1.6"
4457
StatsBase = "0.32, 0.33, 0.34"
@@ -47,6 +60,7 @@ Test = "<0.0.1, 1"
4760
julia = "1.3"
4861

4962
[extras]
63+
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
5064
Calculus = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
5165
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
5266
ChainRulesTestUtils = "cdddcdb0-9152-4a09-a978-84456f9df70a"
@@ -62,4 +76,4 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
6276
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
6377

6478
[targets]
65-
test = ["StableRNGs", "Calculus", "ChainRulesCore", "ChainRulesTestUtils", "DensityInterface", "Distributed", "FiniteDifferences", "ForwardDiff", "JSON", "SparseArrays", "StaticArrays", "Test", "OffsetArrays"]
79+
test = ["Aqua", "StableRNGs", "Calculus", "ChainRulesCore", "ChainRulesTestUtils", "DensityInterface", "Distributed", "FiniteDifferences", "ForwardDiff", "JSON", "SparseArrays", "StaticArrays", "Test", "OffsetArrays"]

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Distributions.jl
44
[![Build Status](https://github.com/JuliaStats/Distributions.jl/workflows/CI/badge.svg)](https://github.com/JuliaStats/Distributions.jl/actions)
55
[![](https://zenodo.org/badge/DOI/10.5281/zenodo.2647458.svg)](https://zenodo.org/record/2647458)
66
[![Coverage Status](https://coveralls.io/repos/JuliaStats/Distributions.jl/badge.svg?branch=master)](https://coveralls.io/r/JuliaStats/Distributions.jl?branch=master)
7+
[![Aqua QA](https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg)](https://github.com/JuliaTesting/Aqua.jl)
78

89
[![](https://img.shields.io/badge/docs-latest-blue.svg)](https://JuliaStats.github.io/Distributions.jl/latest/)
910
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaStats.github.io/Distributions.jl/stable/)

docs/Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
44

55
[compat]
66
Documenter = "0.26, 0.27"
7-
GR = "0.72.1"
7+
GR = "0.72.1, 0.73"

docs/src/fit.md

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ The function `fit_mle` is for maximum likelihood estimation.
2727
### Synopsis
2828

2929
```@docs
30+
fit(D, x)
31+
fit(D, x, w)
3032
fit_mle(D, x)
3133
fit_mle(D, x, w)
3234
```

src/Distributions.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import PDMats: dim, PDMat, invquad
2727
using SpecialFunctions
2828
using Base.MathConstants: eulergamma
2929

30+
import AliasTables
31+
3032
export
3133
# re-export Statistics
3234
mean, median, quantile, std, var, cov, cor,
@@ -127,7 +129,6 @@ export
127129
MatrixBeta,
128130
MatrixFDist,
129131
MatrixNormal,
130-
MatrixReshaped,
131132
MatrixTDist,
132133
MixtureModel,
133134
Multinomial,
@@ -365,7 +366,7 @@ Supported distributions:
365366
NoncentralF, NoncentralHypergeometric, NoncentralT, Normal, NormalCanon,
366367
NormalInverseGaussian, Pareto, PGeneralizedGaussian, Poisson, PoissonBinomial,
367368
QQPair, Rayleigh, Rician, Skellam, Soliton, StudentizedRange, SymTriangularDist, TDist, TriangularDist,
368-
Triweight, Truncated, TruncatedNormal, Uniform, UnivariateGMM,
369+
Triweight, Truncated, Uniform, UnivariateGMM,
369370
VonMises, VonMisesFisher, WalleniusNoncentralHypergeometric, Weibull,
370371
Wishart, ZeroMeanIsoNormal, ZeroMeanIsoNormalCanon,
371372
ZeroMeanDiagNormal, ZeroMeanDiagNormalCanon, ZeroMeanFullNormal,

src/censored.jl

+1
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ _in_open_interval(x::Real, l::Real, ::Nothing) = x > l
431431
_clamp(x, l, u) = clamp(x, l, u)
432432
_clamp(x, ::Nothing, u) = min(x, u)
433433
_clamp(x, l, ::Nothing) = max(x, l)
434+
_clamp(x, ::Nothing, u::Nothing) = x
434435

435436
_to_truncated(d::Censored) = truncated(d.uncensored, d.lower, d.upper)
436437

src/common.jl

+51-56
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,25 @@ usually it is sufficient to implement `logpdf`.
212212
See also: [`logpdf`](@ref).
213213
"""
214214
@inline function pdf(
215-
d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:Real,N}
216-
) where {N}
217-
@boundscheck begin
218-
size(x) == size(d) ||
219-
throw(DimensionMismatch("inconsistent array dimensions"))
215+
d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:Real,M}
216+
) where {N,M}
217+
if M == N
218+
@boundscheck begin
219+
size(x) == size(d) ||
220+
throw(DimensionMismatch("inconsistent array dimensions"))
221+
end
222+
return _pdf(d, x)
223+
else
224+
@boundscheck begin
225+
M > N ||
226+
throw(DimensionMismatch(
227+
"number of dimensions of the variates ($M) must be greater than or equal to the dimension of the distribution ($N)"
228+
))
229+
ntuple(i -> size(x, i), Val(N)) == size(d) ||
230+
throw(DimensionMismatch("inconsistent array dimensions"))
231+
end
232+
return @inbounds map(Base.Fix1(pdf, d), eachvariate(x, variate_form(typeof(d))))
220233
end
221-
return _pdf(d, x)
222234
end
223235

224236
function _pdf(d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:Real,N}) where {N}
@@ -241,13 +253,25 @@ size of `x`.
241253
See also: [`pdf`](@ref).
242254
"""
243255
@inline function logpdf(
244-
d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:Real,N}
245-
) where {N}
246-
@boundscheck begin
247-
size(x) == size(d) ||
248-
throw(DimensionMismatch("inconsistent array dimensions"))
256+
d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:Real,M}
257+
) where {N,M}
258+
if M == N
259+
@boundscheck begin
260+
size(x) == size(d) ||
261+
throw(DimensionMismatch("inconsistent array dimensions"))
262+
end
263+
return _logpdf(d, x)
264+
else
265+
@boundscheck begin
266+
M > N ||
267+
throw(DimensionMismatch(
268+
"number of dimensions of the variates ($M) must be greater than or equal to the dimension of the distribution ($N)"
269+
))
270+
ntuple(i -> size(x, i), Val(N)) == size(d) ||
271+
throw(DimensionMismatch("inconsistent array dimensions"))
272+
end
273+
return @inbounds map(Base.Fix1(logpdf, d), eachvariate(x, variate_form(typeof(d))))
249274
end
250-
return _logpdf(d, x)
251275
end
252276

253277
# `_logpdf` should be implemented and has no default definition
@@ -272,20 +296,6 @@ Base.@propagate_inbounds function pdf(
272296
return map(Base.Fix1(pdf, d), x)
273297
end
274298

275-
@inline function pdf(
276-
d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:Real,M},
277-
) where {N,M}
278-
@boundscheck begin
279-
M > N ||
280-
throw(DimensionMismatch(
281-
"number of dimensions of `x` ($M) must be greater than number of dimensions of `d` ($N)"
282-
))
283-
ntuple(i -> size(x, i), Val(N)) == size(d) ||
284-
throw(DimensionMismatch("inconsistent array dimensions"))
285-
end
286-
return @inbounds map(Base.Fix1(pdf, d), eachvariate(x, variate_form(typeof(d))))
287-
end
288-
289299
"""
290300
logpdf(d::Distribution{ArrayLikeVariate{N}}, x) where {N}
291301
@@ -305,20 +315,6 @@ Base.@propagate_inbounds function logpdf(
305315
return map(Base.Fix1(logpdf, d), x)
306316
end
307317

308-
@inline function logpdf(
309-
d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:Real,M},
310-
) where {N,M}
311-
@boundscheck begin
312-
M > N ||
313-
throw(DimensionMismatch(
314-
"number of dimensions of `x` ($M) must be greater than number of dimensions of `d` ($N)"
315-
))
316-
ntuple(i -> size(x, i), Val(N)) == size(d) ||
317-
throw(DimensionMismatch("inconsistent array dimensions"))
318-
end
319-
return @inbounds map(Base.Fix1(logpdf, d), eachvariate(x, variate_form(typeof(d))))
320-
end
321-
322318
"""
323319
pdf!(out, d::Distribution{ArrayLikeVariate{N}}, x) where {N}
324320
@@ -365,7 +361,7 @@ end
365361
@boundscheck begin
366362
M > N ||
367363
throw(DimensionMismatch(
368-
"number of dimensions of `x` ($M) must be greater than number of dimensions of `d` ($N)"
364+
"number of dimensions of the variates ($M) must be greater than the dimension of the distribution ($N)"
369365
))
370366
ntuple(i -> size(x, i), Val(N)) == size(d) ||
371367
throw(DimensionMismatch("inconsistent array dimensions"))
@@ -414,7 +410,7 @@ See also: [`pdf!`](@ref).
414410
@boundscheck begin
415411
M > N ||
416412
throw(DimensionMismatch(
417-
"number of dimensions of `x` ($M) must be greater than number of dimensions of `d` ($N)"
413+
"number of dimensions of the variates ($M) must be greater than the dimension of the distribution ($N)"
418414
))
419415
ntuple(i -> size(x, i), Val(N)) == size(d) ||
420416
throw(DimensionMismatch("inconsistent array dimensions"))
@@ -445,23 +441,22 @@ be
445441
- an array of dimension `N + 1` with `size(x)[1:N] == size(d)`, or
446442
- an array of arrays `xi` of dimension `N` with `size(xi) == size(d)`.
447443
"""
448-
Base.@propagate_inbounds function loglikelihood(
449-
d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:Real,N},
450-
) where {N}
451-
return logpdf(d, x)
452-
end
453-
@inline function loglikelihood(
444+
Base.@propagate_inbounds @inline function loglikelihood(
454445
d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:Real,M},
455446
) where {N,M}
456-
@boundscheck begin
457-
M > N ||
458-
throw(DimensionMismatch(
459-
"number of dimensions of `x` ($M) must be greater than number of dimensions of `d` ($N)"
460-
))
461-
ntuple(i -> size(x, i), Val(N)) == size(d) ||
462-
throw(DimensionMismatch("inconsistent array dimensions"))
447+
if M == N
448+
return logpdf(d, x)
449+
else
450+
@boundscheck begin
451+
M > N ||
452+
throw(DimensionMismatch(
453+
"number of dimensions of the variates ($M) must be greater than or equal to the dimension of the distribution ($N)"
454+
))
455+
ntuple(i -> size(x, i), Val(N)) == size(d) ||
456+
throw(DimensionMismatch("inconsistent array dimensions"))
457+
end
458+
return @inbounds sum(Base.Fix1(logpdf, d), eachvariate(x, ArrayLikeVariate{N}))
463459
end
464-
return @inbounds sum(Base.Fix1(logpdf, d), eachvariate(x, ArrayLikeVariate{N}))
465460
end
466461
Base.@propagate_inbounds function loglikelihood(
467462
d::Distribution{ArrayLikeVariate{N}}, x::AbstractArray{<:AbstractArray{<:Real,N}},

src/convolution.jl

+14
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and one of
1212
* [`NegativeBinomial`](@ref)
1313
* [`Geometric`](@ref)
1414
* [`Poisson`](@ref)
15+
* [`DiscreteNonParametric`](@ref)
1516
* [`Normal`](@ref)
1617
* [`Cauchy`](@ref)
1718
* [`Chisq`](@ref)
@@ -47,6 +48,19 @@ end
4748
convolve(d1::Poisson, d2::Poisson) = Poisson(d1.λ + d2.λ)
4849

4950

51+
function convolve(d1::DiscreteNonParametric, d2::DiscreteNonParametric)
52+
support_conv = collect(Set(s1 + s2 for s1 in support(d1), s2 in support(d2)))
53+
sort!(support_conv) #for fast index finding below
54+
probs1 = probs(d1)
55+
probs2 = probs(d2)
56+
p_conv = zeros(Base.promote_eltype(probs1, probs2), length(support_conv))
57+
for (s1, p1) in zip(support(d1), probs(d1)), (s2, p2) in zip(support(d2), probs(d2))
58+
idx = searchsortedfirst(support_conv, s1+s2)
59+
p_conv[idx] += p1*p2
60+
end
61+
DiscreteNonParametric(support_conv, p_conv,check_args=false)
62+
end
63+
5064
# continuous univariate
5165
convolve(d1::Normal, d2::Normal) = Normal(d1.μ + d2.μ, hypot(d1.σ, d2.σ))
5266
convolve(d1::Cauchy, d2::Cauchy) = Cauchy(d1.μ + d2.μ, d1.σ + d2.σ)

0 commit comments

Comments
 (0)