expint/0000755000176200001440000000000015136053334011564 5ustar liggesusersexpint/tests/0000755000176200001440000000000015135742277012740 5ustar liggesusersexpint/tests/expint-tests.R0000644000176200001440000002021314326667517015534 0ustar liggesusers### == expint: Exponential Integral and Incomplete Gamma Function == ### ### Tests for the exponential integral Ei and the exponential integral ### of order 'n = 1, 2, ...' ### ### E_n = int_x^infty exp(-t)/t^n dt. ### ### AUTHOR: Vincent Goulet ## Load the package library(expint) ### ### Basic functionality ### ## Some values of x x <- runif(10, 0, 10) ## Equivalence between interfaces stopifnot(exprs = { identical(expint(x, order = 1), expint_E1(x), expint_En(x, order = 1)) identical(expint(x, order = 2), expint_E2(x), expint_En(x, order = 2)) identical(expint(x, order = 3), expint_En(x, order = 3)) identical(expint(x, order = 10), expint_En(x, order = 10)) identical(expint(x, order = 1, scale = TRUE), expint_E1(x, scale = TRUE)) identical(expint(x, order = 2, scale = TRUE), expint_E2(x, scale = TRUE)) identical(expint(x, order = 3, scale = TRUE), expint_En(x, order = 3, scale = TRUE)) identical(expint(x, order = 10, scale = TRUE), expint_En(x, order = 10, scale = TRUE)) }) ## Identity between Ei and E1 stopifnot(exprs = { identical(expint_Ei(x), -expint_E1(-x)) identical(expint_Ei(x, scale = TRUE), -expint_E1(-x, scale = TRUE)) }) ## Vectorization of arguments stopifnot(exprs = { identical(expint(head(x), order = 1:3), c(expint(x[1], 1), expint(x[2], 2), expint(x[3], 3), expint(x[4], 1), expint(x[5], 2), expint(x[6], 3))) }) ### ### Values from Table 5.1 of Abramovitz and Stegun ### ## Target values xsmall <- c(1:4/100, seq(0.05, 0.5, by = 0.05)) TARGET_EI_SMALL <- c(1.002505566, 1.005022306, 1.007550283, 1.010089560, 1.012640202, 1.025566141, 1.038786018, 1.052308298, 1.066141726, 1.080295334, 1.094778451, 1.109600714, 1.124772082, 1.140302841) TARGET_E1_SMALL <- c(0.9975055452, 0.9950221392, 0.9925497201, 0.9900882265, 0.9876375971, 0.9755453033, 0.9637156702, 0.9521414833, 0.9408157528, 0.9297317075, 0.9188827858, 0.9082626297, 0.8978650778, 0.8876841584) xmed <- c(0.50, 0.60, 0.75, 1.00, 1.25, 1.55, 1.80, 2.00) TARGET_EI_MED <- c(0.454219905, 0.769881290, 1.207332816, 1.895117816, 2.581047974, 3.451954503, 4.249867557, 4.954234356) TARGET_E1_MED <- c(0.559773595, 0.454379503, 0.340340813, 0.219383934, 0.146413373, 0.092882108, 0.064713129, 0.048900511) xlarge <- c(2.0, 3.5, 5.0, 7.5, 10.0) TARGET_EI_LARGE <- c(1.340965420, 1.471782389, 1.353831278, 1.200421500, 1.131470205) TARGET_E1_LARGE <- c(0.722657234, 0.807867661, 0.852110880, 0.892687854, 0.915633339) EULER <- 0.57721566490153286060651209008 ## Tests stopifnot(exprs = { all.equal((expint_Ei(xsmall) - log(xsmall) - EULER)/xsmall, TARGET_EI_SMALL) all.equal((expint_E1(xsmall) + log(xsmall) + EULER)/xsmall, TARGET_E1_SMALL) all.equal(expint_Ei(xmed), TARGET_EI_MED) all.equal(expint_E1(xmed), TARGET_E1_MED) all.equal(xlarge * exp(-xlarge) * expint_Ei(xlarge), TARGET_EI_LARGE) all.equal(xlarge * expint_Ei(xlarge, scale = TRUE), TARGET_EI_LARGE) all.equal(xlarge * exp(xlarge) * expint_E1(xlarge), TARGET_E1_LARGE) all.equal(xlarge * expint_E1(xlarge, scale = TRUE), TARGET_E1_LARGE) }) ### ### Values from Table 5.2 of Abramovitz and Stegun ### ## Target values xinv <- seq(0.100, 0.005, by = -0.005) TARGET_EI <- c(1.13147021, 1.12249671, 1.11389377, 1.10564739, 1.09773775, 1.09014087, 1.08283054, 1.07578038, 1.06896548, 1.06236365, 1.05595591, 1.04972640, 1.04366194, 1.03775135, 1.03198503, 1.02635451, 1.02085228, 1.01547157, 1.01020625, 1.00505077) TARGET_E1 <- c(0.9156333394, 0.9192568286, 0.9229315844, 0.9266590998, 0.9304409399, 0.9342787466, 0.9381742450, 0.9421292486, 0.9461456670, 0.9502255126, 0.9543709099, 0.9585841038, 0.9628674711, 0.9672235311, 0.9716549596, 0.9761646031, 0.9807554965, 0.9854308813, 0.9901942287, 0.9950492646) ## Tests stopifnot(exprs = { all.equal(expint_Ei(1/xinv) * exp(-1/xinv)/xinv, TARGET_EI) all.equal(expint_Ei(1/xinv, scale = TRUE)/xinv, TARGET_EI) all.equal(expint_E1(1/xinv) * exp(1/xinv)/xinv, TARGET_E1) all.equal(expint_E1(1/xinv, scale = TRUE)/xinv, TARGET_E1) }) ### ### Values from Table 5.4 of Abramovitz and Stegun ### ## Target values xsmall <- c(0.01, 0.10, 0.25, 0.30, 0.50) osmall <- c(3, 4, 10, 20) TARGET_E2_SMALL <- c(0.9957222, 0.9528035, 0.8643037, 0.8303071, 0.6732175) TARGET_EN_SMALL <- c(0.4902766, 0.3283824, 0.1098682, 0.0520790, 0.4162915, 0.2877361, 0.0992984, 0.0473600, 0.3246841, 0.2325432, 0.0839220, 0.0404285, 0.3000418, 0.2169352, 0.0793524, 0.0383518, 0.2216044, 0.1652428, 0.0634583, 0.0310612) TARGET_EN_SMALL <- matrix(TARGET_EN_SMALL, nrow = length(xsmall), ncol = length(osmall), byrow = TRUE) xlarge <- c(0.55, 1.00, 1.25, 1.50, 2.00) olarge <- c(2, 3, 4, 10, 20) TARGET_EN_LARGE <- c(0.3000996, 0.2059475, 0.1545596, 0.0600159, 0.0294670, 0.1484955, 0.1096920, 0.0860625, 0.0363940, 0.0183460, 0.1034881, 0.0785723, 0.0627631, 0.0275988, 0.0141035, 0.0731008, 0.0567395, 0.0460070, 0.0209461, 0.0108440, 0.0375343, 0.0301334, 0.0250228, 0.0120921, 0.0064143) TARGET_EN_LARGE <- matrix(TARGET_EN_LARGE, nrow = length(xlarge), ncol = length(olarge), byrow = TRUE) ## Tests stopifnot(exprs = { all.equal(expint_E2(xsmall) - xsmall * log(xsmall), TARGET_E2_SMALL, tol = 5e-8) all.equal(outer(xsmall, osmall, expint), TARGET_EN_SMALL, tol = 5e-7) all.equal(outer(xlarge, olarge, expint), TARGET_EN_LARGE, tol = 5e-7) }) ### ### Values from Table 5.5 of Abramovitz and Stegun ### ## Target values xinv <- c(seq(0.50, 0.10, by = -0.05), seq(0.09, 0.01, by = -0.01)) order <- c(2, 3, 4, 10, 20) TARGET_EN <- c(1.10937, 1.11329, 1.10937, 1.07219, 1.04270, 1.09750, 1.10285, 1.10071, 1.06926, 1.04179, 1.08533, 1.09185, 1.09136, 1.06586, 1.04067, 1.07292, 1.08026, 1.08125, 1.06187, 1.03932, 1.06034, 1.06808, 1.07031, 1.05712, 1.03762, 1.04770, 1.05536, 1.05850, 1.05138, 1.03543, 1.03522, 1.04222, 1.04584, 1.04432, 1.03249, 1.02325, 1.02895, 1.03247, 1.03550, 1.02837, 1.01240, 1.01617, 1.01889, 1.02436, 1.02222, 1.01045, 1.01377, 1.01624, 1.02182, 1.02060, 1.00861, 1.01147, 1.01366, 1.01917, 1.01883, 1.00688, 1.00927, 1.01116, 1.01642, 1.01688, 1.00528, 1.00721, 1.00878, 1.01360, 1.01472, 1.00384, 1.00531, 1.00654, 1.01074, 1.01234, 1.00258, 1.00361, 1.00451, 1.00790, 1.00973, 1.00152, 1.00217, 1.00275, 1.00516, 1.00692, 1.00071, 1.00103, 1.00133, 1.00271, 1.00401, 1.00019, 1.00027, 1.00036, 1.00081, 1.00137) TARGET_EN <- matrix(TARGET_EN, nrow = length(xinv), ncol = length(order), byrow = TRUE) ## Tests stopifnot(exprs = { all.equal(outer(1/xinv, order, "+") * exp(1/xinv) * outer(1/xinv, order, expint), TARGET_EN, tolerance = 5e-6) all.equal(outer(1/xinv, order, "+") * outer(1/xinv, order, expint, scale = TRUE), TARGET_EN, tolerance = 5e-6) }) ### ### Examples from section 5.3 of Abramowitz and Stegun ### ## Target values order <- 1:10 xsmall <- 1.275 TARGET_SMALL <- c(0.1408099, 0.0998984, 0.0760303, 0.0608307, 0.0504679, 0.0430168, 0.0374307, 0.0331009, 0.0296534, 0.0268469) xlarge <- 10 TARGET_LARGE <- c(0.41570, 0.38302, 0.35488, 0.33041, 0.30898, 0.29005, 0.27325, 0.25822, 0.24472, 0.23253) ## Tests stopifnot(exprs = { all.equal(expint(xsmall, order), TARGET_SMALL, tolerance = 1e-6) all.equal(expint(xlarge, order) * 1e5, TARGET_LARGE, tolerance = 1e-5) }) expint/tests/gammainc-tests.R0000644000176200001440000000322215133736251015767 0ustar liggesusers### == expint: Exponential Integral and Incomplete Gamma Function == ### ### Tests for the incomplete gamma function ### ### G(a,x) = int_x^infty t^{a-1} exp(-t) dt ### ### for a *real* and x >= 0. ### ### AUTHOR: Vincent Goulet ## Load the package library(expint) ## a > 0; direct link to the standard incomplete gamma function x <- c(0.2, 2.5, 5, 8, 10) a <- 1.2 stopifnot(exprs = { identical(gammainc(a, x), gamma(a) * pgamma(x, a, 1, lower = FALSE)) }) ## a = 0; direct link to the exponential integral x <- c(0.2, 2.5, 5, 8, 10) a <- 0 stopifnot(exprs = { identical(gammainc(a, x), expint(x)) identical(gammainc(a, x), expint_E1(x)) }) ## a < 0; compare to the recursive formula x <- c(0.2, 2.5, 5, 8, 10) a <- c(-0.25, -1.2, -2) stopifnot(exprs = { all.equal(gammainc(a[1], x), -(x^a[1] * exp(-x))/a[1] + gamma(a[1] + 1) * pgamma(x, a[1] + 1, 1, lower = FALSE)/a[1]) all.equal(gammainc(a[2], x), -(x^a[2] * exp(-x))/a[2] + (-(x^(a[2] + 1) * exp(-x))/(a[2] + 1) + gamma(a[2] + 2) * pgamma(x, a[2] + 2, 1, lower = FALSE)/(a[2] + 1))/a[2]) all.equal( gammainc(a[3], x), -(x^a[3] * exp(-x))/a[3] + (-(x^(a[3] + 1) * exp(-x))/(a[3] + 1) + expint_E1(x)/(a[3] + 1))/a[3]) }) ## Issue #2: use the recursion even for -0.5 < a < 0 (unlike GSL ## sources), relying on the accuracy of 'pgamma' near a = 0.5 x <- 1e-5 a <- seq(-0.501, -0.499, length.out = 1000) stopifnot(exprs = { all.equal(gammainc(a, x), -(x^a * exp(-x))/a + gamma(a + 1) * pgamma(x, a + 1, 1, lower = FALSE)/a) }) expint/MD50000644000176200001440000000403415136053334012075 0ustar liggesusersee00e5b9aa754d33a32bcb02023a4537 *DESCRIPTION 5f8a7f85a3e0abba979c1c9979b8b00f *NAMESPACE d7c07c6689aa28184a4df0b6325cabc1 *R/expint.R 7471ef9868ba408f12a5a498e58501f7 *R/gammainc.R f70e478f587c2e106ee85c75343a48ae *build/partial.rdb ea9202c69e928e624bd02d9f70f547e3 *build/vignette.rds 0ceb626122121eb5a213457ab7a72a38 *inst/CITATION 75374b2a4804c80b3499b4e76a092a1f *inst/NEWS.Rd fb5c6a6cab70f2ba56b3fafde3e88d90 *inst/doc/expint.R 68bfa02e0e9e2cc7887d50a5edae5c58 *inst/doc/expint.Rnw daf81804bc41210c2d199ee533c448d6 *inst/doc/expint.pdf d7d472fd5b250cb674d8346b0a542d62 *inst/example_API/DESCRIPTION 3369a2d761d00f69ff6cd4d7239100e3 *inst/example_API/NAMESPACE b5da8158d9ed99f4ea41439428aa0a59 *inst/example_API/R/pkg.R 0e2eb3df0ea6c5c8390f57cfbd4a144a *inst/example_API/man/pkg.Rd 40df19637b270a88d3d38bf46bf91548 *inst/example_API/src/bar.c 9951c44ab3127c3be39de8874b104e98 *inst/example_API/src/foo.c 389d2bce80b57f560da3aaf2d1b11502 *inst/example_API/src/init.c b6d56cad2a4918add4ffec77171ac36e *inst/example_API/src/locale.h 3d2f0b06e8d1485c694ded0525962d94 *inst/example_API/src/pkg.h 779de94c41564597814c2f91ac086985 *inst/include/expintAPI.h 0028cb1f88b81fd2fdc9534a96fe3574 *man/expint-package.Rd f46559b620171a5da7757a0ed91b3bbd *man/expint.Rd bf718b5610becfb0d36c8973b6a033e3 *man/gammainc.Rd a59d7f0b2c6e6a86c611305d1e0a0e89 *po/expint.pot baf05e5561b399035f01b5c8717e6ef2 *po/fr.po 9b1fc46b8311156241488e0d836933b0 *src/Makevars dbd997048f1ec3cd4d6fb04638d622c2 *src/expint.c dfab4ace29e6e8d0eae0628fb1bffd9f *src/expint.h b2dabe9819c9edf4a0772945721a5f6b *src/gamma_inc.c 94a10521f6882d1cd70a9c97b5446c97 *src/init.c 87053b6138fe649fec962930ee98a47e *src/locale.h 40c5dc5621a325aca8b61d06834d65e4 *tests/expint-tests.R 7459a17dc52bfe23262fa81c9b83ed7a *tests/gammainc-tests.R d2a3b910f1f59fe9bfaf43896f526159 *vignettes/Makefile 68bfa02e0e9e2cc7887d50a5edae5c58 *vignettes/expint.Rnw 8afb3b5563b87135d00852144f3ff95f *vignettes/expint.bib 7ec15c16d0d66790f28e90343c5434a3 *vignettes/framed.sty dce48c3209ead3561fa5e6cee54b108e *vignettes/share/preamble.tex expint/po/0000755000176200001440000000000015133736251012205 5ustar liggesusersexpint/po/fr.po0000644000176200001440000000317415133736251013161 0ustar liggesusers# expint: Exponential Integrals and Incomplete Gamma Function # Copyright (C) 2016-2026 Vincent Goulet # This file is distributed under the same license as the expint package. # Vincent Goulet , 2016 # msgid "" msgstr "" "Project-Id-Version: expint 1.0-0\n" "Report-Msgid-Bugs-To: Vincent Goulet\n" "POT-Creation-Date: 2026-01-16 15:52-0500\n" "PO-Revision-Date: 2016-12-15 00:56-0500\n" "Last-Translator: Vincent Goulet \n" "Language-Team: French\n" "Language: fr_CA\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: expint.c:357 msgid "overflow in expint_E1" msgstr "dépassement de capacité dans expint_E1" #: expint.c:403 expint.c:410 msgid "underflow in expint_E1" msgstr "soupassement de capacité dans expint_E1" #: expint.c:428 msgid "overflow in expint_E2" msgstr "dépassement de capacité dans expint_E2" #: expint.c:462 expint.c:469 msgid "underflow in expint_E2" msgstr "soupassement de capacité dans expint_E2" #: expint.c:477 msgid "underflow in expint_En" msgstr "soupassement de capacité dans expint_En" #: expint.c:547 expint.c:614 gamma_inc.c:192 msgid "invalid arguments" msgstr "arguments incorrects" #: expint.c:591 msgid "internal error in expint_do_expint1" msgstr "erreur interne dans expint_do_expint1" #: expint.c:673 msgid "internal error in expint_do_expint2" msgstr "erreur interne dans expint_do_expint2" #: gamma_inc.c:107 msgid "maximum number of iterations reached in gamma_inc_F_CF" msgstr "nombre d'itérations maximal atteint dans gamma_inc_F_CF" expint/po/expint.pot0000644000176200001440000000240215133736251014236 0ustar liggesusers# expint: Exponential Integrals and Incomplete Gamma Function # Copyright (C) 2016-2026 Vincent Goulet # This file is distributed under the same license as the expint package. # Vincent Goulet , 2016 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: expint 1.0-0\n" "Report-Msgid-Bugs-To: Vincent Goulet\n" "POT-Creation-Date: 2026-01-16 15:52-0500\n" "PO-Revision-Date: 2016-12-20 01:57-0500\n" "Last-Translator: Vincent Goulet \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: expint.c:357 msgid "overflow in expint_E1" msgstr "" #: expint.c:403 expint.c:410 msgid "underflow in expint_E1" msgstr "" #: expint.c:428 msgid "overflow in expint_E2" msgstr "" #: expint.c:462 expint.c:469 msgid "underflow in expint_E2" msgstr "" #: expint.c:477 msgid "underflow in expint_En" msgstr "" #: expint.c:547 expint.c:614 gamma_inc.c:192 msgid "invalid arguments" msgstr "" #: expint.c:591 msgid "internal error in expint_do_expint1" msgstr "" #: expint.c:673 msgid "internal error in expint_do_expint2" msgstr "" #: gamma_inc.c:107 msgid "maximum number of iterations reached in gamma_inc_F_CF" msgstr "" expint/R/0000755000176200001440000000000014220225222011753 5ustar liggesusersexpint/R/expint.R0000644000176200001440000000203714220225222013407 0ustar liggesusers### == expint: Exponential Integral and Incomplete Gamma Function == ### ### Functions to compute the exponential integral Ei and the ### exponential integral of order 'n = 1, 2, ...' ### ### E_n = int_x^infty exp(-t)/t^n dt. ### ### Function 'expint' is a unified and fully vectorized interface with ### default the most common case E_1. The other functions are simpler, ### slightly faster interfaces to E_1, E_2, E_n and Ei. ### ### When 'scale' is TRUE, the value returned is scaled by exp(x). ### ### AUTHOR: Vincent Goulet expint <- function(x, order = 1L, scale = FALSE) .External(C_expint_do_expint, "En", x, order, scale) expint_E1 <- function(x, scale = FALSE) .External(C_expint_do_expint, "E1", x, scale) expint_E2 <- function(x, scale = FALSE) .External(C_expint_do_expint, "E2", x, scale) expint_En <- function(x, order, scale = FALSE) .External(C_expint_do_expint, "En", x, order[1L], scale) expint_Ei <- function(x, scale = FALSE) -.External(C_expint_do_expint, "E1", -x, scale) expint/R/gammainc.R0000644000176200001440000000054414220225222013655 0ustar liggesusers### == expint: Exponential Integral and Incomplete Gamma Function == ### ### The incomplete gamma function ### ### G(a,x) = int_x^infty t^{a-1} exp(-t) dt ### ### for a *real* and x >= 0. Note the order of the arguments. ### ### AUTHOR: Vincent Goulet gammainc <- function(a, x) .External(C_expint_do_gammainc, a, x) expint/vignettes/0000755000176200001440000000000015135742277013606 5ustar liggesusersexpint/vignettes/expint.Rnw0000644000176200001440000005352515135742246015613 0ustar liggesusers\input{share/preamble} %\VignetteIndexEntry{expint user manual} %\VignettePackage{expint} %\VignetteDepends{pracma,gsl} %\SweaveUTF8 \title{\pkg{expint}: Exponential integral and incomplete gamma function} \author{Vincent Goulet \\ Université Laval} \date{} %% Additional commands specific to this document \newcommand{\Ei}{\operatorname{Ei}} <>= library(expint) options(width = 60) @ \begin{document} \maketitle \section{Introduction} \label{sec:introduction} The exponential integral \begin{equation*} E_1(x) = \int_x^\infty \frac{e^{-t}}{t}\, dt, \quad x \in \mathbb{R} \end{equation*} and the incomplete gamma function \begin{equation*} \Gamma(a, x) = \int_x^\infty t^{a-1} e^{-t}\, dt, \quad x > 0, \quad a \in \mathbb{R} \end{equation*} are two closely related functions that arise in various fields of mathematics. \pkg{expint} is a small package provides facilities to compute the exponential integral and the incomplete gamma function. Furthermore, and perhaps most conveniently for R package developers, the package also gives easy access to the underlying C workhorses through an API. The C routines are derived from the GNU Scientific Library \citep[GSL;][]{GSL}. The package \pkg{expint} started its life in version~2.0-0 of \pkg{actuar} \citep{actuar}, where I extended the range of admissible values in the computation of limited expected value functions. This required an incomplete gamma function that accepts negative values of argument $a$, as explained at the beginning of Appendix~A of \citet{LossModels4e}. \section{Exponential integral} \label{sec:expint} \citet[Section~5.1]{Abramowitz:1972} first define the exponential integral as \begin{equation} \label{eq:E1} E_1(x) = \int_x^\infty \frac{e^{-t}}{t}\, dt. \end{equation} An alternative definition (to be understood in terms of the Cauchy principal value due to the singularity of the integrand at zero) is \begin{equation*} \Ei(x) = - \int_{-x}^\infty \frac{e^{-t}}{t}\, dt = \int_{-\infty}^x \frac{e^t}{t}\, dt, \quad x > 0. \end{equation*} The above two definitions are related as follows: \begin{equation} \label{eq:Ei_vs_E1} E_1(-x) = - \Ei(x), \quad x > 0. \end{equation} The exponential integral can also generalized to \begin{equation*} E_n(x) = \int_1^\infty \frac{e^{-xt}}{t^n}\, dt, \quad n = 0, 1, 2, \dots, \quad x > 0, \end{equation*} where $n$ is then the \emph{order} of the integral. The latter expression is closely related to the incomplete gamma function (\autoref{sec:gammainc}) as follows: \begin{equation} \label{eq:En_vs_gammainc} E_n(x) = x^{n - 1} \Gamma(1 - n, x). \end{equation} One should note that the first argument of function $\Gamma$ is negative for $n > 1$. The following recurrence relation holds between exponential integrals of successive orders: \begin{equation} \label{eq:En:recurrence} E_{n+1}(x) = \frac{1}{n} [e^{-x} - x E_n(x)]. \end{equation} Finally, $E_n(x)$ has the following asymptotic expansion: \begin{equation} \label{eq:En:asymptotic} E_n(x) \asymp \frac{e^{-x}}{x} \left( 1 - \frac{n}{x} + \frac{n(n+1)}{x^2} - \frac{n(n+1)(n+2)}{x^3} + \dots \right). \end{equation} \section{Incomplete gamma function} \label{sec:gammainc} From a probability theory perspective, the incomplete gamma function is usually defined as \begin{equation*} P(a, x) = \frac{1}{\Gamma(a)} \int_0^x t^{a - 1} e^{-t}\, dt, \quad x > 0, \quad a > 0. \end{equation*} Function \code{pgamma} already implements this function in R (just note the differing order of the arguments). Now, the definition of the incomplete gamma function of interest for this package is rather the following \citep[Section~6.5]{Abramowitz:1972}: \begin{equation} \label{eq:gammainc} \Gamma(a, x) = \int_x^\infty t^{a-1} e^{-t}\, dt, \quad x > 0, \quad a \in \mathbb{R}. \end{equation} Note that $a$ can be negative with this definition. Of course, for $a > 0$ one has \begin{equation} \label{eq:gammainc_vs_pgamma} \Gamma(a, x) = \Gamma(a) [1 - P(a, x)]. \end{equation} Integration by parts of the integral in \eqref{eq:gammainc} yields the recursive relation \begin{equation} \label{eq:gammainc_recursion} \Gamma(a, x) = -\frac{x^a e^{-x}}{a} + \frac{1}{a} \Gamma(a + 1, x). \end{equation} When $a < 0$, this relation can be used repeatedly $k$ times until $a + k$ is a positive number. The right hand side can then be evaluated with \eqref{eq:gammainc_vs_pgamma}. If $a = 0, -1, -2, \dots$, this calculation requires the value of \begin{equation*} G(0, x) = \int_x^\infty \frac{e^{-t}}{t}\, dt = E_1(x), \end{equation*} the exponential integral defined in \eqref{eq:E1}. \section{R interfaces} \label{sec:interfaces} \pkg{expint} provides one main and four auxiliary R functions to compute the exponential integral, and one function to compute the incomplete gamma function. Their signatures are the following: \begin{Schunk} \begin{Sinput} expint(x, order = 1L, scale = FALSE) expint_E1(x, scale = FALSE) expint_E2(x, scale = FALSE) expint_En(x, order, scale = FALSE) expint_Ei(x, scale = FALSE) gammainc(a, x) \end{Sinput} \end{Schunk} Let us first go over function \code{gammainc} since there is less to discuss. The function takes in argument two vectors or real numbers (non-negative for argument \code{x}) and returns the value of $\Gamma(a, x)$. The function is vectorized in arguments \code{a} and \code{x}, so it works similar to, say, \code{pgamma}. We now turn to the \code{expint} family of functions. The function \code{expint} is a unified interface to compute exponential integrals $E_n(x)$ of any (non-negative) order, with default the most common case $E_1(x)$. The function is vectorized in arguments \code{x} and \code{order}. In other words, one can compute the exponential integral of a different order for each value of $x$. <>= expint(c(1.275, 10, 12.3), order = 1:3) @ The argument \code{order} should be a vector of integers. Non-integer values are silently coerced to integers using truncation towards zero. When the argument \code{scale} is \code{TRUE}, the result is scaled by $e^{x}$. The functions \code{expint\_E1}, \code{expint\_E2} and \code{expint\_En} are simpler, slightly faster ways to directly compute exponential integrals $E_1(x)$, $E_2(x)$ and $E_n(x)$, the latter for a \emph{single} order $n$ (the first value of \code{order} if \code{order} is a vector). <>= expint_E1(1.275) expint_E2(10) expint_En(12.3, order = 3L) @ Finally, the function \code{expint\_Ei} is provided as a convenience to compute $\Ei(x)$ using \eqref{eq:Ei_vs_E1}. <>= expint_Ei(5) -expint_E1(-5) # same @ \section{Accessing the C routines} \label{sec:api} The actual workhorses behind the R functions of \autoref{sec:interfaces} are C routines with the following prototypes: \begin{Schunk} \begin{Sinput} double expint_E1(double x, int scale); double expint_E2(double x, int scale); double expint_En(double x, int order, int scale); double gamma_inc(double a, double x); \end{Sinput} \end{Schunk} \pkg{expint} makes these routines available to other packages through declarations in the header file \file{include/expintAPI.h} in the package installation directory. If you want to use a routine --- say \code{expint\_E1} --- in your package \pkg{pkg}, proceed as follows: \begin{enumerate} \item Add the package \pkg{expint} to the \code{Imports} and \code{LinkingTo} directives of the \file{DESCRIPTION} file of \pkg{pkg}; \item Add an entry \samp{import(expint)} in the \file{NAMESPACE} file of \pkg{pkg}; \item Define the routine with a call to \code{R\_GetCCallable} in the initialization routine \code{R\_init\_pkg} of \pkg{pkg} \citep[Section~5.4]{WRE}. For the current example, the file \file{src/init.c} of \pkg{pkg} would contain the following code: \begin{Schunk} \begin{Sinput} void R_init_pkg(DllInfo *dll) { R_registerRoutines(/* native routine registration */); pkg_expint_E1 = (double(*)(double,int,int)) R_GetCCallable("expint", "expint_E1"); } \end{Sinput} \end{Schunk} \item Define a native routine interface, say \code{pkg\_expint\_E1} to avoid any name clash, in \file{src/init.c} that will call \code{expint\_E1}: \begin{Schunk} \begin{Sinput} double(*pkg_expint_E1)(double,int); \end{Sinput} \end{Schunk} \item Declare the routine in a header file of \pkg{pkg} with the keyword \code{extern} to expose the interface to all routines of the package. In our example, \file{src/pkg.h} would contain: \begin{Schunk} \begin{Sinput} extern double(*pkg_expint_E1)(double,int); \end{Sinput} \end{Schunk} \item Include the package header file \file{pkg.h} in any C file making use of the routine \code{pkg\_expint\_E1}. \end{enumerate} To help developers get started, \pkg{expint} ships with a complete test package implementing the above; see the \file{example\_API} sub-directory in the installation directory. This test package uses the \code{.External} R to C interface and, as a bonus, shows how to vectorize an R function on the C side (the code for this being mostly derived from base R). There are various ways to define a package API. The approach described above was derived from the package \pkg{zoo} \citep{zoo}. The package \pkg{xts} \citep{xts} --- and probably a few others on CRAN --- draws from \pkg{Matrix} \citep{Matrix} to propose a somewhat simpler approach where the API exposes routines that can be used directly in a package. However, the provided header file can be included only once in a package, otherwise one gets \samp{duplicate symbols} errors at link time. This constraint does not show in the example provided with \pkg{xts} or in packages \pkg{RcppXts} \citep{RcppXts} and \pkg{TTR} \citep{TTR} that link to it (the only two at the time of writing). A way around the issue is to define a native routine calling the routines exposed in the API. In this scenario, tests I conducted proved the approach I retained to be up to 10\% faster most of the time. \section{Implementation details} \label{sec:implementation} As already stated, the C routines mentioned in \autoref{sec:api} are derived from code in the GNU Scientific Library \citep{GSL}. For exponential integrals, the main routine \code{expint\_E1} computes $E_1(x)$ using Chebyshev expansions \citep[chapter~3]{Gil:2007}. Routine \code{expint\_E2} computes $E_2(x)$ using \code{expint\_E1} with relation \eqref{eq:En:recurrence} for $x < 100$, and using the asymptotic expression \eqref{eq:En:asymptotic} otherwise. Routine \code{expint\_En} simply relies on \code{gamma\_inc} to compute $E_n(x)$ for $n > 2$ through relation \eqref{eq:En_vs_gammainc}. For the sake of providing routines that better fit within the R ecosystem and coding style, I made the following changes to the original GSL code: \begin{enumerate} \item routines compute a single value and return their result by value; \item accordingly, calculation of the approximation error is dropped in all routines; \item \code{gamma\_inc} computes $\Gamma(a, x)$ for $a > 0$ with \eqref{eq:gammainc_vs_pgamma} using the routines \code{gammafn} and \code{pgamma} of the R API, rather than using the GSL routines, as the example below illustrates; <>= op <- options() # remember default number of digits @ <>= options(digits = 20) gammainc(1.2, 3) gamma(1.2) * pgamma(3, 1.2, 1, lower = FALSE) @ <>= options(op) # restore defaults @ \item \code{gamma\_inc} computes $\Gamma(a, x)$ for $-0.5 < a < 0$ using the recursion \eqref{eq:gammainc_recursion} instead of a series expansion as in the GSL routines, thereby relying on the accuracy of \code{pgamma} near $a = 0.5$ (fixes \href{https://gitlab.com/vigou3/expint/-/issues/2}{issue \#2}; see \autoref{sec:computation_gamma_inc} for additional details). \end{enumerate} \section{Alternative packages} \label{sec:alternatives} The Comprehensive R Archive Network\footnote{% \url{https://cran.r-project.org}} % (CRAN) contains a number of packages with features overlapping \pkg{expint}. I review the similarities and differences here. The closest package in functionality is \pkg{gsl} \citep{gsl-package}. This package is an R wrapper for the special functions and quasi random number generators of the GNU Scientific Library. As such, it provides access to basically the same C code as used in \pkg{expint}. Apart from the changes to the GSL code mentioned in \autoref{sec:implementation}, the main difference between the two packages is that installation from source of \pkg{gsl} requires that the GSL be installed on one's system, whereas \pkg{expint} is a regular, free standing R package. \pkg{VGAM} \citep{VGAM} is a large, high quality package that provides functions to compute the exponential integral $\Ei(x)$ for real values, as well as $e^{-x} \Ei(x)$ and $E_1(x)$ and their derivatives (up to the third derivative). Functions \code{expint}, \code{expexpint} and \code{expint.E1} are wrappers to the Netlib\footnote{% \url{https://www.netlib.org}} % FORTRAN subroutines in file \code{ei.f}. \pkg{VGAM} does not provide an API to its C routines. The package \pkg{pracma} \citep{pracma} provides a large number of functions from numerical analysis, linear algebra, numerical optimization, differential equations and special functions. Its versions of \code{expint}, \code{expint\_E1}, \code{expint\_Ei} and \code{gammainc} are entirely written in R with perhaps less focus on numerical accuracy than the GSL and Netlib implementations. The functions are not vectorized, and the incomplete gamma function is supported for $a \geq -1$ only. The package \pkg{frmqa} had a function \code{gamma\_inc\_err} that computed the incomplete gamma function using the incomplete Laplace integral, but it was only valid for $a = j + 0.5$, $j = 0, 1, 2, \dots$. (The package was removed from CRAN in 2022.) Package \pkg{zipfR} \citep{zipfR} introduces a set of functions to compute various quantities related to the gamma and incomplete gamma functions, but these are essentially wrappers around the base R functions \code{gamma} and \code{pgamma} with no new functionalities. \section{Examples} \label{sec:examples} Let us tabulate the values of $E_n(x)$ for $x = 1.275, 10, 12.3$ and $n = 1, 2, \dots, 10$ as found in examples~4--6 of \citet[section~5.3]{Abramowitz:1972}. <>= x <- c(1.275, 10, 12.3) n <- 1:10 structure(t(outer(x, n, expint)), dimnames = list(paste("n =", n), paste("x =", x))) @ We may also tabulate the values of $\Gamma(a, x)$ for $a = -1.5, -1, -0.5, 1$ and $x = 1, 2, \dots, 10$. <>= a <- c(-1.5, -1, -0.5, 1) x <- 1:10 structure(t(outer(a, x, gammainc)), dimnames = list(paste("x =", x), paste("a =", a))) @ \section{Acknowledgments} I built on the source code of R and many of the packages cited in this manual to create \pkg{expint}, so the R Core Team and the package developers deserve credit. I also extend my thanks to Dirk Eddelbuettel who was of great help in putting together the package API, through both his posts in online forums and private communication. Joshua Ulrich provided a fix to the API infrastructure to avoid duplicated symbols that was implemented in version 0.1-6 of the package. \appendix \section{Additional details on the computation of the incomplete gamma function} \label{sec:computation_gamma_inc} \href{https://gitlab.com/vigou3/expint/-/issues/2}{Issue \#2} raised by Geoffrey Poole highlights that the function \code{gammainc} in versions of \pkg{expint} prior to 0.2-0 returned inconsistent results for small negative values of $a$ and a small value of $x$. \autoref{fig:gammainc_vs_incgam} illustrates the problem by comparing the behaviour of $\Gamma(a, 10^{-5})$ around $a = -0.5$ between \code{gammainc} of \pkg{expint} (again, prior to 0.2-0) and \code{incgam} of \pkg{pracma}. \begin{figure}[t] \centering <>= a <- seq(-0.501, -0.499, length.out = 1000) x <- 1e-5 if (requireNamespace("gsl")) gGamma <- gsl::gamma_inc(a, x) if (requireNamespace("pracma")) pGamma <- sapply(a, pracma::incgam, x = x) plot(a, gGamma, type = "l", ylab = expression(Gamma(a, x)), main = "Versions of package expint prior to 0.2-0") lines(a, pGamma, lty = 2, lwd = 2, col = "orange") legend(-0.5002, 635, c("expint::gammainc(a, 1e-05)", "pracma::incgam(1e-05, a)"), lty = c(1, 2), lwd = c(1, 2), col = c("black", "orange")) @ \caption{Incomplete gamma function for small negative values of $a$ and a small value of $x$} \label{fig:gammainc_vs_incgam} \end{figure} The function \code{gamma\_inc} for the package \pkg{gsl} shows the same defect\footnote{% The solid line in Figure \ref*{fig:gammainc_vs_incgam} is actually traced using \code{gamma\_inc}.}, % indicating that the problem must lie in the GSL code. Indeed, the GSL routine for the incomplete gamma function treats specially the case $-0.5 < a < 0$, and reverts to the recursion \eqref{eq:gammainc_recursion} only for $a \leq -0.5$. For $-0.5 < a < 0$, the GSL computes the incomplete gamma function using the relation \begin{equation*} \Gamma(a, x) = \Gamma(a) Q(a, x), \end{equation*} with $Q(a, x)$ defined as follows: \begin{align*} Q(a, x) &= 1 - P(a, x) \\ &= 1 - \frac{\gamma(a, x)}{\Gamma(a)}, \end{align*} with \begin{equation*} \gamma(a, x) = P(a, x) \Gamma(a) = \int_0^x t^{a - 1} e^{-t}\, dt. \end{equation*} The GSL routine \code{gamma\_inc\_Q\_series} carries the computation of $Q(a, x)$ using a series expansion. The code is not obvious and requires a fair share of reverse engineering. Hence, I document my findings here. First, a series expansion for $\gamma(a, x)$ is \citep[section 6.5.33]{Abramowitz:1972}: \begin{equation} \gamma(a, x) = \sum_{n = 0}^\infty \frac{(-1)^n}{a + n} \frac{x^{a + n}}{n!}. \end{equation} We can rewrite this expansion as \begin{align} \gamma(a, x) &= \frac{x^a}{a} - \sum_{n = 1}^\infty \frac{(-1)^{n - 1}}{a + n} \frac{x^{a + n}}{n!} \notag \\ &= \frac{x^a}{a} - \frac{x^{a + 1}}{a + 1} \sum_{n = 1}^\infty (-1)^{n - 1} \left( \frac{a + 1}{a + n} \right) \frac{x^{n - 1}}{n!}. \label{eq:expansion_small_gamma} \end{align} Second, using the fact that $\Gamma(a + 1) = a \Gamma(a)$, we can rewrite $Q(a, x)$ as follows: \begin{align*} Q(a, x) &= 1 - \frac{x^a}{\Gamma(a + 1)} + \frac{x^a}{\Gamma(a + 1)} - \frac{\gamma(a, x)}{\Gamma(a)} \\ &= 1 - \frac{x^a}{\Gamma(a + 1)} + \frac{1}{\Gamma(a)} \left( \frac{x^a}{a} - \gamma(a, x) \right) \\ &= 1 - \frac{x^a}{\Gamma(a + 1)} + \frac{x^a}{\Gamma(a + 1)} \frac{\Gamma(a + 1)}{\Gamma(a)} \frac{x}{x^{a + 1}} \left( \frac{x^a}{a} - \gamma(a, x) \right) \\ &= 1 - \frac{x^a}{\Gamma(a + 1)} + \frac{x^a}{\Gamma(a + 1)} \left( \frac{a}{a + 1} \right) x \left( \frac{a + 1}{x^{a + 1}} \right) \left( \frac{x^a}{a} - \gamma(a, x) \right). \end{align*} If we define $\phi(a) = 1 - x^a/\Gamma(a + 1)$ and we simplify the last term above using \eqref{eq:expansion_small_gamma}, we finally obtain: \begin{equation} \label{eq:gsl_q_series} Q(a, x) = \phi(a) + (1 - \phi(a)) \left( \frac{a}{a + 1} \right) x \sum_{n = 1}^\infty (-1)^{n - 1} \left( \frac{a + 1}{a + n} \right) \frac{x^{n - 1}}{n!}. \end{equation} This is the expression used to compute $Q(a, x)$. The only remaining element is the computation of $\phi(a)$. For this, the routine \code{gamma\_inc\_Q\_series} uses the product of the Taylor series expansion of $x^a$ around $a = 0$, \begin{equation*} x^a = \sum_{n = 0}^\infty \frac{(a \ln x)^n}{n!}, \end{equation*} and the following Taylor series expansion of the reciprocal gamma function \citep{Mathworld:Gamma}: \begin{equation*} \frac{1}{\Gamma(a + 1)} = 1 + \gamma a + \left( \frac{\gamma^2}{2} - \frac{\pi^2}{12} \right) a^2 + \left( \frac{\gamma^3}{6} - \frac{\gamma\pi^2}{12} + \frac{\zeta(3)}{3} \right) a^3 + \cdots, \end{equation*} where $\gamma$ is the Euler constant, and $\zeta$ is the Riemann zeta function \citep[chapters 6 and 23]{Abramowitz:1972}. Putting all these pieces together, we obtain: \begin{align*} \phi(a) &= 1 - \frac{x^a}{\Gamma(a + 1)} \\ &= - (\ln x + \gamma) a + \left\{ \frac{\pi}{12} - (\ln x + \gamma)^2 \right\} a^2 \\ &\phantom{=} + \left\{ (\ln x + \gamma) \left( \frac{\pi}{12} - \frac{(\ln x + \gamma)^2}{6} \right) - \frac{\zeta(3)}{3} \right\} a^3 + \cdots. \end{align*} One will recognize above the coefficients \code{c1}, \code{c2} and \code{c3} of \code{term1} in the routine \code{gamma\_inc\_Q\_series}. It is not clear where the numerical values in the other seven coefficients come from. Here endeth reverse engineering. The fix introduced in \pkg{expint} 0.2-0 follows the same strategy as \pkg{pracma}: just use the recursion \eqref{eq:gammainc_recursion} also for $-0.5 < a < 0$, and rely on the accuracy of \code{pgamma} for small values of $a$ to yield the correct result. \autoref{fig:gammainc_vs_incgam_fixed} shows that the results from \pkg{expint} and \pkg{pracma} now match. One last implementation detail: the original GSL code uses a loop to compute \eqref{eq:gammainc_recursion} as many times as necessary for $a < -0.5$. Simply extending usage of the loop to $a < 0$ does not work due to rounding errors in computations involving values of $a$ in $(-0.5, 0)$. Therefore, \pkg{expint} keeps as a special case the single application of the recursive relation for $a$ in the latter range. \begin{figure}[t] \centering <>= a <- seq(-0.501, -0.499, length.out = 1000) x <- 1e-5 eGamma <- gammainc(a, x) if (requireNamespace("pracma")) pGamma <- sapply(a, pracma::incgam, x = x) plot(a, eGamma, type = "l", ylab = expression(Gamma(a, x)), main = "Versions of package expint from 0.2-0") lines(a, pGamma, lty = 2, lwd = 2, col = "orange") legend(-0.5002, 635, c("expint::gammainc(a, 1e-05)", "pracma::incgam(1e-05, a)"), lty = c(1, 2), lwd = c(1, 2), col = c("black", "orange")) @ \caption{Fixed incomplete gamma function} \label{fig:gammainc_vs_incgam_fixed} \end{figure} \bibliography{expint} \end{document} expint/vignettes/expint.bib0000644000176200001440000001107615135742246015574 0ustar liggesusers@Book{Abramowitz:1972, author = {Abramowitz, M. and Stegun, I. A.}, title = {Handbook of Mathematical Functions}, publisher = {Dover}, year = 1972, url = {https://personal.math.ubc.ca/~cbm/aands/}, language = {english} } @Manual{GSL, title = {{GNU} Scientific Library Reference Manual}, author = {Galassi, M. and Davies, J. and Theiler, J. and Gough, B. and Jungman, G. and Alken P. and Booth, M. and Rossi, F. and Ulerich, R.}, edition = {Third}, year = 2009, isbn = {0-95461207-8}, url = {https://www.gnu.org/software/gsl/}, language = {english} } @Book{Gil:2007, author = {Gil, A. and Segura, J. and Temme, N. M.}, title = {Numerical Methods for Special Functions}, publisher = {Society for Industrial and Applied Mathematics}, year = 2007, isbn = {978-0-89871634-4}, url = {https://dx.doi.org/10.1137/1.9780898717822}, language = {english} } @Book{LossModels4e, author = {Klugman, S. A. and Panjer, H. H. and Willmot, G.}, title = {Loss Models: From Data to Decisions}, edition = 4, publisher = {Wiley}, year = 2012, address = {New York}, isbn = {978-1-11831532-3}, language = {english} } @Misc{Mathworld:Gamma, author = {Weisstein, Eric W.}, title = {Gamma Function}, year = 2026, howpublished = {From MathWorld -- A Wolfram Resource}, url = {https://mathworld.wolfram.com/GammaFunction.html}, language = {english}, } @Manual{Matrix, title = {Matrix: Sparse and Dense Matrix Classes and Methods}, author = {D. Bates and M. Maechler}, year = 2025, note = {R package version 1.7-4}, url = {https://cran.r-project.org/package=Matrix}, language = {english} } @Manual{RcppXts, title = {RcppXts: Interface the xts API via Rcpp}, author = {D. Eddelbuettel}, year = 2022, note = {R package version 0.0.6}, url = {https://cran.r-project.org/package=RcppXts}, language = {english} } @Manual{TTR, title = {TTR: Technical Trading Rules}, author = {J. Ulrich}, year = 2023, note = {R package version 0.24.4}, url = {https://cran.r-project.org/package=TTR}, language = {english} } @Book{VGAM, author = {Yee, T. W.}, title = {Vector Generalized Linear and Additive Models: With an Implementation in {R}}, publisher = {Springer}, year = 2015, isbn = {978-1-49392818-7}, url = {https://cran.r-project.org/package=VGAM}, language = {english} } @Manual{WRE, title = {Writing {R} Extensions}, author = {{R Core Team}}, year = 2025, note = {Manual for {R} version 4.5.2}, url = {https://cran.r-project.org/doc/manuals/R-exts.html}, language = {english}} @Article{actuar, author = {Dutang, C. and Goulet, V. and Pigeon, M.}, title = {\pkg{actuar}: An {R} Package for Actuarial Science}, journal = {Journal of Statistical Software}, year = 2008, volume = 25, number = 7, url = {https://www.jstatsoft.org/v25/i07}, language = {english} } @Article{gsl-package, title = {Special functions in {R}: introducing the \pkg{gsl} package}, author = {Hankin, R. K. S.}, journal = {R News}, year = {2006}, month = {October}, volume = {6}, issue = {4}, language = {english} } @Manual{pracma, title = {\pkg{pracma}: Practical Numerical Math Functions}, author = {Borchers, H. W.}, year = {2016}, note = {R package version 2.4.6}, url = {https://cran.r-project.org/package=pracma}, language = {english} } @Manual{xts, title = {xts: {eXtensible} Time Series}, author = {J. A. Ryan and J. M. Ulrich}, year = 2024, note = {R package version 0.14.1}, url = {https://cran.r-project.org/package=xts}, language = {english} } @InProceedings{zipfR, title = {\pkg{zipfR}: Word Frequency Distributions in {R}}, author = {Evert, S. and Baroni, M.}, booktitle = {Proceedings of the 45\textsuperscript{th} Annual Meeting of the Association for Computational Linguistics, Posters and Demonstrations Sessions}, address = {Prague, Czech Republic}, year = {2007}, pages = {29--32}, note = {R package version 0.6-70}, url = {https://cran.r-project.org/package=zipfR}, language = {english} } @Article{zoo, title = {zoo: S3 Infrastructure for Regular and Irregular Time Series}, author = {A. Zeileis and G. Grothendieck}, journal = {Journal of Statistical Software}, year = 2005, volume = 14, number = 6, pages = {1--27}, doi = {10.18637/jss.v014.i06}, language = {english} }expint/vignettes/framed.sty0000644000176200001440000005366114220225222015574 0ustar liggesusers% framed.sty v 0.96 2011/10/22 % Copyright (C) 1992-2011 by Donald Arseneau (asnd@triumf.ca) % These macros may be freely transmitted, reproduced, or modified % for any purpose provided that this notice is left intact. % %====================== Begin Instructions ======================= % % framed.sty % ~~~~~~~~~~ % Create framed, shaded, or differently highlighted regions that can % break across pages. The environments defined are % framed - ordinary frame box (\fbox) with edge at margin % oframed - framed with open top/bottom at page breaks % shaded - shaded background (\colorbox) bleeding into margin % shaded* - shaded background (\colorbox) with edge at margin % snugshade - shaded with tight fit around text (esp. in lists) % snugshade* - like snugshade with shading edge at margin % leftbar - thick vertical line in left margin % % to be used like % \begin{framed} % copious text % \end{framed} % % But the more general purpose of this package is to facilitate the % definition of new environments that take multi-line material, % wrap it with some non-breakable formatting (some kind of box or % decoration) and allow page breaks in the material. Such environments % are defined to declare (or use) \FrameCommand for applying the boxy % decoration, and \MakeFramed{settings} ... \endMakeFramed wrapped % around the main text argument (environment body). % % The "framed" environment uses "\fbox", by default, as its "\FrameCommand" % with the additional settings "\fboxrule=\FrameRule" and "\fboxsep=\FrameSep". % You can change these lengths (using "\setlength") and you can change % the definition of "\FrameCommand" to use much fancier boxes. % % In fact, the "shaded" environment just redefines \FrameCommand to be % "\colorbox{shadecolor}" (and you have to define the color `"shadecolor"': % "\definecolor{shadecolor}..."). % % Although the intention is for other packages to define the varieties % of decoration, a command "\OpenFbox" is defined for frames with open % tops or bottoms, and used for the "oframed" environment. This facility % is based on a more complex and capable command "\CustomFBox" which can % be used for a wider range of frame styles. One such style of a title-bar % frame with continuation marks is provided as an example. It is used by % the "titled-frame" environment. To make use of "titled-frame" in your % document, or the "\TitleBarFrame" command in your own environment % definitions, you must define the colors TFFrameColor (for the frame) % and a contrasting TFTitleColor (for the title text). % % A page break is allowed, and even encouraged, before the framed % environment. If you want to attach some text (a box title) to the % frame, then the text should be inserted by \FrameCommand so it cannot % be separated from the body. % % The contents of the framed regions are restricted: % Floats, footnotes, marginpars and head-line entries will be lost. % (Some of these may be handled in a later version.) % This package will not work with the page breaking of multicol.sty, % or other systems that perform column-balancing. % % The MakeFramed environment does the work. Its `settings' argument % should contain any adjustments to the text width (via a setting of % "\hsize"). Here, the parameter "\width" gives the measured extra width % added by the frame, so a common setting is "\advance\hsize-\width" % which reduces the width of the text just enough that the outer edge % of the frame aligns with the margins. The `settings' should also % include a `restore' command -- "\@parboxrestore" or "\FrameRestore" % or something similar; for instance, the snugshade environment uses % settings to eliminate list indents and vertical space, but uses % "\hspace" in "\FrameCommand" to reproduce the list margin ouside the % shading. % % There are actually four variants of "\FrameCommand" to allow different % formatting for each part of an environment broken over pages. Unbroken % text is adorned by "\FrameCommand", whereas split text first uses % "\FirstFrameCommand", possibly followed by "\MidFrameCommand", and % finishing with "\LastFrameCommand". The default definitions for % these three just invokes "\FrameCommand", so that all portions are % framed the same way. See the oframe environment for use of distinct % First/Mid/Last frames. % % Expert commands: % \MakeFramed, \endMakeFramed: the "MakeFramed" environment % \FrameCommand: command to draw the frame around its argument % \FirstFrameCommand: the frame for the first part of a split environment % \LastFrameCommand: for the last portion % \MidFrameCommand: for any intermediate segments % \FrameRestore: restore some text settings, but fewer than \@parboxrestore % \FrameRule: length register; \fboxrule for default "framed". % \FrameSep: length register; \fboxsep for default "framed". % \FrameHeightAdjust: macro; height of frame above baseline at top of page % \OuterFrameSep: vertical space before and after the framed env. Defaults to "\topsep" % % This is still a `pre-production' version because I can think of many % features/improvements that should be made. Also, a detailed manual needs % to be written. Nevertheless, starting with version 0.5 it should be bug-free. % % ToDo: % Test more varieties of list % Improve and correct documentation % Propagation of \marks % Handle footnotes (how??) floats (?) and marginpars. % Stretchability modification. % Make inner contents height/depth influence placement. %======================== End Instructions ======================== \ProvidesPackage{framed}[2011/10/22 v 0.96: framed or shaded text with page breaks] \newenvironment{framed}% using default \FrameCommand {\MakeFramed {\advance\hsize-\width \FrameRestore}}% {\endMakeFramed} \newenvironment{shaded}{% \def\FrameCommand{\fboxsep=\FrameSep \colorbox{shadecolor}}% \MakeFramed {\FrameRestore}}% {\endMakeFramed} \newenvironment{shaded*}{% \def\FrameCommand{\fboxsep=\FrameSep \colorbox{shadecolor}}% \MakeFramed {\advance\hsize-\width \FrameRestore}}% {\endMakeFramed} \newenvironment{leftbar}{% \def\FrameCommand{\vrule width 3pt \hspace{10pt}}% \MakeFramed {\advance\hsize-\width \FrameRestore}}% {\endMakeFramed} % snugshde: Shaded environment that % -- uses the default \fboxsep instead of \FrameSep % -- leaves the text indent unchanged (shading bleeds out) % -- eliminates possible internal \topsep glue (\@setminipage) % -- shrinks inside the margins for lists % An \item label will tend to hang outside the shading, thanks to % the small \fboxsep. \newenvironment{snugshade}{% \def\FrameCommand##1{\hskip\@totalleftmargin \hskip-\fboxsep \colorbox{shadecolor}{##1}\hskip-\fboxsep % There is no \@totalrightmargin, so: \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}% \MakeFramed {\advance\hsize-\width \@totalleftmargin\z@ \linewidth\hsize \@setminipage}% }{\par\unskip\@minipagefalse\endMakeFramed} \newenvironment{snugshade*}{% \def\FrameCommand##1{\hskip\@totalleftmargin \colorbox{shadecolor}{##1}% % There is no \@totalrightmargin, so: \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}% \MakeFramed {\advance\hsize-\width \@totalleftmargin\z@ \linewidth\hsize \advance\labelsep\fboxsep \@setminipage}% }{\par\unskip\@minipagefalse\endMakeFramed} \newenvironment{oframed}{% open (top or bottom) framed \def\FrameCommand{\OpenFBox\FrameRule\FrameRule}% \def\FirstFrameCommand{\OpenFBox\FrameRule\z@}% \def\MidFrameCommand{\OpenFBox\z@\z@}% \def\LastFrameCommand{\OpenFBox\z@\FrameRule}% \MakeFramed {\advance\hsize-\width \FrameRestore}% }{\endMakeFramed} % A simplified entry to \CustomFBox with two customized parameters: % the thicknesses of the top and bottom rules. Perhaps we want to % use less \fboxsep on the open edges? \def\OpenFBox#1#2{\fboxsep\FrameSep \CustomFBox{}{}{#1}{#2}\FrameRule\FrameRule} % \CustomFBox is like an amalgamation of \fbox and \@frameb@x, % so it can be used by an alternate to \fbox or \fcolorbox, but % it has more parameters for various customizations. % Parameter #1 is inserted (in vmode) right after the top rule % (useful for a title or assignments), and #2 is similar, but % inserted right above the bottom rule. % The thicknesses of the top, bottom, left, and right rules are % given as parameters #3,#4,#5,#6 respectively. They should be % \fboxrule or \z@ (or some other thickness). % The text argument is #7. % An instance of this can be used for the frame of \fcolorbox by % locally defining \fbox before \fcolorbox; e.g., % \def\fbox{\CustomFBox{}{}\z@\z@\fboxrule\fboxrule}\fcolorbox % % Do we need to use different \fboxsep on different sides too? % \long\def\CustomFBox#1#2#3#4#5#6#7{% \leavevmode\begingroup \setbox\@tempboxa\hbox{% \color@begingroup \kern\fboxsep{#7}\kern\fboxsep \color@endgroup}% \hbox{% % Here we calculate and shift for the depth. Done in % a group because one of the arguments might be \@tempdima % (we could use \dimexpr instead without grouping). \begingroup \@tempdima#4\relax \advance\@tempdima\fboxsep \advance\@tempdima\dp\@tempboxa \expandafter\endgroup\expandafter \lower\the\@tempdima\hbox{% \vbox{% \hrule\@height#3\relax #1% \hbox{% \vrule\@width#5\relax \vbox{% \vskip\fboxsep % maybe these should be parameters too \copy\@tempboxa \vskip\fboxsep}% \vrule\@width#6\relax}% #2% \hrule\@height#4\relax}% }% }% \endgroup } % A particular type of titled frame with continuation marks. % Parameter #1 is the title, repeated on each page. \newenvironment{titled-frame}[1]{% \def\FrameCommand{\fboxsep8pt\fboxrule2pt \TitleBarFrame{\textbf{#1}}}% \def\FirstFrameCommand{\fboxsep8pt\fboxrule2pt \TitleBarFrame[$\blacktriangleright$]{\textbf{#1}}}% \def\MidFrameCommand{\fboxsep8pt\fboxrule2pt \TitleBarFrame[$\blacktriangleright$]{\textbf{#1\ (cont)}}}% \def\LastFrameCommand{\fboxsep8pt\fboxrule2pt \TitleBarFrame{\textbf{#1\ (cont)}}}% \MakeFramed{\advance\hsize-20pt \FrameRestore}}% % note: 8 + 2 + 8 + 2 = 20. Don't use \width because the frame title % could interfere with the width measurement. {\endMakeFramed} % \TitleBarFrame[marker]{title}{contents} % Frame with a label at top, optional continuation marker at bottom right. % Frame color is TFFrameColor and title color is a contrasting TFTitleColor; % both need to be defined before use. The frame itself use \fboxrule and % \fboxsep. If the title is omitted entirely, the title bar is omitted % (use a blank space to force a blank title bar). % \newcommand\TitleBarFrame[3][]{\begingroup \ifx\delimiter#1\delimiter \let\TF@conlab\@empty \else \def\TF@conlab{% continuation label \nointerlineskip \smash{\rlap{\kern\wd\@tempboxa\kern\fboxrule\kern\fboxsep #1}}}% \fi \let\TF@savecolor\current@color \textcolor{TFFrameColor}{% \CustomFBox {\TF@Title{#2}}{\TF@conlab}% \fboxrule\fboxrule\fboxrule\fboxrule {\let\current@color\TF@savecolor\set@color #3}% }\endgroup } % The title bar for \TitleBarFrame \newcommand\TF@Title[1]{% \ifx\delimiter#1\delimiter\else \kern-0.04pt\relax \begingroup \setbox\@tempboxa\vbox{% \kern0.8ex \hbox{\kern\fboxsep\textcolor{TFTitleColor}{#1}\vphantom{Tj)}}% \kern0.8ex}% \hrule\@height\ht\@tempboxa \kern-\ht\@tempboxa \box\@tempboxa \endgroup \nointerlineskip \kern-0.04pt\relax \fi } \chardef\FrameRestore=\catcode`\| % for debug \catcode`\|=\catcode`\% % (debug: insert space after backslash) \newlength\OuterFrameSep \OuterFrameSep=\maxdimen \relax \def\MakeFramed#1{\par % apply default \OuterFrameSep = \topsep \ifdim\OuterFrameSep=\maxdimen \OuterFrameSep\topsep \fi % measure added width and height; call result \width and \height \fb@sizeofframe\FrameCommand \let\width\fb@frw \let\height\fb@frh % insert pre-penalties and skips \begingroup \skip@\lastskip \if@nobreak\else \penalty9999 % updates \page parameters \ifdim\pagefilstretch=\z@ \ifdim\pagefillstretch=\z@ % not infinitely stretchable, so encourage a page break here \edef\@tempa{\the\skip@}% \ifx\@tempa\zero@glue \penalty-30 \else \vskip-\skip@ \penalty-30 \vskip\skip@ \fi\fi\fi \penalty\z@ % Give a stretchy breakpoint that will always be taken in preference % to the \penalty 9999 used to update page parameters. The cube root % of 10000/100 indicates a multiplier of 0.21545, but the maximum % calculated badness is really 8192, not 10000, so the multiplier % is 0.2301. \advance\skip@ \z@ plus-.5\baselineskip \advance\skip@ \z@ plus-.231\height \advance\skip@ \z@ plus-.231\skip@ \advance\skip@ \z@ plus-.231\OuterFrameSep \vskip-\skip@ \penalty 1800 \vskip\skip@ \fi \addvspace{\OuterFrameSep}% \endgroup % clear out pending page break \penalty\@M \vskip 2\baselineskip \vskip\height \penalty9999 \vskip -2\baselineskip \vskip-\height \penalty9999 % updates \pagetotal |\message{After clearout, \pagetotal=\the\pagetotal, \pagegoal=\the\pagegoal. }% \fb@adjheight \setbox\@tempboxa\vbox\bgroup #1% Modifications to \hsize (can use \width and \height) \textwidth\hsize \columnwidth\hsize } \def\endMakeFramed{\par \kern\z@ \hrule\@width\hsize\@height\z@ % possibly bad \penalty-100 % (\hrule moves depth into height) \egroup %%% {\showoutput\showbox\@tempboxa}% \begingroup \fb@put@frame\FrameCommand\FirstFrameCommand \endgroup \@minipagefalse % In case it was set and not cleared } % \fb@put@frame takes the contents of \@tempboxa and puts all, or a piece, % of it on the page with a frame (\FrameCommand, \FirstFrameCommand, % \MidFrameCommand, or \LastFrameCommand). It recurses until all of % \@tempboxa has been used up. (\@tempboxa must have zero depth.) % #1 = attempted framing command, if no split % #2 = framing command if split % First iteration: Try to fit with \FrameCommand. If it does not fit, % split for \FirstFrameCommand. % Later iteration: Try to fit with \LastFrameCommand. If it does not % fit, split for \MidFrameCommand. \def\fb@put@frame#1#2{\relax \ifdim\pagegoal=\maxdimen \pagegoal\vsize \fi | \message{=============== Entering putframe ====================^^J | \pagegoal=\the\pagegoal, \pagetotal=\the\pagetotal. }% \ifinner \fb@putboxa#1% \fb@afterframe \else \dimen@\pagegoal \advance\dimen@-\pagetotal % natural space left on page \ifdim\dimen@<2\baselineskip % Too little room on page | \message{Page has only \the\dimen@\space room left; eject. }% \eject \fb@adjheight \fb@put@frame#1#2% \else % there's appreciable room left on the page \fb@sizeofframe#1% | \message{\string\pagetotal=\the\pagetotal, | \string\pagegoal=\the\pagegoal, | \string\pagestretch=\the\pagestretch, | \string\pageshrink=\the\pageshrink, | \string\fb@frh=\the\fb@frh. \space} | \message{^^JBox of size \the\ht\@tempboxa\space}% \begingroup % temporarily set \dimen@ to be... \advance\dimen@.8\pageshrink % maximum space available on page \advance\dimen@-\fb@frh\relax % max space available for frame's contents %%% LOOKS SUBTRACTED AND ADDED, SO DOUBLE ACCOUNTING! \expandafter\endgroup % expand \ifdim, then restore \dimen@ to real room left on page \ifdim\dimen@>\ht\@tempboxa % whole box does fit | \message{fits in \the\dimen@. }% % ToDo: Change this to use vsplit anyway to capture the marks % MERGE THIS WITH THE else CLAUSE!!! \fb@putboxa#1% \fb@afterframe \else % box must be split | \message{must be split to fit in \the\dimen@. }% % update frame measurement to use \FirstFrameCommand or \MidFrameCommand \fb@sizeofframe#2% \setbox\@tempboxa\vbox{% simulate frame and flexiblity of the page: \vskip \fb@frh \@plus\pagestretch \@minus.8\pageshrink \kern137sp\kern-137sp\penalty-30 \unvbox\@tempboxa}% \edef\fb@resto@set{\boxmaxdepth\the\boxmaxdepth \splittopskip\the\splittopskip}% \boxmaxdepth\z@ \splittopskip\z@ | \message{^^JPadded box of size \the\ht\@tempboxa\space split to \the\dimen@}% % Split box here \setbox\tw@\vsplit\@tempboxa to\dimen@ | \toks99\expandafter{\splitfirstmark}% | \toks98\expandafter{\splitbotmark}% | \message{Marks are: \the\toks99, \the\toks98. }% \setbox\tw@\vbox{\unvbox\tw@}% natural-sized | \message{Natural height of split box is \the\ht\tw@, leaving | \the\ht\@tempboxa\space remainder. }% % If the split-to size > (\vsize-\topskip), then set box to full size. \begingroup \advance\dimen@\topskip \expandafter\endgroup \ifdim\dimen@>\pagegoal | \message{Frame is big -- Use up the full column. }% \dimen@ii\pagegoal \advance\dimen@ii -\topskip \advance\dimen@ii \FrameHeightAdjust\relax \else % suspect this is implemented incorrectly: % If the split-to size > feasible room_on_page, rebox it smaller. \advance\dimen@.8\pageshrink \ifdim\ht\tw@>\dimen@ | \message{Box too tall; rebox it to \the\dimen@. }% \dimen@ii\dimen@ \else % use natural size \dimen@ii\ht\tw@ \fi \fi % Re-box contents to desired size \dimen@ii \advance\dimen@ii -\fb@frh \setbox\tw@\vbox to\dimen@ii \bgroup % remove simulated frame and page flexibility: \vskip -\fb@frh \@plus-\pagestretch \@minus-.8\pageshrink \unvbox\tw@ \unpenalty\unpenalty \ifdim\lastkern=-137sp % whole box went to next page | \message{box split at beginning! }% % need work here??? \egroup \fb@resto@set \eject % (\vskip for frame size was discarded) \fb@adjheight \fb@put@frame#1#2% INSERTED ??? \else % Got material split off at the head \egroup \fb@resto@set \ifvoid\@tempboxa % it all fit after all | \message{box split at end! }% \setbox\@tempboxa\box\tw@ \fb@putboxa#1% \fb@afterframe \else % it really did split | \message{box split as expected. Its reboxed height is \the\ht\tw@. }% \ifdim\wd\tw@>\z@ \wd\tw@\wd\@tempboxa \centerline{#2{\box\tw@}}% ??? \centerline bad idea \else | \message{Zero width means likely blank. Don't frame it (guess)}% \box\tw@ \fi \hrule \@height\z@ \@width\hsize \eject \fb@adjheight \fb@put@frame\LastFrameCommand\MidFrameCommand \fi\fi\fi\fi\fi } \def\fb@putboxa#1{% \ifvoid\@tempboxa \PackageWarning{framed}{Boxa is void -- discard it. }% \else | \message{Frame and place boxa. }% | %{\showoutput\showbox\@tempboxa}% \centerline{#1{\box\@tempboxa}}% \fi } \def\fb@afterframe{% \nointerlineskip \null %{\showoutput \showlists} \penalty-30 \vskip\OuterFrameSep \relax } % measure width and height added by frame (#1 = frame command) % call results \fb@frw and \fb@frh % todo: a mechanism to handle wide frame titles \newdimen\fb@frw \newdimen\fb@frh \def\fb@sizeofframe#1{\begingroup \setbox\z@\vbox{\vskip-5in \hbox{\hskip-5in #1{\hbox{\vrule \@height 4.7in \@depth.3in \@width 5in}}}% \vskip\z@skip}% | \message{Measuring frame addition for \string#1 in \@currenvir\space | gives ht \the\ht\z@\space and wd \the\wd\z@. }% | %{\showoutput\showbox\z@}% \global\fb@frw\wd\z@ \global\fb@frh\ht\z@ \endgroup } \def\fb@adjheight{% \vbox to\FrameHeightAdjust{}% get proper baseline skip from above. \penalty\@M \nointerlineskip \vskip-\FrameHeightAdjust \penalty\@M} % useful for tops of pages \edef\zero@glue{\the\z@skip} \catcode`\|=\FrameRestore % Provide configuration commands: \providecommand\FrameCommand{% \setlength\fboxrule{\FrameRule}\setlength\fboxsep{\FrameSep}% \fbox} \@ifundefined{FrameRule}{\newdimen\FrameRule \FrameRule=\fboxrule}{} \@ifundefined{FrameSep} {\newdimen\FrameSep \FrameSep =3\fboxsep}{} \providecommand\FirstFrameCommand{\FrameCommand} \providecommand\MidFrameCommand{\FrameCommand} \providecommand\LastFrameCommand{\FrameCommand} % Height of frame above first baseline when frame starts a page: \providecommand\FrameHeightAdjust{6pt} % \FrameRestore has parts of \@parboxrestore, performing a similar but % less complete restoration of the default layout. See how it is used in % the "settings" argument of \MakeFrame. Though not a parameter, \hsize % should be set to the desired total line width available inside the % frame before invoking \FrameRestore. \def\FrameRestore{% \let\if@nobreak\iffalse \let\if@noskipsec\iffalse \let\-\@dischyph \let\'\@acci\let\`\@accii\let\=\@acciii % \message{FrameRestore: % \@totalleftmargin=\the \@totalleftmargin, % \rightmargin=\the\rightmargin, % \@listdepth=\the\@listdepth. }% % Test if we are in a list (or list-like paragraph) \ifnum \ifdim\@totalleftmargin>\z@ 1\fi \ifdim\rightmargin>\z@ 1\fi \ifnum\@listdepth>\z@ 1\fi 0>\z@ % \message{In a list: \linewidth=\the\linewidth, \@totalleftmargin=\the\@totalleftmargin, % \parshape=\the\parshape, \columnwidth=\the\columnwidth, \hsize=\the\hsize, % \labelwidth=\the\labelwidth. }% \@setminipage % snug fit around the item. I would like this to be non-global. % Now try to propageate changes of width from \hsize to list parameters. % This is deficient, but a more advanced way to indicate modification to text % dimensions is not (yet) provided; in particular, no separate left/right % adjustment. \advance\linewidth-\columnwidth \advance\linewidth\hsize \parshape\@ne \@totalleftmargin \linewidth \else % Not in list \linewidth=\hsize %\message{No list, set \string\linewidth=\the\hsize. }% \fi \sloppy } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% expint/vignettes/Makefile0000644000176200001440000000074515135742277015254 0ustar liggesusers### -*-Makefile-*- to build expint vignettes ## ## AUTHOR: Vincent Goulet ## List of vignettes to build VIGNETTES = expint.pdf ## Toolset SWEAVE = "$(R_HOME)/bin/R" CMD Sweave --encoding="utf-8" TEXI2DVI = LATEX=xelatex texi2dvi -b RM = rm -rf all: pdf %.pdf: %.tex ${TEXI2DVI} '$<' .PHONY: pdf pdf: ${VIGNETTES} .PHONY: clean clean: ${RM} *.tex *-[0-9][0-9][0-9].pdf \ *.aux *.bbl *.blg *.log *.out *~ Rplots* \ auto/ share/auto/ expint/vignettes/share/0000755000176200001440000000000015135742277014710 5ustar liggesusersexpint/vignettes/share/preamble.tex0000644000176200001440000000616215132507363017216 0ustar liggesusers\documentclass[11pt,x11names,english]{article} \usepackage{amsmath,amsthm} \usepackage[round]{natbib} \usepackage{babel} \usepackage[autolanguage]{numprint} \usepackage[noae]{Sweave} \usepackage{framed} \usepackage{booktabs} \usepackage[shortlabels]{enumitem} %% Fonts \usepackage[babel=true]{microtype} \usepackage{fontenc} \usepackage{unicode-math} \setmainfont{STIXTwoText} [ Extension = .otf, UprightFont = *-Regular, BoldFont = *-SemiBold, ItalicFont = *-Italic, BoldItalicFont = *-SemiBoldItalic, Scale = 1, Ligatures = TeX ] \setmathfont{STIXTwoMath-Regular} [ Extension = .otf, Scale = 1, bold-style = TeX ] \usepackage[book,medium,proportional,lining,scale=0.92]{FiraSans} \usepackage[medium,lining,scale=0.90]{FiraMono} %% Colors \usepackage{xcolor} \definecolor{link}{rgb}{0,0.4,0.6} % internal links \definecolor{url}{rgb}{0.6,0,0} % external links \definecolor{citation}{rgb}{0,0.5,0} % citations \definecolor{codebg}{named}{LightYellow1} % R code background %% Hyperlinks \usepackage{hyperref} \hypersetup{% pdfauthor={Vincent Goulet}, colorlinks = {true}, linktocpage = {true}, urlcolor = {url}, linkcolor = {link}, citecolor = {citation}, pdfpagemode = {UseOutlines}, pdfstartview = {Fit}, bookmarksopen = {true}, bookmarksnumbered = {true}, bookmarksdepth = {subsubsection}} %% Help for \autoref \def\exampleautorefname{Example} %% Sweave Sinput and Soutput environments reinitialized to remove %% default configuration. Space between input and output blocks also %% reduced. \DefineVerbatimEnvironment{Sinput}{Verbatim}{} \DefineVerbatimEnvironment{Soutput}{Verbatim}{} \fvset{listparameters={\setlength{\topsep}{0pt}}} %% Environment Schunk redefined as an hybrid of environments %% snugshade* and leftbar of framed.sty. \makeatletter \renewenvironment{Schunk}{% \setlength{\topsep}{1pt} \def\FrameCommand##1{\hskip\@totalleftmargin \vrule width 2pt\colorbox{codebg}{\hspace{3pt}##1}% % There is no \@totalrightmargin, so: \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}% \MakeFramed {\advance\hsize-\width \@totalleftmargin\z@ \linewidth\hsize \advance\labelsep\fboxsep \@setminipage}% }{\par\unskip\@minipagefalse\endMakeFramed} \makeatother %% Flush left enumerate environment. \setlist[enumerate]{leftmargin=*,align=left} %% Example environment \theoremstyle{definition} \newtheorem{example}{Example} \theoremstyle{remark} \newtheorem{rem}{Remark} %% New math commands \newcommand{\E}[1]{E[ #1 ]} \newcommand{\VAR}[1]{\mathrm{Var} [ #1 ]} \newcommand{\LAS}{\mathrm{LAS}} \newcommand{\D}{\displaystyle} \newcommand{\pt}{{\scriptscriptstyle \Sigma}} \newcommand{\mat}[1]{\symbf{#1}} %% New styling commands similar to those of RJournal.sty \newcommand{\pkg}[1]{\textbf{#1}} \newcommand{\code}[1]{\texttt{#1}} \newcommand{\samp}[1]{{`\normalfont\texttt{#1}'}} \newcommand{\file}[1]{{`\normalfont\textsf{#1}'}} \bibliographystyle{plainnat} expint/src/0000755000176200001440000000000015135742277012365 5ustar liggesusersexpint/src/gamma_inc.c0000644000176200001440000001457715135742246014456 0ustar liggesusers/* == expint: Exponential Integral and Incomplete Gamma Function == * * Functions to compute the incomplete gamma function * * G(a,x) = int_x^infty t^{a-1} exp(-t) dt * * for 'a' real and 'x' >= 0. [This differs from 'pgamma' of base R * in that negative values of 'a' are admitted.] * * Copyright (C) 2016-2026 Vincent Goulet * * The code in part IMPLEMENTATION is derived from the GNU Scientific * Library (GSL) v2.2.1 * * Copyright (C) 2007 Brian Gough * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Gerard Jungman * * The code in part R TO C INTERFACE is derived from R source code. * * Copyright (C) 1998--2025 The R Core Team * Copyright (C) 2003--2023 The R Foundation * Copyright (C) 1995--1997 Robert Gentleman and Ross Ihaka * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * AUTHOR for the GSL: G. Jungman * AUTHOR for expint: Vincent Goulet * with much indirect help from the R Core Team */ #include #include #include #include "locale.h" #include "expint.h" /* * IMPLEMENTATION OF THE WORKHORSE * * Adapted from "special functions" material in the GSL. * */ /* Continued fraction which occurs in evaluation * of Q(a,x) or Gamma(a,x). * * 1 (1-a)/x 1/x (2-a)/x 2/x (3-a)/x * F(a,x) = ---- ------- ----- -------- ----- -------- ... * 1 + 1 + 1 + 1 + 1 + 1 + * * Hans E. Plesser, 2002-01-22 (hans dot plesser at itf dot nlh dot no). * * Split out from gamma_inc_Q_CF() by GJ [Tue Apr 1 13:16:41 MST 2003]. * See gamma_inc_Q_CF() below. * */ double gamma_inc_F_CF(double a, double x) { const int nmax = 5000; const double small = R_pow_di(DBL_EPSILON, 3); double hn = 1.0; /* convergent */ double Cn = 1.0 / small; double Dn = 1.0; int n; /* n == 1 has a_1, b_1, b_0 independent of a,x, so that has been done by hand */ for (n = 2 ; n < nmax ; n++) { double an; double delta; if (E1_IS_ODD(n)) an = 0.5 * (n - 1)/x; else an = (0.5 * n - a)/x; Dn = 1.0 + an * Dn; if (fabs(Dn) < small) Dn = small; Cn = 1.0 + an/Cn; if (fabs(Cn) < small) Cn = small; Dn = 1.0/Dn; delta = Cn * Dn; hn *= delta; if (fabs(delta-1.0) < DBL_EPSILON) break; } if (n == nmax) warning(_("maximum number of iterations reached in gamma_inc_F_CF")); return hn; } /* Adapted from specfun/gamma_inc.c in GSL sources. Note that base R * function 'gammafn' and 'pgamma' are used for positive values of * 'a'. */ double gamma_inc(double a, double x) { #ifdef IEEE_754 if (ISNAN(x) || ISNAN(a)) return a + x; #endif if (x < 0.0) return(R_NaN); else if (x == 0.0) return gammafn(a); else if (a == 0.0) return expint_E1(x, 0); else if (a > 0.0) return gammafn(a) * pgamma(x, a, 1, 0, 0); else if (x > 0.25) { /* continued fraction seems to fail for x too small; otherwise it is ok, independent of the value of |x/a|, because of the non-oscillation in the expansion, i.e. the CF is un-conditionally convergent for a < 0 and x > 0 */ return exp((a - 1) * log(x) - x) * gamma_inc_F_CF(a, x); } else if (fabs(a) < 0.5) { /* expint: use the recursion for -0.5 < a < 0 (instead of a * series expansion as in GSL), relying on the accuracy of * pgamma for small values of 'a', but nevertheless treat * this case separately to avoid rounding errors in the loop * below */ const double da = a + 1.0; const double gax = gammafn(da) * pgamma(x, da, 1, 0, 0); const double shift = exp(-x + a * log(x)); return (gax - shift)/a; } else { /* a = fa + da; da >= 0 */ const double fa = floor(a); const double da = a - fa; double gax = (da > 0.0 ? gammafn(da) * pgamma(x, da, 1, 0, 0) : expint_E1(x, 0)); double alpha = da; /* Gamma(alpha-1,x) = 1/(alpha-1) (Gamma(a,x) - x^(alpha-1) e^-x) */ do { const double shift = exp(-x + (alpha - 1.0) * log(x)); gax = (gax - shift)/(alpha - 1.0); alpha -= 1.0; } while (alpha > a); return gax; } } /* * R TO C INTERFACE * * Adapted from src/main/arithmetic.c in R sources and from a similar * scheme in package actuar. Main difference: everything is in this * one file. * */ #define mod_iterate1(n1, n2, i1, i2) \ for (i = i1 = i2 = 0; i < n; \ i1 = (++i1 == n1) ? 0 : i1, \ i2 = (++i2 == n2) ? 0 : i2, \ ++i) /* Function called by .External() */ SEXP expint_do_gammainc(SEXP args) { SEXP sx, sa, sy; R_xlen_t i, ix, ia, n, nx, na; double ai, *a, xi, *x, *y; Rboolean naflag = FALSE; args = CDR(args); /* drop function name from arguments */ if (!isNumeric(CAR(args)) || !isNumeric(CADR(args))) error(_("invalid arguments")); na = XLENGTH(CAR(args)); nx = XLENGTH(CADR(args)); if ((na == 0) || (nx == 0)) return(allocVector(REALSXP, 0)); n = (nx < na) ? na : nx; PROTECT(sa = coerceVector(CAR(args), REALSXP)); PROTECT(sx = coerceVector(CADR(args), REALSXP)); PROTECT(sy = allocVector(REALSXP, n)); a = REAL(sa); x = REAL(sx); y = REAL(sy); mod_iterate1(na, nx, ia, ix) { ai = a[ia]; xi = x[ix]; if (ISNA(ai) || ISNA(xi)) y[i] = NA_REAL; else if (ISNAN(ai) || ISNAN(xi)) y[i] = R_NaN; else { y[i] = gamma_inc(ai, xi); if (ISNAN(y[i])) naflag = TRUE; } } if (naflag) warning(R_MSG_NA); if (n == na) SHALLOW_DUPLICATE_ATTRIB(sy, sa); else if (n == nx) SHALLOW_DUPLICATE_ATTRIB(sy, sx); UNPROTECT(3); return sy; } expint/src/init.c0000644000176200001440000000171314326537046013473 0ustar liggesusers/* == expint: Exponential Integral and Incomplete Gamma Function == * * Native routines registration, as per "Writing R extensions". * * AUTHOR: Vincent Goulet */ #include #include #include #include "expint.h" static const R_ExternalMethodDef ExternalEntries[] = { {"expint_do_expint", (DL_FUNC) &expint_do_expint, -1}, {"expint_do_gammainc", (DL_FUNC) &expint_do_gammainc, -1}, {NULL, NULL, 0} }; void attribute_visible R_init_expint(DllInfo *dll) { R_registerRoutines(dll, NULL, NULL, NULL, ExternalEntries); R_useDynamicSymbols(dll, FALSE); R_forceSymbols(dll, TRUE); R_RegisterCCallable("expint", "expint_E1", (DL_FUNC) expint_E1); R_RegisterCCallable("expint", "expint_E2", (DL_FUNC) expint_E2); R_RegisterCCallable("expint", "expint_En", (DL_FUNC) expint_En); R_RegisterCCallable("expint", "gamma_inc", (DL_FUNC) gamma_inc); } expint/src/Makevars0000644000176200001440000000012514324537534014054 0ustar liggesusers## Hide entry points (but for R_init_expint in init.c) PKG_CFLAGS = $(C_VISIBILITY) expint/src/locale.h0000644000176200001440000000023714220225222013753 0ustar liggesusers/* Localization */ #include #ifdef ENABLE_NLS #include #define _(String) dgettext ("expint", String) #else #define _(String) (String) #endif expint/src/expint.c0000644000176200001440000004275615133736251014047 0ustar liggesusers/* == expint: Exponential Integral and Incomplete Gamma Function == * * Functions to compute the exponential integral functions * * E_1(x) = int_x^infty exp(-t)/t dt, * E_2(x) = int_x^infty exp(-t)/t^2 dt * * and * * E_n(x) = int_x^infty exp(-t)/t^n dt. * * Copyright (C) 2016-2026 Vincent Goulet * * The code in part IMPLEMENTATION is derived from the GNU Scientific * Library (GSL) v2.2.1 * * Copyright (C) 2007 Brian Gough * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Gerard Jungman * * The code in part R TO C INTERFACE is derived from R source code. * * Copyright (C) 1998--2025 The R Core Team * Copyright (C) 2003--2023 The R Foundation * Copyright (C) 1995--1997 Robert Gentleman and Ross Ihaka * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * AUTHOR for the GSL: G. Jungman * AUTHOR for expint: Vincent Goulet * with much indirect help from the R Core Team */ #include #include #include #include "locale.h" #include "expint.h" /* Prototypes of auxiliary functions */ static SEXP expint1_1(SEXP, SEXP, double (*f)(double, int)); static SEXP expint2_1(SEXP, SEXP, SEXP, double (*f)(double, int, int)); /* * IMPLEMENTATION OF THE WORKHORSES * * Adapted from "special functions" material in the GSL. * */ /* Data structure for a Chebyshev series over a given interval */ struct cheb_series_struct { double * c; /* coefficients */ int order; /* order of expansion */ double a; /* lower interval point */ double b; /* upper interval point */ int order_sp; /* effective single precision order */ }; typedef struct cheb_series_struct cheb_series; /* Chebyshev expansions: based on SLATEC e1.f, W. Fullerton Series for AE11 on the interval -1.00000D-01 to 0. with weighted error 1.76E-17 log weighted error 16.75 significant figures required 15.70 decimal places required 17.55 Series for AE12 on the interval -2.50000D-01 to -1.00000D-01 with weighted error 5.83E-17 log weighted error 16.23 significant figures required 15.76 decimal places required 16.93 Series for E11 on the interval -4.00000D+00 to -1.00000D+00 with weighted error 1.08E-18 log weighted error 17.97 significant figures required 19.02 decimal places required 18.61 Series for E12 on the interval -1.00000D+00 to 1.00000D+00 with weighted error 3.15E-18 log weighted error 17.50 approx significant figures required 15.8 decimal places required 18.10 Series for AE13 on the interval 2.50000D-01 to 1.00000D+00 with weighted error 2.34E-17 log weighted error 16.63 significant figures required 16.14 decimal places required 17.33 Series for AE14 on the interval 0. to 2.50000D-01 with weighted error 5.41E-17 log weighted error 16.27 significant figures required 15.38 decimal places required 16.97 */ static double AE11_data[39] = { 0.121503239716065790, -0.065088778513550150, 0.004897651357459670, -0.000649237843027216, 0.000093840434587471, 0.000000420236380882, -0.000008113374735904, 0.000002804247688663, 0.000000056487164441, -0.000000344809174450, 0.000000058209273578, 0.000000038711426349, -0.000000012453235014, -0.000000005118504888, 0.000000002148771527, 0.000000000868459898, -0.000000000343650105, -0.000000000179796603, 0.000000000047442060, 0.000000000040423282, -0.000000000003543928, -0.000000000008853444, -0.000000000000960151, 0.000000000001692921, 0.000000000000607990, -0.000000000000224338, -0.000000000000200327, -0.000000000000006246, 0.000000000000045571, 0.000000000000016383, -0.000000000000005561, -0.000000000000006074, -0.000000000000000862, 0.000000000000001223, 0.000000000000000716, -0.000000000000000024, -0.000000000000000201, -0.000000000000000082, 0.000000000000000017 }; static cheb_series AE11_cs = { AE11_data, 38, -1, 1, 20 }; static double AE12_data[25] = { 0.582417495134726740, -0.158348850905782750, -0.006764275590323141, 0.005125843950185725, 0.000435232492169391, -0.000143613366305483, -0.000041801320556301, -0.000002713395758640, 0.000001151381913647, 0.000000420650022012, 0.000000066581901391, 0.000000000662143777, -0.000000002844104870, -0.000000000940724197, -0.000000000177476602, -0.000000000015830222, 0.000000000002905732, 0.000000000001769356, 0.000000000000492735, 0.000000000000093709, 0.000000000000010707, -0.000000000000000537, -0.000000000000000716, -0.000000000000000244, -0.000000000000000058 }; static cheb_series AE12_cs = { AE12_data, 24, -1, 1, 15 }; static double E11_data[19] = { -16.11346165557149402600, 7.79407277874268027690, -1.95540581886314195070, 0.37337293866277945612, -0.05692503191092901938, 0.00721107776966009185, -0.00078104901449841593, 0.00007388093356262168, -0.00000620286187580820, 0.00000046816002303176, -0.00000003209288853329, 0.00000000201519974874, -0.00000000011673686816, 0.00000000000627627066, -0.00000000000031481541, 0.00000000000001479904, -0.00000000000000065457, 0.00000000000000002733, -0.00000000000000000108 }; static cheb_series E11_cs = { E11_data, 18, -1, 1, 13 }; static double E12_data[16] = { -0.03739021479220279500, 0.04272398606220957700, -0.13031820798497005440, 0.01441912402469889073, -0.00134617078051068022, 0.00010731029253063780, -0.00000742999951611943, 0.00000045377325690753, -0.00000002476417211390, 0.00000000122076581374, -0.00000000005485141480, 0.00000000000226362142, -0.00000000000008635897, 0.00000000000000306291, -0.00000000000000010148, 0.00000000000000000315 }; static cheb_series E12_cs = { E12_data, 15, -1, 1, 10 }; static double AE13_data[25] = { -0.605773246640603460, -0.112535243483660900, 0.013432266247902779, -0.001926845187381145, 0.000309118337720603, -0.000053564132129618, 0.000009827812880247, -0.000001885368984916, 0.000000374943193568, -0.000000076823455870, 0.000000016143270567, -0.000000003466802211, 0.000000000758754209, -0.000000000168864333, 0.000000000038145706, -0.000000000008733026, 0.000000000002023672, -0.000000000000474132, 0.000000000000112211, -0.000000000000026804, 0.000000000000006457, -0.000000000000001568, 0.000000000000000383, -0.000000000000000094, 0.000000000000000023 }; static cheb_series AE13_cs = { AE13_data, 24, -1, 1, 15 }; static double AE14_data[26] = { -0.18929180007530170, -0.08648117855259871, 0.00722410154374659, -0.00080975594575573, 0.00010999134432661, -0.00001717332998937, 0.00000298562751447, -0.00000056596491457, 0.00000011526808397, -0.00000002495030440, 0.00000000569232420, -0.00000000135995766, 0.00000000033846628, -0.00000000008737853, 0.00000000002331588, -0.00000000000641148, 0.00000000000181224, -0.00000000000052538, 0.00000000000015592, -0.00000000000004729, 0.00000000000001463, -0.00000000000000461, 0.00000000000000148, -0.00000000000000048, 0.00000000000000016, -0.00000000000000005 }; static cheb_series AE14_cs = { AE14_data, 25, -1, 1, 13 }; /* Adapted from specfun/cheb_eval.c in GSL sources */ static inline double cheb_eval(const cheb_series * cs, const double x) { int j; double d = 0.0; double dd = 0.0; double y = (2.0*x - cs->a - cs->b) / (cs->b - cs->a); double y2 = 2.0 * y; for(j = cs->order; j >= 1; j--) { double temp = d; d = y2*d - dd + cs->c[j]; dd = temp; } return y*d - dd + 0.5 * cs->c[0]; } /* Adapted from specfun/expint.c::expint_E1_impl in GSL sources */ double expint_E1(double x, int scale) { #ifdef IEEE_754 if (ISNAN(x)) return x; #endif const double xmaxt = -LOG_DBL_MIN; /* XMAXT = -LOG(DBL_MIN) */ const double xmax = xmaxt - log(xmaxt); /* XMAX = XMAXT - LOG(XMAXT) */ if (x < -xmax && !scale) { warning(_("overflow in expint_E1")); return R_PosInf; } else if (x <= -10.0) { const double s = 1.0/x * (scale ? 1.0 : exp(-x)); const double cheb = cheb_eval(&AE11_cs, 20.0/x+1.0); return s * (1.0 + cheb); } else if (x <= -4.0) { const double s = 1.0/x * (scale ? 1.0 : exp(-x)); const double cheb = cheb_eval(&AE12_cs, (40.0/x+7.0)/3.0); return s * (1.0 + cheb); } else if (x <= -1.0) { const double s = (scale ? exp(x) : 1.0); const double ln_term = -log(fabs(x)); const double cheb = cheb_eval(&E11_cs, (2.0*x+5.0)/3.0); return s * (ln_term + cheb); } else if (x == 0.0) { return R_NaN; } else if (x <= 1.0) { const double s = (scale ? exp(x) : 1.0); const double ln_term = -log(fabs(x)); const double cheb = cheb_eval(&E12_cs, x); return s * (ln_term - 0.6875 + x + cheb); } else if (x <= 4.0) { const double s = 1.0/x * (scale ? 1.0 : exp(-x)); const double cheb = cheb_eval(&AE13_cs, (8.0/x-5.0)/3.0); return s * (1.0 + cheb); } else if (x <= xmax || scale) { const double s = 1.0/x * (scale ? 1.0 : exp(-x)); const double cheb = cheb_eval(&AE14_cs, 8.0/x-1.0); double res = s * (1.0 + cheb); if (res == 0.0) { warning(_("underflow in expint_E1")); return 0.0; } else return res; } else { warning(_("underflow in expint_E1")); return 0.0; } } /* Adapted from specfun/expint.c::expint_E2_impl in GSL sources */ double expint_E2(double x, int scale) { #ifdef IEEE_754 if (ISNAN(x)) return x; #endif const double xmaxt = -LOG_DBL_MIN; const double xmax = xmaxt - log(xmaxt); if (x < -xmax && !scale) { warning(_("overflow in expint_E2")); return R_PosInf; } else if (x == 0.0) { return 1.0; } else if (x < 100.0) { const double ex = (scale ? 1.0 : exp(-x)); return ex - x * expint_E1(x, scale); } else if (x < xmax || scale) { const double s = (scale ? 1.0 : exp(-x)); const double c1 = -2.0; const double c2 = 6.0; const double c3 = -24.0; const double c4 = 120.0; const double c5 = -720.0; const double c6 = 5040.0; const double c7 = -40320.0; const double c8 = 362880.0; const double c9 = -3628800.0; const double c10 = 39916800.0; const double c11 = -479001600.0; const double c12 = 6227020800.0; const double c13 = -87178291200.0; const double y = 1.0/x; const double sum6 = c6+y*(c7+y*(c8+y*(c9+y*(c10+y*(c11+y*(c12+y*c13)))))); const double sum = y*(c1+y*(c2+y*(c3+y*(c4+y*(c5+y*sum6))))); double res = s * (1.0 + sum)/x; if (res == 0.0) { warning(_("underflow in expint_E2")); return 0.0; } else return res; } else { warning(_("underflow in expint_E2")); return 0.0; } } /* Macro used in expint_En (only) */ #define CHECK_UNDERFLOW(x) \ if (fabs(x) < DBL_MIN) { \ warning(_("underflow in expint_En")); \ return 0.0; \ } \ /* Adapted from specfun/expint.c::expint_En_impl in GSL sources */ double expint_En(double x, int n, int scale) { #ifdef IEEE_754 if (ISNAN(x)) return x; #endif if (n < 0) return R_NaN; else if (n == 0) { if (x == 0) return R_NaN; else { double res = (scale ? 1.0 : exp(-x)) / x; CHECK_UNDERFLOW(res); return res; } } else if (n == 1) return expint_E1(x, scale); else if (n == 2) return expint_E2(x, scale); else { if (x < 0) return R_NaN; if (x == 0) { double res = (scale ? exp(x) : 1 ) * (1/(n-1.0)); CHECK_UNDERFLOW(res); return res; } else { double s = (scale ? exp(x) : 1.0); double res = gamma_inc((double) 1 - n, x); res *= s * R_pow_di(x, n - 1); CHECK_UNDERFLOW(res); return res; } } } /* * R TO C INTERFACE * * Adapted from src/main/arithmetic.c in R sources and from a similar * scheme in package actuar. Main difference: everything is in this * one file. * */ /* Functions to handle cases with one argument (REAL) and an integer * flag */ static SEXP expint1_1(SEXP sx, SEXP sI, double (*f)(double, int)) { SEXP sy; R_xlen_t i, nx; double xi, *x, *y; Rboolean naflag = FALSE; if (!isNumeric(sx)) error(_("invalid arguments")); nx = XLENGTH(sx); if (nx == 0) return(allocVector(REALSXP, 0)); PROTECT(sx = coerceVector(sx, REALSXP)); PROTECT(sy = allocVector(REALSXP, nx)); x = REAL(sx); y = REAL(sy); int i_1 = asInteger(sI); for (i = 0; i < nx; i++) { xi = x[i]; if (ISNA(xi)) y[i] = NA_REAL; else if (ISNAN(xi)) y[i] = R_NaN; else { y[i] = f(xi, i_1); if (ISNAN(y[i])) naflag = TRUE; } } if (naflag) warning(R_MSG_NA); SHALLOW_DUPLICATE_ATTRIB(sy, sx); UNPROTECT(2); return sy; } #define EXPINT1_1(A, FUN) expint1_1(CAR(A), CADR(A), FUN); SEXP expint_do_expint1(int code, SEXP args) { switch (code) { case 1: return EXPINT1_1(args, expint_E1); case 2: return EXPINT1_1(args, expint_E2); default: error(_("internal error in expint_do_expint1")); } return args; /* never used; to keep -Wall happy */ } /* Functions to handle cases with two arguments (REAL and INTEGER) and * an integer flag */ #define mod_iterate2(n1, n2, i1, i2) \ for (i = i1 = i2 = 0; i < n; \ i1 = (++i1 == n1) ? 0 : i1, \ i2 = (++i2 == n2) ? 0 : i2, \ ++i) static SEXP expint2_1(SEXP sx, SEXP sa, SEXP sI, double (*f)(double, int, int)) { SEXP sy; R_xlen_t i, ix, ia, n, nx, na; double xi, *x, *y; int ai, *a; Rboolean naflag = FALSE; if (!isNumeric(sx) || !isNumeric(sa)) error(_("invalid arguments")); nx = XLENGTH(sx); na = XLENGTH(sa); if ((nx == 0) || (na == 0)) return(allocVector(REALSXP, 0)); n = (nx < na) ? na : nx; PROTECT(sx = coerceVector(sx, REALSXP)); PROTECT(sa = coerceVector(sa, INTSXP)); PROTECT(sy = allocVector(REALSXP, n)); x = REAL(sx); a = INTEGER(sa); y = REAL(sy); int i_1 = asInteger(sI); mod_iterate2(nx, na, ix, ia) { xi = x[ix]; ai = a[ia]; if (ISNA(xi) || ai == NA_INTEGER) y[i] = NA_REAL; else if (ISNAN(xi)) y[i] = R_NaN; else { if (ai == 1) y[i] = expint_E1(xi, i_1); else if (ai == 2) y[i] = expint_E2(xi, i_1); else y[i] = f(xi, ai, i_1); if (ISNAN(y[i])) naflag = TRUE; } } if (naflag) warning(R_MSG_NA); if (n == nx) SHALLOW_DUPLICATE_ATTRIB(sy, sx); else if (n == na) SHALLOW_DUPLICATE_ATTRIB(sy, sa); UNPROTECT(3); return sy; } #define EXPINT2_1(A, FUN) expint2_1(CAR(A), CADR(A), CADDR(A), FUN); SEXP expint_do_expint2(int code, SEXP args) { switch (code) { case 1: return EXPINT2_1(args, expint_En); default: error(_("internal error in expint_do_expint2")); } return args; /* never used; to keep -Wall happy */ } /* Data structure for internal functions */ typedef struct { char *name; SEXP (*cfun)(int, SEXP); int code; } expint_tab_struct; static expint_tab_struct expint_tab[] = { /* One argument functions */ {"E1", expint_do_expint1, 1}, {"E2", expint_do_expint1, 2}, /* Two argument functions */ {"En", expint_do_expint2, 1}, {0, 0, 0} }; /* Function called by .External() */ SEXP expint_do_expint(SEXP args) { R_xlen_t i; const char *name; /* Extract type of exponential integral */ args = CDR(args); name = CHAR(STRING_ELT(CAR(args), 0)); /* Dispatch to expint_do_expint[1,2] */ for (i = 0; expint_tab[i].name; i++) { if (!strcmp(expint_tab[i].name, name)) { return expint_tab[i].cfun(expint_tab[i].code, CDR(args)); } } /* No dispatch is an error */ error("internal error in expint_do_expint"); return args; /* never used; to keep -Wall happy */ } expint/src/expint.h0000644000176200001440000000162215132730460014032 0ustar liggesusers/* == expint: Exponential Integral and Incomplete Gamma Function == * * Declarations for the package and various constant and macro * definitions. * * AUTHOR: Vincent Goulet */ #include /* Error messages */ #define R_MSG_NA _("NaNs produced") /* Functions accessed from .External() */ SEXP expint_do_expint(SEXP); SEXP expint_do_expint1(int, SEXP); SEXP expint_do_expint2(int, SEXP); SEXP expint_do_gammainc(SEXP); /* Exported functions */ double expint_E1(double, int); double expint_E2(double, int); double expint_En(double, int, int); double gamma_inc(double, double); /* Constants (taken from gsl_machine.h in GSL sources) */ #define LOG_DBL_MIN (-7.0839641853226408e+02) #define LOG_DBL_MAX 7.0978271289338397e+02 #define EULER_CNST 0.57721566490153286060651209008 /* Macros */ #define E1_IS_ODD(n) ((n) & 1) /* taken from GSL */ expint/NAMESPACE0000644000176200001440000000023314220225222012767 0ustar liggesusers### C code useDynLib(expint, .registration = TRUE, .fixes = "C_") ### Exports export(expint, expint_E1, expint_E2, expint_En, expint_Ei) export(gammainc) expint/inst/0000755000176200001440000000000015135742277012553 5ustar liggesusersexpint/inst/include/0000755000176200001440000000000014220225222014152 5ustar liggesusersexpint/inst/include/expintAPI.h0000644000176200001440000000256514220225222016174 0ustar liggesusers/* == expint: Exponential Integral and Incomplete Gamma Function == * * Support for exported functions at the C level. * * This is derived from code in package zoo. * * Copyright (C) 2016 Vincent Goulet * Copyright (C) 2010 Jeffrey A. Ryan jeff.a.ryan @ gmail.com * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * AUTHOR: Vincent Goulet */ #include #include #include #ifdef __cplusplus extern "C" { #endif double expint_E1(double x, int scale); double expint_E2(double x, int scale); double expint_En(double x, int order, int scale); double gamma_inc(double a, double x); #ifdef __cplusplus } #endif expint/inst/CITATION0000644000176200001440000000056615133736251013710 0ustar liggesusersbibentry(bibtype = "Manual", title = "expint: Exponential Integral and Incomplete Gamma Function", author = person("Vincent", "Goulet", email = "vincent.goulet@act.ulaval.ca"), year = 2026, note = "R package", url = "https://cran.r-project.org/package=expint", header = "To cite expint in publications use:") expint/inst/example_API/0000755000176200001440000000000014220225222014653 5ustar liggesusersexpint/inst/example_API/R/0000755000176200001440000000000014220225222015054 5ustar liggesusersexpint/inst/example_API/R/pkg.R0000644000176200001440000000015314220225222015757 0ustar liggesusersfoo <- function(x) .External("pkg_do_foo", x) bar <- function(a, x) .External("pkg_do_bar", a, x) expint/inst/example_API/src/0000755000176200001440000000000014220225222015442 5ustar liggesusersexpint/inst/example_API/src/bar.c0000644000176200001440000000546214220225222016361 0ustar liggesusers/* * Example of a routine making use of the interface defined in * init.c. The routine will iterate on both arguments passed from R, * thereby making the R function vectorized. * * The code is derived from package actuar and base R. * * Copyright (C) 2016 Vincent Goulet * Copyright (C) 1995--1997 Robert Gentleman and Ross Ihaka * Copyright (C) 1998--2016 The R Core Team. * Copyright (C) 2003--2016 The R Foundation * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * AUTHOR: Vincent Goulet */ #include #include #include "locale.h" #include "pkg.h" #define mod_iterate1(n1, n2, i1, i2) \ for (i = i1 = i2 = 0; i < n; \ i1 = (++i1 == n1) ? 0 : i1, \ i2 = (++i2 == n2) ? 0 : i2, \ ++i) SEXP pkg_do_bar(SEXP args) { SEXP sx, sa, sy; int i, ix, ia, n, nx, na; double ai, *a, xi, *x, *y; Rboolean naflag = FALSE; args = CDR(args); /* drop function name from arguments */ if (!isNumeric(CAR(args)) || !isNumeric(CADR(args))) error(_("invalid arguments")); na = LENGTH(CAR(args)); nx = LENGTH(CADR(args)); if ((na == 0) || (nx == 0)) return(allocVector(REALSXP, 0)); n = (nx < na) ? na : nx; PROTECT(sa = coerceVector(CAR(args), REALSXP)); PROTECT(sx = coerceVector(CADR(args), REALSXP)); PROTECT(sy = allocVector(REALSXP, n)); a = REAL(sa); x = REAL(sx); y = REAL(sy); mod_iterate1(na, nx, ia, ix) { ai = a[ia]; xi = x[ix]; if (ISNA(ai) || ISNA(xi)) y[i] = NA_REAL; else if (ISNAN(ai) || ISNAN(xi)) y[i] = R_NaN; else { /* this is where the expint routine is used */ y[i] = pkg_gamma_inc(ai, xi); if (ISNAN(y[i])) naflag = TRUE; } } if (naflag) warning(R_MSG_NA); if (n == na) { SET_ATTRIB(sy, duplicate(ATTRIB(sa))); SET_OBJECT(sy, OBJECT(sa)); } else if (n == nx) { SET_ATTRIB(sy, duplicate(ATTRIB(sx))); SET_OBJECT(sy, OBJECT(sx)); } UNPROTECT(3); return sy; } expint/inst/example_API/src/foo.c0000644000176200001440000000422314220225222016372 0ustar liggesusers/* * Example of a routine making use of the interface defined in * init.c. The routine will iterate on both arguments passed from R, * thereby making the R function vectorized. * * The code is derived from package actuar and base R. * * Copyright (C) 2016 Vincent Goulet * Copyright (C) 1995--1997 Robert Gentleman and Ross Ihaka * Copyright (C) 1998--2016 The R Core Team. * Copyright (C) 2003--2016 The R Foundation * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * AUTHOR: Vincent Goulet */ #include #include #include "locale.h" #include "pkg.h" SEXP pkg_do_foo(SEXP args) { SEXP sx, sy; int i, nx; double xi, *x, *y; Rboolean naflag = FALSE; if (!isNumeric(CADR(args))) error(_("invalid arguments")); nx = LENGTH(CADR(args)); if (nx == 0) return(allocVector(REALSXP, 0)); PROTECT(sx = coerceVector(CADR(args), REALSXP)); PROTECT(sy = allocVector(REALSXP, nx)); x = REAL(sx); y = REAL(sy); for (i = 0; i < nx; i++) { xi = x[i]; if (ISNA(xi)) y[i] = NA_REAL; \ else if (ISNAN(xi)) y[i] = R_NaN; else { /* this is where the expint routine is used */ y[i] = pkg_expint_E1(xi, 0); if (ISNAN(y[i])) naflag = TRUE; } } if (naflag) warning(R_MSG_NA); SET_ATTRIB(sy, duplicate(ATTRIB(sx))); SET_OBJECT(sy, OBJECT(sx)); UNPROTECT(2); return sy; } expint/inst/example_API/src/init.c0000644000176200001440000000404414220225222016553 0ustar liggesusers/* * Native routines registration, as per "Writing R extensions" and * definition of native interfaces to two routines exported by * package expint. * * This is derived from code in packages zoo and xts. * * Copyright (C) 2016 Vincent Goulet * Copyright (C) 2010 Jeffrey A. Ryan jeff.a.ryan @ gmail.com * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * AUTHOR: Vincent Goulet */ #include #include #include /* this is actually optional */ #include "pkg.h" /* This package uses the .External interface between R and C */ static const R_ExternalMethodDef ExternalEntries[] = { {"pkg_do_foo", (DL_FUNC) &pkg_do_foo, -1}, {"pkg_do_bar", (DL_FUNC) &pkg_do_bar, -1}, {NULL, NULL, 0} }; /* Routine registration and native interfaces definitions. We prefix * names with pkg_ to avoid name clashes with expintAPI.h. */ void R_init_pkg(DllInfo *dll) { R_registerRoutines(dll, NULL, NULL, NULL, ExternalEntries); /* native interfaces to routines from package expint */ pkg_expint_E1 = (double(*)(double,int)) R_GetCCallable("expint", "expint_E1"); pkg_gamma_inc = (double(*)(double,double)) R_GetCCallable("expint", "gamma_inc"); } /* Declaration of interfaces to routines from package expint */ double(*pkg_expint_E1)(double,int); double(*pkg_gamma_inc)(double,double); expint/inst/example_API/src/locale.h0000644000176200001440000000023414220225222017051 0ustar liggesusers/* Localization */ #include #ifdef ENABLE_NLS #include #define _(String) dgettext ("pkg", String) #else #define _(String) (String) #endif expint/inst/example_API/src/pkg.h0000644000176200001440000000050714220225222016376 0ustar liggesusers#include /* Error messages */ #define R_MSG_NA _("NaNs produced") /* Functions accessed from .External() */ SEXP pkg_do_foo(SEXP args); SEXP pkg_do_bar(SEXP args); /* Interfaces to routines from package expint */ extern double(*pkg_expint_E1)(double,int); extern double(*pkg_gamma_inc)(double,double); expint/inst/example_API/NAMESPACE0000644000176200001440000000013414220225222016070 0ustar liggesusers### C code useDynLib(pkg, .registration = TRUE) import(expint) ### Exports export(foo,bar) expint/inst/example_API/man/0000755000176200001440000000000014220225222015426 5ustar liggesusersexpint/inst/example_API/man/pkg.Rd0000644000176200001440000000130514220225222016475 0ustar liggesusers\name{foo} \alias{foo} \alias{bar} \title{Test functions} \description{ These functions test the interface to the C routines of package \pkg{expint}. } \usage{ foo(x) bar(a, x) } %- maybe also 'usage' for other objects documented here. \arguments{ \item{x, a}{vectors of real numbers} } \details{ \code{foo} is an interface to \code{expint_E1}. \code{bar} is an interface to \code{gamma_inc}. Both functions are vectorized. } \value{ ... } \author{ ~~who you are~~ } \seealso{ ~~objects to See Also as \code{\link{help}}, ~~~ } \examples{ ## Compare results with functions expint() and gammainc() ## of package expint foo(1.275) x <- c(0.2, 2.5, 5, 8, 10) a <- 1.2 bar(a, x) } \keyword{math} expint/inst/example_API/DESCRIPTION0000644000176200001440000000064214220225222016363 0ustar liggesusersPackage: pkg Type: Package Title: Test package Version: 0.0-1 Date: 2016-12-25 Authors@R: c(person("Vincent", "Goulet", role = c("cre", "aut"), email = "vincent.goulet@act.ulaval.ca")) Description: Tests the interface to include the C routines of package expint in another package. Depends: R (>= 3.3.0) Imports: expint LinkingTo: expint License: GPL (>= 2) Encoding: UTF-8 LazyLoad: yes LazyData: yes expint/inst/doc/0000755000176200001440000000000015135742277013320 5ustar liggesusersexpint/inst/doc/expint.Rnw0000644000176200001440000005352515135742246015325 0ustar liggesusers\input{share/preamble} %\VignetteIndexEntry{expint user manual} %\VignettePackage{expint} %\VignetteDepends{pracma,gsl} %\SweaveUTF8 \title{\pkg{expint}: Exponential integral and incomplete gamma function} \author{Vincent Goulet \\ Université Laval} \date{} %% Additional commands specific to this document \newcommand{\Ei}{\operatorname{Ei}} <>= library(expint) options(width = 60) @ \begin{document} \maketitle \section{Introduction} \label{sec:introduction} The exponential integral \begin{equation*} E_1(x) = \int_x^\infty \frac{e^{-t}}{t}\, dt, \quad x \in \mathbb{R} \end{equation*} and the incomplete gamma function \begin{equation*} \Gamma(a, x) = \int_x^\infty t^{a-1} e^{-t}\, dt, \quad x > 0, \quad a \in \mathbb{R} \end{equation*} are two closely related functions that arise in various fields of mathematics. \pkg{expint} is a small package provides facilities to compute the exponential integral and the incomplete gamma function. Furthermore, and perhaps most conveniently for R package developers, the package also gives easy access to the underlying C workhorses through an API. The C routines are derived from the GNU Scientific Library \citep[GSL;][]{GSL}. The package \pkg{expint} started its life in version~2.0-0 of \pkg{actuar} \citep{actuar}, where I extended the range of admissible values in the computation of limited expected value functions. This required an incomplete gamma function that accepts negative values of argument $a$, as explained at the beginning of Appendix~A of \citet{LossModels4e}. \section{Exponential integral} \label{sec:expint} \citet[Section~5.1]{Abramowitz:1972} first define the exponential integral as \begin{equation} \label{eq:E1} E_1(x) = \int_x^\infty \frac{e^{-t}}{t}\, dt. \end{equation} An alternative definition (to be understood in terms of the Cauchy principal value due to the singularity of the integrand at zero) is \begin{equation*} \Ei(x) = - \int_{-x}^\infty \frac{e^{-t}}{t}\, dt = \int_{-\infty}^x \frac{e^t}{t}\, dt, \quad x > 0. \end{equation*} The above two definitions are related as follows: \begin{equation} \label{eq:Ei_vs_E1} E_1(-x) = - \Ei(x), \quad x > 0. \end{equation} The exponential integral can also generalized to \begin{equation*} E_n(x) = \int_1^\infty \frac{e^{-xt}}{t^n}\, dt, \quad n = 0, 1, 2, \dots, \quad x > 0, \end{equation*} where $n$ is then the \emph{order} of the integral. The latter expression is closely related to the incomplete gamma function (\autoref{sec:gammainc}) as follows: \begin{equation} \label{eq:En_vs_gammainc} E_n(x) = x^{n - 1} \Gamma(1 - n, x). \end{equation} One should note that the first argument of function $\Gamma$ is negative for $n > 1$. The following recurrence relation holds between exponential integrals of successive orders: \begin{equation} \label{eq:En:recurrence} E_{n+1}(x) = \frac{1}{n} [e^{-x} - x E_n(x)]. \end{equation} Finally, $E_n(x)$ has the following asymptotic expansion: \begin{equation} \label{eq:En:asymptotic} E_n(x) \asymp \frac{e^{-x}}{x} \left( 1 - \frac{n}{x} + \frac{n(n+1)}{x^2} - \frac{n(n+1)(n+2)}{x^3} + \dots \right). \end{equation} \section{Incomplete gamma function} \label{sec:gammainc} From a probability theory perspective, the incomplete gamma function is usually defined as \begin{equation*} P(a, x) = \frac{1}{\Gamma(a)} \int_0^x t^{a - 1} e^{-t}\, dt, \quad x > 0, \quad a > 0. \end{equation*} Function \code{pgamma} already implements this function in R (just note the differing order of the arguments). Now, the definition of the incomplete gamma function of interest for this package is rather the following \citep[Section~6.5]{Abramowitz:1972}: \begin{equation} \label{eq:gammainc} \Gamma(a, x) = \int_x^\infty t^{a-1} e^{-t}\, dt, \quad x > 0, \quad a \in \mathbb{R}. \end{equation} Note that $a$ can be negative with this definition. Of course, for $a > 0$ one has \begin{equation} \label{eq:gammainc_vs_pgamma} \Gamma(a, x) = \Gamma(a) [1 - P(a, x)]. \end{equation} Integration by parts of the integral in \eqref{eq:gammainc} yields the recursive relation \begin{equation} \label{eq:gammainc_recursion} \Gamma(a, x) = -\frac{x^a e^{-x}}{a} + \frac{1}{a} \Gamma(a + 1, x). \end{equation} When $a < 0$, this relation can be used repeatedly $k$ times until $a + k$ is a positive number. The right hand side can then be evaluated with \eqref{eq:gammainc_vs_pgamma}. If $a = 0, -1, -2, \dots$, this calculation requires the value of \begin{equation*} G(0, x) = \int_x^\infty \frac{e^{-t}}{t}\, dt = E_1(x), \end{equation*} the exponential integral defined in \eqref{eq:E1}. \section{R interfaces} \label{sec:interfaces} \pkg{expint} provides one main and four auxiliary R functions to compute the exponential integral, and one function to compute the incomplete gamma function. Their signatures are the following: \begin{Schunk} \begin{Sinput} expint(x, order = 1L, scale = FALSE) expint_E1(x, scale = FALSE) expint_E2(x, scale = FALSE) expint_En(x, order, scale = FALSE) expint_Ei(x, scale = FALSE) gammainc(a, x) \end{Sinput} \end{Schunk} Let us first go over function \code{gammainc} since there is less to discuss. The function takes in argument two vectors or real numbers (non-negative for argument \code{x}) and returns the value of $\Gamma(a, x)$. The function is vectorized in arguments \code{a} and \code{x}, so it works similar to, say, \code{pgamma}. We now turn to the \code{expint} family of functions. The function \code{expint} is a unified interface to compute exponential integrals $E_n(x)$ of any (non-negative) order, with default the most common case $E_1(x)$. The function is vectorized in arguments \code{x} and \code{order}. In other words, one can compute the exponential integral of a different order for each value of $x$. <>= expint(c(1.275, 10, 12.3), order = 1:3) @ The argument \code{order} should be a vector of integers. Non-integer values are silently coerced to integers using truncation towards zero. When the argument \code{scale} is \code{TRUE}, the result is scaled by $e^{x}$. The functions \code{expint\_E1}, \code{expint\_E2} and \code{expint\_En} are simpler, slightly faster ways to directly compute exponential integrals $E_1(x)$, $E_2(x)$ and $E_n(x)$, the latter for a \emph{single} order $n$ (the first value of \code{order} if \code{order} is a vector). <>= expint_E1(1.275) expint_E2(10) expint_En(12.3, order = 3L) @ Finally, the function \code{expint\_Ei} is provided as a convenience to compute $\Ei(x)$ using \eqref{eq:Ei_vs_E1}. <>= expint_Ei(5) -expint_E1(-5) # same @ \section{Accessing the C routines} \label{sec:api} The actual workhorses behind the R functions of \autoref{sec:interfaces} are C routines with the following prototypes: \begin{Schunk} \begin{Sinput} double expint_E1(double x, int scale); double expint_E2(double x, int scale); double expint_En(double x, int order, int scale); double gamma_inc(double a, double x); \end{Sinput} \end{Schunk} \pkg{expint} makes these routines available to other packages through declarations in the header file \file{include/expintAPI.h} in the package installation directory. If you want to use a routine --- say \code{expint\_E1} --- in your package \pkg{pkg}, proceed as follows: \begin{enumerate} \item Add the package \pkg{expint} to the \code{Imports} and \code{LinkingTo} directives of the \file{DESCRIPTION} file of \pkg{pkg}; \item Add an entry \samp{import(expint)} in the \file{NAMESPACE} file of \pkg{pkg}; \item Define the routine with a call to \code{R\_GetCCallable} in the initialization routine \code{R\_init\_pkg} of \pkg{pkg} \citep[Section~5.4]{WRE}. For the current example, the file \file{src/init.c} of \pkg{pkg} would contain the following code: \begin{Schunk} \begin{Sinput} void R_init_pkg(DllInfo *dll) { R_registerRoutines(/* native routine registration */); pkg_expint_E1 = (double(*)(double,int,int)) R_GetCCallable("expint", "expint_E1"); } \end{Sinput} \end{Schunk} \item Define a native routine interface, say \code{pkg\_expint\_E1} to avoid any name clash, in \file{src/init.c} that will call \code{expint\_E1}: \begin{Schunk} \begin{Sinput} double(*pkg_expint_E1)(double,int); \end{Sinput} \end{Schunk} \item Declare the routine in a header file of \pkg{pkg} with the keyword \code{extern} to expose the interface to all routines of the package. In our example, \file{src/pkg.h} would contain: \begin{Schunk} \begin{Sinput} extern double(*pkg_expint_E1)(double,int); \end{Sinput} \end{Schunk} \item Include the package header file \file{pkg.h} in any C file making use of the routine \code{pkg\_expint\_E1}. \end{enumerate} To help developers get started, \pkg{expint} ships with a complete test package implementing the above; see the \file{example\_API} sub-directory in the installation directory. This test package uses the \code{.External} R to C interface and, as a bonus, shows how to vectorize an R function on the C side (the code for this being mostly derived from base R). There are various ways to define a package API. The approach described above was derived from the package \pkg{zoo} \citep{zoo}. The package \pkg{xts} \citep{xts} --- and probably a few others on CRAN --- draws from \pkg{Matrix} \citep{Matrix} to propose a somewhat simpler approach where the API exposes routines that can be used directly in a package. However, the provided header file can be included only once in a package, otherwise one gets \samp{duplicate symbols} errors at link time. This constraint does not show in the example provided with \pkg{xts} or in packages \pkg{RcppXts} \citep{RcppXts} and \pkg{TTR} \citep{TTR} that link to it (the only two at the time of writing). A way around the issue is to define a native routine calling the routines exposed in the API. In this scenario, tests I conducted proved the approach I retained to be up to 10\% faster most of the time. \section{Implementation details} \label{sec:implementation} As already stated, the C routines mentioned in \autoref{sec:api} are derived from code in the GNU Scientific Library \citep{GSL}. For exponential integrals, the main routine \code{expint\_E1} computes $E_1(x)$ using Chebyshev expansions \citep[chapter~3]{Gil:2007}. Routine \code{expint\_E2} computes $E_2(x)$ using \code{expint\_E1} with relation \eqref{eq:En:recurrence} for $x < 100$, and using the asymptotic expression \eqref{eq:En:asymptotic} otherwise. Routine \code{expint\_En} simply relies on \code{gamma\_inc} to compute $E_n(x)$ for $n > 2$ through relation \eqref{eq:En_vs_gammainc}. For the sake of providing routines that better fit within the R ecosystem and coding style, I made the following changes to the original GSL code: \begin{enumerate} \item routines compute a single value and return their result by value; \item accordingly, calculation of the approximation error is dropped in all routines; \item \code{gamma\_inc} computes $\Gamma(a, x)$ for $a > 0$ with \eqref{eq:gammainc_vs_pgamma} using the routines \code{gammafn} and \code{pgamma} of the R API, rather than using the GSL routines, as the example below illustrates; <>= op <- options() # remember default number of digits @ <>= options(digits = 20) gammainc(1.2, 3) gamma(1.2) * pgamma(3, 1.2, 1, lower = FALSE) @ <>= options(op) # restore defaults @ \item \code{gamma\_inc} computes $\Gamma(a, x)$ for $-0.5 < a < 0$ using the recursion \eqref{eq:gammainc_recursion} instead of a series expansion as in the GSL routines, thereby relying on the accuracy of \code{pgamma} near $a = 0.5$ (fixes \href{https://gitlab.com/vigou3/expint/-/issues/2}{issue \#2}; see \autoref{sec:computation_gamma_inc} for additional details). \end{enumerate} \section{Alternative packages} \label{sec:alternatives} The Comprehensive R Archive Network\footnote{% \url{https://cran.r-project.org}} % (CRAN) contains a number of packages with features overlapping \pkg{expint}. I review the similarities and differences here. The closest package in functionality is \pkg{gsl} \citep{gsl-package}. This package is an R wrapper for the special functions and quasi random number generators of the GNU Scientific Library. As such, it provides access to basically the same C code as used in \pkg{expint}. Apart from the changes to the GSL code mentioned in \autoref{sec:implementation}, the main difference between the two packages is that installation from source of \pkg{gsl} requires that the GSL be installed on one's system, whereas \pkg{expint} is a regular, free standing R package. \pkg{VGAM} \citep{VGAM} is a large, high quality package that provides functions to compute the exponential integral $\Ei(x)$ for real values, as well as $e^{-x} \Ei(x)$ and $E_1(x)$ and their derivatives (up to the third derivative). Functions \code{expint}, \code{expexpint} and \code{expint.E1} are wrappers to the Netlib\footnote{% \url{https://www.netlib.org}} % FORTRAN subroutines in file \code{ei.f}. \pkg{VGAM} does not provide an API to its C routines. The package \pkg{pracma} \citep{pracma} provides a large number of functions from numerical analysis, linear algebra, numerical optimization, differential equations and special functions. Its versions of \code{expint}, \code{expint\_E1}, \code{expint\_Ei} and \code{gammainc} are entirely written in R with perhaps less focus on numerical accuracy than the GSL and Netlib implementations. The functions are not vectorized, and the incomplete gamma function is supported for $a \geq -1$ only. The package \pkg{frmqa} had a function \code{gamma\_inc\_err} that computed the incomplete gamma function using the incomplete Laplace integral, but it was only valid for $a = j + 0.5$, $j = 0, 1, 2, \dots$. (The package was removed from CRAN in 2022.) Package \pkg{zipfR} \citep{zipfR} introduces a set of functions to compute various quantities related to the gamma and incomplete gamma functions, but these are essentially wrappers around the base R functions \code{gamma} and \code{pgamma} with no new functionalities. \section{Examples} \label{sec:examples} Let us tabulate the values of $E_n(x)$ for $x = 1.275, 10, 12.3$ and $n = 1, 2, \dots, 10$ as found in examples~4--6 of \citet[section~5.3]{Abramowitz:1972}. <>= x <- c(1.275, 10, 12.3) n <- 1:10 structure(t(outer(x, n, expint)), dimnames = list(paste("n =", n), paste("x =", x))) @ We may also tabulate the values of $\Gamma(a, x)$ for $a = -1.5, -1, -0.5, 1$ and $x = 1, 2, \dots, 10$. <>= a <- c(-1.5, -1, -0.5, 1) x <- 1:10 structure(t(outer(a, x, gammainc)), dimnames = list(paste("x =", x), paste("a =", a))) @ \section{Acknowledgments} I built on the source code of R and many of the packages cited in this manual to create \pkg{expint}, so the R Core Team and the package developers deserve credit. I also extend my thanks to Dirk Eddelbuettel who was of great help in putting together the package API, through both his posts in online forums and private communication. Joshua Ulrich provided a fix to the API infrastructure to avoid duplicated symbols that was implemented in version 0.1-6 of the package. \appendix \section{Additional details on the computation of the incomplete gamma function} \label{sec:computation_gamma_inc} \href{https://gitlab.com/vigou3/expint/-/issues/2}{Issue \#2} raised by Geoffrey Poole highlights that the function \code{gammainc} in versions of \pkg{expint} prior to 0.2-0 returned inconsistent results for small negative values of $a$ and a small value of $x$. \autoref{fig:gammainc_vs_incgam} illustrates the problem by comparing the behaviour of $\Gamma(a, 10^{-5})$ around $a = -0.5$ between \code{gammainc} of \pkg{expint} (again, prior to 0.2-0) and \code{incgam} of \pkg{pracma}. \begin{figure}[t] \centering <>= a <- seq(-0.501, -0.499, length.out = 1000) x <- 1e-5 if (requireNamespace("gsl")) gGamma <- gsl::gamma_inc(a, x) if (requireNamespace("pracma")) pGamma <- sapply(a, pracma::incgam, x = x) plot(a, gGamma, type = "l", ylab = expression(Gamma(a, x)), main = "Versions of package expint prior to 0.2-0") lines(a, pGamma, lty = 2, lwd = 2, col = "orange") legend(-0.5002, 635, c("expint::gammainc(a, 1e-05)", "pracma::incgam(1e-05, a)"), lty = c(1, 2), lwd = c(1, 2), col = c("black", "orange")) @ \caption{Incomplete gamma function for small negative values of $a$ and a small value of $x$} \label{fig:gammainc_vs_incgam} \end{figure} The function \code{gamma\_inc} for the package \pkg{gsl} shows the same defect\footnote{% The solid line in Figure \ref*{fig:gammainc_vs_incgam} is actually traced using \code{gamma\_inc}.}, % indicating that the problem must lie in the GSL code. Indeed, the GSL routine for the incomplete gamma function treats specially the case $-0.5 < a < 0$, and reverts to the recursion \eqref{eq:gammainc_recursion} only for $a \leq -0.5$. For $-0.5 < a < 0$, the GSL computes the incomplete gamma function using the relation \begin{equation*} \Gamma(a, x) = \Gamma(a) Q(a, x), \end{equation*} with $Q(a, x)$ defined as follows: \begin{align*} Q(a, x) &= 1 - P(a, x) \\ &= 1 - \frac{\gamma(a, x)}{\Gamma(a)}, \end{align*} with \begin{equation*} \gamma(a, x) = P(a, x) \Gamma(a) = \int_0^x t^{a - 1} e^{-t}\, dt. \end{equation*} The GSL routine \code{gamma\_inc\_Q\_series} carries the computation of $Q(a, x)$ using a series expansion. The code is not obvious and requires a fair share of reverse engineering. Hence, I document my findings here. First, a series expansion for $\gamma(a, x)$ is \citep[section 6.5.33]{Abramowitz:1972}: \begin{equation} \gamma(a, x) = \sum_{n = 0}^\infty \frac{(-1)^n}{a + n} \frac{x^{a + n}}{n!}. \end{equation} We can rewrite this expansion as \begin{align} \gamma(a, x) &= \frac{x^a}{a} - \sum_{n = 1}^\infty \frac{(-1)^{n - 1}}{a + n} \frac{x^{a + n}}{n!} \notag \\ &= \frac{x^a}{a} - \frac{x^{a + 1}}{a + 1} \sum_{n = 1}^\infty (-1)^{n - 1} \left( \frac{a + 1}{a + n} \right) \frac{x^{n - 1}}{n!}. \label{eq:expansion_small_gamma} \end{align} Second, using the fact that $\Gamma(a + 1) = a \Gamma(a)$, we can rewrite $Q(a, x)$ as follows: \begin{align*} Q(a, x) &= 1 - \frac{x^a}{\Gamma(a + 1)} + \frac{x^a}{\Gamma(a + 1)} - \frac{\gamma(a, x)}{\Gamma(a)} \\ &= 1 - \frac{x^a}{\Gamma(a + 1)} + \frac{1}{\Gamma(a)} \left( \frac{x^a}{a} - \gamma(a, x) \right) \\ &= 1 - \frac{x^a}{\Gamma(a + 1)} + \frac{x^a}{\Gamma(a + 1)} \frac{\Gamma(a + 1)}{\Gamma(a)} \frac{x}{x^{a + 1}} \left( \frac{x^a}{a} - \gamma(a, x) \right) \\ &= 1 - \frac{x^a}{\Gamma(a + 1)} + \frac{x^a}{\Gamma(a + 1)} \left( \frac{a}{a + 1} \right) x \left( \frac{a + 1}{x^{a + 1}} \right) \left( \frac{x^a}{a} - \gamma(a, x) \right). \end{align*} If we define $\phi(a) = 1 - x^a/\Gamma(a + 1)$ and we simplify the last term above using \eqref{eq:expansion_small_gamma}, we finally obtain: \begin{equation} \label{eq:gsl_q_series} Q(a, x) = \phi(a) + (1 - \phi(a)) \left( \frac{a}{a + 1} \right) x \sum_{n = 1}^\infty (-1)^{n - 1} \left( \frac{a + 1}{a + n} \right) \frac{x^{n - 1}}{n!}. \end{equation} This is the expression used to compute $Q(a, x)$. The only remaining element is the computation of $\phi(a)$. For this, the routine \code{gamma\_inc\_Q\_series} uses the product of the Taylor series expansion of $x^a$ around $a = 0$, \begin{equation*} x^a = \sum_{n = 0}^\infty \frac{(a \ln x)^n}{n!}, \end{equation*} and the following Taylor series expansion of the reciprocal gamma function \citep{Mathworld:Gamma}: \begin{equation*} \frac{1}{\Gamma(a + 1)} = 1 + \gamma a + \left( \frac{\gamma^2}{2} - \frac{\pi^2}{12} \right) a^2 + \left( \frac{\gamma^3}{6} - \frac{\gamma\pi^2}{12} + \frac{\zeta(3)}{3} \right) a^3 + \cdots, \end{equation*} where $\gamma$ is the Euler constant, and $\zeta$ is the Riemann zeta function \citep[chapters 6 and 23]{Abramowitz:1972}. Putting all these pieces together, we obtain: \begin{align*} \phi(a) &= 1 - \frac{x^a}{\Gamma(a + 1)} \\ &= - (\ln x + \gamma) a + \left\{ \frac{\pi}{12} - (\ln x + \gamma)^2 \right\} a^2 \\ &\phantom{=} + \left\{ (\ln x + \gamma) \left( \frac{\pi}{12} - \frac{(\ln x + \gamma)^2}{6} \right) - \frac{\zeta(3)}{3} \right\} a^3 + \cdots. \end{align*} One will recognize above the coefficients \code{c1}, \code{c2} and \code{c3} of \code{term1} in the routine \code{gamma\_inc\_Q\_series}. It is not clear where the numerical values in the other seven coefficients come from. Here endeth reverse engineering. The fix introduced in \pkg{expint} 0.2-0 follows the same strategy as \pkg{pracma}: just use the recursion \eqref{eq:gammainc_recursion} also for $-0.5 < a < 0$, and rely on the accuracy of \code{pgamma} for small values of $a$ to yield the correct result. \autoref{fig:gammainc_vs_incgam_fixed} shows that the results from \pkg{expint} and \pkg{pracma} now match. One last implementation detail: the original GSL code uses a loop to compute \eqref{eq:gammainc_recursion} as many times as necessary for $a < -0.5$. Simply extending usage of the loop to $a < 0$ does not work due to rounding errors in computations involving values of $a$ in $(-0.5, 0)$. Therefore, \pkg{expint} keeps as a special case the single application of the recursive relation for $a$ in the latter range. \begin{figure}[t] \centering <>= a <- seq(-0.501, -0.499, length.out = 1000) x <- 1e-5 eGamma <- gammainc(a, x) if (requireNamespace("pracma")) pGamma <- sapply(a, pracma::incgam, x = x) plot(a, eGamma, type = "l", ylab = expression(Gamma(a, x)), main = "Versions of package expint from 0.2-0") lines(a, pGamma, lty = 2, lwd = 2, col = "orange") legend(-0.5002, 635, c("expint::gammainc(a, 1e-05)", "pracma::incgam(1e-05, a)"), lty = c(1, 2), lwd = c(1, 2), col = c("black", "orange")) @ \caption{Fixed incomplete gamma function} \label{fig:gammainc_vs_incgam_fixed} \end{figure} \bibliography{expint} \end{document} expint/inst/doc/expint.R0000644000176200001440000000642615135742274014757 0ustar liggesusers### R code from vignette source 'expint.Rnw' ################################################### ### code chunk number 1: expint.Rnw:15-17 ################################################### library(expint) options(width = 60) ################################################### ### code chunk number 2: expint.Rnw:181-182 ################################################### expint(c(1.275, 10, 12.3), order = 1:3) ################################################### ### code chunk number 3: expint.Rnw:196-199 ################################################### expint_E1(1.275) expint_E2(10) expint_En(12.3, order = 3L) ################################################### ### code chunk number 4: expint.Rnw:204-206 ################################################### expint_Ei(5) -expint_E1(-5) # same ################################################### ### code chunk number 5: expint.Rnw:318-319 ################################################### op <- options() # remember default number of digits ################################################### ### code chunk number 6: expint.Rnw:321-324 ################################################### options(digits = 20) gammainc(1.2, 3) gamma(1.2) * pgamma(3, 1.2, 1, lower = FALSE) ################################################### ### code chunk number 7: expint.Rnw:326-327 ################################################### options(op) # restore defaults ################################################### ### code chunk number 8: expint.Rnw:392-397 ################################################### x <- c(1.275, 10, 12.3) n <- 1:10 structure(t(outer(x, n, expint)), dimnames = list(paste("n =", n), paste("x =", x))) ################################################### ### code chunk number 9: expint.Rnw:402-407 ################################################### a <- c(-1.5, -1, -0.5, 1) x <- 1:10 structure(t(outer(a, x, gammainc)), dimnames = list(paste("x =", x), paste("a =", a))) ################################################### ### code chunk number 10: expint.Rnw:439-451 ################################################### a <- seq(-0.501, -0.499, length.out = 1000) x <- 1e-5 if (requireNamespace("gsl")) gGamma <- gsl::gamma_inc(a, x) if (requireNamespace("pracma")) pGamma <- sapply(a, pracma::incgam, x = x) plot(a, gGamma, type = "l", ylab = expression(Gamma(a, x)), main = "Versions of package expint prior to 0.2-0") lines(a, pGamma, lty = 2, lwd = 2, col = "orange") legend(-0.5002, 635, c("expint::gammainc(a, 1e-05)", "pracma::incgam(1e-05, a)"), lty = c(1, 2), lwd = c(1, 2), col = c("black", "orange")) ################################################### ### code chunk number 11: expint.Rnw:607-618 ################################################### a <- seq(-0.501, -0.499, length.out = 1000) x <- 1e-5 eGamma <- gammainc(a, x) if (requireNamespace("pracma")) pGamma <- sapply(a, pracma::incgam, x = x) plot(a, eGamma, type = "l", ylab = expression(Gamma(a, x)), main = "Versions of package expint from 0.2-0") lines(a, pGamma, lty = 2, lwd = 2, col = "orange") legend(-0.5002, 635, c("expint::gammainc(a, 1e-05)", "pracma::incgam(1e-05, a)"), lty = c(1, 2), lwd = c(1, 2), col = c("black", "orange")) expint/inst/doc/expint.pdf0000644000176200001440000030732415135742277015333 0ustar liggesusers%PDF-1.7 % 19 0 obj <> stream xYˎ+51*?( $@b$lˆߧlLAHhnn;v=OxzYݏ^oBfy.vv92>,/ߎ4"+OLF&*p@@GӶFRHh2Y}MHad-zH=%0+٬E[*Bܞ@WkmLD Ѯ)Z8L-Ҋ  aE4:Y>18r&TZ2mƃ$#c:%j?TôN|ip1XR>2sdI\L0}e%eѴ:BrPX:^3 <"eʲUrmj+G.ǃSp{$٬.}6^1Md+َv3І TX"dj[v' vF9t Cve<5}]On{A h=)4va4\#/ 6"'/14tYqH5;c`8{N6+s6H*d`M=m % Md|+"8kzA=ȅ9ûrs%o1 r^aNq2`َG,$s3}uT3{hK8-378]Aۥ )T4J'PHcLԧ Hm\̴H`ɕwI&*K +n 19!{汵ObntbVZ/̢e~BEMہH-U+9VqgU֭Id^{JN[R8w4IR!|*#@UͭylT/lbbMGhwi"N$ ENz E{DKY_?ڴlWly—aT፣aAqcP2xylxCEy1p]whƑd>ɉv`mEVyU*-?6<+cKMAx>i| ;&yں{>]wZ_֡~LJ%O~\PD E|ݎt/#t P^CK5$6 Ŧ:_WRhP}/ӳ8O~2U65ƝJ_{Ju~Tnek?B n8ZYnNq UAMwiɇNiSb_-U~] [RǦIWt󶏤8^WtuDC|M!M@;xi2rV1g"w=1?ô|'Ɵmv B O,tM:-t@A[ipT{-G0'룵1+ؚ6'Ot}4ﳨ%z#g[ zWސɵ_Av,['oQbj2VsΒ\xesg:aDqa)I`WA"Ǘ9^ĽCgqcqLPAP8&08{g ?Q_ 'L4p}?hqmzD[A endstream endobj 29 0 obj <> stream xڽZɎ$7W,R;P`/2?vE(2# XPH?Xr|?~R Hd8)2z4.I)y}?twYwFWkM|_alAc0w2KxNAVe@j ؤa#{צQtgܬijY[=범^T_j- W C8+tk&G&6h*5%MyжWz)#:EƁLQ E!%!DP Bb<̍=wl+|ҖH 4:>!8mdE/ۻl@-~%"]1N};J6vyAbXQF bۈg䲅GF&mAr۰B+r]MV Em" c cV{  R}ѾhT#>ptDEkPHSnϦ*F۪1$PļߟŎJ4+E,vMż9]kt"i۰2.~N6hw9{){CcC pmH;*ª"|o|~p—0u YEu +D'{  _GHH.3} MBPMc[ˎ_^=jbϩU7)҃^ZSbd2dŊ.uuz^d/Ҧp1;<0;i .:- EVX2_CBAPBI2PoC\ &\Sb+ kLL;J4XLU<[~dHbay/D~l )]LOكo?w7e2 yueEkЦKwZ 򐿌X"9i s4i !"niQH@G4Jr<b"= w%&1 1V“DLl!&PڼK:Xk~&յ U6ܕۥٗ'.4T%ܹ́ 7''XnRKh8xaW90#sfLK6KfتV` Iq:`çR GrNL*Nz՘U:ӫCQNy}xe>=NGfG]$͐bՌdG"r<$BS 8@P؇((`D o^d* ߉)ljߘN$cĭ\O(3DRGca9$d:3f]e!r/rAOha̫Ech՘#E$~Y]d:ICuwtGCv|ibV!!f}૊'ţ_+ŒY.O[dJNJAiaAG{!L;a"01iRTU?AޱG(IM3_CȾޥz݁d|G2弾.ɂ6m,^|UE2N1O<_1H0dA߿<^X;w3h"v"M^;t$U;Dn[ [qHlPWC?8}{|~nWt(W<Oqx句f!^9oM='c#W_\% ҢĔ== endstream endobj 35 0 obj <> stream xZɎ#+D3n@6v $sߟΤmѣK0EP 6-`s(E,Z`n ~;X7A7Eл~@ ߬kzɔf2ziR:B}@ g]FhZ3~嫓fЖI:C;6/y1h`Yɣ͡y?pTMx(Zb@9Z.=`*$R:p^NKURS`=#Lȇ[(v䩈GY4?oE U%QĎo<"]4/:/AoGrL^.$!+}g}i-) ɜ"G+2vtZ_;S[ULa=?qr%'/*SE8݋h@ۡU9NNّ:n ; u0҉ 7jc$S@op*1DY| qXf,Y [Kf.bX.ceюY[篛lpojŁYE"Uvl헅۰GmyS~lC VqJt[Ě\h)ؕh.A[9'{fhA @s&+*gltD\|'Ot7@-'amF^r zD`M<45X̑APxAu;sqMs^4\kqZQhz2L1amv5iU2ߥ?</p6-e!`*rM[6 7z `mdSgAG;Ks(JI(CXí%M,MG}{ؘpN _PªP9/I&h 3rSJ{KpGeI\;.{/ @52eߺo bd{Z6bQ ș0tw;N,-Vi`(FS^%CdFys@PoAssZ@( >Af2z]$$2z TEI@sqR D@R5l_:tnB_Y.GÐlUSTp=ζD]JWa iA.(\C{KCK(92QǬ_² &1Y?H]r\t-$䣄Q<|(u+D{PT3"Y Js2[EzZBTAҏ|>خR7䂾ΘfDMEa*҆Bui|i7$?st.9ѓGUw)0nVjb({7#XsN X yFBƶI+^vdBy×8vpԅDb M&`i!+1. nJL% pjcPe,)W4@7Op#s1& =jE'Zf[ZI|%vȗ\v*::]TK8LӐTH#<3 .!yěq:Id{Qp+0Gey%lm-md:ϵt~F)nIK`Ykڨdl K3LKfe\g4zf yؽì ~B}%tfi*v9qK+ԝ=7 I]O3u5x;{ȋvG.oHciNz$M64ԍ8gKs wn(+ %P,C#o;[U_Z YRahmyS뱙*KNݩf@N@1 bX_ž 󐞸Vh$L8ӽ0~uf)q%ړCᚄnTf|;Ü+I9~GA އ@/F/Kv6Cc̝Ib(\R77~K?W(%пZC)g0afnIp,ym%ߨ-OT{(@XJt;D6pˮ+͚DǍN;J[bb pzccF|IK睶9NJܟo?%y{.њ'NE<4ѳgoz:!)D2?&/v_Vn/G_?zڤ7%;?*X+xCx|Js[ endstream endobj 42 0 obj <> stream xYˎ++DoBl]f&^n9|-j$]Fbx폍6?_n׏~chA k{{aY8kln?( _~~FW+U"o.'d+ϰcvpZH7}`ēvR.>I&I#i\K]DoW_-6c^g'w +Eu<).i3Ct*|Gy,Sf3 i4+$1㩍2$9)k %xA &›IDxcp׸ǯ;pHU3ŅQ}!Ȗ5pq()g/>qeKasKAq,n\4C}bxPS Q{B@I8gUfdܔ0:qE+(Ub 2!"UK}FQ9,_X]PNI}tH"ی뢉0t92EEA]AYa2MUY]ՕWF(绫lp/ݗ۽zT[s}%]ȶ;4c;Y_bF7݂׸v#3rEFi*KgmVY!$1B03B}`^lu@2Q=9oXb]M|+ifI]n4B"Y(<I:'[]G /h`۵M "v\#.J|+M߀l6{Lm/~+Yp.i835`3iwLeiv fAP%+"P e=!퐷F󕔣dCTbbMKd|%u/{Wj;.3g]I+QV>ABF[nWb(kMws%0ByΖ7e([xEu(Qtc(Q}F-k|0֨p.R{Et7Y]AE Cp>ߖ ;2KCyax|c_\|d!BLu22Ϻr ]i 0Tc&{+[10Pu+ GB,lʡh@?\ktiwb|ifjEtx€!^WDZ@򫈮 mG.!Snw(^$(;0ƙF3BQd/?[}g84 >8ЖKL>+5zYgCzsk-vA(or~ 5+Kek,#uO&ʒQ^ekF%SlNjXs'a8'l9l^-N^}Rp Dz52k3C NI $S5K_Ʃ8W]}Rd;WK?Wt Ut+ vFl–-n'ϩD =t&ě P"/rM_d* 3D4IQZO PQѹ}"]Д` Imss,5Iy{;(WS I㌌ ? 7]o6)x`И(͕fIv|o#7Ģ֫q=A> A3^qzS(_[*)u6d(yT㔑3ǡ+YQ K|_D9omjS8i gpyYr㱹a?5_U9Цv}n՛ g0c:xǒ!:AZ6M z{ 0j&_܆sLpB6 Q%;f+oSԇWj̲VB2)7笫Z׽iJ7esUV2,;!+'4챒 endstream endobj 53 0 obj <> stream xZɮ+ +T.f@"@l ;'od!]I {ɚ[ýesݝ!*CT##TԡZYM7f&j\j|k>5gcϹj]DFkK ##FȜuM̻gJEH<뙆okv_P[~2.aPMե.$v]RCIL/Sٸ"|b,Kd30oV]RH Z$DK `ow[î:!sjlhwV-M0iIz|T5{kf#*.Y.&n${J t~]M<:oP >"j/N/kAݮv iL:ї7 NPCn ֧7}ci{&cœi+gA1tÈmh]P!F+/"xZ`ǵ}}"(pM0~h '腠1Rwј7iW/] #m411 ӒXulB=YWsJd9:0 6hlMJ4TJY(7x ]~k-Q/_~xR1w2G/>)lQ`ܒ-ܖu'ё`)dp9\D8t.3?{:^V=maTl!]^s_%/o a!8 Њl < &%*qkQM!Ih쳑ʬ.1YHXZ+3{"Ww\p:N~p8JsQ^kWAk4l͊A`*2V^ҫ5P81h_U+HՌ*?ΰQɮ_7]c'Y(^gpWz ཋeDxƢ!zšTO8&&y= ={n)j R\-xenwkI"\?o_?X`H/.Civ٨-߆!wa2n|9OHm߯|HNwU,x2s*j$'=Tp Q){u0iKy"gLPNXWyCAӍ2d,y|P +Y|&+S[w0|Yω1(֖.3TwR$--5(c8C@Pgߡ[ qc$;M5ei@>q F'J}?ȗ4'Tɭ].yj\4LsY N* :KeGV)ZY˼.),LU$lR%y!V(3sY# 4\u-4~M6Cɍ`@p7AT4aQrjkeCZ s,˰T+4z:N B~khM<{ܚ4fy>+$:=J( lV8ˣPߢ%E"[f9啺^6dd3nϾD1 =oV]NjW׎NC.I=S άU eݩggI @9탄!4YN٥CZrkGv͜sǖI{쎯RV6Q9[iHC[zk^ƽW&deyGt7+a[3.oxZ{*8)Rz eVrǤZ[3~0߆$w_lWqN֬>c&k̪&'vS[XZ7Co( _q5B[d]qa1@Tz&YЯwQ;g) r;A-Ƕi]}; e5&o 0BkLD!'QWHznIl S,{^u_6tY6߆Fj%oe Ϯ`lXEWSxT;u+݊9wn*MΏl*3k endstream endobj 73 0 obj <> stream x[cDH@P`؝IwGNeu)/p xQg?N->@`0D\\Y+%:z_9Ӄhjߌ;%R+7z CWI? ouY[wPPl^v?$Y't@4ȶʺ(41C#&WVuy3JtPĤ,3eLsl"~qڧ[\dLdLo;E)FaW%*uA(kx@+:AIli#ZV8YLL&G#B6 _ K}ce:x!5lHHfӟI-4NjV,("L1ƴ ,;F=n›LS_H#;":S̈l-!R[\Ic<Ζz\s/mdeHjBI7f4¼<%ty$xBNVFxkIzi`]__ lI͝rfY+": 3\Y^x ybo-Lw(Dre2"rw{rs\vb]!4vbKo2 Sǩ(4oVMwYh=4jd'?@]t^S2GB1PDp4qR_'VF gPu FkK_A蠶;C^,D]YjR)ǍN͒ƙ&Ѳ9B:1`Vl]ԣAҗu䳄/b0'Ye/RxY/$ $vɋ[yԄ c-UI{:8B/,Y\B;2dzD^<(.r^b䋹U( 58Tm3ҷ3|_$7zi2H2|IZ7)>Rve5 g <9hNLރoܬdLa_&JCV'G>RFE^E$軤XRvˉ.9pHqW_;9a5 I0-u#N'.3 6/ާ&9hj5/a&"Sl5hľ+RIj̯e{Jϔ!iJumV]%Yy×\%ލKcE0`WI.'#'5'j6V{I{Ǧ)lK w|K90913}@W˫)z8X.BiU+-`?t@Z ܙ/8RK}K9ү'';+q1]>2]P&GM>~EtsVLQp[piՙE@1$ K`?ȥ4AVaZ㝚|'O_?rsnWwV4msgm*Xx,Ɛ+#f/.d\TWcLUޒ=ɡ/a F(mЇTi6T@O$'jVrsķv8)GE ۥNhyήʝ-xOGtB&8vô;q#&\%nX\W}Eh'BXLtX!PG͹{ZwpJ7'iS5CcƙӧIr=#vfpJӬ|xg;N&-[Jw,sb[]]uUqa`kɯw-Oceզ;21df: ib_ +ixiH/od]OcLw‡cWK4 3tǩ+:7y6z.MCE? endstream endobj 91 0 obj <> stream xڵ[c ~kE.dHtA߷4b뇒(ґ3sEQ|$8H<\ë_?;3m:|{> ޹$} ],q|Y?._n{D|BҰ]$@#IQOhiu~"|iE };A[2ZXœ:Uw[ߏƁ-;g0]TMuDzZ>R%իoQԲ`ącݞpod9F6syiqGboAY: He; Bwa—UL(3}_H A6hoU$}U<9\o3?`Wi ?l.h(.w.} iU<+`+9zvݱL0`vP7N̰YA4}),h\ߍ56sI}n4.ɳDODr@/21:+M3D!!zm7Q"Lذ)B`f/h+r+/7e_>{~E䫗c$ _c.k*Uw>*3]%5Xݦ"t_U61eljUo#6 VDev6"ת VZj~^j70[s(KdzIxO( zn۰"-S, AУ?)s/S]jQ?(VC6MyzoTCʘC}j' |H5j ]IWRٚR7_7t@cOu[)7NZ*KPhzOV;V6U }T|VC k ܩu&}V #֝袌 uu3;ehQЏ+67 _'"|`y@b܆z)6o{Dg$8V*zqX\A ܯO_sH 6n%sQ&Dt1,\iYXj8Ue*>]zҕba!Ф1й!rG5RWԞev7cLl(=G[uWTz7傳CG*ceOuss`2ZyP)?TGcRIş- 4ٔRA=S1kIpl8eӑ IB-ҭ `ع"J;$f)/ԊW%VH%7bjn)Pok6l<$59 XlNmdROX~}:j> CeW[栱 ֆ9*,jq[-v(vjgSg&Spo M^G s=|ZTʁzgmd&kћ4תzT[8pmx^a7w?]2O*Za>h u9Ha&6s31Aܻn諢\QGy_JjصAL PYI2C3J;,B(v2r`rҙΐAƉ%Xf6 f?m|3/E$/5ЮiGҏ@0YN L(ͰZa>:c׊,vS 06L\}Ϗ BćPy$Te `&ϩF_!R(w:Yr=5}r`) RJ9"!RHfu:CbVSĵ]gɦ,6?\h΅?CRI{nM˟+NAʔ;5__6T endstream endobj 94 0 obj <> stream xY=6+8\ 6uA n׍]8M~z/8yOCj=}$񟚼?9~ûOx}~qQVI#ӷk;NN+z!L|Z|>:6sfZ 8<]n8n2}( jzLNaXa:y+ĞRg)Y/l*WjVc~w $@qڦ8r36gD_g&_UYSŒ_ʸ<yyZ:Aʷ-ƜqKu{YY$|38IЋ] 3e`jhlY}stcDZR⤔,pLh3/\$a@bK#o${\^q3皼KZ:4[>RxZVDqݹz\/:2TKW+Vj K*ɢ# u"iOt?@a+vz(beUyF [8 ǣ$ C<[wvog< Ob v]PV[|"Ѱγ<GH6uҴy-_ᖶy߲< T.O#vw%#:ǣ(> bdYM:o&%m3’͟l Xu$]lr{߻0z P־jRK(ݕpTo/UfRRDKٌE7Ώ^D׊ /&D\*GYzأ{m~nt8rqt³q67yk gl#P(o: _/giܓ|+ :V'> u3-3*(ZDXκ*kxdۣ4bšBZk^! /)#a| Zԇ E~2BrkhHM'[CAM(fkMc0zeu^C{hnlw(;O$;*;#QڮS{ #?qIrk۫O)B[YYC׋<'fNrsT't[RQ:ӗf|U)XUWeQb 7XEKq )EfFc UîTH(0rb[_QR&=U yИ '$s{?D_KzVYI\d 4.vL'}͎:ZMy(+LF7]v)p]VX8 ir1sIZ,v8.zR(d1ĂK~h\˳GX&VX1 [#zɺט-gہ|9={牅eȩւ%?=4n{pp:+s:3Ms=ҠB pI#irnΓ}t^w.<?F ]N/d&u3s*O endstream endobj 101 0 obj <> stream xڥZˎ++D& h6 i$orƿ"YE9# fb 6Ez}_߿m?8e]0۷歊9mTtxgr?~s1o oZe,Alki}L0e s~FlybmEο m]ַ< q}@3YGc48ڨ#o|:&Gllr&,0n۝Ya\J NnuDV*wTs6 ζ8HJD6r8t!~Jba_R܉ީ jW !&H~]Q4燞dzM/$\`SL4Tc@ *S4J4tox!z! Նoª͐Z)̧jfJ}V23_A nfw[c>=ztކ9k/}50ьmbWedl}<]vEuXi¼e 񼃏Z5{`djcYDםqc$^nҌ}U`BeF+8@ōN&"! V,XpN,u +5~\# M:+[@*cqC],]4'd~ eoh.9vYuH,2Tln{]7g  ДB1:~ߺC1HxO1 5*=cf9GIO2u|\9Dѭ)fiǃ2ʸJ8, eE"9 p/APS/dyJ]X;Ɓ2k.cJ@O$|NޠZ5$Θuwmңm`*f.ы1DdhQD8 {וwU_SO-ʤ"eC uhuAr}- ~UF8p1h+l'f'h"Z:MS_ϒr\&)W(Oy687ڭ}Śm̌X:L{0z6j,wކp;9"|8QtyםttlWq_i)\7)2['K&3=bEgV etX`W0XSHz.{ ϡG*Sm"ޣ dd8Q*tBZ@z@$jPȐr5RMѨ-8!ɩmG3 fʵΤbڕ@ݻu>=`2ܡʦ ?a^h\+ {3yľ8yn둺t8L1 ᫷ r40LAc"NLb''k05E ="euLiD8 ߜK;JnC]dR˘k EU.1)?+ QH &}nT̰$Qc"6fs FnE)h]W Ahn 7<^3VJڞv9drMtcMA%SO[.$2F[:4) TGu _Ei&L9sz˭tSJ Phzz°mIʫ!:L}ؖ} W!.O(;[f4/~X`4zNC>T\ɅՖH^ѽ+2' Ozk1 `LSIG!hXq˺cGr]L 7<s*95NkiѶUHjvIQDŤ+/butqO'UUU$}di-jR FT/]ٴ$ khE#h;\8gp]V3+RN 4gjb2~^_z{JWM+m:\$71RyX&'8z^G*t` / 7 \i)tv'LuD=JOip^bNQmxKS+BGcS"s <}3rm5*++MPhph*k!j~3PEV E}6P/V;ɕfu?`0iCH((EpRgh{`BK;n@VUP@mi-Ѱ@ihx݂AaU %QLD[aEp[+b#ڮ vB+S[J\B~[o)kc,ox]Xy6<Ci# |RL|m=5\F:Cz5!Ӟ΍9@kwC$v/(;z^YTflai+"/\-OIډ(>RLg{;'d8ɛ Tr4c9QONy|A} 茊`\I`TX@`cv*jU G)=a*4,bOt%D5'ެ뭄~о:"출0:D!޸cC<}Ճu]p7)0.0@qQ ˓+T)X#Ma endstream endobj 109 0 obj <> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 110 0 obj <>/ExtGState<<>>/ColorSpace<>>>/Filter/FlateDecode/Length 9614>> stream xKmqW& HPFb@@8"ЎS)OGuL8Vp笽ڵƬYjԷ_շ߾ӧyy?1hw{k~>__S\Jy{=ϧ??շ_SO~>Lb\}X>p\ao:+8nT]ısڄ3<}Gϭθɹ"\Y`Y794bas҅W;{;^~>組;^~m}Ɵ}WMlGxqN5W'%ɊgX-غ&+F#!؊ĕ?纉 {-3;?hXp&>x;mKNd|eGx.p.^{ n M\M/p+C7G8pOb݆0*!%܅AYG;qva;^aDn[pㅽDC*ĺW^ / 2".oP({,RcT֩e_pQC,4C-ע\Ǟe^f`֮LV K? 8q;xx 1C853_3ظ<\YF A>)E`gpfh5*(~!#p] SDZu3T4^C^NEd^D\XeX"(Z2"= Bfyj,=jLzȔ(z odN = CO! =yXU|I/g%K \+8.V|pG`X3G`ȊX*_c_!T` ^i_݉r|a5n1CV|_\8:T+xu+~+ȊNah+Ȋ;IV|!dWҐB~u>h+8l;΃__"6%uSkP+x- !K" =mgY_H;YbkK%36\8)A~ER[q5G3K8~(G'KoOr/i~ZkP6;Ycd _þI`-6aZCOZcz 8!>bsȋ[zmCO[l>bCZc_$ Z!31+x~Rcdu2i+ x6+wؖvkRʿbpz]eUE(hނ-7zڎ76.z\COK566.z _lp7Xw_lp_l:Y{X0[ M+LT[ 6/zڬ K 6oFy{1CO`iu}&v zZ}i=Sԓz\u,7s)x-2ds.x,x>~cw!W]eÅs)| ު|]uðW묇u[=|]#?Wj(ڹp6w뷛uo$>Y}*?_$J43?k딯KQSx f~[SxĹuoOCG늯~.W$1_C&KOu FV qVxAN>딯/} 4COG8V.}ܸcy*_|/}ޠǸǥwc(?ֻ1^u)_/B :/딯KPS.[zty׵^tG8(+_ &>`whu u,},t5|]*_z:Y8+^&7v`$dFiPIV̡jC!Rޫy+_W@Ȕk}TJ1x)_W̩tk?GSަy)_W̥t9^V~ޡ^|]28`dkוߩeLǃ|\u/s` +^kue\zujSܕ+^xA!n/+?Օ^ },}A!1O늗0Xx />o)?]֗|ubץ/(*_W|}u|ub/2_mץ/u~ޮS<+^Pvۼ0XnOe7 ׯy8_|]hO=nKpw~k+_|]kQO_zz`}) OYk=B>POWt뜯vu ^ ׫y+_WzV]Uy)?u]וOU#u׻y)_1*_T:< )Xzth|\zt"XzzV^[_C(x+_n4sWBN\"qXz+ ()P;de;xB2eˀS 9/COʏ#˃3)_ Xu٘Tq}`_(U _ _]CO7ȭo;6`GǍ"x63t =^O=^O =^O8 =^OS6f^2xl,@B +|ԻB?wh,-xAA%+6xlLm`, cjCOgw<66ͣ9h V<6nVxll,+ -`c8Vh`#uxD.wV<CO hTz7Yz`c獁`h#>l`cgMI񈃸JV<⠮hRPɊڸY`cgXx\Z0tTt mw3tcgc0چzگ mqC=W  ޟz z=ם`惘_vO)zڗC}zܨ^6rMQcb6nGW!t=xl,fi^)ji? ",u=6R3Ml=fiUW`T =CO8K3SڀMh6d‹[`cX;8lfis?+Fbe=,|]pwm =msX_ ڠN`d\mπ0y?1~ =mπ~ZX6^VHCwrcVN&*`ܥO`SAK's_+~'7JlųJ881bB %X. #mwq \zZbx 36Ӛ8 ű >_5%. 8. =-. =-XXAKձzcmaq4c6biq zZ0֣x_Q}qxGu wcI_m6sl阡jCOK^o&Zfiq z}sФ<z`i9O7磲7ϥb0$kI}s6v ɺn|S}}\w=vmo;vߜS%`<;UQw:A<ɾfZ?>]z^CӢ}8tpX|>YR8%9( t W? 36'_p:_vp{zo>x*vĚn懷~߾ /I+_ _pk_1{ӿ"`y5ҟ=W0~w?&?w=!b5ao=?ۨ2_?_lZ忾DH_~?T$bfqCzV9jw)Y=]g0q-课xo_7~oz%_ǟ|^?/??S/7SUY}ZM8k;/O/k믾;o坿巭2~_̟:\WdXcر~_ZeN-܆ǩ8r9}9MºN-&8|$l|$zZZr㭝ZN-S˂/EvjRdNǩqj[&?_-WvnaI8p=N-SkN-IP;&ASkN-IP;pS 'A9ԙSrjY_SKZj֗²yZXS/ ǩqj$yZ8 :SS 'Anqj$yZ8 :Crj$~ZIyLsǩN-p:TRsN-5GRsN- -ZjI9Ԓ5rj)7kRRSKy:ӍZFN-t#rSKy9ȩ,;?ة-ZJ'9SKq?Z:M;%rj)#KRF:ȩt.SK\"vj)9ovj)9ovj)9oRcRcRc_SK/٨5*dlZ^riyMʤ5*cr'reЂqٳi\ڜNʛNʚ,m6f|YnXȖvk\YPZڏ)ug=YdK+ّ%J6dɪXd;Q\ڌC^,u ;iM:4ʐI ɐ I 4ɐ myі m9Ж˙ViIw"4'Io"y7Ӈ&{ zurYi X/Zc g kXҶV٫*{9sm/U{l[ZeI*F6V-}DF[ڈpht"kpGT#[lQe׆*M6m"K:dڞdLTw#QYތxfy/b孈MTVzCe,TV:Ae TퟲlhQrOYiu± ߯}F+Lfdr^)+e2gDF)39Lcd273]<{J|;s[d"KWܶUEN)RPTۏOʜik2]zIt)Ӆw[tCi1ӏ[d2B(3,d2B(3,d2M(3d2f_*-JNe\LQƵ^SeDyq$CJetat4af,Prm2܏k'18cGco ӡ16]ck 7=ݏ 7y">(//9 Ӄ2?ɦ!۟dϐOe'1dd(i>=i(ۓjezOzzhŶO+ O$76< OvcÓ)Ó)Ó{ۃEM"˦ OHlx_>$ G ˇDE)2I O,mxҋM'mb9|Ѡw^s\PcSSQ>A?|}믾[e/3~u·/~W޾}w)܊ endstream endobj 113 0 obj <> stream xڭXɎ7+fUqrs2 4%zQ 2-Yի " Ʒc.T!țILS[2✉ϯv+>]OX6t6dXtsgMgaxK0hwS#Ű1Ec=6!6GcE ㄡ#C͏z=ۻGè]UK$iJ-] XIX!ɇHű](_rIJDmɪGѧ~sAH_‡z7OܰHbIoA~dq?TZ>'zѿ hMDGGi.9\DU>vWڽ[Be${ʦ9|X`2bg,n9iX!TG;<[2.(49r:lD3h;-LA<6B;VhƍzΒeڔ݀ˆ<^CJ:c0DoZM mC&8 qq Cu_H4h.xYhB!*PPJQ!BsE #$hB c;IR#"V:T)+ &s"?=j%7q}kD xgR{>٩/lz0Bs9ܰ x[H1`sP'v:n8:sj. 7;ɀ<( @3tE]NǠΒ_aA."j-EꃄEbw&bA6}xcNA.`|ҠS[q;!u/+)z#2DRӆ@1R8j[԰!?pr2ijF)\Pٴ[!v>#hAcm>=&j|Y"OrrﳠdW!ZXlA5%kKBlh rr앷e/n1 {K5GجYj3FeF%8޺yʣUnw4Z=oDn2g܆fzD3-C1 n\Xٶ*|୮b:/q7ͯ-af2E`, ?덤vR:3Co N t"^j#Q{ھ}ˠ!;a:k=ʢul߭`򥟵H2\~hڭr0,m~Opݽ Ǵс=-3`b{Tzן7<~ endstream endobj 122 0 obj <> stream xZˎ +WD=B-$d7I,#bP/K\UStk[IqHjyQ?xr_?- -J(Z=Kǰ\\/RI\W^~+4Z c06>Eit4*^s/.ܽzNk}|2ʼn(T2p S\HDIPٟ-?/`P忋2rRxiɿ/?fa \JJ-BQYlt_6yd"l պ F;4iAWG~?;OA;񦞩Ŏ/m0z<FomSDMtV ]jT*+g}\;5>4櫴ˆ?ҭke&:Ax{@x#RFWV7Nua v,2" +e,KvIz'mafQ9݅WXd?tן]^wˣkί3~u9֧O k$?hԣVC^гtPoQHFғZ%>-RF!xW0W|*= 2=nOZɔR˰[LG5ذE +IU Uo?t?3-`/E}:QthzM./$4$ydn"_< io> ROƮ֣zvux7Šb㸦JÚ9 .< -C^ZMO1JaLXĹ “/%=f9{L(xܔ O5Ipn~ }m$R̷J}bgR$vcxŀ‰E6`}8SP #T@ .RǛm+6M%{ud|f0xI +ŲRM6k` U9O%g7g崇q"P m4R(#t Ϳ<ߤ{;D2XAGc7c`.I\\ 'IG_mLUeBpRmq:ߓv{fRiH^>6!o$W:EbOH"dZgZej]p3dqtC-Ȧrb9B-SI]*қTP5L욧JzN Pb0yr0 [-A'X )<6V9Tίڤ5V\k\m/MgjRԀ1dlNv %wSN *.%v %f ^P0pz;O䤾v:з~,MH: 6q )ё_hUVCj;O׮$6ɳXʮ~?KΛtXJRv^JѤv(tpL}&$YJ@.JOw=p˵r9BENpc֖2a\mo3`@>WQ_1.>AsJ`F+$L/Bϙ KFN`sE\ IB<Ȼ(\t"ͻ7NH{ؒkj s*kΫl`Kj|IHc/oܷO[r$Y_p.'R ?̚*\FFP0eqfnS\ 7[uDߔn%})ʀ>c?_R%_B<7(LBiuAEuMydL0 i+WgR5ɑêT4 D^uc4t4Y ]DU0 ,XWRf1VSf[Uk?|V}tT>cB"kLFw/Gsi&*c9F sK3:! Fx!Ȫu7ֱ:c=bz?FLBox+O R#lTi*caO@T:q} vdDD>?( V!}@TwuvO5#wmʓCk#Mg'nUiސ*'\N,̱Sv8>dW|V!>tqlrEɪ w_ q~%Ÿj]:U߭W+4)3ݭ hgDuBl=oU% gopك85Xvz,qkeϩջowY@on綇sn2 GyX#;g5|9t.>܅eWh7t(Ir,u ]VXZ߫}֮}n_ 6uJ{W_B T(Ȭ߯u.BPk9mץ?g@ߜ^Oy>C~r,5A~ !b{ElŭvꑀwC Gdl endstream endobj 130 0 obj <> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 131 0 obj <>/ExtGState<<>>/ColorSpace<>>>/Filter/FlateDecode/Length 6828>> stream xeGqWܥGw%HHDf1r 0HO=[gp Y{[]vuuuO8/W꣞2/񣟽^zoxq=My$7<*/=,/{=޿YqbGx5Fa> 6hk ֍/55^j/k˸^N7Ƨ9 Z/ e촬 5_#iym\UԔ ئtΫ eMxU%ˢ]xPf[(^b$PfM(!wK=/̾Kf_e52/-Zf\E(2{`foekPf wӄcACX1qs 0*,˸g~Y} [3#hꔗ87a?5UMZoa965 :֤)fi,)|1|daS;Z%DZXX3iJaP{MS_Sdf$Ȑ۫+=2`ٳ~ Sli#&4d$f瞈ZȺjM[cCO&f2z4r`GLi#=i[?bFO)^IFOޑz4L+=eU{MlFOe&1o+B0JFO&S0ݚɡk ֏?j0֏Q֏#xQJ8WkWFÐ58F4f ^C<ޤ^xt9" ޴Ύש#l CV~Mp@pt4x`N@p86x xべS@pJ%)#lべ1t%}sg;>Mx`jkd<J@z"=%Փ`'z"= z\O,s0zKB{<\bǯ)ͺ=%*bM̋=x^JU)fr{ ,ki)x㙎JhQ 1Q=L;ZHֻ`iP/4z!b[J$L}蠧9l U%IR"BOGK; +y➌(v{Sz::Y%vr$uu"XV>[zaׇG gQGÎ_"FO`>@{5iߞ`)afIFO{*im=PYX=}>@JFO#>'=A%_wĽ%#=~}=iߧDeeĚio}p>Kz˔Ӓ9^=XȢQYcYB==B~9ӞZOQ`][{`ebۧh}^z W&X%ׅ=JaۇDH>NGS?!_Ŷ:ͩZH qG oh>Sz48YXmmi-=m8NhaS618!_wĶS >U6lbۇ|]_o!ym6V!Q-CmZo FO?U9!_7Ŷ:uGzOzZo FO?4MCoqi`ۧ)ƍlo; wGGO|Bo@b3im>M Y=-[rOS"N(p=!,GraMYr_MIɊgKO=5mimſHO=yO2w%Ddr$JFO=u-|`ۇ|`ԴY4w&)} =-0%=-hbPϒ^wӕ8>SzzeI^YSWUȠtʚW2zzeL}FO9k@aJKFO +g=2~ӫ{}@PZŊ~w)Нb/`.=r=rWu>E0rd^b^S؞^+_Za)8lɡp,VrtacÿgpɃs@A^ca h?ZH^bߵЬbߵbiJ~k#v7Vʯkam&)|œmp?ђOW6>Xz> Cvj"23H-3Gw{=Su+u'{-Kr=J ÞO6`%-|B.߹߮DQ[/^hu x)[/m28^.)|4˥[/I-;R/f`j dzz=.փ@^.%z`WQ5pdfrb%,nKg%NzTRvkxCl\*wGl=X 4ʝV"Nփr矕hb#ăJSҀփ"Dz[c`v!BOaVI{+$i= _w2=]+/h@OWz=]Yzj0ibA8.zZ;%vDn[#=]5'Z;~ڪhd|@?GOW/=])#<[|;>FOgάәbBm? ftSd7\\G'l"Yw6>N.1GQl? a;a٨=![bQ!Jw&Kl? aQl'0~dxmsd`ft;w=3وGOg׶yaa= W2z:]a*Lb tw>7a<#kQatd1*P߀7;5lw=%r|RܒP肞xFOGs<9Ѽ_Ca zaTK<]|dt30z:Bz5Mzz0piKIFOGym`$X`|QTKji/jq=/eSi==eeIxdg =`=?5(33=YB.VLzC,R!g>?g>FO{aGSXhNjV|4 =Ӟy=p=Ӟyb^bgUH֫0zr? FO[QӖa*,-a{j# vVʔU? 9i{li WidzBZͻ?pەy瑞\QȋRvv%gbgB8MfFO[S܏Ӗ0zr?g~|s:iٟ|Q?0w3] wssBgFK2z2Vy_3Va?&IG2IEe;=;gSl*L,3HOS?CHBG2zZ~^G .oiٟ]OgQ&y-T;ڳ?ⴼ=YO[Fl*luIe5=uٯ=yBKzu,gC>Of鈓 0|27L1fOOO[JL5gNK?[J$ ] E`c[] d? @D{*?y@ 8lu\|l횜{*ؾWNS{rr[g=5}H:iW[6;qq`lgw*fWP>@_;}xWgi/ &拯|C ]u֕O9 T~>S?*n߽ԎG)o~GʷE|ssz"V 6:(wC>`|UH|?pTW׾?W6+|hfir)!-~|~G;~|tVv}޸W`+~)E72k>n?-A bqhoO#BOmo~y߿m8|mV>=~?E/;je0׻?aFj(mǷ. ?n7_U<ǏXß{_Jz M4]Lx 0`7> stream xڝXɎ7 +J h!Hl 7s rpwOd(QKUW{еHE>|[h%w0ymQ!8cBZJUb1.uNE减_i3}kVYgZ^ Yµ~yuZ'M1&rt'j;阒~_X~91?KL0"xW+Rg=Y j]^tU&oMM8 Q*$+')*CNdaL᝛ys#0@! j>ҬDRew޵؏X$7'VMmqLՇ}'^dJ<11i;69q猫$Kstl9q{ש{QirjR`1Y`mVkXJVye6`|r/l.r*,~n;Ӥ\5͑{tVֈ>ՊHg9#u/7"O/lNz `at_$W<RT3MG-϶虗Z=S{C;qq5\AWDOuE~H5B {7nKAh Bk ؽ8j6[mi.Fx)Ґ*&҉YvC6|;,uɮ t)Fi響[%xRvImieQT43c`fãlU:+X|kBGɊ[ֱfQlP >tV^e]RM#(rXccػ<ӈJqDH֨T<~_^4XĐ6.dџ6S> 25m.{N;[Wr&D}CR+K}yp ~=aI ^'#&(6XW@GJިl6xJ=փAqD`80f0=62LnF}7x򴫓1Y!YԦ #hm''aF(.oKaFh6AIAXlo#G{6ܧSfௗX}IHJwsJjvۗQhnj=“۩)jM }J$iMfo>tNYL8[;CK:ru`2H}黁x߾8]fw'\3+2.;NEɇfK/U^8kw|ā9gtjE>ifqLb{-CY w_7bpT=N|fL *LQMo tW}}+xpZdhe{zWy~~!2X?XyڽkYgEv=:?5XREj [?B endstream endobj 156 0 obj <> stream xZˎ+ +VD^H.YU/B嶯;tlWI*J!)?Ezw7ӏbwUv?;oUiIEgv?8h惎ri}k{t WS?WN.ﵳ6؋^g(]s eUG&` x"eyJb$$[kw-L+B#5.ҜNyUe+[K#Lz Ǻ0q|YJx<pD\) H}cU [/J._沲$eI2xy9[V iQY^1vtQ:i 2@K2Xi=s?@m,H?ԏ?>ŀ͠,t޴p&Bt(_T;jMjQ|- R1eW?O ^ B ;e.+b@(À.jG'LK_ӌDaXKmN݀QXS4U6}}FR@&4vSc q]wa1&F:Ӆ:pbxWZBԸ1M6 K ^lQh&Oy!*ς@/x^BN6$pɦX΂Q7N[nl C_mR5=w Pl!@LSx!NI:VQɤEV೪uV2FXZ-li}a)7_Gj/3%.TIU|u3U;02V|=٤RʳЩ 5>M*M9ϏuKC~}/ТI҄Y\^V^Z›% /.J| % +rX?* Dr'2B1 58<{l>?`8N] ;Nbeò# f]`ý.)tT_@Mf^8rk"۴5ċR-ЊVm۲F$نvA:oUt rPlǃCFOgAq^P6%tHTOnn*If\ _*;3$H}B+\[Y"uڡ>ߠ)hD=FڮC #禅2Wd f޻oEIU%Jmz2ahɪpN1p۸j)ⷐ;Jk:,^\t~>4Z*@rLOARbq2ԉ+4h\vql+PgS_rr̓=Yb2T~|-WIVܧVY'X:M-ajl$mr52ѷ <o 0ɇ;Sԇx ԄkP& oeg.UWﭏʅjć.tGډ[YW*GI[|DI"꨸]5X=+ݟ?P7W%4@*qoi=~eG:xJ10.W'&AH֋ZM=)miD]4O48SJ aH RVr}&n\6<RhK8-Ǣi J@w[k H7>/r$Or$g_{@2܏3YԌ@A:yv r)j|ΐjN5:erq@F=l VeMNCэʆ {^vHƈlM/(WyƲ&z0qѭ9,k7r毸;eK!k^iD} ֮\*xԮ7c_Wj/p4inp_I 0Em?jࢃ~F[9-6kZLѺi* mF SF缵2B3ou'cMyȖfn7؊( B3l^+VP&P']7 _jJXh*B1ϻ~>@%3713C*ͻ?GK;ZKu˦xL^ZFF^C[IbײrFeK,dp% Dx}- sn""F֟v M0N_x'gȹ?G=p!TlT1پo=\Al5^HA`}:4S5W7M{aP i םg~4bͥÂcfe4Tcxb(ַ-Ykoo1z̎"(S8ރˎwcx+Z\9@?fR{\ uD:NtD́LZRYu>l 7""=\c9JBPD믻z#I5$1Fmֳdpx ?b# g$VDePE3=ƋR endstream endobj 162 0 obj <> stream xڥV0s9 *dH]bmYR$_dNJvɹgޣ_L`tpx4=< tZ]m:j ivWa>PqאiNIG" AWn/C'u /|W&'hF;ѓ69UbaU<~مyմθJ4q`$0+} I$+>.2`~]N]][Uy<J0+k:Mק[ڧ4n+@uЂ ikz>]WF, KQY[q?c銋}kzESU솾@z^6yyV^ha+mT;w 9cwXН\ }^ZGjcCТEN1YAg"a(]D&.&e9nЃL&U!噇pus .-oI`RjRu'"E4hYӯ ܴؔki >KPJxl\5v)=r+0$K2KLSBV\Hek"?볉 6?sCl!d\MrDȮrۗ6F]q,2a%T7̳qL$|2i.z\0}^;lrr)*A:ryH{ Rs6PggU|!vLHL.kHAnnnaqص)&_x[s#FW8`ݪL2+WWz~R.z> jJdԯlbUA /Z֣rNCo)i=}Rv5"sԂy($1yb"ˋt}}x_dx*7yA#;TWS}Q{/`g\ endstream endobj 11 0 obj <> stream x\IWL*َlU$%)gL˘5!=f7Qərh46d! BL+-r PPb=>EJжP2BcJF`J\SiB( )% 1IVF3k_LezxڥTX|8Y8bdӅQ A *pGx:D €)(Z;oR 'J $}JxZHp 5tL4Qs9 pu}JQ ` )h D . A % (?I |M(vWhoBQN $I()-x1 Gم%H7T Oj>#\ j$I#&vS!S({4hwRWO UQ-i0IcDjfzxg8KtcSs9Y!>3PMCPJ\*NrlG1SzG8h8C';2*#㠴=PWP@{1UTQU;+C1Sjr(CZqEK\\XF*. (4; LI\̤A-4y\;-6%^Ӥ'L²Њ4GgF~J, FOV/BKxv83'ЦX5:!X5>QsE Ԧ,#Ń#G$ #mR jB R i<5 ̴UÎpDG ҙ>W<>(-@j&4sKsKOk!Z|,+_)U9u O h>qlp\o!j%AHກ= 4/!Q((Qڧ($""[giȿ[˷lYY]-z5\~9;zS|Y~b9)_:-+͛W/(_W;,}A aL* K5tz+h;.?XVPkt0F#htB  = Qd 'uNȯfwa5^j ?Y"$Ry-< Y6\Rjޟ>}\2 c"ll1b6] hB|too_(VwS}U|Y|MnthZl*̖ EF8IDGP*`Xف9'1K佐= :L  SFp,)\g -m* ՁGxL FpZ-'w: Pm.jHVha$/#oH[6-"ILU^1scV{[DX\D/ ;/7 U,_GUr-. $ȩV] ,1H5m6kK@2a @HRPtm:ċlrZ7FYPzȹw5<kplB`/磻-dh.Xvf>^r+mhyYۧ ?Uhnzcq$(:7$h +x,V,,VK(հI rCub6.A۷[~&l2u,R^,̄[Eb`OWʞ!VV Q]*i> EbIt~(5֩\h2 Y: "OYG |(l#m7ɨZPoDY[mb0Arm*|:7m>kR͖ pi h\c,T:0Vj$ 8n]YD"Ⳳ-+1M_G7)tY>+GŪZݲ "ZL Bsi_GwyK G5Jx/i 4^fKZYQ\#6jingϠ" Üs#qt{7X VO0`N]pW@ I4$ߵrh/xj>Y,j5\ 7}=-K@."ﲍܞ5i~Qi(a409+N v!S,6!u+U+7>"B`ƙɖ\=E@*5rH1pw?T̟g?o6ic:b}Bk>v떗@%T(sX!\f5oG$uuMHZj'/QuT5X=4Hk[ uh[j(5M{F`Wc{Ol8ޔ_U~4}>]ףj^M +'jQ$_3Gul9Qy3ZjY|\r9rgj^ tq8hQ 0yX]sTxo^ɸZٴ9a^զk7K:ӚƿVѠ!-̼"s`g_淳j6Ơw˯!Oqw*V09@Xc$=uQWE\P2ݸ'zSe^3Ey5C@&P\Rl>~M 7( H$҈cXvQ0 ZJH;TZAļ/ԏ<4`  OL`–0u:ڟ|l9#t>6RRX׹(aDb27ԝCE#$&gH]\Lc"ȝoAm5_̦ @@3t([%qk]uzg˃꘳ݭw͹'˄r]7&yT|z"!ǣmp!L,H]"i/_+G!rIn,R <HۿͭuC$N Y6&(EQibfYS`If&!,E.D̺e>rba;yDe>r rLW!ׇ*o屴CrVXoͰ^މlс֠`¹u񡁽ͥ`LXJ>¬?^/ďxNhz{ORIy>2Jgp0'yYˣ>k`lTLq\|r*^x",h #nFrckk/9_YOJM6ɽ0_#XMGn+uDyC^_M6l"/>޳lp&^ =v}o{^ u͛͌(< tS<^AleR]ɭAN)yg&uׅwJdd_-jdV)Ϸ_`օiV?v4xlOɴR twgΫ9Ϋ}v觷 t~8'k ZSo>Dcݻp6ҽPmڿn]kǻܧeκ;YT1zn#[w(`o`/a1mkۢ. o۹]ЖnDNml8}Cn7<ɉЌ-yd$OE\!ɭC?y#RRTnL \<=90v\t}-p:9LJw~ Y][71~e(ײHp";M奠ԚXYW{czB,{PXc"`E8n3q%{ݹ Rw1E'i e%et9CeO;߯aHy';;[wݷfm_e2 endstream endobj 284 0 obj <> stream x]Qk0yEZUi{섚hwl Dw'9;\F i0ЫJL0~ҖT쟋2?_aY@E,e}&򦁹3iqr(Ec[N4ތ3[#U t XqrJ@L%`Eθbe-x:,;5ge0gc5G6DюhCH|v|QHmBT|9 xyç4>{9wP9%KxK0Mv⏝Ղ\ztӜǤ3li*?J^ endstream endobj 285 0 obj <> stream x}]o0tY EĐ hƒ}d`[#B*f߯=}$<9Sz$K3}mC϶5ۓm`( V7U?~C9nTv?}^dg[W?~i_Xհgi~>pԶeØkҚcl܋A7jF$Ǚu{8Dq`p tv=Dl2O䀪%emGm4_hϛ"(F2JCQ3>'%&g$( JW~aM'aJN)PT`̻ *!Ø $"Z "*OD\D+$9D"AqKD'HH%ׇ7 m~#qBQ{l+vBuJj6 ~[k;7 endstream endobj 286 0 obj <> stream x]ێ0ܪZI(G)VMv$d6Qo_{`sh.Uϖ랝ufG}pVVE?~K.K/-M߾ÿ%?3_(V?|wˮ>5lY04fյSX6Gj?RwU}fOm?E=-`є<[̳]|X7T|.lZl (&JC(5@>QF4"ZB$ED R8qH5A;#ADqF]P%&\[!S~^'?k"r8DP< D%gN^5 Q8%Ii T.)QzT(* | ֔OI#xqjMVB&X:%D% R|N+K< ppRw)S0\> stream x]QO0}1 ma !AFXrLQHa}{ ߟڳtz`iUj]ۓQp%$+k5̄oe'E-`=ݽfy9| t(ZX 9]g~&Ub~".=Lړ)$C%;uVT[B L`|\ 7,( F;c4箈&iőF> stream x]n0 @ T(o?i75DcǿYR 2W0F@FÁ\)1ىqKZ[! ;)6Ў7f6soI :]̫{?@WF8vq0NVZ]a=>M FȖ.Ye-ը :$z8&[pboZ i%_® aƺG qp)R=)C*rKRCʑR$sRa)³w3%; iJQ+ endstream endobj 289 0 obj <> stream x][k@RoB酚@_NRijg>tA۝9sfw|_u7 ME8w547Ӑ8ѥӎT͵7J}|͟Oegj߫㡔h̑@BY}^l6,> stream x]Mk09n)݋[E {hiIx&|E]RX?b Zg dDRٝ&xN񥬊cַGk NEtxm+r}(kW\:[j+Ȳ rSfkV8\a}Fעfz $sߎ=8kP9`%.r*yU]ϾN9IH@E2PPO$(ϩm c1nkoc[]H;ުM endstream endobj 292 0 obj <> stream xUX \׺O 3֌nhݵJZQ\AD@1,Bdٷ@Z`Z.zYm׾M~df|gKKT*U{zyDybUKB7Vւ(HD,%AX q"k3֖6-H3φBqWXO $JdNK%$.Ov\UZ6vf_ KTk#}U|#5QaA*{(*[2_XF|CD7,Te,4PREF9P.a᱑ 3fN5cu|]dX0t6(,2>H r TkvI1mUi;n #Aa;ɇOAR R$"*HeaR[p\IGHR;ґ e,ڋ>r~ oq8=GJ2h "⮥6(;a6+*oY=$(3u e6uE&[ηVhQ.~"tw^!~ Ц(F wa휮-ีL(pÏU0.ܤפl 'L'N[+rXc6(`w&Lۆe0?gGs`:$}w v&9X_r` ny@[Sz(<^ "BPA ykkakGh Uqq A)g_#{HR-? ESe@$)`;qh5~}TqٵW`;o s:!Mrqiqa\n%rޝTzUH3= hWoa.9/J?]A v@!<leW^)xwm#I) ɔԴu+K%$h~# Ⱥlx$5S_h?¢ GDnӃQNM-P{"jؒ_(?@_\d!RcOg'/>gB8jNBī?Igf1!T#θOLYh JN%]*(xOa&<0f*nG^yVcb:D4g˭ew %pdp;/,w_/Y%'U^r+U:6/&qX !Fp9%EEaTNkMw;cZk`W3s[1#HD0{$~m%%;g(r#4NfLƄ%4VXA%RQQliL]{Y.Dc702igbR q}RԧF=prUIG{"TdX'L\C@WI8Ffp)uHGc,eeČBL8]&`udŵx?˅l+_m=Մ˙=8^GQ#H֝$C :ꦪ g˵smFh(i )B"a|PtcX6Y7xBC-0W- i>ԗ o)7]ZuHFlX/dA7K&kpCnqMEFПy #gāp@ga*V 0-du.,[K> WE1+lrQt}cWo(D׻S0{]RvJi Er MiX=yE"0Bb[xK rc b7m>aY,5\g3x#_#rO)=ORlɓs&yKAz؁sv>vuЩp=0tE`Rb"cw22e7mC5ڂ` QCeUm%]:rԿ-?sB[u}e ˧')(#āL&I];`|דwOtS2NCާ8Xw,wP_QCĚWO}yv' &UqeKuew)tjٶY0 692_:u;?i}0wH|{yLWei`e$4>>6*QJ_q {5L؊T}xj&&4%zYs򣵺.6kRiV\.$+mW۫/g5,7f0MihSb% Y@[Lw QEl㷅.B*D̷{eS/D,脡;¡+Mqsv5/V1 { ֍Zˋ ݐyPYRt]0 M<Ϊt{A`(gN1Qwpt,#&!3L|c6P^gdgEe$+?mQ\DIO}["eQ6Tn :Q2KGz327f>jQ73`9LedE4_;B1 L]UYq3BeAMg=&&62 EbzLDo#'A| ,7"MBCaQQKe= )ʘ49ɧewoGp)k 4 ;08g]OB1v 3ʮo߲XR?41@]qcK,B٭h)[î}47!ƯUy Aڬ&ފA `  ŮV3ZmΓ'k:s7Л _(8^'hКl(ѲÕH9LD zPݕꞚ650>ڈ"'o+~M^eǜn4V]{!?]y%ݺ6s!x7޼&.",6g,[X8=Zz[p[ qO_OE?yGtOU 8'č-?'&d0u+'8ĖfYsQ{RG)'lvB.{!qaa;R;ÍN&0# !Q[Q7}~{fMNp/`,H}Ef$"$<ɡCq#,W,<M]W]a>^XhЉuJ- ыY̕yeI>ݟRL򆷳4琖ˆ` | "'[o(9!s78Vn\7lV;)?6B0R_k6k]}~W:+Oܝ5-=AkulaqkiAKJ0i%ؒYDuÇ}Nj0vy{dB=#a5*\C.=gjXf~h+H$w#r履O"lo\dar#7 j endstream endobj 294 0 obj <> stream xڛȵ7`0C endstream endobj 296 0 obj <> stream xڝzwTo7mAV)K0QPt̘1gED d$5%IMBw$ fӨ̌i:qΨ]{Nzk=Uug Ţ^DbxкK7W+5ظD" M7N$bL$ 3KfINj_5PHߟ 8tphlq(X\'EOynK=>vllvX/PX*ݭ{^]֮֡ `OK!D2,øcghNWOJ!֋^>J Dd>^ޡv66ll{_"o=/,; 8;440dOwۤ F~#sML?CAY}cwP*69π~k> 3)$/suX kKKLˇVdV VǬ O4L>O+k&? 8D3вV<, ͳOouw~)4+gx쯕G\Nʄ<7Ӑ MbcLi7zۊCk8C`Ei^5ϼl ϨWW_=Ó[ȃWC)^,/z{6R2]k1*0O%XfꀶhO &[*O/2FG)L6ʿS8^hhmH#.vZ*B (`k)7zEԷBVBo_0= 4MUvgobLug諨F4 jo1 j{~pGYRQ2 m6c'/W_nRC^3Z];!u^_xظ' w {nǖe?h0-T<XK3 t\=7LC3c's?9TfL(X^W#Zū2^zom 5'uHB +)? _fbh7D=h?z*K0fBpĘ|fIe(͎'#+$S6?`C.;x>II }V=L3/2+dBnfW[c4/*nGPV5psL)u̯MeQzQJz~\b=ZUpя7{ҩ{ ޡhv9hdL[? >D| ך{DZdyMdd(ݮa.bGGG"бzU;/H#&B3PR*jz/}/8l~0 <`+ Jrq(v`F։h 7/'v΋F jV  kfr0%T` '@ŃxI3 tT7GԱ!Tj(GřDTtf-tb5>XI!PӃhސ}lN>'UQ·1n s6?y}iE xFEA?A?όr݉1բ v92+JOTtLL|P *),b |ˢK՗K/\N\ba+׭N8,+ʗݡ>uy9/uo,~)oT 9C?la7s3 $l Pl,o^Xb|*\^Em ׇm/ #0 a H?VSDl3 gkݕڤK/OƔѫTƒ)?,Wv1t.'=i%*q\ "67Kki{eO[bmpQNK8Ag2O\0cg^!~r_{w1]Y<8G0z9 i,yUeޜ! L)AC O69xrJQ-6Wke1]dʶ"00dV)L.?ek(G. c@ dG*aaA :8}N=1Ϲ;` $[-(J-?!M[9Nl].D#DHQQx|`>KFax1?@nT%CFƉ a7:X=&McNrlTL\J ex$ .QzInWΐǫW8%G`$k#l#YxpgHCR'*gvk8w1 {󐂴-u-0G+SIR+Am7nVnXϥ'T>Gֲ̝%Ξ6)4s1GBhm0YN_sWd֝4@m6 V?Ҫ_wiAj@͎rRY0 /Lz:'>f<݈Pӌ^3jzp.~r @P u0QYg|cƶkaLW'+}"^dW&J ʤՕ~`svpH1ɰA9gTѩ0R1]Tla]k~3{/#ɷyElq]8,SRI*~A3Y@pl뾻&O&IS0<yMUlۦ4 _E:ﯕ5q҃<|">jUύ0"xQ}Y~Y"*1"`Ƚ^IbE:xZaFcwof7yF5a=[d-4)䘐rb['nzQg ^dB<0PD(; 3%&V(T_F\ !T&%7O^鰗UaW&ݾf]'poD I2׃߃1`o(NؕC0fPyqP)\yAnV#Pe|b^J$@cI3gcxb1Lm(42'{`&~/xapٞE<)0ҕ3OJ_;:jwt'm C(C5sUkoɍr#w=66oڇULۗsHS]?>Į I]q%%1ݞZxWs0 4SxyO\y&QMfbdUbzO"?%=IZ8$qJ(̓fsL*Q&641G*75V\9/,aT )Ǵp-n0fV2+n`Ƕ`Y I2z(p F?I7`HeCa('iԁÖ!r %/.ERai_oK9 F밻:!-Y9Q^S1SH녇u_ W e`{8q.B_jGVx-^t4R{L_`#lm{щ>q/]BH$g,\(<^m7nr9yɝlPlhxP9p) SUo g^%L]E,j9%%\+86Z'du&}D\ hRtA'XMU*BX }ѪPƈ{Č#"Љ۟AO5\H&ϰn|ba^{tۍԆs$⪅/>?&O1?C߮ z7t}mbkm]ȥ".~3壺7)FQzϯK6Ǽ^s129Ko[乔|Zt'']r(.Aw'}&yL #9] 8l0A|;bsQEX$j絗0Xz;<~^ 2U-WւgUmNe~֝30gdD9̉v.f'ͷԴf^|Ԣ|>3kR+mVy 6ja<> stream xڛ ܀`qq`9, YP6  - endstream endobj 300 0 obj <> stream xڍYy\SGNL *z⽈;UQQܪ *(K!a_E* aYTk ֥֍շ\:&&g3sdg~ bP(y:C?i_dBMi, xNț "\l/jkT_`:h1B z^?1g}sQPyo! e\g?s;0O>e4Ӧ1[06Ιy(|̔ oEPYl}/Ϧ6B"("&b/EahElڔ)S'M2m1",ۛE*fJ8sȕP? ~mJ7|~EmpamבMHMR }PETl45hd0|v9o4w764~qJmJy<LJ%}pP ZLJV8gs97Il=SoUt(JZ \J0B|精t`x2qsn+Zph"H,2JZ1~{錄-PK(c$iCWF+to˄'(Uᅡ/.|7s%m}sme/6e?Օ`UAD1OvSyk4@#r.MDCdVس+[EZ[uza*2<eIHmOLe4 چ&#퐡17Ɓ` _?@^lb ߤM#k˲/VW lBk,B*R̃ Qm>XE d>Ox1dӴv2OzŽwyLZrf&|?%o*0iq~@'aQ\3ΰB>Xnr niZCk9հUF`|ZJf7" n4o;?N7@[ 7pfJVZ|v Mø0;A A3xgYy$kP{mLTɸIRsﶕy(Fu3uNIgzȾZE7s˼J6SrB 8nj;08Sg㐲d"CϣfmPqD lzA0ï9ׂ'ѶߢQXg"!"ōLzQxquq#ƭvb [ C| tq?)gܰwoqY 0C3"%CU7!dZ.rxa vd^\ZQ+EL<:`]4"e Xix7w4M$hDH4 p &~D2B:M"zӷIHJrx sViDk&o_$ab?(׮ xGL;}Oc$Rq-zWڌ[_L yBu2%\h72*)R. ̏):Ur}k*tx:6-`2Ҹ;ء2Yulaopļ]',qC)i'Yt^+;"D"dYd𖷼w.mDfu$!X3j'y: '#;Jv]ZN|8C_~'2?Su5\¯Br*NT4/*?6`Æ?!R]8?u. H+9 u8>5.PBC@rdW_0|u$iV,WA8"5A"Ƶ)—Б$2M"%iGONc\",݂-4ܚ;W.\k2I*nwbjT,@UYmSέxy`cN4nEj/߲i)!K0iK7sT\ p: eR!,}}A?Hi7/2ߊ\ uME"4MS>wUh' ÔVO )EU5A CZ[.DBJC]Ke*v!o.~,K5cbRX1t(0P /*8ZJ7'wxbzq֟gYnS&ƤT#'`6jDs#mޣ9U0!U*wUÿ.&P T'''rxӍ$v.o?w1z_G@LG)N(KK|sDVw ,xIʹBtAs>] FFPޝ0u3E1JuJ1 {v䆶ޮ-m4 H:}KrڸϡB db[q8X"Du|Ʀt0j"sbw] 51&";T+r#V9WɵJ#- *뫜BLGCGS#Qp&X]*Su\{Ke%1EK|6lsҹy0*CIKW"5{;Ȍs NFm,aW(_@F=zRK$,l=f]J^0_EU6Ubf;r29;~BREjEzMs6]fI Ȱ\D Y]]WgDZ$&َgG-U* ۺTɏ_>1(@_c-lec+uF9['a^>V`*q%p٥4}VS?!pY{?meL7}J- A`S؉Ƣݱ ̀` s`1kBZ[ox ̛gOOėZ?x{䰼6接+%(i(`J822v':/Q%lD|<,ɯ#0ȄEdHp2 @®w2 fDGۯWFim紫="֭Bb$n4ƒ'\3{q}竚J0ԇol歷T IVOXp3W@Z&w0yBnpeYK7ObL7_/7gj"PmnpfZ9{2e^ yRUz 0̆hY$mM/!K=BxXjfҠp<_;(Ķ:fC_'6mWW 78Þu|>ՑErF`~וKp&Sթ 'oep gbvd(Nk{@z5K,c6!bZNz7Voo=ſZeS2sgyTidqd—M$)IhT+N٥Yѻiv 񚬅]9P!Ɉ>g,JNIg]pgۺyZ#oQjp:F0 C_gg|5r1%voKEy^Æ%|i5N|${l_Lku-|'>zߞ\uIubDV$\#|Ja[UWǦ0i,pWF+9jOx~ 5-q"LOcr.3A!M28TÔi4 ]qR~KZWPjEoPUPk[1k~d}`ah.7z]tEфKMů/_u~s)Kxʊx0zSr$o7gഊ~%2}`uq|@^y$J̕T6  endstream endobj 302 0 obj <> stream xk``)ƬnS<@&]A ,0;b X+0 @)a ^lJ3pYD endstream endobj 304 0 obj <> stream xmYw\WO "F1yVk[w{:p WBBdž’ 7b:ZGZ;l˯#{~ϹN  /V/r_YH距_^̽ 299c܋"2:(pk=g$ xO8uYrq^(t"?2+{wO7j1#C W`/1WpoWewGx5u`zoWm1$ou^`opeBB5~;|ƌ;rܘqc |ex?:;BpU*CSw)}#GDO_$( d7B>" )X #tJNBZ8P(: +t+_E篖D1&:M,#lM,8p8;c 6Vrf``W RrZ xT=Kѓul-A:Eh|,ECLF]]Ec?횆 O%VBվfx&ϭAs - lNKg?u0z 4*rp?GAl!Ic39ڭa`,nǒ./HU>3gUp2+1? 7QbVڏ==j1)EaxZG+0*w9pD#56[I sͺJ7<ysXqA)YEI~> WޗTT񃘌e]R{0X8mӰbr'x,(8Z(WhW_ɗAE$P e}K>ާpcW[/dUDz"ܼ<K+d4Tʚx,)I+p))Rs~I^^i];T#GkA0eZ:.X<PrBF' KpsEn@w t: %cZ7D]c/H6ׁeBŦ"sQU.Jd0q,ZkZIm\HmK##T~e6V8梏[6:rt$ &Xve䖬`=`w*@JU7]Zo`%u7TR8*Jhw ,]I~wg(2WktI:^9s?IwGa|qfkj! ܝ[*4WqJ ޲}pD?^/o߷TWyy54n2)OQJzVk)qMƃlӛ!-١|˯Ȋ~0?!_slMۅߥ }_*;.Z+!G rߡ>|V>y}nIoI>B<&c=.1S=nqT9&yv;TszL#7AHhcxHH@ZC'MpuLeu8u90!Lhnuzt&!,Q#_]nfڜ\yr7djp܎=[7Ք6%Yaf*[AhX(9Q2>%k1[,Xvȷ͋t;|6/; FNid"C|A,9RP#6MK -*}0cH-ʬ7LeT%b~|bJI{咸sv:> H?z+0rMjAX}lk}L=mˉ.M>v,&9?L`r="`68fb/-HabJnvJSdWEl5qJ2|,042N)H`LZP䛎$->x,y2enDD+()9L}qS:[eO%$7E].% v` ΅5g*&#cd>G)~BX[@@j«ǧ̔\>Ӹ)`0pk|v #=ҾjVU*Eiyª.":􏨺RPZTce  Km c7L"24z^Ot(;)kJzg/4z.,_̈́UJKSֱ~'y= ) Du8|V5gjO8T0 lN03{f퉼&~!zMܫ]#ņ*X> h潓E`qJvvJ6әu}{B!Ӱ]N̓C/ ;EP҂dT d>.qrn;7WJ=&TWQKdQ~vPKf*% K"E#p&r"pr `j @68/[LVSez^.fO/Qog5ʰZeVdߟc ꤷ>E%V,.QDl$_.:<Ý/ endstream endobj 306 0 obj <> stream xڛ{܀}S`@9lP2 endstream endobj 308 0 obj <> stream xMX XTWv_[#v;&(*"Ӳ4!Jk$q,5q+(hDwTThVE%ƘEwesT󼭗.=*@29*ݲ1q FMDۃ Vm.Dq\{俲a3jᖍ،U ;k Κp9%ׇrvI=ן pZn7ɍ܇Xn7s&r87n27sٜyqޜ8.s @. r\[-¹\$̊qE+_η[}ɽy=_W=ë2fuAV 'apK[>N>O&?*P)t"TԳg5ofb?I^mT6 zr2Mߧg>ЧS}lmmlMvvU*Hu?7`yrݫUr|֫ɡs# R8t^/ޑ]ՒQQԉ7ӯN "m<زy~~) WfStSdZ+g{ZՕ5of߾eԆLF?gjf/u2A¥qH cH~a%)Գ3qe]qf "LQbAI<ھK8 ԍtUJPTy 'NvA9:KtÁo\~N(Q_\~CƋJoqrY ߐ| ri8!aU/yZt@t)MD%@m :dbG?8+71 '2N""4I'{?ܣ[Bx&tZG={{}}/Wf !Äfiщe'*.ğ [X91{DfvZ3\PftEg{cDgR]EW7S:c3p5*z~эFean'2LCӭX'(,*+i`ŕ?kR(گl>Ct7`@d `,/+#3@3 @iR&c;h3hUDeV-`ɎhP-|?$ ΖMDCuTJr&=+-.?7__MTڐ[u?L}HՖf"q2R_H.|= aN< @=i/AyxT>F= 5oMroĺ6$Y3GCÄawCPjT`&$^!b (,NoB>S,yCpڲ9_[ȵ (>J<~M="DG4ihQkjVI!n#+]5 qTQI75;x},F7?RL"$T<ʙ*BfF4%n&R$s#Z_&/?}jDtxCc]xf|5jVDWVѦLXcE] ,+ˇߗ _N =ME*E;+(E eMRMg/n0hQ /T=MJh{<~ji :%̻>$sg%.u O0Cƻ]]Mtx8Y6CA'Υ;~(8q!wIYq}n(iT\m*/GQs'/҇Zj)!,7R/-MU$ypˆ.C+%ۮ KnJЈ t)Sf.Ɔhc!-e"*ʍ >9ES" oc-Aݚ698Ƙ"*,>57KδuS^܂|I1jElj-v=H8q`.!ͤ=ɷYfhpUQW@A-U%4O3ɑu85VofOd;7="NZyVvX]>x{MOYS?Qɚ <_RA_xv\XJs8 hR[5=#n8Cz[,+jT'go F dBh '5>UUSZ㞩gC,-Lr-x.,}nrq?k./ K J.^ viU?d9C+]v%x~)ƀpq\MINFO4'*Y@$ kX} mte0h'r5fb)rRY!kZzTNoa\)t.?XS^Vݪ$ǛI>D]CYet)*}"Hg |O-^?ztc;GR|fZBEՌ̇yc 倮]ʀ~ HG nI+pzWa򖐚_ bXK$Wg.68Yi!QkgbBTg@|s4/grT2o݀q|c$tӨ@'Qs M^}q=[ݦxhՑq?ڦL?%DZJ,DZ fղpPsW[IS,Ф6xKO˺(rfN8).6ߵ-Ěpv,lZlΆ9OMx஖(邪 nI2BoaŶ[S%l߿@=R.ÃcݤluXɻtxᐢ<|wL`8&"L 0~9ihKp[|:2}XZ~]gcAzRbg5cJ,E5¸;leLPŖlQܬ|EEժ=X滱2(R#b8WdMOB v7 U)cYJHx s["p [j rKFo# #ND? ޘQ&b_kH0ɔ= A3]%XF6 X.GK ݌U$MFJB@Gc$ƅ BҦ&EPnG@mލeȉٶG2j4f9,<h~Ğ5 "Tc63 h Pz _{@`j~z/6f@a-Uc (>naEqϜڜeZmmhus6f(r 1ֹ?|˷Od[|1> vokY9b*` hR>Pɢ2 9V`ުÍi]!2ϔ#epuq1%I0~ŸIe8:E6*;"%X3#/Kg yǶ^XTLBRSaŎYb$Nd$J7۾dHG)/~ !98:,GNu9sI~.:49ZMm6`ӫֺƦWM  endstream endobj 309 0 obj <> stream xkem`?h/` : endstream endobj 311 0 obj <> stream xMV XW$L8*LpVZ!hZ7lt*BC^ ^4vJEPjF(.Q?UBA3$TI§7I$jB}b*NdatRؤPJ! L&RE'DDUGgEa!N, +:`1+*! Ngsĥ>iL"E"V{D`}XU$PIkN^<E`O4BJߑIIq (W;¸m*K[sC%̰ޛvƕ+⌏'ap56oܚwoƞ}܁_u+SL~_r^d/:#!-Ygۜn&4z-_ +cJO7srss8h<ޱxo(aP#1Gx/J0S{[~ <\Πi-D( dh|RVQk֫H.*ӢW5'=YVB6O%sPɠI#Jp' %Pf7"?v A[QAbnw6H!H!|X2P%s2C:$(gTl^BQ$Z'e.rޏqaB8 p5~d<vXƊ! aBwpH~k ]p;Y A̜'Ej'8G]ArA*@w6mygAޗ6y!2`|)&HG0`l Gg"0X uR(sf+\c8G@ .RDQUѴ!=A@=?dLJ{_IGLX~hv 9/S!$(Bow7pi\sګn&~ŋL-;x!n{މ'Y@zi)vR!+:b`T;wZ{m;9@hmИV0Y%/kjHHʪ*nW71+?|J硄O؁ HPDB(g> stream x;L , `"\F82*@ :Jr0p0(0 e 9k endstream endobj 315 0 obj <> stream xmTmLSgNK^Kb+^ʼnJMD񃅥2Tٲ~\hVc%RʗH-2G7PZ1͉ōd&lLsen-={qp,.q\%? ܒ9[RZIkLF] I>)-И+ńy1X!9n4&S;({02O$ ÛgFcw[h!$}{&ñlawI\YzsfȻSEY3og5f=8Y6+vYKo]D\xQ1=>I-fn0g/!uf,6lzZڲiy6Kgxfg yCL[tn=@\1Pc{ 5^aUgkE24{2a:-=4qީWaƷ fR m-$ᬰT| \'Q[?Ӯ<~ou;t)=yX_RcP&*3$H00"Dw|U8RQθv&JduCn'_1"mh#QvaZր= o R@N=+yŦ~=5QB* \W[55F@!2u:z tWV|UG=Uݮ)yyɮ :`Ew iT#d$v@Au|/O\hvKRa+%ђvzj'F YtT҅>¢K]-(I}V4)8 :tQ203o+ endstream endobj 317 0 obj <> stream xk` 8 endstream endobj 253 0 obj <> stream xڽZko~~>f_;o6iP;MRvH$ɿݥMbb4rsf̃B 0'% mID\Y'fBsF$;)GI{Oj tuZXc?/2玍{榙Mt\Հ_;?oXXghn'O>R"LEf9]\4(9Z?4@vsHpTJEp6swmUtIyݗ֎d=M&)R]U}zYm<`hҩN0C:>=|m(;c)LJ2ъSKbMH"N 5Vr%r9DN+"]d>lQ#2DNhí|F3 d=B#d=B#]B%]B% ȣ~$zgJZX#>uިr=\tGY똵Fܠ+W+~M"&N(E[K*MmW(U 6isEi{";C6`Ju('21"sT"vTDS[T`0Ur*IL,JSg~-tUVUKd3Uҙr(w:U[ubK!lL-zLG_>E3^;ϛx9Es;:]/Joh]gH=|r{,v>N>Lo&??wԖ?ww34UsorR'JIf:LnhVuɳ\6ޮ3=A& ɴOǫ*{PXʑ#ft:_+[Ek-+/MuZS"&]r*$ξ"$9JG dXRxع+y%TM_@ Q;FR|U`ueUԐdv\IE.DfXYhP%J"Gv7Hb]R!GңQꥈDNFC@iFH.G-B!l/)r"a=eH?t=a? P#+_;5@nd8T: ! _΅ٵc[c7\$SNAȰ΃5Bx"=w6mmMp<*h4IDtUrL͌$m"r E^0p8gU4ʎApsMRlHRR `! D! 'x6pu0Z-I8L>`8Cq<քA'B5V8YŨ"&{ױ|?E9v9;’4bWmDS[ ĔcJK$o:}&^K?C1 k5o3:dkP9IC+(q&.DI-'h;FgoW`5ߐw_yg积7W{gzO}Zyjxd4jt&e a77{YAp,/ Q\@_ѫ;zpy{y74&΀w) ufz./:pj:A[bً,( uzt=8]]7BNWK`^geDo y15Ut6~ǻiޏf <2eM1O;MA,ͼk@[i㿆6Q>kL!fg,%['M؂4=g^׿xW%g:gT_Ù`8erƃ3c;ފ4нCcDk Icg4F-H3,a[ćqۓ?N_Fl3&r~Uy)  yfOB/T3l.ih4n ؖ3<$ߞ4G/NO?.K3^zGEDc;DqM.! # 6K/xQjn-~ G2d.G:G~k 3O>OhƳ|o@\sQ~TFٚ(xg5Fڮ1Q Q6ڮX,ٴ!"q{<ƞU}R^` _OoPl.:m٤6)? !! endstream endobj 318 0 obj <]/Root 1 0 R/Info 2 0 R/Size 319/W[1 3 2]/Filter/FlateDecode/Length 722>> stream x-YPQQ*,eIɖX*زEٷʾ"d)Sve 7 3]c1gy_Ş0S1`?.I"dF聞腍[E&8T۵xڂ~81hI@S+ 9ag1J6{cZU"mء5p;b'c+v*l5zb,8}0b&c b?OVj%sw阡Ls!831 U&:_Tˮ*evd#p$\RdWaq8p\!\x_b |Gpcoj&5wp-÷ܘQq'.܍p?%ƍx9X;T7{@?D/lh>B{}`4`+ C-;avQ|}ߊ9Wo_{*fKw)\osjLݹxrT3mNPͯyjA.j#Cm5.?Y'F?= endstream endobj startxref 101162 %%EOF expint/inst/NEWS.Rd0000644000176200001440000001000515135742246013606 0ustar liggesusers\name{NEWS} \title{\pkg{expint} News} \encoding{UTF-8} \section{CHANGES IN \pkg{expint} VERSION 0.2-1}{ \itemize{ \item{The package vignette now contains an appendix providing more details on the fix introduced in version 0.2-0 for the computation of the incomplete gamma function for small negative values of \code{a}.} } } \section{CHANGES IN \pkg{expint} VERSION 0.2-0}{ \subsection{BUG FIXES}{ \itemize{ \item{\code{gammainc} now handles values of \code{a} in \eqn{(-0.5, 0)} correctly by using the standard recursion, relying on the accuracy of \code{pgamma} for small values of \code{a}; fixes \href{https://gitlab.com/vigou3/expint/-/issues/2}{issue #2}}. } } } \section{CHANGES IN \pkg{expint} VERSION 0.1-9}{ \subsection{BUG FIXES}{ \itemize{ \item{Replacement of a few API entry points for C API compliance introduced in R 4.5.0.} } } } \section{CHANGES IN \pkg{expint} VERSION 0.1-8}{ \subsection{NEW FEATURE}{ \itemize{ \item{Unit tests for the incomplete gamma function based on the definition, and for the exponential integrals based on a table of Abramowitz and Stegun.} } } \subsection{BUG FIXES}{ \itemize{ \item{Include prototypes for all C level functions to please \code{-Wstrict-prototypes}.} } } } \section{CHANGES IN \pkg{expint} VERSION 0.1-7}{ \subsection{BUG FIXES}{ \itemize{ \item{Replace deprecated (as of R 4.2.0) macro \code{DOUBLE_EPS} by \code{DBL_EPSILON} in C code.} \item{Remove the unnecessary \code{LazyData} entry in the \code{DESCRIPTION} file.} } } } \section{CHANGES IN \pkg{expint} VERSION 0.1-6}{ \itemize{ \item{Fixed the example API and the documentation in the vignette. The previous implementation yielded duplicated symbols with option \code{-fno-common} that will be the default in gcc starting with version 10.0.x. Thanks to Joshua Ulrich \email{josh.m.ulrich@gmail.com}, maintainer of \pkg{xts} and \pkg{TTR} for proposing the fix.} } } \section{CHANGES IN \pkg{expint} VERSION 0.1-5}{ \itemize{ \item{Minor documentation and comments updates.} } } \section{CHANGES IN \pkg{expint} VERSION 0.1-4}{ \subsection{BUG FIX}{ \itemize{ \item{Usage of \code{R_useDynamicSymbols} to preclude compilation \code{NOTE}s, better registration of native routines and reduced symbol visibility.} \item{Vignette no longer uses LaTeX package framed as it was not found on OS X in CRAN builds.} } } } \section{CHANGES IN \pkg{expint} VERSION 0.1-3}{ \subsection{BUG FIX}{ \itemize{ \item{Fixed wrong values for expint_E1(x, scale = TRUE) for x in (-4, -1] or x in (0, 1]. Thanks to Vincent Dorie \email{vjd4@nyu.edu} for the catch and report.} } } } \section{CHANGES IN \pkg{expint} VERSION 0.1-2}{ \itemize{ \item{Yet more authors (actually copyright holders) added to the list of authors.} } } \section{CHANGES IN \pkg{expint} VERSION 0.1-1}{ \subsection{BUG FIX}{ \itemize{ \item{Fixed improper use of macro \code{ISNAN} (and \code{ISNA}) that caused compilation to fail on Linux and Solaris.} } } \subsection{OTHER CHANGES}{ \itemize{ \item{Original author of GSL code for \code{expint} and \code{gamma_inc} (G. Jungman) added as an author of the package.} \item{Improved (read: more explicit) copyright notices to GSL, R Core Team and R Foundation where appropriate.} } } } \section{CHANGES IN \pkg{expint} VERSION 0.1-0}{ \itemize{ \item{Initial release. The package provides the \R functions to compute the exponential integrals \eqn{E_1(x)}, \eqn{E_2(x)}, \eqn{E_n(x)} and \eqn{Ei(x)}, and the incomplete gamma function \eqn{G(a, x)}. The package also provides a C API to access the actual workhorses \code{expint_E1}, \code{expint_E2}, \code{expint_En} and \code{gamma_inc}. Sub-directory \file{example_API} of the package installation directory contains a complete test package implementing API usage.} } } expint/build/0000755000176200001440000000000015135742277012675 5ustar liggesusersexpint/build/vignette.rds0000644000176200001440000000033015135742277015230 0ustar liggesusersuOA0,mA!11^+/x@1$PAo\\5Rcvv!u1JB ȇ;7Y>h!ab`,J U0kܓ v M+X;KupE1??-a6rU MUi)Iud_clv͛? MpEuAz #|^expint/build/partial.rdb0000644000176200001440000000765115135742274015030 0ustar liggesuserskWFV 材'M;0fJd iklTdɕd [ {<2r^x{GARBO:%)z%lb|TU4k*2ioAhIe._4.j7:}#*)* ϯ.y裟vc_ ֊heӚToL1 B`I*h~d#i{h8d2T7kfj(uٺddK*cf+~.~>ZAyMK?ren`UK}Tj*r ++ՕlEҲ^;/>R/)G:?3ԥa@]^iё70gnф_7d=5Gnn7-vVޚG #KWTE2vddiP-!hx+$#zqsnWyPc Q+_ZL G4OD>ܕC"͚j ye?XOPX2 p2gX,xRB/ĩv6noK9Yb m@h1٘V9=gdZpbyr"8"4~Ab &:; )co +c@Q30LͿ[D˝"'F lٶ xHX1ZC(%bUCj}&qcixE^QHq"阣u#u>R uI nbX,Z@5G2ZR^ VeZ턝s@X|=,FHd5 (E3t/`Nkva2uW6Ц0 ԲYg;2iP=(P&TMM IU.L&8Fh[7-_5H,Bt_-$w~:w@9w@:)FdqzmZ%QYc3.0e5I%ElKi26cE+MtabRzO|m321f'v6rɻq{Օ- ʹB=`H0;[hR4`QJTdحuR,A0z[S.bةا0x>TF3$2O=ʙ>߷$=<OCJ>@hu(.;4.LJ‡ٞMI<l6-v@ ;;Hu d䁹{I($$SZ(÷nyg6/u+a hO]GeKInG s8?؈i>\K9w?~2gzY&f,E>~g)xsAKIHS5I >ŋ`XZhԬe95D9OM 0^VB)}G!1JB<݊&6sRњR]RRN.*jɺ+%)1+G:~(UBKh}Tu#pU<.՝)/ٝ3aB)GmRE?T_f˿C6<}8 9Phϖy<_Ft.[ۍR~ ױ:!YQSL0~f{?^ul&)xrH`5 b 7`_*# 8X ?wneNɏ1ZBZ顇=Br5O$SIg;J~Т W1$x^Pk_Xwθw=5bsԦDKkRe]#ei13~V+;=zC5itubn`Z`ŒRlWMCb?;=vNiQ-?N9:.ӃY31\~ٝ J5WnJW}\;v3xIɞNȖZ^i;nZ}/ r;ډ#Uf ;L vk㙖{74oTO 6$q] :GxבD7"Y7L8c%&` X[NbMVXۘl.gnm'O[&Y]kbAʺ*b/`DKl<)Ǐ8kКOɪ [ OɃ,K5c A9 oGkwQhz(3ggO,o#%VTֆaJ¾nr4=}~.k\riW K֢ncT_81ӷߞɭ}J.Ӣi_"3?."Pq$[׭𑦒a:I5xEio:ױ&te :CB-39V:Cs͝e s6: scM/gd[9Bp.xEڊ Pme{ vK$Bo5&vRK/nƬgufmXԬ ٺ-ݲAiPpiѵ7(6{9速f f_$Dѓf0_r̬OSfcD境xB$s]g's\c_4z 8s{#`Fގ>)(NWG'4?;9q(8g 0/ $9f=eIےPgj2Ǚ3`qǣLT Je ,t2J"r SZN5Z6qNJܺHF)dtF,lK$X_NstڟHl1`gc0E NHk.p2Q3x͊}qAh衍4 ƽ UM}\9kcsԕϖ&+vKHqˈ=--|;YzM2]3<˃=/ɮ#W- /gW2xÌ)=+{-!<9뀯m ^ϕ R`ˀˉGG_5-< 2h|~=Fj*)v LϯA7tIeexpint/man/0000755000176200001440000000000014220225222012325 5ustar liggesusersexpint/man/expint-package.Rd0000644000176200001440000000300614220225222015513 0ustar liggesusers\name{expint-package} \alias{expint-package} \docType{package} \title{ \packageTitle{expint} } \description{ The exponential integrals \eqn{E_1(x)}, \eqn{E_2(x)}, \eqn{E_n(x)} and \eqn{Ei(x)}, and the incomplete gamma function \eqn{\Gamma(a, x)}{G(a, x)} that is defined for negative values of its first argument. } \details{ The exponential integral \deqn{ E_1(x) = \int_x^\infty \frac{e^{-t}}{t}\, dt}{% E_1(x) = int_x^Inf exp(-t)/t dt} and the incomplete gamma function \deqn{ \Gamma(a, x) = \int_x^\infty t^{a-1} e^{-t}\, dt}{% G(a, x) = int_x^Inf t^(a-1) exp(-t) dt} are closely related functions that arise in various fields of mathematics. \pkg{expint} is a small package that provides \R functions to compute the exponential integral and the incomplete gamma function. Most conveniently for \R package developers, the package also gives access to the underlying C workhorses through an API; see the package vignette for instructions. The C routines are adapted versions of those of the GNU Scientific Library \url{https://www.gnu.org/software/gsl/}. } \seealso{ \code{\link{expint}} for the exponential integral family of functions. \code{\link{gammainc}} for the incomplete gamma function. \code{vignette("expint")} for a detailed presentation of the package. } \author{ Vincent Goulet \email{vincent.goulet@act.ulaval.ca} } \references{ Abramowitz, M. and Stegun, I. A. (1972), \emph{Handbook of Mathematical Functions}, Dover. } \keyword{package} \keyword{math} expint/man/expint.Rd0000644000176200001440000000647514220225222014137 0ustar liggesusers\name{expint} \alias{expint} \alias{expint_E1} \alias{expint_E2} \alias{expint_En} \alias{expint_Ei} \alias{ExponentialIntegral} \title{Exponential Integral} \description{ The exponential integrals \eqn{E_1(x)}, \eqn{E_2(x)}, \eqn{E_n(x)} and \eqn{Ei}. } \usage{ expint(x, order = 1L, scale = FALSE) expint_E1(x, scale = FALSE) expint_E2(x, scale = FALSE) expint_En(x, order, scale = FALSE) expint_Ei(x, scale = FALSE) } \arguments{ \item{x}{vector of real numbers.} \item{order}{vector of non-negative integers; see Details.} \item{scale}{logical; when \code{TRUE} the result will be scaled by \eqn{e^x}{exp(x)}.} } \details{ Abramowitz and Stegun (1972) first define the exponential integral as \deqn{ E_1(x) = \int_x^\infty \frac{e^{-t}}{t}\, dt, \quad x \ne 0.}{% E_1(x) = int_x^Inf exp(-t)/t dt, x != 0.} An alternative definition (to be understood in terms of the Cauchy principal value due to the singularity of the integrand at zero) is \deqn{ \mathrm{Ei}(x) = - \int_{-x}^\infty \frac{e^{-t}}{t}\, dt = - E_1(-x).}{% Ei(x) = - int_{-x}^Inf exp(-t)/t dt = - E_1(-x).} The exponential integral can also generalized to \code{order} \eqn{n} as \deqn{ E_n(x) = \int_1^\infty \frac{e^{-xt}}{t^n}\, dt,}{% E_n(x) = int_1^Inf exp(-xt)/t^n dt,} for \eqn{n = 0, 1, 2, \dots}; \eqn{x} a real number (non-negative when \eqn{n > 2}). The following relation holds: \deqn{ E_n(x) = x^{n - 1} \Gamma(1 - n, x),}{% E_n(x) = x^(n-1) G(1-n, x),} where \eqn{\Gamma(a, x)}{G(a, x)} is the incomplete gamma function implemented in \code{\link{gammainc}}. By definition, \eqn{E_0(x) = x^{-1} e^{-x}}{E_0(x) = exp(-x)/x}, \eqn{x \ne 0}{x != 0}. Function \code{expint} is vectorized in both \code{x} and \code{order}, whereas function \code{expint_En} expects a single value for \code{order} and will only use the first value if \code{order} is a vector. Non-integer values of \code{order} will be silently coerced to integers using truncation towards zero. } \value{ The value of the exponential integral. Invalid arguments will result in return value \code{NaN}, with a warning. } \note{ The C implementation is based on code from the GNU Software Library \url{https://www.gnu.org/software/gsl/}. } \references{ Abramowitz, M. and Stegun, I. A. (1972), \emph{Handbook of Mathematical Functions}, Dover. } \seealso{ \code{\link{gammainc}} } \author{ Vincent Goulet \email{vincent.goulet@act.ulaval.ca} } \examples{ ## See section 5.3 of Abramowitz and Stegun expint(1.275, order = 1:10) expint(10, order = 1:10) * 1e5 expint(c(1.275, 10), order = c(1, 2)) expint_E1(1.275) # same as above expint_E2(10) # same as above ## Figure 5.1 of Abramowitz and Stegun curve(expint_Ei, xlim = c(0, 1.6), ylim = c(-3.9, 3.9), ylab = "y") abline(h = 0) curve(expint_E1, add = TRUE) x <- 1.5 text(x, c(expint_Ei(x), expint_E1(x)), expression(Ei(x), E[1](x)), adj = c(0.5, -0.5)) ## Figure 5.2 of Abramowitz and Stegun plot(NA, xlim = c(-1.6, 1.6), ylim = c(0, 1), xlab = "x", ylab = expression(E[n](x))) n <- c(10, 5, 3, 2, 1, 0) for (order in n) curve(expint_En(x, order), add = TRUE) x <- c(0.1, 0.15, 0.25, 0.35, 0.5, 0.7) text(x, expint(x, n), paste("n =", n), adj = c(-0.2, -0.5)) } \keyword{math} expint/man/gammainc.Rd0000644000176200001440000000352114220225222014371 0ustar liggesusers\name{gammainc} \alias{gammainc} \alias{gamma_inc} \alias{IncompleteGammaFunction} \title{Incomplete Gamma Function} \description{ The incomplete gamma function \eqn{\Gamma(a, x)}{G(a, x)}. } \usage{ gammainc(a, x) } \arguments{ \item{a}{vector of real numbers.} \item{x}{vector of non-negative real numbers.} } \details{ As defined in 6.5.3 of Abramowitz and Stegun (1972), the incomplete gamma function is \deqn{ \Gamma(a, x) = \int_x^\infty t^{a-1} e^{-t}\, dt}{% G(a, x) = int_x^Inf t^(a - 1) exp(-t) dt} for \eqn{a} real and \eqn{x \ge 0}. For non-negative values of \eqn{a}, we have \deqn{ \Gamma(a, x) = \Gamma(a) (1 - P(a, x)),}{% G(a, x) = Gamma(a) (1 - P(a, x)),} where \eqn{\Gamma(a)}{Gamma(a)} is the function implemented by \R's \code{\link{gamma}()} and \eqn{P(a, x)}{P(a, x)} is the cumulative distribution function of the gamma distribution (with scale equal to one) implemented by \R's \code{\link{pgamma}()}. Also, \eqn{\Gamma(0, x) = E_1(x)}{G(0, x) = E_1(x)}, \eqn{x > 0}, where \eqn{E_1(x)} is the exponential integral implemented in \code{\link{expint}}. } \value{ The value of the incomplete gamma function. Invalid arguments will result in return value \code{NaN}, with a warning. } \note{ The C implementation is based on code from the GNU Software Library \url{https://www.gnu.org/software/gsl/}. } \references{ Abramowitz, M. and Stegun, I. A. (1972), \emph{Handbook of Mathematical Functions}, Dover. } \seealso{ \code{\link{expint}} } \author{ Vincent Goulet \email{vincent.goulet@act.ulaval.ca} } \examples{ ## a > 0 x <- c(0.2, 2.5, 5, 8, 10) a <- 1.2 gammainc(a, x) gamma(a) * pgamma(x, a, 1, lower = FALSE) # same ## a = 0 a <- 0 gammainc(a, x) expint(x) # same ## a < 0 a <- c(-0.25, -1.2, -2) sapply(a, gammainc, x = x) } \keyword{math} expint/DESCRIPTION0000644000176200001440000000427315136053334013300 0ustar liggesusersPackage: expint Type: Package Title: Exponential Integral and Incomplete Gamma Function Version: 0.2-1 Date: 2026-01-26 Authors@R: c(person("Vincent", "Goulet", role = c("cre", "aut"), email = "vincent.goulet@act.ulaval.ca"), person("Gerard", "Jungman", role = "aut", email = "jungman@lanl.gov", comment = "Original GSL code"), person("Brian", "Gough", role = "aut", email = "jungman@lanl.gov", comment = "Original GSL code"), person("Jeffrey A.", "Ryan", role = "aut", email = "jeff.a.ryan@gmail.com", comment = "Package API"), person("Robert", "Gentleman", role = "aut", comment = "Parts of the R to C interface"), person("Ross", "Ihaka", role = "aut", comment = "Parts of the R to C interface"), person(given = "R Core Team", role = "aut", comment = "Parts of the R to C interface"), person(given = "R Foundation", role = "aut", comment = "Parts of the R to C interface")) Description: The exponential integrals E_1(x), E_2(x), E_n(x) and Ei(x), and the incomplete gamma function G(a, x) defined for negative values of its first argument. The package also gives easy access to the underlying C routines through an API; see the package vignette for details. A test package included in sub-directory example_API provides an implementation. C routines derived from the GNU Scientific Library . Depends: R (>= 3.3.0) Suggests: gsl, pracma License: GPL (>= 2) URL: https://gitlab.com/vigou3/expint BugReports: https://gitlab.com/vigou3/expint/-/issues Encoding: UTF-8 NeedsCompilation: yes Packaged: 2026-01-26 19:47:11 UTC; vincent Author: Vincent Goulet [cre, aut], Gerard Jungman [aut] (Original GSL code), Brian Gough [aut] (Original GSL code), Jeffrey A. Ryan [aut] (Package API), Robert Gentleman [aut] (Parts of the R to C interface), Ross Ihaka [aut] (Parts of the R to C interface), R Core Team [aut] (Parts of the R to C interface), R Foundation [aut] (Parts of the R to C interface) Maintainer: Vincent Goulet Repository: CRAN Date/Publication: 2026-01-27 06:10:36 UTC