From 00d80b4f7162fc6a5b22ab2533e7ab64ec186da0 Mon Sep 17 00:00:00 2001 From: David Widmann Date: Fri, 11 Apr 2025 15:02:57 +0200 Subject: [PATCH 1/3] Do not promote mean and covariance of `MvNormal` to common element type --- src/multivariate/mvnormal.jl | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/multivariate/mvnormal.jl b/src/multivariate/mvnormal.jl index 6126c1d8f1..731aed482f 100644 --- a/src/multivariate/mvnormal.jl +++ b/src/multivariate/mvnormal.jl @@ -182,14 +182,9 @@ const ZeroMeanDiagNormal{Axes} = MvNormal{Float64,PDiagMat{Float64,Vector{Float6 const ZeroMeanFullNormal{Axes} = MvNormal{Float64,PDMat{Float64,Matrix{Float64}},Zeros{Float64,1,Axes}} ### Construction -function MvNormal(μ::AbstractVector{T}, Σ::AbstractPDMat{T}) where {T<:Real} - size(Σ, 1) == length(μ) || throw(DimensionMismatch("The dimensions of mu and Sigma are inconsistent.")) - MvNormal{T,typeof(Σ), typeof(μ)}(μ, Σ) -end - function MvNormal(μ::AbstractVector{<:Real}, Σ::AbstractPDMat{<:Real}) - R = Base.promote_eltype(μ, Σ) - MvNormal(convert(AbstractArray{R}, μ), convert(AbstractArray{R}, Σ)) + size(Σ, 1) == length(μ) || throw(DimensionMismatch("The dimensions of mu and Sigma are inconsistent.")) + return MvNormal{Base.promote_eltype(μ, Σ),typeof(Σ),typeof(μ)}(μ, Σ) end # constructor with general covariance matrix From 5a69e1db0ca65a0901a20c1b057969d1592df41f Mon Sep 17 00:00:00 2001 From: David Widmann Date: Fri, 11 Apr 2025 23:49:45 +0200 Subject: [PATCH 2/3] Fix failing test --- test/mixture.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/mixture.jl b/test/mixture.jl index 0b25a2346a..0f335a814a 100644 --- a/test/mixture.jl +++ b/test/mixture.jl @@ -1,5 +1,6 @@ using Distributions, Random using Test +using FillArrays using ForwardDiff: Dual @@ -253,9 +254,9 @@ end @testset "Testing MultivariatevariateMixture" begin g_m = MixtureModel( - IsoNormal[ MvNormal([0.0, 0.0], I), - MvNormal([0.2, 1.0], I), - MvNormal([-0.5, -3.0], 1.6 * I) ], + IsoNormal[ MvNormal([0.0, 0.0], Eye(2)), + MvNormal([0.2, 1.0], Eye(2)), + MvNormal([-0.5, -3.0], 1.6 * Eye(2)) ], [0.2, 0.5, 0.3]) @test isa(g_m, MixtureModel{Multivariate, Continuous, IsoNormal}) @test length(components(g_m)) == 3 From 7637c4de6c83c0fb67dea48a6b686c730f8032de Mon Sep 17 00:00:00 2001 From: David Widmann Date: Sat, 12 Apr 2025 00:31:00 +0200 Subject: [PATCH 3/3] More test fixes --- src/multivariate/mvnormal.jl | 7 +++++-- test/mixture.jl | 7 +++---- test/multivariate/mvnormal.jl | 10 +++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/multivariate/mvnormal.jl b/src/multivariate/mvnormal.jl index 731aed482f..e5add960fc 100644 --- a/src/multivariate/mvnormal.jl +++ b/src/multivariate/mvnormal.jl @@ -196,8 +196,11 @@ Construct a multivariate normal distribution with mean `μ` and covariance matri MvNormal(μ::AbstractVector{<:Real}, Σ::AbstractMatrix{<:Real}) = MvNormal(μ, PDMat(Σ)) MvNormal(μ::AbstractVector{<:Real}, Σ::Diagonal{<:Real}) = MvNormal(μ, PDiagMat(Σ.diag)) MvNormal(μ::AbstractVector{<:Real}, Σ::Union{Symmetric{<:Real,<:Diagonal{<:Real}},Hermitian{<:Real,<:Diagonal{<:Real}}}) = MvNormal(μ, PDiagMat(Σ.data.diag)) -MvNormal(μ::AbstractVector{<:Real}, Σ::UniformScaling{<:Real}) = - MvNormal(μ, ScalMat(length(μ), Σ.λ)) +function MvNormal(μ::AbstractVector{<:Real}, Σ::UniformScaling{<:Real}) + # Promote `Bool` (`I`) to avoid surprising covariance element types + λ = Σ isa UniformScaling{Bool} ? promote_type(eltype(μ), Bool)(Σ.λ) : Σ.λ + return MvNormal(μ, ScalMat(length(μ), λ)) +end function MvNormal( μ::AbstractVector{<:Real}, Σ::Diagonal{<:Real,<:FillArrays.AbstractFill{<:Real,1}} ) diff --git a/test/mixture.jl b/test/mixture.jl index 0f335a814a..0b25a2346a 100644 --- a/test/mixture.jl +++ b/test/mixture.jl @@ -1,6 +1,5 @@ using Distributions, Random using Test -using FillArrays using ForwardDiff: Dual @@ -254,9 +253,9 @@ end @testset "Testing MultivariatevariateMixture" begin g_m = MixtureModel( - IsoNormal[ MvNormal([0.0, 0.0], Eye(2)), - MvNormal([0.2, 1.0], Eye(2)), - MvNormal([-0.5, -3.0], 1.6 * Eye(2)) ], + IsoNormal[ MvNormal([0.0, 0.0], I), + MvNormal([0.2, 1.0], I), + MvNormal([-0.5, -3.0], 1.6 * I) ], [0.2, 0.5, 0.3]) @test isa(g_m, MixtureModel{Multivariate, Continuous, IsoNormal}) @test length(components(g_m)) == 3 diff --git a/test/multivariate/mvnormal.jl b/test/multivariate/mvnormal.jl index 4af9275b3f..604064931d 100644 --- a/test/multivariate/mvnormal.jl +++ b/test/multivariate/mvnormal.jl @@ -82,9 +82,9 @@ end C = [4. -2. -1.; -2. 5. -1.; -1. -1. 6.] J = inv(C) h = J \ mu - @test typeof(MvNormal(mu, PDMat(Array{Float32}(C)))) == typeof(MvNormal(mu, PDMat(C))) - @test typeof(MvNormal(mu, Array{Float32}(C))) == typeof(MvNormal(mu, PDMat(C))) - @test typeof(@test_deprecated(MvNormal(mu, 2.0f0))) == typeof(@test_deprecated(MvNormal(mu, 2.0))) + @test MvNormal(mu, PDMat(Array{Float32}(C))) isa MvNormal{Float64, PDMat{Float32, Matrix{Float32}}, Vector{Float64}} + @test MvNormal(mu, Array{Float32}(C)) isa MvNormal{Float64, PDMat{Float32, Matrix{Float32}}, Vector{Float64}} + @test @test_deprecated(MvNormal(mu, 2.0f0)) isa MvNormal{Float64, ScalMat{Float32}, Vector{Float64}} @test typeof(MvNormalCanon(h, PDMat(Array{Float32}(J)))) == typeof(MvNormalCanon(h, PDMat(J))) @test typeof(MvNormalCanon(h, Array{Float32}(J))) == typeof(MvNormalCanon(h, PDMat(J))) @@ -102,9 +102,9 @@ end @test typeof(convert(MvNormalCanon{Float64}, d)) == typeof(MvNormalCanon(mu, h, PDMat(J))) @test typeof(convert(MvNormalCanon{Float64}, d.μ, d.h, d.J)) == typeof(MvNormalCanon(mu, h, PDMat(J))) - @test MvNormal(mu, I) === @test_deprecated(MvNormal(mu, 1)) + @test MvNormal(mu, I) === @test_deprecated(MvNormal(mu, 1.0)) @test MvNormal(mu, 9 * I) === @test_deprecated(MvNormal(mu, 3)) - @test MvNormal(mu, 0.25f0 * I) === @test_deprecated(MvNormal(mu, 0.5)) + @test MvNormal(mu, 0.25f0 * I) === @test_deprecated(MvNormal(mu, 0.5f0)) @test MvNormal(mu, I) === MvNormal(mu, Diagonal(Ones(length(mu)))) @test MvNormal(mu, 9 * I) === MvNormal(mu, Diagonal(Fill(9, length(mu))))