1
1
export Affine, AffineTransform
2
-
3
- struct AffineTransform{N,T}
2
+ using LinearAlgebra
3
+ @concrete terse struct AffineTransform{N,T}
4
4
par:: NamedTuple{N,T}
5
5
end
6
6
@@ -22,16 +22,21 @@ Base.propertynames(d::AffineTransform{N}) where {N} = N
22
22
(f:: AffineTransform{(:μ,:σ)} )(x) = f. σ * x + f. μ
23
23
(f:: AffineTransform{(:μ,:ω)} )(x) = f. ω \ x + f. μ
24
24
25
+
26
+ logjac (x:: AbstractMatrix ) = first (logabsdet (x))
27
+
28
+ logjac (x:: Number ) = log (abs (x))
29
+
25
30
# 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. ω)
30
35
logjac (f:: AffineTransform{(:μ,)} ) = 0.0
31
36
32
37
# ##############################################################################
33
38
34
- struct Affine{N,M,T} <: AbstractMeasure
39
+ @concrete terse struct Affine{N,M,T} <: AbstractMeasure
35
40
f:: AffineTransform{N,T}
36
41
parent:: M
37
42
end
@@ -62,21 +67,40 @@ Base.propertynames(d::Affine{N}) where {N} = N ∪ (:parent,)
62
67
end
63
68
end
64
69
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 ),)
67
73
68
- logdensity (d:: Affine{(:μ,:σ)} , x) = logdensity (d. parent, d. σ \ (x - d. μ))
69
- logdensity (d:: Affine{(:μ,:ω)} , x) = logdensity (d. parent, d. ω * (x - d. μ))
70
74
logdensity (d:: Affine{(:σ,)} , x) = logdensity (d. parent, d. σ \ x)
71
75
logdensity (d:: Affine{(:ω,)} , x) = logdensity (d. parent, d. ω * x)
72
76
logdensity (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
73
93
74
94
basemeasure (d:: Affine ) = affine (getfield (d, :f ), basemeasure (d. parent))
75
95
76
96
# We can't do this until we know we're working with Lebesgue measure, since for
77
97
# example it wouldn't make sense to apply a log-Jacobian to a point measure
78
98
basemeasure (d:: Affine{N,L} ) where {N, L<: Lebesgue } = weightedmeasure (- logjac (d), d. parent)
79
99
100
+ function basemeasure (d:: Affine{N,L} ) where {N, L<: PowerMeasure{typeof(identity), <:Lebesgue} }
101
+ weightedmeasure (- logjac (d), d. parent)
102
+ end
103
+
80
104
logjac (d:: Affine ) = logjac (getfield (d, :f ))
81
105
82
106
0 commit comments