diff --git a/src/univariate/discrete/bernoulli.jl b/src/univariate/discrete/bernoulli.jl index c1dee968c..6e7169c6c 100644 --- a/src/univariate/discrete/bernoulli.jl +++ b/src/univariate/discrete/bernoulli.jl @@ -96,11 +96,13 @@ ccdf(d::Bernoulli, x::Bool) = x ? zero(d.p) : succprob(d) ccdf(d::Bernoulli, x::Int) = x < 0 ? one(d.p) : x < 1 ? succprob(d) : zero(d.p) -function quantile(d::Bernoulli{T}, p::Real) where T<:Real - 0 <= p <= 1 ? (p <= failprob(d) ? zero(T) : one(T)) : T(NaN) +function quantile(d::Bernoulli, p::Real) + _check_quantile_arg(p) + p <= failprob(d) ? false : true end -function cquantile(d::Bernoulli{T}, p::Real) where T<:Real - 0 <= p <= 1 ? (p >= succprob(d) ? zero(T) : one(T)) : T(NaN) +function cquantile(d::Bernoulli, p::Real) + _check_cquantile_arg(p) + p >= succprob(d) ? false : true end mgf(d::Bernoulli, t::Real) = failprob(d) + succprob(d) * exp(t) diff --git a/src/univariate/discrete/bernoullilogit.jl b/src/univariate/discrete/bernoullilogit.jl index f82059fed..dfd3b14c6 100644 --- a/src/univariate/discrete/bernoullilogit.jl +++ b/src/univariate/discrete/bernoullilogit.jl @@ -87,12 +87,12 @@ logccdf(d::BernoulliLogit, x::Bool) = x ? oftype(float(d.logitp), -Inf) : logsuc logccdf(d::BernoulliLogit, x::Int) = x < 0 ? zero(float(d.logitp)) : (x < 1 ? logsuccprob(d) : oftype(float(d.logitp), -Inf)) function quantile(d::BernoulliLogit, p::Real) - T = float(partype(d)) - 0 <= p <= 1 ? (p <= failprob(d) ? zero(T) : one(T)) : T(NaN) + _check_quantile_arg(p) + p <= failprob(d) ? false : true end function cquantile(d::BernoulliLogit, p::Real) - T = float(partype(d)) - 0 <= p <= 1 ? (p >= succprob(d) ? zero(T) : one(T)) : T(NaN) + _check_cquantile_arg(q) + p >= succprob(d) ? false : true end mgf(d::BernoulliLogit, t::Real) = failprob(d) + exp(t + logsuccprob(d)) diff --git a/src/univariate/discrete/binomial.jl b/src/univariate/discrete/binomial.jl index f4102cbb8..1a889b756 100644 --- a/src/univariate/discrete/binomial.jl +++ b/src/univariate/discrete/binomial.jl @@ -126,7 +126,60 @@ end #### Evaluation & Sampling -@_delegate_statsfuns Binomial binom n p +# We rely on Rmath for (log)pdf, (log)cdf, and quantile functions +# We do not use the `@_delegate_statsfuns` macro to work around some issues in the +# quantile functions such as `StatsFuns.binominvcdf(10, 0.0, 1.0) = 10`. +pdf(d::Binomial, x::Real) = binompdf(d.n, d.p, x) +logpdf(d::Binomial, x::Real) = binomlogpdf(d.n, d.p, x) +cdf(d::Binomial, x::Real) = binomcdf(d.n, d.p, x) +ccdf(d::Binomial, x::Real) = binomccdf(d.n, d.p, x) +logcdf(d::Binomial, x::Real) = binomlogcdf(d.n, d.p, x) +logccdf(d::Binomial, x::Real) = binomlogccdf(d.n, d.p, x) + +function quantile(d::Binomial, q::Real)::Int + _check_quantile_arg(q) + if iszero(d.p) + return 0 + elseif isone(d.p) + return d.n + else + return binominvcdf(d.n, d.p, q) + end +end +function cquantile(d::Binomial, q::Real)::Int + _check_cquantile_arg(q) + if iszero(d.p) + return 0 + elseif isone(d.p) + return d.n + else + return binominvccdf(d.n, d.p, q) + end +end +function invlogcdf(d::Binomial, lq::Real)::Int + _check_invlogcdf_arg(lq) + if iszero(d.p) + return 0 + elseif isone(d.p) + return d.n + elseif isinf(lq) + return 0 + else + return binominvlogcdf(d.n, d.p, lq) + end +end +function invlogccdf(d::Binomial, lq::Real)::Int + _check_invlogccdf_arg(lq) + if iszero(d.p) + return 0 + elseif isone(d.p) + return d.n + elseif isinf(lq) + return d.n + else + return binominvlogccdf(d.n, d.p, lq) + end +end function rand(rng::AbstractRNG, d::Binomial) p, n = d.p, d.n diff --git a/src/univariate/discrete/dirac.jl b/src/univariate/discrete/dirac.jl index 94d082b0f..3b563302a 100644 --- a/src/univariate/discrete/dirac.jl +++ b/src/univariate/discrete/dirac.jl @@ -47,7 +47,10 @@ logcdf(d::Dirac, x::Real) = x < d.value ? -Inf : isnan(x) ? NaN : 0.0 ccdf(d::Dirac, x::Real) = x < d.value ? 1.0 : isnan(x) ? NaN : 0.0 logccdf(d::Dirac, x::Real) = x < d.value ? 0.0 : isnan(x) ? NaN : -Inf -quantile(d::Dirac{T}, p::Real) where {T} = 0 <= p <= 1 ? d.value : T(NaN) +function quantile(d::Dirac, p::Real) + _check_quantile_arg(p) + return d.value +end mgf(d::Dirac, t) = exp(t * d.value) cgf(d::Dirac, t) = t*d.value diff --git a/src/univariate/discrete/discreteuniform.jl b/src/univariate/discrete/discreteuniform.jl index 263818828..4d68082a2 100644 --- a/src/univariate/discrete/discreteuniform.jl +++ b/src/univariate/discrete/discreteuniform.jl @@ -85,7 +85,10 @@ function cdf(d::DiscreteUniform, x::Int) end end -quantile(d::DiscreteUniform, p::Real) = iszero(p) ? d.a : d.a - 1 + ceil(Int, p * span(d)) +function quantile(d::DiscreteUniform, p::Real) + _check_quantile_arg(p) + iszero(p) ? d.a : d.a - 1 + ceil(Int, p * span(d)) +end function mgf(d::DiscreteUniform, t::Real) a, b = d.a, d.b diff --git a/src/univariate/discrete/geometric.jl b/src/univariate/discrete/geometric.jl index f89cebfed..7f9b3ce4c 100644 --- a/src/univariate/discrete/geometric.jl +++ b/src/univariate/discrete/geometric.jl @@ -105,21 +105,23 @@ logcdf(d::Geometric, x::Int) = log1mexp(log1p(-d.p) * max(x + 1, 0)) logccdf(d::Geometric, x::Real) = logccdf_int(d, x) logccdf(d::Geometric, x::Int) = log1p(-d.p) * max(x + 1, 0) -quantile(d::Geometric, p::Real) = invlogccdf(d, log1p(-p)) - -cquantile(d::Geometric, p::Real) = invlogccdf(d, log(p)) - -invlogcdf(d::Geometric, lp::Real) = invlogccdf(d, log1mexp(lp)) +function quantile(d::Geometric, p::Real) + _check_quantile_arg(p) + return invlogccdf(d, log1p(-p)) +end +function cquantile(d::Geometric, p::Real) + _check_cquantile_arg(p) + return invlogccdf(d, log(p)) +end -function invlogccdf(d::Geometric{T}, lp::Real) where T<:Real - if (lp > zero(d.p)) || isnan(lp) - return T(NaN) - elseif isinf(lp) - return T(Inf) - elseif lp == zero(d.p) - return zero(T) - end - max(ceil(lp/log1p(-d.p)) - 1, zero(T)) +function invlogcdf(d::Geometric, lp::Real) + _check_invlogcdf_arg(lp) + return invlogccdf(d, log1mexp(lp)) +end +function invlogccdf(d::Geometric, lp::Real) + _check_invlogccdf_arg(lp) + z = lp/log1p(-d.p) - 1 + return ceil(Int, max(z, zero(z))) end function laplace_transform(d::Geometric, t) diff --git a/src/univariate/discrete/negativebinomial.jl b/src/univariate/discrete/negativebinomial.jl index 0ca8f3c9b..53a77239b 100644 --- a/src/univariate/discrete/negativebinomial.jl +++ b/src/univariate/discrete/negativebinomial.jl @@ -112,10 +112,30 @@ cdf(d::NegativeBinomial, x::Real) = nbinomcdf(d.r, d.p, x) ccdf(d::NegativeBinomial, x::Real) = nbinomccdf(d.r, d.p, x) logcdf(d::NegativeBinomial, x::Real) = nbinomlogcdf(d.r, d.p, x) logccdf(d::NegativeBinomial, x::Real) = nbinomlogccdf(d.r, d.p, x) -quantile(d::NegativeBinomial, q::Real) = convert(Int, nbinominvcdf(d.r, d.p, q)) -cquantile(d::NegativeBinomial, q::Real) = convert(Int, nbinominvccdf(d.r, d.p, q)) -invlogcdf(d::NegativeBinomial, lq::Real) = convert(Int, nbinominvlogcdf(d.r, d.p, lq)) -invlogccdf(d::NegativeBinomial, lq::Real) = convert(Int, nbinominvlogccdf(d.r, d.p, lq)) +function quantile(d::NegativeBinomial, q::Real)::Int + _check_quantile_arg(q) + return nbinominvcdf(d.r, d.p, q) +end +function cquantile(d::NegativeBinomial, q::Real)::Int + _check_cquantile_arg(q) + return nbinominvccdf(d.r, d.p, q) +end +function invlogcdf(d::NegativeBinomial, lq::Real)::Int + _check_invlogcdf_arg(lq) + if isinf(lq) + return nbinominvcdf(d.r, d.p, zero(lq)) + else + return nbinominvlogcdf(d.r, d.p, lq) + end +end +function invlogccdf(d::NegativeBinomial, lq::Real)::Int + _check_invlogccdf_arg(lq) + if isinf(lq) + return nbinominvccdf(d.r, d.p, zero(lq)) + else + return nbinominvlogccdf(d.r, d.p, lq) + end +end ## sampling function rand(rng::AbstractRNG, d::NegativeBinomial) diff --git a/src/univariate/discrete/noncentralhypergeometric.jl b/src/univariate/discrete/noncentralhypergeometric.jl index 52853cfc0..a344f2397 100644 --- a/src/univariate/discrete/noncentralhypergeometric.jl +++ b/src/univariate/discrete/noncentralhypergeometric.jl @@ -9,23 +9,23 @@ abstract type NoncentralHypergeometric{T<:Real} <: DiscreteUnivariateDistributio # Functions -function quantile(d::NoncentralHypergeometric{T}, q::Real) where T<:Real - if !(zero(q) <= q <= one(q)) - T(NaN) - else - range = support(d) - if q > 1/2 - q = 1 - q - range = reverse(range) - end +function quantile(d::NoncentralHypergeometric, q::Real) + _check_quantile_arg(q) - qsum, i = zero(T), 0 - while qsum < q - i += 1 - qsum += pdf(d, range[i]) - end - range[i] + range = support(d) + if q > 1/2 + q = 1 - q + range = reverse(range) + end + + # Support must not be empty + r, state = iterate(range) + qsum = pdf(d, r) + while qsum < q && (r_state = iterate(range, state)) !== nothing + r, state = r_state + qsum += pdf(d, r) end + return r end params(d::NoncentralHypergeometric) = (d.ns, d.nf, d.n, d.ω) diff --git a/src/univariates.jl b/src/univariates.jl index b60e5a294..678c2a9c3 100644 --- a/src/univariates.jl +++ b/src/univariates.jl @@ -396,7 +396,10 @@ quantile(d::UnivariateDistribution, p::Real) The complementary quantile value, i.e. `quantile(d, 1-q)`. """ -cquantile(d::UnivariateDistribution, p::Real) = quantile(d, 1.0 - p) +function cquantile(d::UnivariateDistribution, p::Real) + _check_cquantile_arg(p) + quantile(d, 1 - p) +end """ invlogcdf(d::UnivariateDistribution, lp::Real) @@ -406,7 +409,10 @@ The (generalized) inverse function of [`logcdf`](@ref). For a given `lp ≤ 0`, `invlogcdf(d, lp)` is the smallest value `x` in the support of `d` for which `logcdf(d, x) ≥ lp`. """ -invlogcdf(d::UnivariateDistribution, lp::Real) = quantile(d, exp(lp)) +function invlogcdf(d::UnivariateDistribution, lp::Real) + _check_invlogcdf_arg(lp) + quantile(d, exp(lp)) +end """ invlogccdf(d::UnivariateDistribution, lp::Real) @@ -416,7 +422,10 @@ The (generalized) inverse function of [`logccdf`](@ref). For a given `lp ≤ 0`, `invlogccdf(d, lp)` is the smallest value `x` in the support of `d` for which `logccdf(d, x) ≤ lp`. """ -invlogccdf(d::UnivariateDistribution, lp::Real) = quantile(d, -expm1(lp)) +function invlogccdf(d::UnivariateDistribution, lp::Real) + _check_invlogccdf_arg(lp) + quantile(d, -expm1(lp)) +end # gradlogpdf @@ -619,6 +628,38 @@ function integerunitrange_logccdf(d::DiscreteUnivariateDistribution, x::Integer) return result end +### Error messages + +const QUANTILE_ARG_ERROR = "`Distributions.quantile(d, p)` only accepts arguments `p` in `[0, 1]`." +const CQUANTILE_ARG_ERROR = "`Distributions.cquantile(d, p)` only accepts arguments `p` in `[0, 1]`." +const INVLOGCDF_ARG_ERROR = "`Distributions.invlogcdf(d, lp)` only accepts non-negative arguments `lp`." +const INVLOGCCDF_ARG_ERROR = "`Distributions.invlogccdf(d, lp)` only accepts non-negative arguments `lp`." + +function _check_quantile_arg(p::Real) + if !(zero(p) <= p <= oneunit(p)) + throw(DomainError(p, QUANTILE_ARG_ERROR)) + end + nothing +end +function _check_cquantile_arg(p::Real) + if !(zero(p) <= p <= oneunit(p)) + throw(DomainError(p, CQUANTILE_ARG_ERROR)) + end + nothing +end +function _check_invlogcdf_arg(lp::Real) + if !(lp <= zero(lp)) + throw(DomainError(lp, INVLOGCDF_ARG_ERROR)) + end + nothing +end +function _check_invlogccdf_arg(lp::Real) + if !(lp <= zero(lp)) + throw(DomainError(lp, INVLOGCDF_ARG_ERROR)) + end + nothing +end + ### macros to use StatsFuns for method implementation macro _delegate_statsfuns(D, fpre, psyms...) @@ -649,10 +690,34 @@ macro _delegate_statsfuns(D, fpre, psyms...) $Distributions.ccdf(d::$D, x::Real) = $(fccdf)($(pargs...), x) $Distributions.logccdf(d::$D, x::Real) = $(flogccdf)($(pargs...), x) - $Distributions.quantile(d::$D, q::Real) = convert($T, $(finvcdf)($(pargs...), q)) - $Distributions.cquantile(d::$D, q::Real) = convert($T, $(finvccdf)($(pargs...), q)) - $Distributions.invlogcdf(d::$D, lq::Real) = convert($T, $(finvlogcdf)($(pargs...), lq)) - $Distributions.invlogccdf(d::$D, lq::Real) = convert($T, $(finvlogccdf)($(pargs...), lq)) + function $Distributions.quantile(d::$D, q::Real)::$T + _check_quantile_arg(q) + return $(finvcdf)($(pargs...), q) + end + function $Distributions.cquantile(d::$D, q::Real)::$T + _check_cquantile_arg(q) + return $(finvccdf)($(pargs...), q) + end + + # There is a bug in some functions in StatsFuns.RFunctions/Rmath: + # For `lq = -Inf` they return `NaN` + # We work around this issue by falling back to quantile/cquantile + function $Distributions.invlogcdf(d::$D, lq::Real)::$T + _check_invlogcdf_arg(lq) + if isinf(lq) + return $(finvcdf)($(pargs...), zero(lq)) + else + return $(finvlogcdf)($(pargs...), lq) + end + end + function $Distributions.invlogccdf(d::$D, lq::Real)::$T + _check_invlogccdf_arg(lq) + if isinf(lq) + return $(finvccdf)($(pargs...), zero(lq)) + else + return $(finvlogccdf)($(pargs...), lq) + end + end end end diff --git a/test/testutils.jl b/test/testutils.jl index 8acd37853..e3fbd2f45 100644 --- a/test/testutils.jl +++ b/test/testutils.jl @@ -447,6 +447,7 @@ end function test_evaluation(d::DiscreteUnivariateDistribution, vs::AbstractVector, testquan::Bool=true) + T = eltype(vs) nv = length(vs) p = Vector{Float64}(undef, nv) c = Vector{Float64}(undef, nv) @@ -477,11 +478,10 @@ function test_evaluation(d::DiscreteUnivariateDistribution, vs::AbstractVector, if testquan ep = 1.0e-8 if p[i] > 2 * ep # ensure p[i] is large enough to guarantee a reliable result - @test quantile(d, c[i] - ep) == v - @test cquantile(d, cc[i] + ep) == v - @test invlogcdf(d, lc[i] - ep) == v - if 0.0 < c[i] < 1.0 - @test invlogccdf(d, lcc[i] + ep) == v + for (f, z) in ((quantile, c[i] - ep), (cquantile, cc[i] + ep), (invlogcdf, lc[i] - ep), (invlogccdf, lcc[i] + ep)) + fz = @inferred(f(d, z)) + @test fz isa T + @test fz == v end end end @@ -499,6 +499,7 @@ end function test_evaluation(d::ContinuousUnivariateDistribution, vs::AbstractVector, testquan::Bool=true) + T = eltype(vs) nv = length(vs) p = Vector{Float64}(undef, nv) c = Vector{Float64}(undef, nv) @@ -534,10 +535,11 @@ function test_evaluation(d::ContinuousUnivariateDistribution, vs::AbstractVector qtol = isa(d, InverseGaussian) ? 1.0e-4 : 1.0e-10 qtol = isa(d, StudentizedRange) ? 1.0e-5 : qtol if p[i] > 1.0e-6 - @test isapprox(quantile(d, c[i]) , v, atol=qtol * (abs(v) + 1.0)) - @test isapprox(cquantile(d, cc[i]) , v, atol=qtol * (abs(v) + 1.0)) - @test isapprox(invlogcdf(d, lc[i]) , v, atol=qtol * (abs(v) + 1.0)) - @test isapprox(invlogccdf(d, lcc[i]), v, atol=qtol * (abs(v) + 1.0)) + for (f, z) in ((quantile, c[i]), (cquantile, cc[i]), (invlogcdf, lc[i]), (invlogccdf, lcc[i])) + fz = @inferred(f(d, z)) + @test fz isa T + @test fz ≈ v atol = qtol * (abs(v) + 1.0) + end end end end diff --git a/test/truncate.jl b/test/truncate.jl index 9c2a286d0..88a2d3098 100644 --- a/test/truncate.jl +++ b/test/truncate.jl @@ -232,3 +232,9 @@ end @test @inferred(cdf(dist, 2.82)) === 1.0 @test @inferred(ccdf(dist, 2.82)) === 0.0 end + +@testset "inconsistent types of samples (#1798)" begin + @test @inferred(rand(truncated(Geometric(0.6); lower = 2))) isa Int + @test @inferred(rand(truncated(Geometric(0.6); upper = 4))) isa Int +end + diff --git a/test/univariate/continuous/lognormal.jl b/test/univariate/continuous/lognormal.jl index 1cc44b433..833dd829c 100644 --- a/test/univariate/continuous/lognormal.jl +++ b/test/univariate/continuous/lognormal.jl @@ -55,10 +55,10 @@ isnan_type(::Type{T}, v) where {T} = isnan(v) && v isa T @test iszero(cquantile(LogNormal(0.25, 0), 1)) @test iszero(invlogcdf(LogNormal(), -Inf)) - @test isnan_type(Float64, invlogcdf(LogNormal(), NaN)) + @test_throws DomainError invlogcdf(LogNormal(), NaN) @test invlogccdf(LogNormal(), -Inf) === Inf - @test isnan_type(Float64, invlogccdf(LogNormal(), NaN)) + @test_throws DomainError invlogccdf(LogNormal(), NaN) # test for #996 being fixed let d = LogNormal(0, 1), x = exp(1), ∂x = exp(2) @@ -264,22 +264,22 @@ end @test @inferred(quantile(LogNormal(1.0, 0.0), 0.0f0)) === 0.0 @test @inferred(quantile(LogNormal(1.0, 0.0f0), 1.0)) === Inf @test @inferred(quantile(LogNormal(1.0f0, 0.0), 0.5)) === exp(1) - @test isnan_type(Float64, @inferred(quantile(LogNormal(1.0f0, 0.0), NaN))) + @test_throws DomainError @inferred(quantile(LogNormal(1.0f0, 0.0), NaN)) @test @inferred(quantile(LogNormal(1.0f0, 0.0f0), 0.0f0)) === 0.0f0 @test @inferred(quantile(LogNormal(1.0f0, 0.0f0), 1.0f0)) === Inf32 @test @inferred(quantile(LogNormal(1.0f0, 0.0f0), 0.5f0)) === exp(1.0f0) - @test isnan_type(Float32, @inferred(quantile(LogNormal(1.0f0, 0.0f0), NaN32))) + @test_throws DomainError @inferred(quantile(LogNormal(1.0f0, 0.0f0), NaN32)) @test @inferred(quantile(LogNormal(1//1, 0//1), 1//2)) === exp(1) # cquantile @test @inferred(cquantile(LogNormal(1.0, 0.0), 0.0f0)) === Inf @test @inferred(cquantile(LogNormal(1.0, 0.0f0), 1.0)) === 0.0 @test @inferred(cquantile(LogNormal(1.0f0, 0.0), 0.5)) === exp(1) - @test isnan_type(Float64, @inferred(cquantile(LogNormal(1.0f0, 0.0), NaN))) + @test_throws DomainError @inferred(cquantile(LogNormal(1.0f0, 0.0), NaN)) @test @inferred(cquantile(LogNormal(1.0f0, 0.0f0), 0.0f0)) === Inf32 @test @inferred(cquantile(LogNormal(1.0f0, 0.0f0), 1.0f0)) === 0.0f0 @test @inferred(cquantile(LogNormal(1.0f0, 0.0f0), 0.5f0)) === exp(1.0f0) - @test isnan_type(Float32, @inferred(cquantile(LogNormal(1.0f0, 0.0f0), NaN32))) + @test_throws DomainError @inferred(cquantile(LogNormal(1.0f0, 0.0f0), NaN32)) @test @inferred(cquantile(LogNormal(1//1, 0//1), 1//2)) === exp(1) # gradlogpdf diff --git a/test/univariate/continuous/normal.jl b/test/univariate/continuous/normal.jl index 0378e0548..c900ad370 100644 --- a/test/univariate/continuous/normal.jl +++ b/test/univariate/continuous/normal.jl @@ -59,9 +59,9 @@ isnan_type(::Type{T}, v) where {T} = isnan(v) && v isa T @test 0.25 == cquantile(Normal(0.25, 0), 0.95) @test -Inf === cquantile(Normal(0.25, 0), 1) @test -Inf === invlogcdf(Normal(), -Inf) - @test isnan_type(Float64, invlogcdf(Normal(), NaN)) + @test_throws DomainError invlogcdf(Normal(), NaN) @test Inf === invlogccdf(Normal(), -Inf) - @test isnan_type(Float64, invlogccdf(Normal(), NaN)) + @test_throws DomainError invlogccdf(Normal(), NaN) # test for #996 being fixed let d = Normal(0, 1), x = 1.0, ∂x = 2.0 @inferred cdf(d, ForwardDiff.Dual(x, ∂x)) ≈ ForwardDiff.Dual(cdf(d, x), ∂x * pdf(d, x)) @@ -162,11 +162,11 @@ end @test @inferred(quantile(Normal(1.0, 0.0), 0.0f0)) === -Inf @test @inferred(quantile(Normal(1.0, 0.0f0), 1.0)) === Inf @test @inferred(quantile(Normal(1.0f0, 0.0), 0.5)) === 1.0 - @test isnan_type(Float64, @inferred(quantile(Normal(1.0f0, 0.0), NaN))) + @test_throws DomainError @inferred(quantile(Normal(1.0f0, 0.0), NaN)) @test @inferred(quantile(Normal(1.0f0, 0.0f0), 0.0f0)) === -Inf32 @test @inferred(quantile(Normal(1.0f0, 0.0f0), 1.0f0)) === Inf32 @test @inferred(quantile(Normal(1.0f0, 0.0f0), 0.5f0)) === 1.0f0 - @test isnan_type(Float32, @inferred(quantile(Normal(1.0f0, 0.0f0), NaN32))) + @test_throws DomainError @inferred(quantile(Normal(1.0f0, 0.0f0), NaN32)) @test @inferred(quantile(Normal(1//1, 0//1), 1//2)) === 1.0 @test @inferred(quantile(Normal(1f0, 0f0), 1//2)) === 1f0 @test @inferred(quantile(Normal(1f0, 0.0), 1//2)) === 1.0 @@ -174,11 +174,11 @@ end @test @inferred(cquantile(Normal(1.0, 0.0), 0.0f0)) === Inf @test @inferred(cquantile(Normal(1.0, 0.0f0), 1.0)) === -Inf @test @inferred(cquantile(Normal(1.0f0, 0.0), 0.5)) === 1.0 - @test isnan_type(Float64, @inferred(cquantile(Normal(1.0f0, 0.0), NaN))) + @test_throws DomainError @inferred(cquantile(Normal(1.0f0, 0.0), NaN)) @test @inferred(cquantile(Normal(1.0f0, 0.0f0), 0.0f0)) === Inf32 @test @inferred(cquantile(Normal(1.0f0, 0.0f0), 1.0f0)) === -Inf32 @test @inferred(cquantile(Normal(1.0f0, 0.0f0), 0.5f0)) === 1.0f0 - @test isnan_type(Float32, @inferred(cquantile(Normal(1.0f0, 0.0f0), NaN32))) + @test_throws DomainError @inferred(cquantile(Normal(1.0f0, 0.0f0), NaN32)) @test @inferred(cquantile(Normal(1//1, 0//1), 1//2)) === 1.0 @test @inferred(cquantile(Normal(1f0, 0f0), 1//2)) === 1f0 @test @inferred(cquantile(Normal(1f0, 0.0), 1//2)) === 1.0