|
| 1 | +export Affine, AffineTransform |
| 2 | + |
| 3 | +struct AffineTransform{N,T} |
| 4 | + par::NamedTuple{N,T} |
| 5 | +end |
| 6 | + |
| 7 | +@inline Base.getproperty(d::AffineTransform, s::Symbol) = getfield(getfield(d, :par), s) |
| 8 | + |
| 9 | +Base.propertynames(d::AffineTransform{N}) where {N} = N |
| 10 | + |
| 11 | +@inline Base.inv(f::AffineTransform{(:μ,:σ)}) = AffineTransform((μ = -(f.σ \ f.μ), ω = f.σ)) |
| 12 | +@inline Base.inv(f::AffineTransform{(:μ,:ω)}) = AffineTransform((μ = - f.ω * f.μ, σ = f.ω)) |
| 13 | + |
| 14 | +(f::AffineTransform{(:μ,:σ)})(x) = f.σ * x + f.μ |
| 15 | + |
| 16 | +(f::AffineTransform{(:μ,:ω)})(x) = f.ω \ x + f.μ |
| 17 | + |
| 18 | +############################################################################### |
| 19 | + |
| 20 | +struct Affine{N,M,T} <: AbstractMeasure |
| 21 | + f::AffineTransform{N,T} |
| 22 | + parent::M |
| 23 | +end |
| 24 | + |
| 25 | +Affine(nt::NamedTuple, μ::AbstractMeasure) = Affine(AffineTransform(nt), μ) |
| 26 | + |
| 27 | +Affine(nt::NamedTuple) = μ -> Affine(nt, μ) |
| 28 | + |
| 29 | +Base.propertynames(d::Affine{N}) where {N} = N ∪ (:parent,) |
| 30 | + |
| 31 | +@inline function Base.getproperty(d::Affine, s::Symbol) |
| 32 | + if s === :parent |
| 33 | + return getfield(d, :parent) |
| 34 | + else |
| 35 | + return getfield(getfield(d, :f), s) |
| 36 | + end |
| 37 | +end |
| 38 | + |
| 39 | +logdensity(d::Affine{(:μ,:σ)}, x) = logdensity(d.parent, d.σ \ (x - d.μ)) - log(d.σ) |
| 40 | + |
| 41 | +logdensity(d::Affine{(:μ,:ω)}, x) = logdensity(d.parent, d.ω * (x - d.μ)) + log(d.ω) |
0 commit comments