From 610bc12b6a27844c6c1cd4acc1374fb48f08deaa Mon Sep 17 00:00:00 2001 From: David Widmann Date: Thu, 23 Feb 2023 22:00:41 +0100 Subject: [PATCH] Fix inconsistency of `pdf`/`cdf` of `Uniform` (#1682) * Fix inconsistency of `pdf`/`cdf` of `Uniform` * Fix existing tests * Fixes * Fix --- src/univariate/continuous/uniform.jl | 10 +++++--- test/univariate/continuous/uniform.jl | 34 +++++++++++++++++++++++++++ test/univariates.jl | 24 ------------------- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/univariate/continuous/uniform.jl b/src/univariate/continuous/uniform.jl index dd3fd59ed6..6386628e8c 100644 --- a/src/univariate/continuous/uniform.jl +++ b/src/univariate/continuous/uniform.jl @@ -72,12 +72,16 @@ entropy(d::Uniform) = log(d.b - d.a) #### Evaluation function pdf(d::Uniform, x::Real) - val = inv(d.b - d.a) + # include dependency on `x` for return type to be consistent with `cdf` + a, b, _ = promote(d.a, d.b, x) + val = inv(b - a) return insupport(d, x) ? val : zero(val) end function logpdf(d::Uniform, x::Real) - diff = d.b - d.a - return insupport(d, x) ? -log(diff) : log(zero(diff)) + # include dependency on `x` for return type to be consistent with `logcdf` + a, b, _ = promote(d.a, d.b, x) + val = - log(b - a) + return insupport(d, x) ? val : oftype(val, -Inf) end gradlogpdf(d::Uniform, x::Real) = zero(partype(d)) / oneunit(x) diff --git a/test/univariate/continuous/uniform.jl b/test/univariate/continuous/uniform.jl index 5936c3ea8a..e3a5d729ed 100644 --- a/test/univariate/continuous/uniform.jl +++ b/test/univariate/continuous/uniform.jl @@ -1,6 +1,7 @@ using Distributions using ChainRulesTestUtils using OffsetArrays +using StatsFuns using Random using Test @@ -80,4 +81,37 @@ using Test end end end + # issue #1677 + @testset "consistency of pdf and cdf" begin + for T in (Int, Float32, Float64) + d = Uniform{T}(T(2), T(4)) + for S in (Int, Float32, Float64) + TS = float(promote_type(T, S)) + + @test @inferred(pdf(d, S(1))) === TS(0) + @test @inferred(pdf(d, S(3))) === TS(1//2) + @test @inferred(pdf(d, S(5))) === TS(0) + + @test @inferred(logpdf(d, S(1))) === TS(-Inf) + @test @inferred(logpdf(d, S(3))) === -TS(logtwo) + @test @inferred(logpdf(d, S(5))) === TS(-Inf) + + @test @inferred(cdf(d, S(1))) === TS(0) + @test @inferred(cdf(d, S(3))) === TS(1//2) + @test @inferred(cdf(d, S(5))) === TS(1) + + @test @inferred(logcdf(d, S(1))) === TS(-Inf) + @test @inferred(logcdf(d, S(3))) === -TS(logtwo) + @test @inferred(logcdf(d, S(5))) === TS(0) + + @test @inferred(ccdf(d, S(1))) === TS(1) + @test @inferred(ccdf(d, S(3))) === TS(1//2) + @test @inferred(ccdf(d, S(5))) === TS(0) + + @test @inferred(logccdf(d, S(1))) === TS(0) + @test @inferred(logccdf(d, S(3))) === -TS(logtwo) + @test @inferred(logccdf(d, S(5))) === TS(-Inf) + end + end + end end diff --git a/test/univariates.jl b/test/univariates.jl index 675ef6909f..e16c52f59b 100644 --- a/test/univariates.jl +++ b/test/univariates.jl @@ -177,30 +177,6 @@ end @test invlogccdf(d, log(0.6)) isa Int end -@testset "Uniform type inference" begin - for T in (Int, Float32) - d = Uniform{T}(T(2), T(3)) - FT = float(T) - XFT = promote_type(FT, Float64) - - @test @inferred(pdf(d, 1.5)) === zero(FT) - @test @inferred(pdf(d, 2.5)) === one(FT) - @test @inferred(pdf(d, 3.5)) === zero(FT) - - @test @inferred(logpdf(d, 1.5)) === FT(-Inf) - @test @inferred(logpdf(d, 2.5)) === -zero(FT) # negative zero - @test @inferred(logpdf(d, 3.5)) === FT(-Inf) - - @test @inferred(cdf(d, 1.5)) === zero(XFT) - @test @inferred(cdf(d, 2.5)) === XFT(1//2) - @test @inferred(cdf(d, 3.5)) === one(XFT) - - @test @inferred(ccdf(d, 1.5)) === one(XFT) - @test @inferred(ccdf(d, 2.5)) === XFT(1//2) - @test @inferred(ccdf(d, 3.5)) === zero(XFT) - end -end - # #1471 @testset "InverseGamma constructor (#1471)" begin @test_throws DomainError InverseGamma(-1, 2)