# R functions for ESN distributions # Author: A.Azzalini (Universita` di Padova): # # Original S-plus code: July-October 1999, ported to R in October 2007, # amedend in February 2010; public distribution in March 2011 # # This code is freely usable under GPL license available from # http://www.gnu.org/licenses/gpl.html # AND # the promise that you do not complain about the lack of documentation, # being content to look at the documentation for the matching routines # (without the "e") in the "sn" package available from CRAN: # http://cran.r-project.org/web/packages/sn/index.html # while for the extra parameter "tau" it is your responsibility to read # the published papers, specifically Capitanio et al. (2003), cf # http://azzalini.stat.unipd.it/SN/abstracts.html #--------------------------------------------------------------- rmesn <- function(n=1, xi=rep(0,k), Omega, alpha, tau=0) {# generates SN_k(xi,Omega,alpha,tau) variates using conditioning method k <- ncol(Omega) Z <- mesn.quantities(xi,Omega,alpha,tau) O.star <- rbind(c(1,Z$delta),cbind(Z$delta,Z$Omega.cor)) z<- norm.censor(n,k,chol(O.star),tau) y <- t(xi+Z$omega*t(z)) return(y) } norm.censor <- function(n, k, root.cov, tau) {# routine di supporto per rmesn (ma non si puo` inserire al suo interno) if(n<=0 | k<1) return() if(tau>0) eff <- pnorm(tau) else eff <- 2*pnorm(tau) n0 <- round(n/eff) x <- matrix(rnorm(n0*(k+1)),n0,(k+1)) %*% root.cov # each row of x is N_{k+1}(0,Omega*) id<- (x[,1]+tau>0) z <- x[id,-1,drop=F] if(tau<=0) { id<- (-x[,1]+tau>=0) z <- rbind(z,-x[id,-1,drop=F]) } if(is.null(dim(z))) n.sampled<-0 else n.sampled<-nrow(z) if(n.sampled1) diag(d) else d y <- as.matrix(y) k <- ncol(y) m.y <- apply(y, 2, mean) var.y <- var(y) y0<- (t(y) - outer(m.y, rep(1,nrow(y))))/sqrt(diag(var.y)) gamma1 <- apply(y0^3, 1, mean) out <- (abs(gamma1) > 0.99527) gamma1[out] <- sign(gamma1[out]) * 0.995 a <- sign(gamma1) * ((2 * abs(gamma1))/(4 - pi))^0.33333 delta <- (sqrt(pi/2) * a)/sqrt(1 + a^2) m.z <- delta * sqrt(2/pi) omega <- sqrt(diag(var.y)/(1 - m.z^2)) Omega <- var.y + outer(omega * m.z, omega * m.z) xi <- m.y - omega * m.z O.cor <- Diag(1/omega) %*% Omega %*% Diag(1/omega) O.cor <- (t(O.cor) + O.cor)/2 O.inv <- solve(O.cor) tmp <- as.vector(1 - t(delta) %*% O.inv %*% delta) if(tmp <= 0) { tmp <- 0.0001 admissible <- F } else admissible <- T alpha <- as.vector(O.inv %*% delta)/sqrt(tmp) list(xi = xi, Omega = Omega, alpha = alpha, Omega.cor = O.cor, omega = omega, delta = delta, skewness = gamma1, admissible = admissible) } mesn.quantities <- function(xi, Omega, alpha, tau=0) { # 21-12/1997; computes various quantieies related to SN_k(xi,Omega,alpha) k <- length(alpha) Diag<-function(d) if(length(d)>1) diag(d) else d if(length(xi) != k | any(dim(Omega) != c(k, k))) stop("dimensions of arguments do not match") omega <- sqrt(diag(Omega)) O.cor <- diag(1/omega) %*% Omega %*% diag(1/omega) tmp <- as.vector(sqrt(1 + t(as.matrix(alpha)) %*% O.cor %*% alpha)) delta <- as.vector(O.cor %*% alpha)/tmp lambda <- delta/sqrt(1 - delta^2) D <- Diag(sqrt(1 + lambda^2)) if(tau==0) { Psi <- D %*% (O.cor - outer(delta, delta)) %*% D Psi <- (Psi + t(Psi))/2 } else Psi <- NULL O.inv <- solve(Omega) oi <- sqrt(diag(O.inv)) O.conc <- Diag(1/oi) %*% (-O.inv) %*% Diag(1/oi) diag(O.conc) <- rep(1, k) muZ <- delta * zeta(1,tau) muY <- xi + omega * muZ # Sigma <- diag(omega) %*% (O.cor - outer(muZ, muZ)) %*% diag(omega) Sigma <- Omega + zeta(2,tau) * outer(omega*delta, omega*delta) Sigma <- (Sigma + t(Sigma))/2 cv <- muZ/sqrt(1 - muZ^2) # gamma1 <- 0.5 * (4 - pi) * cv^3 gamma1 <- NULL list(xi = xi, Omega = Omega, alpha = alpha, tau=tau,omega = omega, mean = muY, variance = Sigma, Omega.cor = O.cor, Omega.conc = O.conc, Psi = Psi, lambda = lambda, delta = delta, skewness = gamma1) } zeta <- function(k, x) { # k integer \in (0,4) k <- as.integer(k) na <- is.na(x) x <- replace(x, na, 0) if(any(abs(x) == Inf)) stop("Inf not allowed") # funzionerebbe per k=0 e 1, ma non per k>1 ok <- (-30 < x) if(k == 0) { ax <- ( - x[!ok]) ay <- (-0.918938533204673) - 0.5 * ax^2 - log(ax) y <- rep(NA, length(x)) y[ok] <- log(2 * pnorm(x[ok])) y[!ok] <- ay } else { if(k == 1) { y <- ( - x) * (1 + 1/x^2) y[ok] <- dnorm(x[ok])/pnorm(x[ok]) } else { if(k == 2) y <- ( - zeta(1, x) * (x + zeta(1, x))) else { if(k == 3) y <- ( - zeta(2, x) * (x + zeta(1, x)) - zeta(1, x) * (1 + zeta( 2, x))) else { if(k == 4) y <- ( - zeta(3, x) * (x + 2 * zeta(1, x)) - 2 * zeta( 2, x) * (1 + zeta( 2, x))) else { warning("k>4") y <- rep(NA, length(x)) } } } } } replace(y, na, NA) }