# R/distributions.R In LaplacesDemon: Complete Environment for Bayesian Inference

```###########################################################################
# Asymmetric Laplace Distribution                                         #
#                                                                         #
# These functions are similar to those in the VGAM package.               #
###########################################################################

dalaplace <- function(x, location=0, scale=1, kappa=1, log=FALSE)
{
x <- as.vector(x); location <- as.vector(location)
scale <- as.vector(scale); kappa <- as.vector(kappa)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
NN <- max(length(x), length(location), length(scale), length(kappa))
x <- rep(x, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN); kappa <- rep(kappa, len=NN)
logconst <- 0.5 * log(2) - log(scale) + log(kappa) - log1p(kappa^2)
temp <- which(x < location); kappa[temp] <- 1/kappa[temp]
exponent <- -(sqrt(2) / scale) * abs(x - location) * kappa
dens <- logconst + exponent
if(log == FALSE) dens <- exp(logconst + exponent)
return(dens)
}
palaplace <- function(q, location=0, scale=1, kappa=1)
{
q <- as.vector(q); location <- as.vector(location)
scale <- as.vector(scale); kappa <- as.vector(kappa)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
if((kappa <= 0)) stop("The kappa parameter must be positive.")
NN <- max(length(q), length(location), length(scale), length(kappa))
q <- rep(q, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN); kappa <- k2 <- rep(kappa, len=NN)
temp <- which(q < location); k2[temp] <- 1/kappa[temp]
exponent <- -(sqrt(2) / scale) * abs(q - location) * k2
temp <- exp(exponent) / (1 + kappa^2)
p <- 1 - temp
index1 <- (q < location)
p[index1] <- (kappa[index1])^2 * temp[index1]
return(p)
}
qalaplace <- function(p, location=0, scale=1, kappa=1)
{
p <- as.vector(p); location <- as.vector(location)
scale <- as.vector(scale); kappa <- as.vector(kappa)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(scale <= 0)) stop("The scale parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
NN <- max(length(p), length(location), length(scale), length(kappa))
p <- rep(p, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN); kappa <- rep(kappa, len=NN)
q <- p
temp <- kappa^2 / (1 + kappa^2)
index1 <- (p <= temp)
exponent <- p[index1] / temp[index1]
q[index1] <- location[index1] + (scale[index1] * kappa[index1]) *
log(exponent) / sqrt(2)
q[!index1] <- location[!index1] - (scale[!index1] / kappa[!index1]) *
(log1p((kappa[!index1])^2) + log1p(-p[!index1])) / sqrt(2)
q[p == 0] = -Inf
q[p == 1] = Inf
return(q)
}
ralaplace <- function(n, location=0, scale=1, kappa=1)
{
location <- rep(location, len=n)
scale <- rep(scale, len=n)
kappa <- rep(kappa, len=n)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
x <- location + scale *
log(runif(n)^kappa / runif(n)^(1/kappa)) / sqrt(2)
return(x)
}

###########################################################################
# Asymmetric Log-Laplace Distribution                                     #
#                                                                         #
# These functions are similar to those in the VGAM package.               #
###########################################################################

dallaplace <- function(x, location=0, scale=1, kappa=1, log=FALSE)
{
x <- as.vector(x); location <- as.vector(location)
scale <- as.vector(scale); kappa <- as.vector(kappa)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
NN <- max(length(x), length(location), length(scale), length(kappa))
x <- rep(x, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN); kappa <- rep(kappa, len=NN)
Alpha <- sqrt(2) * kappa / scale
Beta  <- sqrt(2) / (scale * kappa)
Delta <- exp(location)
exponent <- -(Alpha + 1)
temp <- which(x >= Delta); exponent[temp] <- Beta[temp] - 1
exponent <- exponent * (log(x) - location)
dens <- -location + log(Alpha) + log(Beta) -
log(Alpha + Beta) + exponent
if(log == FALSE) dens <- exp(dens)
return(dens)
}
pallaplace <- function(q, location=0, scale=1, kappa=1)
{
q <- as.vector(q); location <- as.vector(location)
scale <- as.vector(scale); kappa <- as.vector(kappa)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
NN <- max(length(q), length(location), length(scale), length(kappa))
q <- rep(q, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN); kappa <- rep(kappa, len=NN)
Alpha <- sqrt(2) * kappa / scale
Beta  <- sqrt(2) / (scale * kappa)
Delta <- exp(location)
temp <- Alpha + Beta
p <- (Alpha / temp) * (q / Delta)^(Beta)
p[q <= 0] <- 0
index1 <- (q >= Delta)
p[index1] <- (1 - (Beta/temp) * (Delta/q)^(Alpha))[index1]
return(p)
}
qallaplace <- function(p, location=0, scale=1, kappa=1)
{
p <- as.vector(p); location <- as.vector(location)
scale <- as.vector(scale); kappa <- as.vector(kappa)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(scale <= 0)) stop("The scale parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
NN <- max(length(p), length(location), length(scale), length(kappa))
p <- rep(p, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN); kappa <- rep(kappa, len=NN)
Alpha <- sqrt(2) * kappa / scale
Beta  <- sqrt(2) / (scale * kappa)
Delta <- exp(location)
temp <- Alpha + Beta
q <- Delta * (p * temp / Alpha)^(1/Beta)
index1 <- (p > Alpha / temp)
q[index1] <- (Delta * ((1-p) * temp / Beta)^(-1/Alpha))[index1]
q[p == 0] <- 0
q[p == 1] <- Inf
return(q)
}
rallaplace <- function(n, location=0, scale=1, kappa=1)
{
location <- rep(location, len=n); scale <- rep(scale, len=n)
kappa <- rep(kappa, len=n)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
x <- exp(location) *
(runif(n)^kappa / runif(n)^(1/kappa))^(scale / sqrt(2))
return(x)
}

###########################################################################
# Asymmetric Multivariate Laplace Distribution                            #
###########################################################################

daml <- function (x, mu, Sigma, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(Sigma)) Sigma <- diag(ncol(x))
if(!is.matrix(Sigma)) Sigma <- matrix(Sigma)
Sigma <- as.symmetric.matrix(Sigma)
if(!is.positive.definite(Sigma))
stop("Matrix Sigma is not positive-definite.")
k <- nrow(Sigma)
Omega <- as.inverse(Sigma)
x.Omega.mu <- rowSums(x %*% Omega * mu)
x.Omega.x <- rowSums(x %*% Omega * x)
mu.Omega.mu <- rowSums(mu %*% Omega * mu)
dens <- as.vector(log(2) + x.Omega.mu -
(log(2*pi)*(k/2) + logdet(Sigma)*0.5) +
(log(x.Omega.x) - (log(2 + mu.Omega.mu)))*((2-k)/4) +
log(besselK(sqrt((2 + mu.Omega.mu) * x.Omega.x), (2-k)/2)))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
raml <- function(n, mu, Sigma)
{
mu <- rbind(mu)
if(missing(Sigma)) Sigma <- diag(ncol(mu))
if(!is.matrix(Sigma)) Sigma <- matrix(Sigma)
if(!is.positive.definite(Sigma))
stop("Matrix Sigma is not positive-definite.")
k <- ncol(Sigma)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
e <- matrix(rexp(n, 1), n, k)
z <- rmvn(n, rep(0, k), Sigma)
x <- mu*e + sqrt(e)*z
return(x)
}

###########################################################################
# Bernoulli Distribution                                                  #
#                                                                         #
# These functions are similar to those in the Rlab package.               #
###########################################################################

dbern <- function(x, prob, log=FALSE)
{return(dbinom(x, 1, prob, log))}
pbern <- function(q, prob, lower.tail=TRUE, log.p=FALSE)
{return(pbinom(q, 1, prob, lower.tail, log.p))}
qbern <- function(p, prob, lower.tail=TRUE, log.p=FALSE)
{return(qbinom(p, 1, prob, lower.tail, log.p))}
rbern <- function(n, prob)
{return(rbinom(n, 1, prob))}

###########################################################################
# Categorical Distribution                                                #
###########################################################################

dcat <- function (x, p, log=FALSE)
{
if(!is.matrix(p)) {
if(is.vector(x)) p <- matrix(p, length(x), length(p), byrow=TRUE)
else p <- matrix(p, nrow(x), length(p), byrow=TRUE)}
if(is.vector(x)) {
if(length(x) == 1) {
temp <- rbind(rep(0, ncol(p)))
temp[1,x] <- 1
x <- temp
}
else x <- as.indicator.matrix(x)}
if(!identical(nrow(x), nrow(p)))
stop("The number of rows of x and p differ.")
if(!identical(ncol(x), ncol(p))) {
x.temp <- matrix(0, nrow(p), ncol(p))
x.temp[, as.numeric(colnames(x))] <- x
x <- x.temp}
dens <- x * log(p)
if(log == FALSE) dens <- x * p
dens <- as.vector(rowSums(dens))
return(dens)
}
qcat <- function(pr, p, lower.tail=TRUE, log.pr=FALSE)
{
if(!is.vector(pr)) pr <- as.vector(pr)
if(!is.vector(p)) p <- as.vector(p)
if(log.pr == FALSE) {
if(any(pr < 0) | any(pr > 1))
stop("pr must be in [0,1].")}
else if(any(!is.finite(pr)) | any(pr > 0))
stop("pr, as a log, must be in (-Inf,0].")
if(sum(p) != 1) stop("sum(p) must be 1.")
if(lower.tail == FALSE) pr <- 1 - pr
breaks <- c(0, cumsum(p))
if(log.pr == TRUE) breaks <- log(breaks)
breaks <- matrix(breaks, length(pr), length(breaks), byrow=TRUE)
x <- rowSums(pr > breaks)
return(x)
}
rcat <- function(n, p)
{
if(is.vector(p)) {
x <- as.vector(which(rmultinom(n, size=1, prob=p) ==
1, arr.ind=TRUE)[, "row"])
}
else {
d <- dim(p)
n <- d[1]
k <- d[2]
lev <- dimnames(p)[[2]]
if(!length(lev)) lev <- 1:k
z <- colSums(p)
U <- apply(p, 1, cumsum)
U[,k] <- 1
un <- rep(runif(n), rep(k,n))
x <- lev[1 + colSums(un > U)]}
return(x)
}

###########################################################################
# Continuous Relaxation of a Markov Random Field Distribution             #
###########################################################################

dcrmrf <- function(x, alpha, Omega, log=FALSE)
{
alpha <- as.vector(alpha)
if(missing(Omega)) Omega <- diag(length(alpha))
if(!is.matrix(Omega)) Omega <- matrix(Omega)
Omega <- as.symmetric.matrix(Omega)
if(!is.positive.definite(Omega))
stop("Matrix Omega is not positive-definite.")
dens <- as.vector(-0.5*t(x) %*% as.inverse(Omega) %*% x) +
log(prod(1 + exp(x + alpha)))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rcrmrf <- function(n=1, alpha, Omega)
{
alpha <- as.vector(alpha)
J <- length(alpha)
if(missing(Omega)) Omega <- diag(J)
if(!is.matrix(Omega)) Omega <- matrix(Omega)
if(!is.positive.definite(Omega))
stop("Matrix Omega is not positive-definite.")
dens <- rep(0,J)
x <- rep(0,n)
for (i in 1:n) {
for (j in 1:J) {
z <- as.vector(rmvn(1,
as.vector(Omega %*% diag(J)[j,]), Omega))
dens[j] <- dcrmrf(z, alpha, Omega, log=FALSE)}
x[i] <- sample(1:J, size=1, replace=TRUE, prob=dens)}
return(x)
}

###########################################################################
# Dirichlet Distribution                                                  #
#                                                                         #
# These functions are similar to those in the MCMCpack package.           #
###########################################################################

ddirichlet <- function(x, alpha, log=FALSE)
{
if(missing(x)) stop("x is a required argument.")
if(missing(alpha)) stop("alpha is a required argument.")
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(alpha))
alpha <- matrix(alpha, nrow(x), length(alpha), byrow=TRUE)
if(any(rowSums(x) != 1)) x / rowSums(x)
if(any(x < 0)) stop("x must be non-negative.")
if(any(alpha <= 0)) stop("alpha must be positive.")
dens <- as.vector(lgamma(rowSums(alpha)) - rowSums(lgamma(alpha)) +
rowSums((alpha-1)*log(x)))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rdirichlet <- function (n, alpha)
{
alpha <- rbind(alpha)
alpha.dim <- dim(alpha)
if(n > alpha.dim[1])
alpha <- matrix(alpha, n, alpha.dim[2], byrow=TRUE)
x <- matrix(rgamma(alpha.dim[2]*n, alpha), ncol=alpha.dim[2])
sm <- x %*% rep(1, alpha.dim[2])
return(x/as.vector(sm))
}

###########################################################################
# Generalized Pareto Distribution                                         #
###########################################################################

dgpd <- function(x, mu, sigma, xi, log=FALSE)
{
x <- as.vector(x)
mu <- as.vector(mu)
sigma <- as.vector(sigma)
xi <- as.vector(xi)
if(any(sigma <= 0)) stop("The sigma parameter must be positive.")
NN <- max(length(x), length(mu), length(sigma), length(xi))
x <- rep(x, len=NN); mu <- rep(mu, len=NN)
sigma <- rep(sigma, len=NN); xi <- rep(xi, len=NN)
xi.ge.0 <- which(xi >= 0)
xi.lt.0 <- which(xi < 0)
if(any(mu > x) |
any(mu[xi.lt.0] < x[xi.lt.0] + sigma[xi.lt.0] / xi[xi.lt.0]))
stop("x is outside of support.")
z <- (x - mu) / sigma
xi0 <- which(xi == 0)
xi1 <- which(xi != 0)
dens <- rep(NA, NN)
dens[xi0] <- -z[xi0] - log(sigma[xi0])
dens[xi1] <- log(1/sigma[xi1]) + log(1 + xi[xi1] *
z[xi1]) * (-1/xi[xi1] - 1)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rgpd <- function(n, mu, sigma, xi)
{
mu <- as.vector(mu)
sigma <- as.vector(sigma)
xi <- as.vector(xi)
if(any(sigma <= 0)) stop("The sigma parameter must be non-negative.")
mu <- rep(mu, len=n); sigma <- rep(sigma, len=n)
xi <- rep(xi, len=n)
x <- rep(NA,n)
u <- runif(n, min=0.001)
xi0 <- which(xi == 0)
xi1 <- which(xi != 0)
x[xi0] <- mu[xi0] - sigma[xi0] * log(u[xi0])
x[xi1] <- mu[xi1] + sigma[xi1] *
(u[xi1]^(-xi[xi1]) - 1) / xi[xi1]
return(x)
}

###########################################################################
# Generalized Poisson                                                     #
###########################################################################

dgpois <- function(x, lambda=0, omega=0, log=FALSE)
{
x <- as.vector(x); lambda <- as.vector(lambda)
omega <- as.vector(omega)
lambda.star <- (1 - omega)*lambda + omega*x
dens <- log(1 - omega) + log(lambda) + (x - 1)*log(lambda.star) -
lgamma(x + 1) - lambda.star
if(log == FALSE) dens <- exp(dens)
return(dens)
}

###########################################################################
# Half-Cauchy Distribution                                                #
###########################################################################

dhalfcauchy <- function(x, scale=25, log=FALSE)
{
x <- as.vector(x); scale <- as.vector(scale)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(x), length(scale))
x <- rep(x, len=NN); scale <- rep(scale, len=NN)
dens <- log(2*scale) - log(pi*{x*x + scale*scale})
if(log == FALSE) dens <- exp(dens)
return(dens)
}
phalfcauchy <- function(q, scale=25)
{
q <- as.vector(q); scale <- as.vector(scale)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(q), length(scale))
q <- rep(q, len=NN); scale <- rep(scale, len=NN)
z <- {2/pi}*atan(q/scale)
return(z)
}
qhalfcauchy <- function(p, scale=25)
{
p <- as.vector(p); scale <- as.vector(scale)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(p), length(scale))
p <- rep(p, len=NN); scale <- rep(scale, len=NN)
q <- scale*tan({pi*p}/2)
return(q)
}
rhalfcauchy <- function(n, scale=25)
{
scale <- rep(scale, len=n)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
p <- runif(n, 0, 1)
x <- scale*tan({pi*p}/2)
return(x)
}

###########################################################################
# Half-Normal Distribution                                                #
#                                                                         #
# This half-normal distribution has mean=0 and is similar to the halfnorm #
# functions in package fdrtool.                                           #
###########################################################################

dhalfnorm <- function(x, scale=sqrt(pi/2), log=FALSE)
{
dens <- log(2) + dnorm(x, mean=0, sd=sqrt(pi/2) / scale, log=TRUE)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
phalfnorm <- function(q, scale=sqrt(pi/2), lower.tail=TRUE, log.p=FALSE)
{
q <- as.vector(q); scale <- as.vector(scale)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(q), length(scale))
q <- rep(q, len=NN); scale <- rep(scale, len=NN)
p <- 2*pnorm(q, mean=0, sd=sqrt(pi/2) / scale) - 1
if(lower.tail == FALSE) p <- 1-p
if(log.p == TRUE) p <- log.p(p)
return(p)
}
qhalfnorm <- function(p, scale=sqrt(pi/2), lower.tail=TRUE, log.p=FALSE)
{
p <- as.vector(p); scale <- as.vector(scale)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(p), length(scale))
p <- rep(p, len=NN); scale <- rep(scale, len=NN)
if(log.p == TRUE) p <- exp(p)
if(lower.tail == FALSE) p <- 1-p
q <- qnorm((p+1)/2, mean=0, sd=sqrt(pi/2) / scale)
return(q)
}
rhalfnorm <- function(n, scale=sqrt(pi/2))
{
scale <- rep(scale, len=n)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
x <- abs(rnorm(n, mean=0, sd=sqrt(pi/2) / scale))
return(x)
}

###########################################################################
# Half-t Distribution                                                     #
###########################################################################

dhalft <- function(x, scale=25, nu=1, log=FALSE)
{
x <- as.vector(x); scale <- as.vector(scale); nu <- as.vector(nu)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(x), length(scale), length(nu))
x <- rep(x, len=NN); scale <- rep(scale, len=NN)
nu <- rep(nu, len=NN)
dens <- log(2) -log(scale) + lgamma((nu + 1)/2) - lgamma(nu/2) -
.5*log(pi*nu) - (nu + 1)/2 * log(1 + (1/nu) * (x/scale) * (x/scale))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
phalft <- function(q, scale=25, nu=1)
{
q <- as.vector(q); scale <- as.vector(scale); nu <- as.vector(nu)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(q), length(scale), length(nu))
q <- rep(q, len=NN); scale <- rep(scale, len=NN)
p <- ptrunc(q, "st", a=0, b=Inf, mu=0, sigma=scale, nu=nu)
return(p)
}
qhalft <- function(p, scale=25, nu=1)
{
p <- as.vector(p); scale <- as.vector(scale); nu <- as.vector(nu)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(p), length(scale), length(nu))
p <- rep(p, len=NN); scale <- rep(scale, len=NN)
q <- rtrunc(p, "st", a=0, b=Inf, mu=0, sigma=scale, nu=nu)
return(q)
}
rhalft <- function(n, scale=25, nu=1)
{
scale <- rep(scale, len=n); nu <- rep(nu, len=n)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
x <- rtrunc(n, "st", a=0, b=Inf, mu=0, sigma=scale, nu=nu)
return(x)
}

###########################################################################
# Horseshoe Distribution                                                  #
###########################################################################

dhs <- function(x, lambda, tau, log=FALSE)
{
dens <- dnorm(x, 0, lambda*tau, log=log)
return(dens)
}
rhs <- function(n, lambda, tau)
{
x <- rnorm(n, 0, lambda*tau)
return(x)
}

###########################################################################
# Huang-Wand Distribution                                                 #
###########################################################################

dhuangwand <- function(x, nu=2, a, A, log=FALSE)
{
if(!is.matrix(x)) x <- matrix(x)
if(!is.positive.definite(x))
stop("Matrix x is not positive-definite.")
a <- as.vector(a)
A <- as.vector(A)
k <- nrow(x)
if(!identical(length(a), length(A), k, ncol(x)))
stop("Dimensions of x, a, and A do not agree.")
dens <- sum(dinvgamma(a, 0.5, 1/A^2, log=TRUE)) +
dinvwishart(x, nu + k - 1, 2*nu*diag(1/a), log=TRUE)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rhuangwand <- function(nu=2, a, A)
{
if(missing(A)) k <- length(a)
else {
k <- length(A)
a <- rinvgamma(k, 0.5, 1/A^2)}
x <- rinvwishart(nu + k - 1, 2*nu*diag(1/a))
return(x)
}

###########################################################################
# Huang-Wand Distribution (Cholesky Parameterization)                     #
###########################################################################

dhuangwandc <- function(x, nu=2, a, A, log=FALSE)
{
if(!is.matrix(x)) x <- matrix(x)
a <- as.vector(a)
A <- as.vector(A)
k <- nrow(x)
if(!identical(length(a), length(A), k, ncol(x)))
stop("Dimensions of x, a, and A do not agree.")
dens <- sum(dinvgamma(a, 0.5, 1/A^2, log=TRUE)) +
dinvwishartc(x, nu + k - 1, 2*nu*diag(1/a), log=TRUE)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rhuangwandc <- function(nu=2, a, A)
{
if(missing(A)) k <- length(a)
else {
k <- length(A)
a <- rinvgamma(k, 0.5, 1/A^2)}
x <- rinvwishartc(nu + k - 1, 2*nu*diag(1/a))
return(x)
}

###########################################################################
# Inverse Beta Distribution                                               #
###########################################################################

dinvbeta <- function(x, a, b, log=FALSE)
{
const <- lgamma(a + b) - lgamma(a) - lgamma(b)
dens <- const + (a - 1) * log(x) - (a + b) * log(1 + x)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rinvbeta <- function(n, a, b)
{
x <- rbeta(n, a, b)
x <- x / (1-x)
return(x)
}

###########################################################################
# Inverse Chi-Squared Distribution                                        #
#                                                                         #
# These functions are similar to those in the GeoR package.               #
###########################################################################

dinvchisq <- function(x, df, scale=1/df, log=FALSE)
{
x <- as.vector(x); df <- as.vector(df); scale <- as.vector(scale)
if(any(x <= 0)) stop("x must be positive.")
if(any(df <= 0)) stop("The df parameter must be positive.")
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(x), length(df), length(scale))
x <- rep(x, len=NN); df <- rep(df, len=NN);
scale <- rep(scale, len=NN)
nu <- df / 2
dens <- nu*log(nu) - log(gamma(nu)) + nu*log(scale) -
(nu+1)*log(x) - (nu*scale/x)
if(log == FALSE) dens <- exp(dens)
return(dens)
}

rinvchisq <- function(n, df, scale=1/df)
{
df <- rep(df, len=n); scale <- rep(scale, len=n)
if(any(df <= 0)) stop("The df parameter must be positive.")
if(any(scale <= 0)) stop("The scale parameter must be positive.")
z <- rchisq(n, df=df)
z[which(z == 0)] <- 1e-100
x <- (df*scale) / z
return(x)
}

###########################################################################
# Inverse Gamma Distribution                                              #
#                                                                         #
# These functions are similar to those in the MCMCpack package.           #
###########################################################################

dinvgamma <- function(x, shape=1, scale=1, log=FALSE)
{
x <- as.vector(x); shape <- as.vector(shape)
scale <- as.vector(scale)
if(any(shape <= 0) | any(scale <=0))
stop("The shape and scale parameters must be positive.")
NN <- max(length(x), length(shape), length(scale))
x <- rep(x, len=NN); shape <- rep(shape, len=NN)
scale <- rep(scale, len=NN)
alpha <- shape; beta <- scale
dens <- alpha * log(beta) - lgamma(alpha) -
{alpha + 1} * log(x) - {beta/x}
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rinvgamma <- function(n, shape=1, scale=1)
{
x <- rgamma(n=n, shape=shape, rate=scale)
x[which(x < 1e-300)] <- 1e-300
return(1 / x)
}

###########################################################################
# Inverse Gaussian Distribution                                           #
###########################################################################

dinvgaussian <- function(x, mu, lambda, log=FALSE)
{
x <- as.vector(x); mu <- as.vector(mu); lambda <- as.vector(lambda)
if(any(x <= 0)) stop("x must be positive.")
if(any(mu <= 0)) stop("The mu parameter must be positive.")
if(any(lambda <= 0)) stop("The lambda parameter must be positive.")
NN <- max(length(x), length(mu), length(lambda))
x <- rep(x, len=NN); mu <- rep(mu, len=NN)
lambda <- rep(lambda, len=NN)
dens <- log(lambda / (2*pi*x^3)^0.5) -
((lambda*(x - mu)^2) / (2*mu^2*x))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rinvgaussian <- function(n, mu, lambda)
{
mu <- rep(mu, len=n); lambda <- rep(lambda, len=n)
if(any(mu <= 0)) stop("The mu parameter must be positive.")
if(any(lambda <= 0)) stop("The lambda parameter must be positive.")
nu <- rnorm(n)
y <- nu^2
x <- mu + ((mu^2*y)/(2*lambda)) - (mu/(2*lambda)) *
sqrt(4*mu*lambda*y + mu^2*y^2)
z <- runif(n)
temp <- which(z > {mu / (mu + x)})
x[temp] <- mu[temp] * mu[temp] / x[temp]
return(x)
}

###########################################################################
# Inverse Matrix Gamma Distribution                                       #
###########################################################################

dinvmatrixgamma <- function(X, alpha, beta, Psi, log=FALSE)
{
if(!is.matrix(X)) stop("X is not a matrix.")
if(alpha <= 2) stop("The alpha parameter must be greater than 2.")
if(beta <= 0) stop("The beta parameter must be positive.")
if(missing(Psi)) Psi <- diag(ncol(X))
if(!is.positive.definite(Psi))
stop("Matrix Psi is not positive-definite.")
k <- nrow(Psi)
gamsum <- 0
for (i in 1:k) gamsum <- gamsum + lgamma(alpha - 0.5*(i-1))
gamsum <- gamsum + log(pi)*(k*(k-1)/4)
Omega <- as.inverse(Psi)
dens <- logdet(Psi)*alpha - (log(beta)*(k*alpha) + gamsum) +
logdet(X)*(-alpha-(k+1)/2) +
tr(-(1/beta)*(Psi %*% as.inverse(X)))
if(log == FALSE) dens <- exp(dens)
return(dens)
}

rinvmatrixgamma <- function(alpha, beta, Psi){
rinvwishart(2*alpha, 2/beta*Psi)
}

###########################################################################
# Inverse Wishart Distribution                                            #
###########################################################################

dinvwishart <- function(Sigma, nu, S, log=FALSE)
{
if(!is.matrix(Sigma)) Sigma <- matrix(Sigma)
if(!is.positive.definite(Sigma))
stop("Matrix Sigma is not positive-definite.")
if(!is.matrix(S)) S <- matrix(S)
if(!is.positive.semidefinite(S))
stop("Matrix S is not positive-semidefinite.")
if(!identical(dim(S), dim(Sigma)))
stop("The dimensions of Sigma and S differ.")
if(nu < nrow(S))
stop("The nu parameter is less than the dimension of S.")
k <- nrow(Sigma)
gamsum <- 0
for (i in 1:k) {gamsum <- gamsum + lgamma((nu + 1 - i)/2)}
dens <- -(nu*k/2)*log(2) - ((k*(k - 1))/4)*log(pi) - gamsum +
(nu/2)*log(det(S)) - ((nu + k + 1)/2)*logdet(Sigma) -
0.5*tr(S %*% as.inverse(Sigma))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rinvwishart <- function(nu, S)
{return(chol2inv(rwishartc(nu, chol2inv(chol(S)))))}

###########################################################################
# Inverse Wishart Distribution (Cholesky Parameterization)                #
###########################################################################

dinvwishartc <- function(U, nu, S, log=FALSE)
{
if(missing(U)) stop("Upper triangular U is required.")
Sigma <- t(U) %*% U
if(!is.matrix(S)) S <- matrix(S)
if(!is.positive.semidefinite(S))
stop("Matrix S is not positive-semidefinite.")
if(!identical(dim(S), dim(Sigma)))
stop("The dimensions of Sigma and S differ.")
if(nu < nrow(S))
stop("The nu parameter is less than the dimension of S.")
k <- nrow(Sigma)
gamsum <- 0
for (i in 1:k) {gamsum <- gamsum + lgamma((nu + 1 - i)/2)}
dens <- -(nu*k/2)*log(2) - ((k*(k - 1))/4)*log(pi) - gamsum +
(nu/2)*log(det(S)) - ((nu + k + 1)/2)*logdet(Sigma) -
0.5*tr(S %*% as.inverse(Sigma))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rinvwishartc <- function(nu, S)
{return(chol(as.inverse(rwishart(nu, as.inverse(S)))))}

###########################################################################
# Laplace Distribution                                                    #
#                                                                         #
# These functions are similar to those in the VGAM package.               #
###########################################################################

dlaplace <- function(x, location=0, scale=1, log=FALSE)
{
x <- as.vector(x); location <- as.vector(location)
scale <- as.vector(scale)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(x), length(location), length(scale))
x <- rep(x, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN)
dens <- (-abs(x - location) / scale) - log(2 * scale)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
plaplace <- function(q, location=0, scale=1)
{
q <- as.vector(q); location <- as.vector(location)
scale <- as.vector(scale)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
z <- {q - location} / scale
NN <- max(length(q), length(location), length(scale))
q <- rep(q, len=NN); location <- rep(location, len=NN)
p <- q
temp <- which(q < location); p[temp] <- 0.5 * exp(z[temp])
temp <- which(q >= location); p[temp] <- 1 - 0.5 * exp(-z[temp])
return(p)
}
qlaplace <- function(p, location=0, scale=1)
{
p <- as.vector(p); location <- as.vector(location)
scale <- as.vector(scale)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(p), length(location), length(scale))
p <- p2 <- rep(p, len=NN); location <- rep(location, len=NN)
temp <- which(p > 0.5); p2[temp] <- 1 - p[temp]
q <- location - sign(p - 0.5) * scale * log(2 * p2)
return(q)
}
rlaplace <- function(n, location=0, scale=1)
{
location <- rep(location, len=n); scale <- rep(scale, len=n)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
r <- r2 <- runif(n)
temp <- which(r > 0.5); r2[temp] <- 1 - r[temp]
x <- location - sign(r - 0.5) * scale * log(2 * r2)
return(x)
}

###########################################################################
# Laplace Distribution (Precision Parameterization)                       #
###########################################################################

dlaplacep <- function(x, mu=0, tau=1, log=FALSE)
{
x <- as.vector(x); mu <- as.vector(mu); tau <- as.vector(tau)
if(any(tau <= 0)) stop("The tau parameter must be positive.")
NN <- max(length(x), length(mu), length(tau))
x <- rep(x, len=NN); mu <- rep(mu, len=NN); tau <- rep(tau, len=NN)
dens <- log(tau/2) + (-tau*abs(x-mu))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
plaplacep <- function(q, mu=0, tau=1)
{
q <- as.vector(q); mu <- as.vector(mu)
if(any(tau <= 0)) stop("The tau parameter must be positive.")
NN <- max(length(q), length(mu), length(tau))
q <- rep(q, len=NN); mu <- rep(mu, len=NN); tau <- rep(tau, len=NN)
p <- plaplace(q, mu, scale=1/tau)
return(p)
}
qlaplacep <- function(p, mu=0, tau=1)
{
p <- as.vector(p); mu <- as.vector(mu)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(tau <= 0)) stop("The tau parameter must be positive.")
NN <- max(length(p), length(mu), length(tau))
p <- rep(p, len=NN); mu <- rep(mu, len=NN); tau <- rep(tau, len=NN)
q <- qlaplace(p, mu, scale=1/tau)
return(q)
}
rlaplacep <- function(n, mu=0, tau=1)
{
mu <- rep(mu, len=n); tau <- rep(tau, len=n)
if(any(tau <= 0)) stop("The tau parameter must be positive.")
x <- rlaplace(n, mu, scale=1/tau)
return(x)
}

###########################################################################
# Laplace Distribution Mixture                                            #
###########################################################################

dlaplacem <- function(x, p, location, scale, log=FALSE)
{
if(missing(x)) stop("x is a required argument.")
x <- as.vector(x)
n <- length(x)
if(missing(p)) stop("p is a required argument.")
p <- as.vector(p)
if(any(p <= 0) | any(p > 1)) stop("p must be in (0,1].")
if(sum(p) != 1) stop("p must sum to 1 for all components.")
m <- length(p)
p <- matrix(p, n, m, byrow=TRUE)
if(missing(location)) stop("location is a required argument.")
location <- as.vector(location)
if(!identical(m, length(location)))
stop("p and location differ in length.")
location <- matrix(location, n, m, byrow=TRUE)
if(missing(scale)) stop("scale is a required argument.")
scale <- as.vector(scale)
if(!identical(m, length(scale)))
stop("p and scale differ in length.")
scale <- matrix(scale, n, m, byrow=TRUE)
dens <- matrix(dlaplace(x, location, scale, log=TRUE), n, m)
dens <- dens + log(p)
if(log == TRUE) dens <- apply(dens, 1, logadd)
else dens <- rowSums(exp(dens))
return(dens)
}
plaplacem <- function(q, p, location, scale)
{
n <- length(q)
m <- length(p)
q <- matrix(q, n, m)
p <- matrix(p, n, m, byrow=TRUE)
location <- matrix(location, n, m, byrow=TRUE)
scale <- matrix(scale, n, m, byrow=TRUE)
cdf <- matrix(plaplace(q, location, scale), n, m)
cdf <- rowSums(cdf * p)
return(cdf)
}
rlaplacem <- function(n, p, location, scale)
{
if(missing(p)) stop("p is a required argument.")
p <- as.vector(p)
if(any(p <= 0) | any(p > 1)) stop("p must be in (0,1].")
if(sum(p) != 1) stop("p must sum to 1 for all components.")
m <- length(p)
p <- matrix(p, n, m, byrow=TRUE)
if(missing(location)) stop("location is a required argument.")
location <- as.vector(location)
if(!identical(m, length(location)))
stop("p and location differ in length.")
if(missing(scale)) stop("scale is a required argument.")
scale <- as.vector(scale)
if(!identical(m, length(scale)))
stop("p and scale differ in length.")
if(any(scale <= 0)) stop("scale must be positive.")
z <- rcat(n, p)
x <- rlaplace(n, location=location[z], scale=scale[z])
return(x)
}

###########################################################################
# LASSO Distribution                                                      #
###########################################################################

dlasso <- function(x, sigma, tau, lambda, a=1, b=1, log=FALSE)
{
if(any(c(sigma, tau, lambda, a, b) <= 0))
stop("Scale parameters must be positive.")
dens <- sum(dmvn(x, 0, sigma^2*diag(tau^2), log=TRUE)) +
log(1/sigma^2) + sum(dexp(tau^2, lambda^2/2, log=TRUE)) +
dgamma(lambda^2, a, b, log=TRUE)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rlasso <- function(n, sigma, tau, lambda, a=1, b=1)
{
a <- as.vector(a)[1]
b <- as.vector(b)[1]
if(missing(sigma)) sigma <- runif(1, 1e-100, 1000)
if(missing(lambda)) lambda <- sqrt(rgamma(1, a, b))
if(missing(tau)) stop("The tau parameter is a required argument.")
sigma <- as.vector(sigma)[1]
lambda <- as.vector(lambda)[1]
x <- rnorm(n, 0, sigma^2*diag(tau^2))
return(x)
}

###########################################################################
# Log-Laplace Distribution                                                #
###########################################################################

dllaplace <- function(x, location=0, scale=1, log=FALSE)
{
x <- as.vector(x); location <- as.vector(location)
scale <- as.vector(scale)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(x), length(location), length(scale))
x <- rep(x, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN)
Alpha <- sqrt(2) * scale
Beta  <- sqrt(2) / scale
Delta <- exp(location)
exponent <- -(Alpha + 1)
temp <- which(x < Delta); exponent[temp] <- Beta[temp] - 1
exponent <- exponent * (log(x) - location)
dens <- -location + log(Alpha) + log(Beta) -
log(Alpha + Beta) + exponent
if(log == FALSE) dens <- exp(dens)
return(dens)
}
pllaplace <- function(q, location=0, scale=1)
{
q <- as.vector(q); location <- as.vector(location)
scale <- as.vector(scale)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(q), length(location), length(scale))
q <- rep(q, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN)
Alpha <- sqrt(2) * scale
Beta  <- sqrt(2) / scale
Delta <- exp(location)
temp <- Alpha + Beta
p <- (Alpha / temp) * (q / Delta)^(Beta)
p[q <= 0] <- 0
index1 <- (q >= Delta)
p[index1] <- (1 - (Beta/temp) * (Delta/q)^(Alpha))[index1]
return(p)
}
qllaplace <- function(p, location=0, scale=1)
{
p <- as.vector(p); location <- as.vector(location)
scale <- as.vector(scale)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(scale <= 0)) stop("The scale parameter must be positive.")
NN <- max(length(p), length(location), length(scale))
p <- rep(p, len=NN); location <- rep(location, len=NN)
scale <- rep(scale, len=NN)
Alpha <- sqrt(2) * scale
Beta  <- sqrt(2) / scale
Delta <- exp(location)
temp <- Alpha + Beta
q <- Delta * (p * temp / Alpha)^(1/Beta)
index1 <- (p > Alpha / temp)
q[index1] <- (Delta * ((1-p) * temp / Beta)^(-1/Alpha))[index1]
q[p == 0] <- 0
q[p == 1] <- Inf
return(q)
}
rllaplace <- function(n, location=0, scale=1)
{
location <- rep(location, len=n); scale <- rep(scale, len=n)
if(any(scale <= 0)) stop("The scale parameter must be positive.")
x <- exp(location) * (runif(n) / runif(n))^(scale / sqrt(2))
return(x)
}

###########################################################################
# Log-Normal Distribution (Precision Parameterization)                    #
###########################################################################

dlnormp <- function(x, mu, tau = NULL, var = NULL, log = FALSE)
{
if (!is.null(tau) & !is.null(var))
stop("use either tau or var, but not both")

x <- as.vector(x); mu <- as.vector(mu);
if (!is.null(tau))
{
tau <- as.vector(tau)
if(any(tau <= 0))
stop("The tau parameter must be positive.")

NN <- max(length(x), length(mu), length(tau))
x <- rep(x, len=NN); mu <- rep(mu, len=NN); tau <- rep(tau, len=NN)
dens <- 0.5*(log(tau) - log(2*pi)) - log(x) - tau/2*(log(x) - mu)^2
}

if (!is.null(var))
{
var <- as.vector(var)
if(any(var <= 0))
stop("The var parameter must be positive.")

NN <- max(length(x), length(mu), length(var))
x <- rep(x, len=NN); mu <- rep(mu, len=NN); var <- rep(var, len=NN)
dens <- -0.5*log(2*pi*var) - log(x) - (log(x) - mu)^2/(2*var)
}

if(log == FALSE)
dens <- exp(dens)

return(dens)
}
plnormp <- function(q, mu, tau, lower.tail=TRUE, log.p=FALSE)
{
q <- as.vector(q); mu <- as.vector(mu); tau <- as.vector(tau)
if(any(tau <= 0)) stop("The tau parameter must be positive.")
NN <- max(length(q), length(mu), length(tau))
q <- rep(q, len=NN); mu <- rep(mu, len=NN); tau <- rep(tau, len=NN)
p <- pnorm(q, mu, sqrt(1/tau), lower.tail, log.p)
return(p)
}
qlnormp <- function(p, mu, tau, lower.tail=TRUE, log.p=FALSE)
{
p <- as.vector(p); mu <- as.vector(mu); tau <- as.vector(tau)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(tau <= 0)) stop("The tau parameter must be positive.")
NN <- max(length(p), length(mu), length(tau))
p <- rep(p, len=NN); mu <- rep(mu, len=NN); tau <- rep(tau, len=NN)
q <- qnorm(p, mu, sqrt(1/tau), lower.tail, log.p)
return(q)
}

rlnormp <- function(n, mu, tau = NULL, var = NULL)
{
if (!is.null(tau) & !is.null(var))
stop("use either tau or var, but not both")

mu <- rep(mu, len=n);
if (!is.null(tau))
{
if(any(tau <= 0))
stop("The tau parameter must be positive.")

tau <- rep(tau, len=n)
x <- rlnorm(n, log(mu^2 / sqrt(1/tau^2 + mu^2)), sqrt(log(1 + 1/(mu^2*tau^2))))
}
if (!is.null(var))
{
var = rep(var, len=n)
if(any(var <= 0))
stop("The var parameter must be positive.")

var <- rep(var, len=n)
x <- rlnorm(n, log(mu^2 / sqrt(var^2 + mu^2)), sqrt(log(1 + (var^2/mu^2))))
}
return(x)
}

###########################################################################
# Matrix Gamma Distribution                                               #
###########################################################################

dmatrixgamma <- function(X, alpha, beta, Sigma, log=FALSE)
{
if(!is.matrix(X)) stop("X is not a matrix.")
if(alpha <= 2) stop("The alpha parameter must be greater than 2.")
if(beta <= 0) stop("The beta parameter must be positive.")
if(missing(Sigma)) Sigma <- diag(ncol(X))
if(!is.positive.definite(Sigma))
stop("Matrix Sigma is not positive-definite.")
k <- nrow(Sigma)
gamsum <- 0
for (i in 1:k) gamsum <- gamsum + lgamma(alpha - 0.5*(i-1))
gamsum <- gamsum + log(pi)*(k*(k-1)/4)
Omega <- as.inverse(Sigma)
dens <- alpha*logdet(Omega) + logdet(X)*(alpha - 0.5*(k+1)) -
(log(beta)*(k*alpha) + gamsum) + (-1/beta)*tr(Omega %*% X)
if(log == FALSE) dens <- exp(dens)
return(dens)
}

rmatrixgamma <- function(alpha, beta, Sigma){
rwishart(2*alpha, beta/2*Sigma)
}
###########################################################################
# Matrix Normal Distribution                                              #
###########################################################################

dmatrixnorm <- function(X, M, U, V, log=FALSE)
{
if(!is.matrix(X)) X <- rbind(X)
if(!is.matrix(M)) M <- matrix(M, nrow(X), ncol(X), byrow=TRUE)
if(missing(U)) U <- diag(nrow(X))
if(!is.matrix(U)) U <- matrix(U)
if(!is.positive.definite(U))
stop("Matrix U is not positive-definite.")
if(missing(V)) V <- diag(ncol(X))
if(!is.matrix(V)) V <- matrix(V)
if(!is.positive.definite(V))
stop("Matrix V is not positive-definite.")
n <- nrow(X)
k <- ncol(X)
ss <- X - M
dens <- -0.5*tr(as.inverse(V) %*% t(ss) %*%
as.inverse(U) %*% ss) - (log(2*pi)*(n*k/2) +
logdet(V)*(n/2) + logdet(U)*(k/2))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmatrixnorm <- function(M, U, V)
{
if(missing(M)) stop("Matrix M is missing.")
if(!is.matrix(M)) M <- matrix(M)
if(missing(U)) stop("Matrix U is missing.")
if(!is.matrix(U)) U <- matrix(U)
if(!is.positive.definite(U))
stop("Matrix U is not positive-definite.")
if(missing(V)) stop("Matrix V is missing.")
if(!is.matrix(V)) V <- matrix(V)
if(!is.positive.definite(V))
stop("Matrix V is not positive-definite.")
if(nrow(M) != nrow(U))
stop("Dimensions of M and U are incorrect.")
if(ncol(M) != ncol(V))
stop("Dimensions of M and V are incorrect.")
n <- nrow(U)
k <- ncol(V)
Z <- matrix(rnorm(n * k), n, k)
X <- M + t(chol(U)) %*% Z %*% chol(V)
return(X)
}

###########################################################################
# Multivariate Cauchy Distribution                                        #
###########################################################################

dmvc <- function(x, mu, S, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(S)) S <- diag(ncol(x))
if(!is.matrix(S)) S <- matrix(S)
if(!is.positive.definite(S))
stop("Matrix S is not positive-definite.")
k <- nrow(S)
ss <- x - mu
Omega <- as.inverse(S)
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(lgamma((1 + k)/2) - (lgamma(0.5) +
(k/2)*log(pi) + 0.5*logdet(S) + ((1+k)/2)*log(1+z)))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvc <- function(n=1, mu=rep(0,k), S)
{
mu <- rbind(mu)
if(missing(S)) S <- diag(ncol(mu))
if(!is.matrix(S)) S <- matrix(S)
if(!is.positive.definite(S))
stop("Matrix S is not positive-definite.")
k <- ncol(S)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
x <- rchisq(n,1)
x[which(x == 0)] <- 1e-100
z <- rmvn(n, rep(0,k), S)
x <- mu + z/sqrt(x)
return(x)
}

###########################################################################
# Multivariate Cauchy Distribution (Cholesky Parameterization)            #
###########################################################################

dmvcc <- function(x, mu, U, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(U)) stop("Upper triangular U is required.")
k <- nrow(U)
S <- t(U) %*% U
ss <- x - mu
Omega <- as.inverse(S)
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(lgamma(k/2) - (lgamma(0.5) + log(1^(k/2)) +
(k/2)*log(pi) + 0.5*logdet(S) + ((1+k)/2)*log(1+z)))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvcc <- function(n=1, mu=rep(0,k), U)
{
mu <- rbind(mu)
if(missing(U)) stop("Upper triangular U is required.")
k <- ncol(U)
S <- t(U) %*% U
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
x <- rchisq(n,1)
x[which(x == 0)] <- 1e-100
z <- rmvnc(n, rep(0,k), U)
x <- mu + z/sqrt(x)
return(x)
}

###########################################################################
# Multivariate Cauchy Distribution (Precision Parameterization)           #
###########################################################################

dmvcp <- function(x, mu, Omega, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(Omega)) Omega <- diag(ncol(x))
if(!is.matrix(Omega)) Omega <- matrix(Omega)
if(!is.positive.definite(Omega))
stop("Matrix Omega is not positive-definite.")
k <- nrow(Omega)
logdetOmega <- logdet(Omega)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(lgamma((1+k)/2) - (lgamma(0.5) + log(1^(k/2)) +
(k/2)*log(pi)) + 0.5*logdetOmega + (-(1+k)/2)*log(1 + z))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvcp <- function(n=1, mu, Omega)
{
mu <- rbind(mu)
if(missing(Omega)) Omega <- diag(ncol(mu))
if(!is.matrix(Omega)) Omega <- matrix(Omega)
if(!is.positive.definite(Omega))
stop("Matrix Omega is not positive-definite.")
Sigma <- as.inverse(Omega)
k <- ncol(Sigma)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
x <- rchisq(n,1)
x[which(x == 0)] <- 1e-100
z <- rmvn(n, rep(0,k), Sigma)
x <- mu + z/sqrt(x)
return(x)
}

###########################################################################
# Multivariate Cauchy Distribution (Precision-Cholesky Parameterization)  #
###########################################################################

dmvcpc <- function(x, mu, U, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(U)) stop("Upper triangular U is required.")
k <- nrow(U)
Omega <- t(U) %*% U
logdetOmega <- logdet(Omega)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(lgamma((1+k)/2) - (lgamma(0.5) + log(1^(k/2)) +
(k/2)*log(pi)) + 0.5*logdetOmega + (-(1+k)/2)*log(1 + z))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvcpc <- function(n=1, mu, U)
{
mu <- rbind(mu)
if(missing(U)) stop("Upper triangular U is required.")
k <- ncol(U)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
x <- rchisq(n,1)
x[which(x == 0)] <- 1e-100
z <- rmvnc(n, rep(0,k), U)
x <- mu + z/sqrt(x)
return(x)
}

###########################################################################
# Multivariate Laplace Distribution                                       #
###########################################################################

dmvl <- function(x, mu, Sigma, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(Sigma)) Sigma <- diag(ncol(x))
if(!is.matrix(Sigma)) Sigma <- matrix(Sigma)
Sigma <- as.symmetric.matrix(Sigma)
if(!is.positive.definite(Sigma))
stop("Matrix Sigma is not positive-definite.")
k <- nrow(Sigma)
Omega <- as.inverse(Sigma)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
z[which(z == 0)] <- 1e-300
dens <- as.vector(log(2) - log(2*pi)*(k/2) + logdet(Sigma)*0.5 +
(log(pi) - log(2) + log(2*z)*0.5)*0.5 - log(2*z)*0.5 -
log(z/2)*0.5*(k/2 - 1))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvl <- function(n, mu, Sigma)
{
mu <- rbind(mu)
if(missing(Sigma)) Sigma <- diag(ncol(mu))
if(!is.matrix(Sigma)) Sigma <- matrix(Sigma)
if(!is.positive.definite(Sigma))
stop("Matrix Sigma is not positive-definite.")
k <- ncol(Sigma)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
e <- matrix(rexp(n, 1), n, k)
z <- rmvn(n, rep(0, k), Sigma)
x <- mu + sqrt(e)*z
return(x)
}

###########################################################################
# Multivariate Laplace Distribution (Cholesky Parameterization)           #
###########################################################################

dmvlc <- function(x, mu, U, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(U)) stop("Upper triangular U is required.")
k <- ncol(U)
Sigma <- t(U) %*% U
Omega <- as.inverse(Sigma)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
z[which(z == 0)] <- 1e-300
dens <- as.vector(log(2) - log(2*pi)*(k/2) + logdet(Sigma)*0.5 +
(log(pi) - log(2) + log(2*z)*0.5)*0.5 - log(2*z)*0.5 -
log(z/2)*0.5*(k/2 - 1))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvlc <- function(n, mu, U)
{
mu <- rbind(mu)
if(missing(U)) stop("Upper triangular U is required.")
k <- ncol(U)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
e <- matrix(rexp(n, 1), n, k)
z <- rmvnc(n, rep(0, k), U)
x <- mu + sqrt(e)*z
return(x)
}

###########################################################################
# Multivariate Normal Distribution                                        #
###########################################################################

dmvn <- function(x, mu, Sigma, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(Sigma)) Sigma <- diag(ncol(x))
if(!is.matrix(Sigma)) Sigma <- matrix(Sigma)
Sigma <- as.symmetric.matrix(Sigma)
if(!is.positive.definite(Sigma))
stop("Matrix Sigma is not positive-definite.")
k <- nrow(Sigma)
Omega <- as.inverse(Sigma)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(-0.5 * (k * log(2 * pi) + logdet(Sigma)) - (0.5 * z))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvn <- function(n=1, mu=rep(0,k), Sigma)
{
mu <- rbind(mu)
if(missing(Sigma)) Sigma <- diag(ncol(mu))
if(!is.matrix(Sigma)) Sigma <- matrix(Sigma)
if(!is.positive.definite(Sigma))
stop("Matrix Sigma is not positive-definite.")
k <- ncol(Sigma)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
z <- matrix(rnorm(n*k),n,k) %*% chol(Sigma)
x <- mu + z
return(x)
}

###########################################################################
# Multivariate Normal Distribution (Cholesky Parameterization)            #
###########################################################################

dmvnc <- function(x, mu, U, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(U)) stop("Upper triangular U is required.")
k <- ncol(U)
Sigma <- t(U) %*% U
k <- nrow(Sigma)
Omega <- as.inverse(Sigma)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(-0.5 * (k * log(2 * pi) + logdet(Sigma)) - (0.5 * z))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvnc <- function(n=1, mu=rep(0,k), U)
{
mu <- rbind(mu)
if(missing(U)) stop("Upper triangular U is required.")
k <- ncol(U)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
z <- matrix(rnorm(n*k),n,k) %*% U
x <- mu + z
return(x)
}

###########################################################################
# Multivariate Normal Distribution (Precision Parameterization)           #
###########################################################################

dmvnp <- function(x, mu, Omega, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(Omega)) Omega <- diag(ncol(x))
if(!is.matrix(Omega)) Omega <- matrix(Omega)
if(!is.positive.definite(Omega))
stop("Matrix Omega is not positive-definite.")
k <- nrow(Omega)
logdetOmega <- logdet(Omega)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector((-k/2)*log(2*pi) + 0.5*logdetOmega - 0.5*z)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvnp <- function(n=1, mu=rep(0, k), Omega)
{
mu <- rbind(mu)
if(missing(Omega)) Omega <- diag(ncol(mu))
if(!is.matrix(Omega)) Omega <- matrix(Omega)
if(!is.positive.definite(Omega))
stop("Matrix Omega is not positive-definite.")
k <- ncol(Omega)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
z <- matrix(rnorm(n*k),n,k) %*% solve(t(chol(Omega)))
x <- mu + z
return(x)
}

###########################################################################
# Multivariate Normal Distribution (Precision-Cholesky Parameterization)  #
###########################################################################

dmvnpc <- function(x, mu, U, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(U)) stop("Upper triangular U is required.")
k <- ncol(U)
Omega <- t(U) %*% U
logdetOmega <- logdet(Omega)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector((-k/2)*log(2*pi) + 0.5*logdetOmega - 0.5*z)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvnpc <- function(n=1, mu=rep(0,k), U)
{
mu <- rbind(mu)
if(missing(U)) stop("Upper triangular U is required.")
Sigma <- as.inverse(t(U) %*% U)
k <- ncol(Sigma)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
z <- matrix(rnorm(n*k),n,k) %*% chol(Sigma)
x <- mu + z
return(x)
}

###########################################################################
# Multivariate Polya Distribution                                         #
###########################################################################

dmvpolya <- function(x, alpha, log=FALSE)
{
x <- as.vector(x)
alpha <- as.vector(alpha)
if(!identical(length(x), length(alpha)))
stop("x and alpha differ in length.")
dens <- (log(factorial(sum(x))) - sum(log(factorial(x)))) +
(log(factorial(sum(alpha)-1)) -
log(factorial(sum(x) + sum(alpha)-1))) +
(sum(log(factorial(x + alpha - 1)) - log(factorial(alpha - 1))))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvpolya <- function(n=1, alpha)
{
p <- rdirichlet(n, alpha)
x <- rcat(n,p)
return(x)
}

###########################################################################
# Multivariate Power Exponential Distribution                             #
###########################################################################

dmvpe <- function(x=c(0,0), mu=c(0,0), Sigma=diag(2), kappa=1, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(Sigma)) Sigma <- diag(ncol(x))
if(!is.matrix(Sigma)) Sigma <- matrix(Sigma)
if(!is.positive.definite(Sigma))
stop("Matrix Sigma is not positive-definite.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
k <- nrow(Sigma)
Omega <- as.inverse(Sigma)
ss <- x - mu
temp <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(((log(k)+lgamma(k/2)) - ((k/2)*log(pi) +
0.5*logdet(Sigma) + lgamma(1 + k/(2*kappa)) +
(1 + k/(2*kappa))*log(2))) + kappa*(-0.5*temp))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvpe <- function(n, mu=c(0,0), Sigma=diag(2), kappa=1)
{
mu <- rbind(mu)
k <- ncol(mu)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
if(k != nrow(Sigma)) {
stop("mu and Sigma have non-conforming size.")}
ev <- eigen(Sigma, symmetric=TRUE)
if(!all(ev\$values >= -sqrt(.Machine\$double.eps) *
abs(ev\$values[1]))) {
stop("Sigma must be positive-definite.")}
SigmaSqrt <- ev\$vectors %*% diag(sqrt(ev\$values),
length(ev\$values)) %*% t(ev\$vectors)
runifsphere <- function(n, k)
{
p <- as.integer(k)
if(!is.integer(k))
stop("k must be an integer in [2,Inf)")
if(k < 2) stop("k must be an integer in [2,Inf).")
Mnormal <- matrix(rnorm(n*k,0,1), nrow=n)
rownorms <- sqrt(rowSums(Mnormal^2))
unifsphere <- sweep(Mnormal,1,rownorms, "/")
return(unifsphere)
}
un <- runifsphere(n=n, k=k)
x <- mu + radius * un %*% SigmaSqrt
return(x)
}

###########################################################################
# Multivariate Power Exponential Distribution (Cholesky Parameterization) #
###########################################################################

dmvpec <- function(x=c(0,0), mu=c(0,0), U, kappa=1, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(U)) stop("Upper triangular U is required.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
Sigma <- t(U) %*% U
k <- nrow(Sigma)
Omega <- as.inverse(Sigma)
ss <- x - mu
temp <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(((log(k)+lgamma(k/2)) - ((k/2)*log(pi) +
0.5*logdet(Sigma) + lgamma(1 + k/(2*kappa)) +
(1 + k/(2*kappa))*log(2))) + kappa*(-0.5*temp))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvpec <- function(n, mu=c(0,0), U, kappa=1)
{
mu <- rbind(mu)
k <- ncol(mu)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
if(k != nrow(U)) {
stop("mu and U have non-conforming size.")}
Sigma <- t(U) %*% U
ev <- eigen(Sigma, symmetric=TRUE)
if(!all(ev\$values >= -sqrt(.Machine\$double.eps) *
abs(ev\$values[1]))) {
stop("Sigma must be positive-definite.")}
SigmaSqrt <- ev\$vectors %*% diag(sqrt(ev\$values),
length(ev\$values)) %*% t(ev\$vectors)
runifsphere <- function(n, k)
{
p <- as.integer(k)
if(!is.integer(k))
stop("k must be an integer in [2,Inf)")
if(k < 2) stop("k must be an integer in [2,Inf).")
Mnormal <- matrix(rnorm(n*k,0,1), nrow=n)
rownorms <- sqrt(rowSums(Mnormal^2))
unifsphere <- sweep(Mnormal,1,rownorms, "/")
return(unifsphere)
}
un <- runifsphere(n=n, k=k)
x <- mu + radius * un %*% SigmaSqrt
return(x)
}

###########################################################################
# Multivariate t Distribution                                             #
###########################################################################

dmvt <- function(x, mu, S, df=Inf, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(S)) S <- diag(ncol(x))
if(!is.matrix(S)) S <- matrix(S)
if(!is.positive.definite(S))
stop("Matrix S is not positive-definite.")
if(any(df <= 0)) stop("The df parameter must be positive.")
if(any(df > 10000)) return(dmvn(x, mu, S, log))
k <- nrow(S)
ss <- x - mu
Omega <- as.inverse(S)
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(lgamma((df+k)/2) - lgamma(df/2) - (k/2)*log(df) -
(k/2)*log(pi) - 0.5*logdet(S) - ((df+k)/2)*log(1 + (1/df) * z))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvt <- function(n=1, mu=rep(0,k), S, df=Inf)
{
mu <- rbind(mu)
if(missing(S)) S <- diag(ncol(mu))
if(!is.matrix(S)) S <- matrix(S)
if(!is.positive.definite(S))
stop("Matrix S is not positive-definite.")
if(any(df <= 0)) stop("The df parameter must be positive.")
k <- ncol(S)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
if(df==Inf) x <- 1 else x <- rchisq(n,df) / df
x[which(x == 0)] <- 1e-100
z <- rmvn(n, rep(0,k), S)
x <- mu + z/sqrt(x)
return(x)
}

###########################################################################
# Multivariate t Distribution (Cholesky Parameterization)                 #
###########################################################################

dmvtc <- function(x, mu, U, df=Inf, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(U)) stop("Upper triangular U is required.")
if(any(df <= 0)) stop("The df parameter must be positive.")
if(any(df > 10000)) return(dmvnc(x, mu, U, log))
k <- nrow(U)
ss <- x - mu
S <- t(U) %*% U
Omega <- as.inverse(S)
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(lgamma((df+k)/2) - lgamma(df/2) + (k/2)*df +
(k/2)*log(pi) + 0.5*logdet(S) + ((df+k)/2)*log(1 + (1/df) * z))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvtc <- function(n=1, mu=rep(0,k), U, df=Inf)
{
mu <- rbind(mu)
if(missing(U)) stop("Upper triangular U is required.")
if(any(df <= 0)) stop("The df parameter must be positive.")
k <- ncol(U)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
if(df==Inf) x <- 1 else x <- rchisq(n,df) / df
x[which(x == 0)] <- 1e-100
z <- rmvnc(n, rep(0,k), U)
x <- mu + z/sqrt(x)
return(x)
}

###########################################################################
# Multivariate t Distribution (Precision Parameterization)                #
###########################################################################

dmvtp <- function(x, mu, Omega, nu=Inf, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(Omega)) Omega <- diag(ncol(x))
if(!is.matrix(Omega)) Omega <- matrix(Omega)
if(!is.positive.definite(Omega))
stop("Matrix Omega is not positive-definite.")
if(any(nu <= 0)) stop("The nu parameter must be positive.")
if(any(nu > 10000)) return(dmvnp(x, mu, Omega, log))
k <- ncol(Omega)
logdetOmega <- logdet(Omega)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(lgamma((nu+k)/2) - (lgamma(nu/2) + (k/2)*log(nu) +
(k/2)*log(pi)) + 0.5*logdetOmega +
(-(nu+k)/2)*log(1 + (1/nu) * z))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvtp <- function(n=1, mu, Omega, nu=Inf)
{
mu <- rbind(mu)
if(missing(Omega)) Omega <- diag(ncol(mu))
if(!is.matrix(Omega)) Omega <- matrix(Omega)
if(!is.positive.definite(Omega))
stop("Matrix Omega is not positive-definite.")
if(any(nu <= 0)) stop("The nu parameter must be positive.")
Sigma <- as.inverse(Omega)
k <- ncol(Sigma)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
if(nu == Inf) x <- 1 else x <- rchisq(n,nu) / nu
x[which(x == 0)] <- 1e-100
z <- rmvn(n, rep(0,k), Sigma)
x <- mu + z/sqrt(x)
return(x)
}

###########################################################################
# Multivariate t Distribution (Precision-Cholesky Parameterization)       #
###########################################################################

dmvtpc <- function(x, mu, U, nu=Inf, log=FALSE)
{
if(!is.matrix(x)) x <- rbind(x)
if(!is.matrix(mu)) mu <- matrix(mu, nrow(x), ncol(x), byrow=TRUE)
if(missing(U)) stop("Upper triangular U is required.")
if(any(nu <= 0)) stop("The nu parameter must be positive.")
if(any(nu > 10000)) return(dmvnpc(x, mu, U, log))
k <- ncol(U)
Omega <- t(U) %*% U
logdetOmega <- logdet(Omega)
ss <- x - mu
z <- rowSums({ss %*% Omega} * ss)
dens <- as.vector(lgamma((nu+k)/2) - (lgamma(nu/2) + (k/2)*log(nu) +
(k/2)*log(pi)) + 0.5*logdetOmega +
(-(nu+k)/2)*log(1 + (1/nu) * z))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rmvtpc <- function(n=1, mu, U, nu=Inf)
{
mu <- rbind(mu)
if(missing(U)) stop("Upper triangular U is required.")
if(any(nu <= 0)) stop("The nu parameter must be positive.")
k <- ncol(U)
if(n > nrow(mu)) mu <- matrix(mu, n, k, byrow=TRUE)
if(nu == Inf) x <- 1 else x <- rchisq(n,nu) / nu
x[which(x == 0)] <- 1e-100
z <- rmvnpc(n, rep(0,k), U)
x <- mu + z/sqrt(x)
return(x)
}

###########################################################################
# Normal Distribution Mixture                                             #
###########################################################################

dnormm <- function(x, p, mu, sigma, log=FALSE)
{
if(missing(x)) stop("x is a required argument.")
x <- as.vector(x)
n <- length(x)
if(missing(p)) stop("p is a required argument.")
p <- as.vector(p)
if(any(p <= 0) | any(p > 1)) stop("p must be in (0,1].")
if(sum(p) != 1) stop("p must sum to 1 for all components.")
m <- length(p)
p <- matrix(p, n, m, byrow=TRUE)
if(missing(mu)) stop("mu is a required argument.")
mu <- as.vector(mu)
if(!identical(m, length(mu)))
stop("p and mu differ in length.")
mu <- matrix(mu, n, m, byrow=TRUE)
if(missing(sigma)) stop("sigma is a required argument.")
sigma <- as.vector(sigma)
if(!identical(m, length(sigma)))
stop("p and sigma differ in length.")
sigma <- matrix(sigma, n, m, byrow=TRUE)
dens <- matrix(dnorm(x, mu, sigma, log=TRUE), n, m)
dens <- dens + log(p)
if(log == TRUE) dens <- apply(dens, 1, logadd)
else dens <- rowSums(exp(dens))
return(dens)
}
pnormm <- function(q, p, mu, sigma, lower.tail=TRUE, log.p=FALSE)
{
n <- length(q)
m <- length(p)
q <- matrix(q, n, m)
p <- matrix(p, n, m, byrow=TRUE)
mu <- matrix(mu, n, m, byrow=TRUE)
sigma <- matrix(sigma, n, m, byrow=TRUE)
cdf <- matrix(pnorm(q, mu, sigma, lower.tail=lower.tail,
log.p=log.p), n, m)
if(log.p == FALSE) cdf <- rowSums(cdf * p)
else stop("The log.p argument does not work yet.")
return(cdf)
}
rnormm <- function(n, p, mu, sigma)
{
if(missing(p)) stop("p is a required argument.")
p <- as.vector(p)
if(any(p <= 0) | any(p > 1)) stop("p must be in (0,1].")
if(sum(p) != 1) stop("p must sum to 1 for all components.")
m <- length(p)
p <- matrix(p, n, m, byrow=TRUE)
if(missing(mu)) stop("mu is a required argument.")
mu <- as.vector(mu)
if(!identical(m, length(mu)))
stop("p and mu differ in length.")
if(missing(sigma)) stop("sigma is a required argument.")
sigma <- as.vector(sigma)
if(!identical(m, length(sigma)))
stop("p and sigma differ in length.")
if(any(sigma <= 0)) stop("sigma must be positive.")
z <- rcat(n, p)
x <- rnorm(n, mean=mu[z], sd=sigma[z])
return(x)
}

###########################################################################
# Normal Distribution (Precision Parameterization)                        #
###########################################################################

dnormp <- function(x, mean=0, prec=1, log=FALSE)
{
#dens <- sqrt(prec/(2*pi)) * exp(-(prec/2)*(x-mu)^2)
dens <- dnorm(x, mean, sqrt(1/prec), log)
return(dens)
}
pnormp <- function(q, mean=0, prec=1, lower.tail=TRUE, log.p=FALSE)
{return(pnorm(q, mean=mean, sd=sqrt(1/prec), lower.tail, log.p))}
qnormp <- function(p, mean=0, prec=1, lower.tail=TRUE, log.p=FALSE)
{return(qnorm(p, mean=mean, sd=sqrt(1/prec), lower.tail, log.p))}
rnormp <- function(n, mean=0, prec=1)
{return(rnorm(n, mean=mean, sd=sqrt(1/prec)))}

###########################################################################
# Normal Distribution (Variance Parameterization)                         #
###########################################################################

dnormv <- function(x, mean=0, var=1, log=FALSE)
{
#dens <- (1/(sqrt(2*pi*var))) * exp(-((x-mu)^2/(2*var)))
dens <- dnorm(x, mean, sqrt(var), log)
return(dens)
}
pnormv <- function(q, mean=0, var=1, lower.tail=TRUE, log.p=FALSE)
{return(pnorm(q, mean=mean, sd=sqrt(var), lower.tail, log.p))}
qnormv <- function(p, mean=0, var=1, lower.tail=TRUE, log.p=FALSE)
{return(qnorm(p, mean=mean, sd=sqrt(var), lower.tail, log.p))}
rnormv <- function(n, mean=0, var=1)
{return(rnorm(n, mean=mean, sd=sqrt(var)))}

###########################################################################
# Normal-Inverse-Wishart Distribution                                     #
###########################################################################

dnorminvwishart <- function(mu, mu0, lambda, Sigma, S, nu, log=FALSE)
{
dens <- dinvwishart(Sigma, nu, S, log=TRUE) +
dmvn(mu, mu0, 1/lambda*Sigma, log=TRUE)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rnorminvwishart <- function(n=1, mu0, lambda, S, nu)
{
Sigma <- rinvwishart(nu, S)
mu <- rmvn(n, mu0, 1/lambda*Sigma)
return(list(mu=mu, Sigma=Sigma))
}

###########################################################################
# Normal-Laplace Distribution                                             #
###########################################################################

dnormlaplace <- function(x, mu=0, sigma=1, alpha=1, beta=1, log=FALSE)
{
x <- as.vector(x)
mu <- as.vector(mu)
sigma <- as.vector(sigma)
alpha <- as.vector(alpha)
beta <- as.vector(beta)
if(any(sigma <= 0))
stop("The sigma parameter must be positive.")
if(any(alpha <= 0))
stop("The alpha parameter must be positive.")
if(any(beta <= 0))
stop("The beta parameter must be positive.")
NN <- max(length(x), length(mu), length(sigma), length(alpha),
length(beta))
x <- rep(x, len=NN)
mu <- rep(mu, len=NN)
sigma <- rep(sigma, len=NN)
alpha <- rep(alpha, len=NN)
beta <- rep(beta, len=NN)
a <- dnorm((x - mu) / sigma, log=TRUE)
z <- alpha*sigma - (x - mu) / sigma
b <- pnorm(z, lower.tail=FALSE, log.p=TRUE) -
dnorm(z, log=TRUE)
z <- beta*sigma + (x - mu) / sigma
cc <- pnorm(z, lower.tail=FALSE, log.p=TRUE) -
dnorm(z, log=TRUE)
z <- log(alpha*beta / (alpha + beta))
d <- pnorm(z, lower.tail=FALSE, log.p=TRUE) -
dnorm(z, log=TRUE)
if(log == FALSE) dens <- exp(d + a + b) + exp(d + a + cc)
else {
dens <- rep(NA, NN)
e <- d + a + b
f <- d + a + cc
for (i in 1:NN) dens[i] <- logadd(c(e[i], f[i]))
}
return(dens)
}
rnormlaplace <- function(n, mu=0, sigma=1, alpha=1, beta=1)
{
z <- rnorm(n, 0, sigma^2)
w <- rslaplace(n, mu, 1/beta, 1/alpha)
return(z + w)
}

###########################################################################
# Normal-Wishart Distribution                                             #
###########################################################################

dnormwishart <- function(mu, mu0, lambda, Omega, S, nu, log=FALSE)
{
dens <- dwishart(Omega, nu, S, log=TRUE) +
dmvnp(mu, mu0, lambda*Omega, log=TRUE)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rnormwishart <- function(n=1, mu0, lambda, S, nu)
{
Omega <- rwishart(nu, S)
mu <- rmvn(n, mu0, as.inverse(lambda*Omega))
return(list(mu=mu, Omega=Omega))
}

###########################################################################
# Pareto Distribution                                                     #
###########################################################################

dpareto <- function(x, alpha, log=FALSE)
{
x <- as.vector(x); alpha <- as.vector(alpha)
if(any(alpha <= 0)) stop("The alpha parameter must be positive.")
NN <- max(length(x), length(alpha))
x <- dens <- rep(x, len=NN); alpha <- rep(alpha, len=NN)
dens[which(x < 1)] <- -Inf
temp <- which(x >= 1)
dens[temp] <- log(alpha[temp]) - (alpha[temp] + 1)*log(x[temp])
if(log == FALSE) dens <- exp(dens)
return(dens)
}
ppareto <- function(q, alpha)
{
q <- as.vector(q); alpha <- as.vector(alpha)
if(any(alpha <= 0)) stop("The alpha parameter must be positive.")
NN <- max(length(q), length(alpha))
p <- q <- rep(q, len=NN); alpha <- rep(alpha, len=NN)
p[which(q < 1)] <- 0
temp <- which(q >= 1)
p[temp] <- 1 - 1 / q[temp]^alpha[temp]
return(p)
}
qpareto <- function(p, alpha)
{
p <- as.vector(p); alpha <- as.vector(alpha)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(alpha <= 0)) stop("The alpha parameter must be positive.")
NN <- max(length(p), length(alpha))
p <- rep(p, len=NN); alpha <- rep(alpha, len=NN)
q <- (1-p)^(-1/alpha)
return(q)
}
rpareto <- function(n, alpha)
{
alpha <- rep(alpha, len=n)
if(any(alpha <= 0)) stop("The alpha parameter must be positive.")
x <- runif(n)^(-1/alpha)
return(x)
}

###########################################################################
# Power Exponential Distribution                                          #
#                                                                         #
# These functions are similar to those in the normalp package.            #
###########################################################################

dpe <- function(x, mu=0, sigma=1, kappa=2, log=FALSE)
{
x <- as.vector(x); mu <- as.vector(mu); sigma <- as.vector(sigma)
kappa <- as.vector(kappa)
if(any(sigma <= 0)) stop("The sigma parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
NN <- max(length(x), length(mu), length(sigma), length(kappa))
x <- rep(x, len=NN); mu <- rep(mu, len=NN)
sigma <- rep(sigma, len=NN); kappa <- rep(kappa, len=NN)
cost <- 2 * kappa^(1/kappa) * gamma(1 + 1/kappa) * sigma
expon1 <- (abs(x - mu))^kappa
expon2 <- kappa * sigma^kappa
dens <- log(1/cost) + (-expon1 / expon2)
if(log == FALSE) dens <- exp(dens)
return(dens)
}
ppe <- function(q, mu=0, sigma=1, kappa=2, lower.tail=TRUE, log.p=FALSE)
{
q <- as.vector(q); mu <- as.vector(mu); sigma <- as.vector(sigma)
kappa <- as.vector(kappa)
if(any(sigma <= 0)) stop("The sigma parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
NN <- max(length(q), length(mu), length(sigma), length(kappa))
q <- rep(q, len=NN); mu <- rep(mu, len=NN)
sigma <- rep(sigma, len=NN); kappa <- rep(kappa, len=NN)
z <- (q - mu) / sigma
zz <- abs(z)^kappa
p <- pgamma(zz, shape=1/kappa, scale=kappa)
p <- p / 2
temp <- which(z < 0); p[temp] <- 0.5 - p[temp]
temp <- which(z >= 0); p[temp] <- 0.5 + p[temp]
if(lower.tail == FALSE) p <- 1 - p
if(log.p == TRUE) p <- log(p)
return(p)
}
qpe <- function(p, mu=0, sigma=1, kappa=2, lower.tail=TRUE, log.p=FALSE)
{
p <- as.vector(p); mu <- as.vector(mu); sigma <- as.vector(sigma)
kappa <- as.vector(kappa)
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(sigma <= 0)) stop("The sigma parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
NN <- max(length(p), length(mu), length(sigma), length(kappa))
p <- rep(p, len=NN); mu <- rep(mu, len=NN)
sigma <- rep(sigma, len=NN); kappa <- rep(kappa, len=NN)
if(log.p == TRUE) p <- log(p)
if(lower.tail == FALSE) p <- 1 - p
zp <- 0.5 - p
temp <- which(p >= 0.5); zp[temp] <- p[temp] - 0.5
zp <- 2 * zp
qg <- qgamma(zp, shape=1/kappa, scale=kappa)
z <- qg^(1/kappa)
temp <- which(p < 0.5); z[temp] <- -z[temp]
q <- mu + z * sigma
return(q)
}
rpe <- function(n, mu=0, sigma=1, kappa=2)
{
mu <- rep(mu, len=n); sigma <- rep(sigma, len=n)
kappa <- rep(kappa, len=n)
if(any(sigma <= 0)) stop("The sigma parameter must be positive.")
if(any(kappa <= 0)) stop("The kappa parameter must be positive.")
qg <- rgamma(n, shape=1/kappa, scale=kappa)
z <- qg^(1/kappa)
u <- runif(n)
temp <- which(u < 0.5); z[temp] <- -z[temp]
x <- mu + z * sigma
return(x)
}

###########################################################################
# Scaled Inverse Wishart Distribution                                     #
###########################################################################

dsiw <- function(Q, nu, S, zeta, mu, delta, log=FALSE)
{
dens <- dinvwishart(Q, nu, S, log=TRUE) +
sum(dmvn(log(zeta), mu, diag(delta), log=TRUE))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
rsiw <- function(nu, S, mu, delta)
{
Q <- rinvwishart(nu, S)
Zeta <- diag(as.vector(exp(rmvn(1, mu, diag(delta)))))
x <- Zeta %*% Q %*% Zeta
return(x)
}

###########################################################################
# Skew Discrete Laplace Distribution                                      #
###########################################################################

dsdlaplace <- function(x, p, q, log=FALSE)
{
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(q < 0) || any(q > 1)) stop("q must be in [0,1].")
NN <- max(length(x), length(p), length(q))
x <- rep(x, len=NN); p <- rep(p, len=NN); q <- rep(q, len=NN)
dens <- log(1-p) + log(1-q) - (log(1-p*q) + x*log(p))
temp <- which(x < 0)
dens[temp] <- log(1-p[temp]) + log(1-q[temp]) -
(log(1-p[temp]*q[temp]) + abs(x[temp])*log(q[temp]))
if(log == FALSE) dens <- exp(dens)
return(dens)
}
psdlaplace <- function(x, p, q)
{
if(any(p < 0) || any(p > 1)) stop("p must be in [0,1].")
if(any(q < 0) || any(q > 1)) stop("q must be in [0,1].")
NN <- max(length(x), length(p), length(q))
x <- rep(x, len=NN); p <- rep(p, len=NN); q <- rep(q, len=NN)
pr <- 1-(1-q)*p^(floor(x)+1)/(1-p*q)
temp <- which(x < 0)
pr[temp] <- (1-p[temp])*q[temp]^(-floor(x[temp]))/(1-p[temp]*q[temp])
return(pr)
}
qsdlaplace <- function(prob, p, q)
{
if(any(prob < 0) || any(prob > 1)) stop("prob must be in [0,1].")
if(any(p < 0) || any(p > 1))```