using LinearAlgebra, Random, Statistics

# Bayesian linear regression with a Normal-Inverse-Gamma prior:
#   σ² ~ InvGamma(a0, b0),  β | σ² ~ Normal(0, σ² V0)
# The posterior is the same family, so it has a closed form.
function nig_posterior(y, cols...; v0 = 100.0, a0 = 1.0, b0 = 0.01, intercept = true)
    Z  = intercept ? hcat(ones(length(y)), cols...) : hcat(cols...)
    Λn = I / v0 + Z' * Z                      # posterior precision (per σ²)
    mn = Λn \ (Z' * y)
    an = a0 + length(y) / 2
    bn = b0 + (y' * y - mn' * Λn * mn) / 2
    (m = mn, L = cholesky(Symmetric(inv(Λn))).L, a = an, b = bn)
end

# Gamma(k, 1) for k a multiple of 1/2, with the standard library only
gamma_draw(k) = sum(randexp(floor(Int, k))) + (isinteger(k) ? 0.0 : randn()^2 / 2)

function draw(post)
    σ² = post.b / gamma_draw(post.a)
    post.m .+ sqrt(σ²) .* (post.L * randn(length(post.m)))
end
