The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

mhn: The Modified Half-Normal Distribution

Lifecycle: experimental License: MIT R-CMD-check pkgdown

An R package providing density, distribution, quantile, and random generation functions for the Modified Half-Normal (MHN) distribution, together with closed-form / recurrence-based helpers for its moments and mode.

Overview

The MHN(\(\alpha\), \(\beta\), \(\gamma\)) distribution has support on \((0, \infty)\) and density

\[f(x \mid \alpha, \beta, \gamma) \;\propto\; x^{\alpha - 1} \exp(-\beta x^2 + \gamma x), \qquad x > 0,\]

where \(\alpha, \beta > 0\) and \(\gamma \in \mathbb{R}\). It arises as a conditional posterior in Bayesian MCMC for several common models (skew-elliptical regression, \(t\)-shrinkage priors, log-concave likelihoods with a quadratic Bayesian penalty) and generalises a number of familiar one-sided distributions:

Constraint Reduction
\(\gamma = 0\) \(\sqrt{\mathrm{Gamma}}\): \(X^2 \sim \mathrm{Gamma}(\alpha/2, \beta)\)
\(\alpha = 1\) Truncated normal on \((0, \infty)\) with location \(\gamma / (2\beta)\) and scale \(1/\sqrt{2\beta}\)
\(\alpha = 1,\; \gamma = 0\) Half-normal with scale \(1/\sqrt{2\beta}\)
\(\beta \to 0^+,\; \gamma < 0\) \(\mathrm{Gamma}(\alpha, -\gamma)\) (limit)

The package implements the efficient samplers of Sun, Kong & Pal (2023) (Algorithms 1 / 3) and the Gao & Wang (2025) Relaxed Transformed Density Rejection (RTDR) method with a uniform 1/e acceptance bound, and dispatches between them automatically.

Installation

install.packages("mhn")

The development version is on GitHub:

# install.packages("remotes")
remotes::install_github("t-momozaki/mhn")

Quick start

library(mhn)

# Density, CDF, quantile, random generation
dmhn(c(0.5, 1, 2), alpha = 2, beta = 1, gamma = 1)
pmhn(1.5,           alpha = 2, beta = 1, gamma = 1)
qmhn(0.95,          alpha = 2, beta = 1, gamma = 1)
rmhn(10,            alpha = 2, beta = 1, gamma = 1)

# Summary statistics
mhn_mean(2, 1, 1); mhn_var(2, 1, 1); mhn_mode(2, 1, 1)

Function reference

Distribution functions

Function Description
dmhn() Density (vectorised over x and parameters; supports log = TRUE)
pmhn() Cumulative distribution function (lower.tail and log.p à la pgamma)
qmhn() Quantile function via TOMS 748 root-finder
rmhn() Random generation; method dispatch via method = c("auto", "rtdr", "sun")
dmhn(1.5, alpha = 2, beta = 1, gamma = 1, log = TRUE)
pmhn(1.5, alpha = 2, beta = 1, gamma = 1, lower.tail = FALSE)
qmhn(log(0.05), alpha = 2, beta = 1, gamma = 1, log.p = TRUE)
rmhn(5, alpha = c(1, 2, 3), beta = 1, gamma = c(0, 1, -1))  # recycled

Summary statistics

Function Description
mhn_mean() \(E(X) = \Psi[(\alpha+1)/2,\, z] \,/\, (\sqrt{\beta}\, \Psi[\alpha/2,\, z])\), with \(z = \gamma/\sqrt{\beta}\)
mhn_var() Variance, Sun et al. (2023, Lemma 2c) where that form is well conditioned
mhn_skewness() Skewness \(\gamma_1\)
mhn_kurtosis() Excess kurtosis \(\gamma_2\)
mhn_mode() Mode (returns NA when no interior mode exists)
mhn_mean(2, 1, 1)       # 1.1337...
mhn_skewness(2, 1, 1)   # positive (density right-skewed)
mhn_mode(0.5, 1, -1)    # NA: monotone-decreasing density

Algorithm dispatch for rmhn(method = "auto")

The default method routes each parameter triple to the cheapest sampler that is provably correct in that region. The decision rules are benchmarked in inst/benchmarks/auto_dispatch.R:

Closed-form shortcuts:
  α = 1, γ = 0    -> half-normal via |rnorm|
  γ = 0           -> sqrt(rgamma(...))
  α = 1           -> truncated normal

Region α < 1, γ > 0:
  Gao & Wang (2025) RTDR  (Sun et al. (2023) Algorithm 2 is
                           intentionally not implemented; RTDR is
                           uniformly faster here)

Region γ > 0, α > 1:
  Sun et al. (2023, Algorithm 1) (Normal or sqrt-Gamma proposal,
                                 closed-form optimal parameters)

Region γ ≤ 0:
  n-dependent (the crossover is benchmarked, not theoretical; see
  vignette("theory") for the cost-decomposition derivation):
    α ≥ 10                        -> Sun Algorithm 3 (lower per-proposal
                                     cost than RTDR once the mode sharpens)
    samples per setup ≥ N*, α < 10 -> RTDR (lighter per-proposal cost)
    samples per setup <  N*        -> Sun Algorithm 3 (lighter setup cost)
  where N* = 25, raised to 100 for α < 0.1: the crossover moves to larger
  batches as the shape shrinks.

Choosing a specific sampler:

rmhn(1000, 2, 1, 1, method = "rtdr")   # RTDR for the general case
rmhn(1000, 2, 1, 1, method = "sun")    # Sun for the general case
                                       # (errors for α < 1, γ > 0)

method selects the sampler used for the general case. The closed-form special cases are taken first whatever it is set to: a negligible tilt draws from the square root of a Gamma, and α ≈ 1 from a truncated normal. Both are exact and cheaper than any rejection scheme.

Documentation

Full documentation, with a searchable function reference and rendered vignettes, is published at https://t-momozaki.github.io/mhn/.

Citation

If you use this package in academic work, please cite both the package and the methodology papers (citation("mhn") prints all four):

References

License

MIT © 2026 Tomotaka Momozaki. See LICENSE.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.