## Copyright (C) 2012 Marius Hofert, Ivan Kojadinovic, Martin Maechler, and Jun Yan ## ## This program is free software; you can redistribute it and/or modify it under ## the terms of the GNU General Public License as published by the Free Software ## Foundation; either version 3 of the License, or (at your option) any later ## version. ## ## This program is distributed in the hope that it will be useful, but WITHOUT ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ## details. ## ## You should have received a copy of the GNU General Public License along with ## this program; if not, see . ## MM --- addition: to be put into /tests/*.R ## --- diagnose the .libPaths setup and why the wrong lme4 is found ... (.lP <- .libPaths()) (.ip <- installed.packages(lib.loc = .lP[1]))[,c("Version", "Priority", "Built")] ## (l.lme4 <- with(ll, results[results[,"Package"] == "lme4", , drop=FALSE])) ## sapply(l.lme4[,"LibPath"], function(lib) packageDescription("lme4", lib.loc=lib)) sessionInfo() ## ------ end{diagnose_libPaths} require(copula) (isLinux <- identical("Linux", Sys.info()[["sysname"]])) (doExtras <- copula:::doExtras()) sessionInfo() ## From source(system.file("test-tools-1.R", package = "Matrix")) : showSys.time <- function(expr) { ## prepend 'Time' for R CMD Rdiff st <- system.time(expr) writeLines(paste("Time", capture.output(print(st)))) invisible(st) } ### Stirling numbers of the 1st kind ########################################### S1.10 <- c(0, -362880, 1026576, -1172700, 723680, -269325, 63273, -9450, 870, -45, 1) stopifnot(sapply(0:10, Stirling1, n=10) == S1.10, Stirling1.all(10) == S1.10[-1]) options(str = strOptions(vec.len = 10, digits.d = 20)) # for ls.str() below ls.str(copula:::.nacopEnv) showSys.time(S <- Stirling1(30, 7))# updating table -> typically not zero showSys.time(S. <- Stirling1(30, 7))# lookup --> should be zero stopifnot(identical(S, S.)) ls.str(copula:::.nacopEnv) showSys.time(s1c <- Stirling1(100,10)) s1c (s1 <- system.time(for(i in 1:20) S. <- Stirling1(100, 10))[[1]]) stopifnot(identical(S., s1c), !isLinux || s1 <= 0.020) showSys.time(s2c <- Stirling1(200,190)); s2c (s2 <- system.time(for(i in 1:20) S. <- Stirling1(200,190))[[1]]) stopifnot(identical(S., s2c), !isLinux || s2 <= 0.020) ## 0.010 occasionally barely fails (prints "0.010") on Martin's X201 ### Stirling numbers of the 2nd kind ########################################### S2.10 <- c(0, 1, 511, 9330, 34105, 42525, 22827, 5880, 750, 45, 1) stopifnot(sapply(0:10, Stirling2, n=10, method="direct") == S2.10, sapply(0:10, Stirling2, n=10, method="lookup") == S2.10, Stirling2.all(10) == S2.10[-1]) ls.str(copula:::.nacopEnv) showSys.time(S <- Stirling2(30, 7))# updating table -> typically not zero showSys.time(S. <- Stirling2(30, 7))# lookup --> should be zero stopifnot(identical(S, S.), all.equal(S, Stirling2(30,7, method="direct"), tolerance=1e-15)) ls.str(copula:::.nacopEnv) rbind(C.direct = system.time(Sd <- Stirling2(100,10, method="direct")), C.lookup = system.time(Sl <- Stirling2(100,10, method="lookup"))) ## should be equal; and lookup time should be "zero" when called again: (s3 <- system.time(for(i in 1:20) S. <- Stirling2(100, 10))[[1]]) stopifnot(all.equal(Sd, Sl, tolerance = 1e-15), !isLinux || s3 <= 0.020) ## 0.010 fails on good ole' Solaris when that is busy.. ## Here, the direct method already overflows, but the "lookup" still works rbind(C.direct = system.time(Sd <- Stirling2(200,190, method="direct")), C.lookup = system.time(Sl <- Stirling2(200,190, method="lookup"))) Sd ; Sl (s4 <- system.time(for(i in 1:20) S. <- Stirling2(200,190))[[1]]) stopifnot(!isLinux || s4 <= 0.025) # 0.010 occasionally barely fails (prints "0.010") on Martin's X201 ### Eulerian Numbers ########################################################### ##' cheap "direct" version of Eulerian.all(): Euleri.A <- function(n) sapply(0:max(0,n-1), Eulerian, n=n, method="direct") stopifnot(identical(Euler.l5 <- lapply(0:5, Euleri.A), list(1, 1, c(1, 1), c(1, 4, 1), c(1, 11, 11, 1), c(1, 26, 66, 26, 1)))) p.Eul <- function(n) { plot(E1 <- Eulerian.all(n), log="y", yaxt="n", xlab = "k", ylab = bquote(A(.(n), k)), main = bquote("Eulerian numbers "* A(.(n), k))) if(require("sfsmisc")) eaxis(2, quantile(axTicks(2), (0:16)/16, type=3), at.small=numeric()) else axis(2) lines(E2 <- Euleri.A(n), col="green3", type="o") invisible(cbind(E1=E1, E2=E2)) } if(!dev.interactive(orNone=TRUE)) pdf("Eulerian-ex.pdf") e60 <- p.Eul(60); all.equal(e60[,2],e60[,1], tolerance=0) ## 3.82e-09 e70 <- p.Eul(70); all.equal(e70[,2],e70[,1]) ## 2.97e-6 e90 <- p.Eul(90); all.equal(e90[,2],e90[,1]) ## 0.032 e100 <- p.Eul(100); all.equal(e100[,2],e100[,1]) ## 0.80028 --- visible in center e110 <- p.Eul(110); all.equal(e110[,2],e110[,1]) ## 0.992 --- visible in center e120 <- p.Eul(120); all.equal(e120[,2],e120[,1]) ## 1 -- problem in center e150 <- p.Eul(150) ## clear problem in center -- close to overflow though e170 <- p.Eul(170) ## clear problem in center -- close to overflow though max(e170[,"E1"]) # 7.5964e+305 -- almost maximum dev.off() ### Bernoulli numbers ========================================================= ##--- see example(Bernoulli) ---> ../man/Bernoulli.Rd ------ ##--- ~~~~~~~~~~~~~~~~~~~ ------ ## BUT -- the algorithm is *really* not accurate enough ... ## ---> try to work with higher precision ## ---> Use package "Rmpfr" and its own Bernoulli() / Bernoulli.all() ## NB: The following does not print *unless* you evaluate it *outside* ## the if(..) clause if(doExtras && require("Rmpfr")) { ## note that it has its own Bernoulli() ! if(!dev.interactive(orNone=TRUE)) pdf("Bernoulli-ex.pdf") ## Bernoulli.all(.. prec = ) --> automatically uses 'Rmpfr' arithmetic showSys.time(B100 <- Bernoulli.all(100)) # still less than a milli second showSys.time(B100.250 <- as.numeric(Bernoulli.all(100, prec = 250))) ## 0.75 sec [Core i5 (2010)] re <- log(abs(1 - B100/B100.250)) m <- cbind(Bn = B100, Bn.250 = B100.250, "-log10(rel.Err)" = -round(re/log(10), 2)) rownames(m) <- paste("n=",0:100, sep="") m[1:5,] print(m[2*(1:15) -1,]) ## for n=10: still 8 correct digits showSys.time(B100.1k <- as.numeric(Bernoulli.all(100, prec = 1024))) ## The first 34 are "the same", but after [41], ## even 250 precBits were *not* sufficient: print(round(log10(abs(1 - B100.250/B100.1k))[seq(1,99,by=2)], 2)) ## some accuracy investigation: nn <- 8:100; nn <- nn[nn %% 2 == 0]; nn B.asy <- sapply(nn, copula::Bernoulli, method="asymp") B.sumB <- sapply(nn, copula::Bernoulli, method="sumBin") B.prec <- Rmpfr::Bernoulli(nn, precBits = 2048) relErr <- as.numeric(1 - B.asy / B.prec) relE2 <- as.numeric(1 - B.sumB / B.prec) matplot(nn, abs(cbind(relErr, relE2)), pch=1:2, main = "| rel.Error { Bernoulli(n) } |", xlab = expression(n), axes=FALSE, ylim = c(1e-15, 1e-4), log="y", type="b") sfsmisc::eaxis(1); sfsmisc::eaxis(2) legend("topright", c("asymp","sumBin"), bty="n", col=1:2, lty=1:2, pch=1:2) ##--> an optimal "hybrid" method will use "asymp" from about n ~= 20 dev.off() } ## end if(require("Rmpfr")) ### Polylogarithm Function ##################################################### EQ <- function(x,y, tol = 1e-15) all.equal(x,y, tolerance=tol) x <- (0:127)/128 # < 1 stopifnot(EQ(polylog(s = 1, x, n.sum=10000), -log(1-x)), EQ(polylog(s = -1, .1, n.sum= 100), 10/81), EQ(polylog(s = -1, .1, "negI-s-Stirling"), 10/81), EQ(polylog(x, -1, "negI-s-Stirling"), x /(1-x)^2), EQ(polylog(x, -2, "negI-s-Stirling"), x*(1+x)/(1-x)^3), EQ(polylog(x, -4, "negI-s-Stirling"), x*(1+x)*(1+x*(10+x)) / (1-x)^5), identical( polylog (x, -4, "negI-s-Stirling"), Vectorize(polylog,"z")(x, -4, "negI-s-Stirling")), identical( polylog (x, -4, "sum", n.sum=10000), Vectorize(polylog,"z")(x, -4, "sum", n.sum=10000)), EQ(polylog(x, -1, "negI-s-Eulerian"), x /(1-x)^2), EQ(polylog(x, -2, "negI-s-Eulerian"), x*(1+x)/(1-x)^3), EQ(polylog(x, -4, "negI-s-Eulerian"), x*(1+x)*(1+x*(10+x)) / (1-x)^5), TRUE) ##--> now do plots etc in ../man/polylog.Rd : ## ~~~~~~~~~~~~~~~~~ ### Debye Functions ---- Better treat with (NA, NaN, Inf) than gsl's debye: ## --------------- -> ../R/special-func.R x <- c(NA, NaN, 0, 1e-100, 1e-10, .01, .1, 1:10, 20, 1e10, 1e100, Inf) D1 <- copula:::debye1(x) D2 <- copula:::debye2(x) (isI <- which(x == Inf)) cbind(x, D1, D2) stopifnot(is.na(c(D1[1],D2[1])), is.nan(c(D1[2],D2[2])), !is.na(D1[-(1:2)]), !is.nan(D1[-2]), !is.na(D2[-(1:2)]), !is.nan(D2[-2]), D1[isI] == 0, D2[isI] == 0) ### lsum() and lssum() -------------- lsum <- copula:::lsum lssum <- copula:::lssum lsum0 <- function(lx) log(sum(exp(lx))) lx1 <- 10*(-80:70) # is easy lx2 <- 600:750 # lsum0() not ok [could work with rescaling] lx3 <- -(750:900) # lsum0() = -Inf - not good enough m3 <- cbind(lx1,lx2,lx3) lx6 <- lx5 <- lx4 <- lx3 lx4[149:151] <- -Inf ## = log(0) lx5[150] <- Inf lx6[1] <- NA_real_ m6 <- cbind(m3,lx4,lx5,lx6) stopifnot(all.equal(lsum(lx1), lsum0(lx1)), all.equal((ls1 <- lsum(lx1)), 700.000045400960403, tol=8e-16), all.equal((ls2 <- lsum(lx2)), 750.458675145387133, tol=8e-16), all.equal((ls3 <- lsum(lx3)), -749.541324854612867, tol=8e-16), ## identical: matrix-version <==> vector versions identical(lsum(lx4), ls3), identical(lsum(lx4), lsum(head(lx4, -3))), # the last three were -Inf identical(lsum(lx5), Inf), identical(lsum(lx6), lx6[1]), identical((lm3 <- lsum(m3)), c(lx1=ls1, lx2=ls2, lx3=ls3)), identical(lsum(m6), c(lm3, lx4=ls3, lx5=Inf, lx6=lx6[1])), TRUE) ## TODO: lssum() testing !!