Calling the NAG Routines from R Under WindowsIndexGeneral Notes on Calling Fortran Routines from RNotes on Calling the NAG routines from R Example 1: Description, Fortran Wrapper, R Code Example 2: Description, Fortran Wrapper, R Code Example 3: Description, Fortran Wrapper, R Code Compaq Visual Fortran Compiler General Notes on Calling Fortran Routines from R
Notes on Calling the NAG routines from R
Example 1 Description In this example the NAG routine S13AAF is used to obtain the value of an exponential integral. The data given in the R code corresponds to the example given in section 9 of the NAG documentation for this routine. Fortran Wrapper
C Sample wrapper for a function (S13AAF)
SUBROUTINE rS13AAF(X, Z, IFAIL)
C X and IFAIL are the parameters specified in the documentation
C for NAG routine S13AAF. Z is a new output parameter that will
C hold the results of integral.
INTEGER X, IFAIL
DOUBLE PRECISION Z
DOUBLE PRECISION S13AAF
EXTERNAL S13AAF
Z = S13AAF(X, IFAIL)
END
R Code
## Load the dynamic library
dyn.load("C:/users/Martyn/SampleRoutineCalls.dll")
## Call the routine (S13AAF - Example)
.Fortran("rS13AAF",
x=as.double(2),
z=as.double(0),
ifail=as.integer(-1))
Example 2 Description In this example the NAG routine C02AGF is used to find all the roots of a real polynomial using a variant of Laguerre's Method. The data given in the R code corresponds to the example given in section 9.1 of the NAG documentation for this routine. Fortran Wrapper
C Sample wrapper for a routine that expects logical input
C C02AGF)
SUBROUTINE rC02AGF(A, N, ISCALE, Z, W, IFAIL)
C A, N, Z, W and IFAIL are the parameters specified in the
C documentation for NAG routine C02AGF. ISCALE is an integer
C representation of SCALE
INTEGER ISCALE, N, IFAIL
DOUBLE PRECISION A(N+1), Z(2,N), W(2*(N+1))
LOGICAL SCALE
EXTERNAL C02AGF
IF (ISCALE.EQ.0) THEN
SCALE = .FALSE.
ELSE
SCALE = .TRUE.
END IF
CALL C02AGF(A, N, SCALE, Z, W, IFAIL)
END
R Code
rC02AGF <- function(a, scale=T, format=T) {
## Wrapper for Fortran function rC02AGF (which in turn is a Fortran
## wrapper for NAG routine C02AGF)
## a - Corresponds to NAG parameter A
## scale - Corresponds to NAG parameter SCALE
## format - Logical indicating whether the roots are formatted for
## output.
n <- length(a) - 1
ans <- .Fortran("rC02AGF",
a=as.double(a),
n=as.integer(n),
iscale=as.integer(scale),
z=matrix(as.double(0), 2, n),
w=numeric(20*(n+1)),
ifail=as.integer(-1))
if (format) {
## Format the results, if required
ff <- apply(ans$z, 1, function(a) {
ans <- c(paste("z = ", a[1]), T)
if (a[2] != 0)
ans <- c(paste(ans[1], " + / - ", abs(a[2]), "*i"),
(a[2] < 0))
return(ans)
})
return(ff[1,][as.logical(ff[2,])])
}
else
return(ans$z)
}
## Calling the function
rC02AGF(1:6)
Example 3 Description In this example the NAG routine G01NAF is used to compute the cumulants and moments of quadratic forms in Normal variates. The data given in the R code corresponds to the example given in section 9 of the NAG documentation for this routine. Fortran Wrapper
SUBROUTINE rG01NAF(IMOM, IMEAN, N, A, LDA, EMU, SIGMA, LDSIG,
+ L, RKUM, RMOM, WK, IFAIL)
C All variables, with the exception of IMOM and IMEAN are the
C same as specified in the documentation for NAG routine G01NAF.
C IMOM and IMEAN are numeric representations of MOM and MEAN
INTEGER N, LDA, LDSIG, L, IFAIL, IMOM, IMEAN
DOUBLE PRECISION A(LDA,N), EMU(*), SIGMA(LDSIG,N)
DOUBLE PRECISION RKUM(L), RMOM(*), WK(3*N*(N+1)/2+N)
CHARACTER*1 MOM, MEAN
EXTERNAL G01NAF
IF (IMOM.EQ.1) THEN
MOM = 'C'
ELSE
MOM = 'M'
END IF
IF (IMEAN.EQ.1) THEN
MEAN = 'Z'
ELSE
MEAN = 'M'
ENDIF
CALL G01NAF(MOM, MEAN, N, A, LDA, EMU, SIGMA, LDSIG, L,
+ RKUM, RMOM, WK, IFAIL)
END
R Code
rG01NAF <- function(mom='C', mean='Z', a, emu, sigma, l, ifail=-1) {
## Wrapper for fortran routine rG01NAF (which in turn is a fortran
## wrapper for NAG routine G01NAF)
## mom - Corresponds to NAG parameter MOM
## mean - Corresponds to MAG parameter MEAN
## a - Corresponds to NAG parameter A
## emu - Corresponds to NAG parameter EMU
## sigma - Corresponds to NAG parameter SIGMA
## l - Corresponds to NAG parameter L
## ifail - Corresponds to NAG parameter IFAIL
n <- ncol(a)
## Call the fortran routine
ans <- .Fortran("rG01NAF",
imom=as.integer(ifelse(mom=='C', 1, 2)),
imean=as.integer(ifelse(mean=='Z', 1, 2)),
n=as.integer(n),
a=matrix(as.double(a), ncol=ncol(a)),
lda=as.integer(nrow(a)),
emu=as.double(emu),
sigma=matrix(as.double(sigma), ncol=ncol(sigma)),
ldsig=as.integer(nrow(sigma)),
l=as.integer(l),
rkum=numeric(l),
rmom=numeric(l),
wk=numeric(3*n*(n+1)/2+n),
ifail=as.integer(ifail))
## Only really interested in the cumulants and moments
aa <- cbind(ans$rkum, ans$rmom)
colnames(aa) <- c("Cumulants", "Moments")
return(aa)
}
## Generate the data
beta <- 0.8
con <- 1
n <- 10
l <- 4
a <- matrix(0, n, n)
a[matrix(c(2:n, 1:(n-1)), ncol=2)] <- 0.5
emu <- numeric(n)
emu[1] <- con*beta
sigma <- matrix(0, n, n)
sigma[1,1] <- 1
for (i in 1:n) {
if (i != 1) {
emu[i] <- beta * emu[i-1]
sigma[i, i] <- beta * beta * sigma[i-1, i-1] + 1
}
if (i != n) {
for (j in (i+1):n)
sigma[j, i] = beta*sigma[j-1, i]
}
}
## Call the function and output the results
print(paste("N =", ans$n, "BETA =", beta, "CON =", con))
print(rG01NAF('M', 'M', a, emu, sigma, l))
Compaq Visual Fortran Compiler When creating a DLL to load into R using the Compaq Visual Fortran Compiler, the following DEC attributes need to be set:
SUBROUTINE TEST(A)
C The two DEC lines are compiler specific and used to create a C
DLL with the correct calling convention.
!DEC$ ATTRIBUTES DLLEXPORT :: TEST
!DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'TEST_' :: TEST
INTEGER A
END
Attributes C and REFERENCE ensure that the DLL is using the correct calling convention. The ALIAS statement adds an underscore to the subroutine name before exporting it as the R function .Fortan() assumes that an underscore is present. More details on this particular compiler can be found via http://h18009.www1.hp.com/fortran/docs/, details on other compilers can be found at http://www.stats.uwo.ca/faculty/murdoch/software/compilingDLLs |
© Numerical Algorithms Group
Visit NAG on the web at:
www.nag.co.uk (Europe and ROW)
www.nag.com (North America)
www.nag-j.co.jp (Japan)
http://www.nag.com/numeric/RunderWindows.asp