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.
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.
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.
install.packages("mhn")The development version is on GitHub:
# install.packages("remotes")
remotes::install_github("t-momozaki/mhn")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 | 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| 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 densityrmhn(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.
Full documentation, with a searchable function reference and rendered vignettes, is published at https://t-momozaki.github.io/mhn/.
vignette("introduction", package = "mhn") — a 5-minute
tour of every exported function with worked examples.?dmhn, ?pmhn, ?qmhn,
?rmhn — full argument documentation including the recycling
rules and the method argument.citation("mhn") — package + underlying papers.If you use this package in academic work, please cite both the
package and the methodology papers (citation("mhn") prints
all four):
rmhn.)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.