11export Affine, AffineTransform
2-
3- struct AffineTransform{N,T}
2+ using LinearAlgebra
3+ @concrete terse struct AffineTransform{N,T}
44 par:: NamedTuple{N,T}
55end
66
@@ -22,16 +22,21 @@ Base.propertynames(d::AffineTransform{N}) where {N} = N
2222(f:: AffineTransform{(:μ,:σ)} )(x) = f. σ * x + f. μ
2323(f:: AffineTransform{(:μ,:ω)} )(x) = f. ω \ x + f. μ
2424
25+
26+ logjac (x:: AbstractMatrix ) = first (logabsdet (x))
27+
28+ logjac (x:: Number ) = log (abs (x))
29+
2530# TODO : `log` doesn't work for the multivariate case, we need the log absolute determinant
26- logjac (f:: AffineTransform{(:μ,:σ)} ) = log (f. σ)
27- logjac (f:: AffineTransform{(:μ,:ω)} ) = - log (f. ω)
28- logjac (f:: AffineTransform{(:σ,)} ) = log (f. σ)
29- logjac (f:: AffineTransform{(:ω,)} ) = - log (f. ω)
31+ logjac (f:: AffineTransform{(:μ,:σ)} ) = logjac (f. σ)
32+ logjac (f:: AffineTransform{(:μ,:ω)} ) = - logjac (f. ω)
33+ logjac (f:: AffineTransform{(:σ,)} ) = logjac (f. σ)
34+ logjac (f:: AffineTransform{(:ω,)} ) = - logjac (f. ω)
3035logjac (f:: AffineTransform{(:μ,)} ) = 0.0
3136
3237# ##############################################################################
3338
34- struct Affine{N,M,T} <: AbstractMeasure
39+ @concrete terse struct Affine{N,M,T} <: AbstractMeasure
3540 f:: AffineTransform{N,T}
3641 parent:: M
3742end
@@ -62,21 +67,40 @@ Base.propertynames(d::Affine{N}) where {N} = N ∪ (:parent,)
6267 end
6368end
6469
65- # Note: We could also write
66- # logdensity(d::Affine, x) = logdensity(inv(getfield(d, :f)), x)
70+ Base. size (d) = size (d. μ)
71+ Base. size (d:: Affine{(:σ,)} ) = (size (d. σ, 1 ),)
72+ Base. size (d:: Affine{(:ω,)} ) = (size (d. ω, 2 ),)
6773
68- logdensity (d:: Affine{(:μ,:σ)} , x) = logdensity (d. parent, d. σ \ (x - d. μ))
69- logdensity (d:: Affine{(:μ,:ω)} , x) = logdensity (d. parent, d. ω * (x - d. μ))
7074logdensity (d:: Affine{(:σ,)} , x) = logdensity (d. parent, d. σ \ x)
7175logdensity (d:: Affine{(:ω,)} , x) = logdensity (d. parent, d. ω * x)
7276logdensity (d:: Affine{(:μ,)} , x) = logdensity (d. parent, x - d. μ)
77+ logdensity (d:: Affine{(:μ,:σ)} , x) = logdensity (d. parent, d. σ \ (x - d. μ))
78+ logdensity (d:: Affine{(:μ,:ω)} , x) = logdensity (d. parent, d. ω * (x - d. μ))
79+
80+ # logdensity(d::Affine{(:μ,:ω)}, x) = logdensity(d.parent, d.σ \ (x - d.μ))
81+ function logdensity (d:: Affine{(:μ,:σ), Tuple{AbstractVector, AbstractMatrix}} , x)
82+ z = x - d. μ
83+ ldiv! (d. σ, z)
84+ logdensity (d. parent, z)
85+ end
86+
87+ # logdensity(d::Affine{(:μ,:ω)}, x) = logdensity(d.parent, d.ω * (x - d.μ))
88+ function logdensity (d:: Affine{(:μ,:ω), Tuple{AbstractVector, AbstractMatrix}} , x)
89+ z = x - d. μ
90+ lmul! (d. ω, z)
91+ logdensity (d. parent, z)
92+ end
7393
7494basemeasure (d:: Affine ) = affine (getfield (d, :f ), basemeasure (d. parent))
7595
7696# We can't do this until we know we're working with Lebesgue measure, since for
7797# example it wouldn't make sense to apply a log-Jacobian to a point measure
7898basemeasure (d:: Affine{N,L} ) where {N, L<: Lebesgue } = weightedmeasure (- logjac (d), d. parent)
7999
100+ function basemeasure (d:: Affine{N,L} ) where {N, L<: PowerMeasure{typeof(identity), <:Lebesgue} }
101+ weightedmeasure (- logjac (d), d. parent)
102+ end
103+
80104logjac (d:: Affine ) = logjac (getfield (d, :f ))
81105
82106
0 commit comments