R & Fortran call - r

I don't have experience with Fortran, but I am trying to run a very simple loop in that language by calling it from R via the .Fortran() function. Whenever I run the last line of the R code that is pasted below, the R gui crashes and I get no result. I am interest in bringing back the vector of real values x from Fortran into R for further analysis. g is a numeric value between 0 and 1, and n an integer, and they are both supplied by the user in R.
Any help would be much appreciated! Best,
Vincent
Fortran code saved in bar.f:
subroutine bar(n, g, x)
integer n
double precision g
double precision x(n)
integer i
x(1)=1
do 100 i = 2, n
x(i) = x(i-1) * g + 1
100 continue
end
Compiling the DLL in Cygwin with gfortran:
gfortran -shared -obar.dll bar.f
R code:
dyn.load("d:/bar.dll")
is.loaded("bar")
.Fortran("bar", n=as.integer(15), g=as.double(5), x=as.double(rnorm(5)))

When I compile your code, I can execute the call to .Fortran once. When I run it a second time, it crashes. However, I noticed that if I make the vector passed for x the same length as the integer passed for n suggests it should be, i.e:
.Fortran('bar', n = as.integer(15), g = as.double (5), x = as.double(rnorm(15)) )
I can run the function as many times as I want. So the problem may be that you are telling the Fortran routine it has a vector of length 15 to work with, but are only sending in a vector of length 5. This could be causing the Fortran routine to access memory it is not supposed to which would explain a crash.
Since it looks like you are generating all values of x in the routine anyway, you could skip generating random numbers and just send in an empty vector using R's double(n) function, where n is the length of the empty vector you want to generate:
.Fortran('bar', n = as.integer(15), g = as.double(5), x = double(15))
integer and character are useful functions that return vectors like double.
Also some friendly suggestions concerning Fortran style since you mention you are just getting started with the language:
It might be wise to name your files with a .f90 extension---files ending in .f are assumed by most compilers to adhere to the old "fixed-form" format which is a PITA as it was designed to be used on punch cards.
The Do 100 ... 100 continue statements are an style of ending loops in Fortran 77. The modern equivalent is Do .. end do.
With Fortran functions and subroutines, it is wise to declare the "intent" of variables passing in and out of the routine. The available intent declarations are:
intent(in): Signifies variables that are entering the routine only as inputs. Once inside the routine, they should be treated as parameters and the compiler will raise an error if any attempt is made to change them.
intent(out): Signifies variables whose values should be generated inside the routine as outputs. The compiler will issue a warning if an intent out variable is not assigned within the routine.
intent(inout): Signifies variables that may enter the routine carrying a certain set of values and leave the routine with different values.
Setting intents on variables will help the compiler generate warnings and errors that may save you some bug hunting.
Fortran has a default behavior where any variable not declared in the header of the routine will be an integer if its name starts with i-n and real otherwise. This can cause misspelled variable names to "magically" become variables without the compiler batting an eye or telling you. Setting implicit none at the top of your routines disables this behavior and allows the compiler to notify you of mistakes that can be very hard to track down otherwise.
A version of your subroutine that takes these suggestions into account would look like the following:
subroutine bar(n, g, x)
implicit none
integer, intent(in):: n
double precision, intent(in):: g
double precision, intent(inout):: x(n)
integer:: i
x(1) = 1
do i = 2, n
x(i) = x(i - 1) * g + 1
end do
end subroutine bar
Also, it is useful to let R compile your libraries using the SHLIB subcommand of R CMD:
R CMD SHLIB -o bar.dll bar.f90
This will compile your programs against the R libraries which contain useful functions---such as BLAS routines, stats routines and methods that can print information to the R console. See Writing R Extensions, Section 6 for more info.
Hope this helps!

Related

Fortran epsilon function equivalent in Julia

I'm starting to learn Julia, and I was wondering if there is an equivalent function in Julia that is doing the same as the epsilon function in Fortran.
In Fortran, the epsilon function of variable x gives the smallest number of the same kind of x that satisfies 1+epsilon(x)>1
I thought the the function eps() in Julia would be something similar, so I tried
eps(typeof(x))
but I got the error:
MethodError: no method matching eps(::Type{Int64})
Is there any other function that resembles the Fortran one that can be used on the different variables of the code?
If you really need eps to work for both Float and Int types, you can overload a method of eps for Int by writing Base.eps(Int) = one(Int). Then your code will work. This is okay for personal projects, but not a good idea for code you intend to share.
As the docstring for eps says:
help?> eps
eps(::Type{T}) where T<:AbstractFloat
eps()
eps is only defined for subtypes of AbstractFloat i.e. floating point numbers. It seems that your variable x is an integer variable, as the error message says no method matching eps(::Type{Int64}). It doesn't really make sense to define an eps for integers since the "the smallest number of the same kind of x that satisfies 1 + epsilon(x) > 1" is always going to be 1 for integers.
If you did want to get a 1 of the specific type of integer you have, you can use the one function instead:
julia> x = UInt8(42)
0x2a
julia> one(typeof(x))
0x01
It seems like what you actually want is
eps(x)
not
eps(typeof(x))
The former is exactly equivalent to your Fortran function.

Sparse Matrix Multiplication Sparsekit Fortran in R

I'm trying to write a subroutine for matrix sparse matrix multiplication in R using Sparsekit. It is a simple Fortran subroutine that calls two subroutines in the Sparsekit
subroutine mprod(nrowa,ncola,ncolb,job,ra,fa,ca,rb,fb,cb,rc,fc, cc, nnzc, iwi,err)
call amubdg(nrowa,ncola,ncolb,fa,ca,fb,cb,ndegr,nnzc,iwi)
call amub (nrowa,ncolb,job,ra,fa,ca,rb,fb,cb, rc,fc, cc, nnzc,iwi,err)
return
end
The subroutine amubdg gets the number of nonzero elements in each row of the product, i.e., it returns nnzc that I need to specify in amub to compute the product. Here comes my question, in R after compiling with no problem the function in the package I'm working on.
z <- .Fortran("mprod",
nrowa=as.integer(nrowa),
ncola=as.integer(ncola),
ncolb=as.integer(ncolb),
job= as.integer(1),
ra=as.double(A.csr#ra),
fa=as.integer(A.csr#ja),
ca=as.integer(A.csr#ia),
rb=as.double(B.csr#ra),
fb=as.integer(B.csr#ja),
cb=as.integer(B.csr#ia),
rc=double(nnzc),
fb=integer(nnzc),
cb=integer(A.csr#ia+1),
ndegr=integer(nrowa),
iwi=integer(ncola),
err=integer(1),
PACKAGE = "naus")
The question is the following then, is there a way to call the subroutine from R without having to specify the size of the arrays that I want out? This is, a priori I don't know what nnzc is going to be, this is calculated by amubdg, but to call it from R I need it to specify it. Any guidance will be greatly appreciated.

How to call LAPACK code (cpbtrf) in Julia

I'm currently trying to translate my existing Python code into Julia, and I need to compute a Cholesky Decomposition of a banded, complex matrix. The correct LAPACK routine is cpbtrf (the one currently called by SciPy), and I'm struggling to get it to work in Julia.
I'm not sure what extra details to give, I'm pretty new to Julia and I'm sure I'm doing something stupid. The LAPACK call returns a 1 in the info variable, indicating that something isn't positive definite, but I know it is (SciPy happily decomposes the same matrix).
BlasInt = Base.LinAlg.BlasInt
chk = Base.LinAlg.chkstride1
function cholesky_banded!(ab::StridedMatrix{Complex128}, uplo::Char, n::Integer, kd::Integer)
chk(ab)
ldab = size(ab,1)
info = Ref{BlasInt}()
ccall((:cpbtrf_,Base.liblapack_name),Void,(Ptr{UInt8},Ptr{BlasInt},Ptr{BlasInt},
Ptr{Complex128},Ptr{BlasInt},Ptr{BlasInt}),&uplo,&n,&kd,ab,&ldab,info)
ab, info[]
end
mat = zeros(Complex128,2,3)
mat[1,1:end] = 2
mat[2,1:end-1] = -1
cholesky_banded!(mat,'L',3,1)
edit: Just to clarify, this is a skeleton example. The code I'm writing deals with matrices of order 10^5 or bigger, and can need penta-, hexa-, hepta-diagonal matrices and so on. I need a banded-specific algorithm.
It's all correct except for the LAPACK subroutine. You are using 128 bit complex numbers so you should use :zpbtrf_ instead of :cpbtrf_.

Fortran 90 difference between compaq visual fortran and gfortran

This may be a specific question, but I think it pertains to how memory is handled with these two compilers (Compaq visual Fortran Optimizing Compiler Version 6.5 and minGW). I am trying to get an idea of best practices with using pointers in Fortran 90 (which I must use). Here is an example code, which should work "out of the box" with one warning from a gfortran compiler: "POINTER valued function appears on RHS of assignment", and no warnings from the other compiler.
module vectorField_mod
implicit none
type vecField1D
private
real(8),dimension(:),pointer :: x
logical :: TFx = .false.
end type
contains
subroutine setX(this,x)
implicit none
type(vecField1D),intent(inout) :: this
real(8),dimension(:),target :: x
logical,save :: first_entry = .true.
if (first_entry) nullify(this%x); first_entry = .false.
if (associated(this%x)) deallocate(this%x)
allocate(this%x(size(x)))
this%x = x
this%TFx = .true.
end subroutine
function getX(this) result(res)
implicit none
real(8),dimension(:),pointer :: res
type(vecField1D),intent(in) :: this
logical,save :: first_entry = .true.
if (first_entry) nullify(res); first_entry = .false.
if (associated(res)) deallocate(res)
allocate(res(size(this%x)))
if (this%TFx) then
res = this%x
endif
end function
end module
program test
use vectorField_mod
implicit none
integer,parameter :: Nx = 15000
integer :: i
real(8),dimension(Nx) :: f
type(vecField1D) :: f1
do i=1,10**4
f = i
call setX(f1,f)
f = getX(f1)
call setX(f1,f)
if (mod(i,5000).eq.1) then
write(*,*) 'i = ',i,f(1)
endif
enddo
end program
This program runs in both compilers. However, changing the loop from 10**4 to 10**5 causes a serious memory problem with gfortran.
Using CTR-ALT-DLT, and opening "performance", the physical memory increases rapidly when running in gfortran, and doesn't seem to move for the compaq compiler. I usually cancel before my computer crashes, so I'm not sure of the behavior after it reaches the maximum.
This doesn't seem to be the appropriate way to use pointers (which I need in derived data types). So my question is: how can I safely use pointers while maintaining the same sort of interface and functionality?
p.s. I know that the main program does not seem to do anything constructive, but the point is that I don't think that the loop should be limited by the memory, but rather it should be a function of run-time.
Any help is greatly appreciated.
This code has a few problems, perhaps caused by misunderstandings around the language. These problems have nothing to do with the specific compiler - the code itself is broken.
Conceptually, note that:
There is one and only one instance of a saved variable in a procedure per program in Fortran 90.
The variable representing the function result always starts off undefined each time a function is called.
If you want a pointer in a calling scope to point at the result of a function with a pointer result, then you must use pointer assignment.
If a pointer is allocated, you need to have a matching deallocate.
There is a latent logic error, in that the saved first_entry variables in the getX and setX procedures are conflated with object specific state in the setX procedure and procedure instance specific state in the getX procedure.
The first time setX is ever called the x pointer component of the particular this object will be nullified due to the if statement (there's an issue of poor style there too - be careful having multiple statements after an if statement - it is only the first one that is subject to the conditional!). If setX is then called again with a different this, first_entry will have been set to false and the this object will not be correctly set-up. I suspect you are supposed to be testing this%TFX instead.
Similarly, the first time getX is called the otherwise undefined function result variable res will be nullified. However, in all subsequent calls the function result will not be nullified (the function result starts off undefined each execution of the function) and will then be erroneously used in an associated test and also perhaps erroneously in a deallocate statement. (It is illegal to call associated (or deallocate for that matter) on a pointer with an undefined association status - noting that an undefined association status is not the same thing as dissociated.)
getX returns a pointer result - one that is created by the pointer being allocated. This pointer is then lost because "normal" assignment is used to access the value that results from evaluating the function. Because this pointer is lost there can't be (and so there isn't...) a matching deallocate statement to reverse the pointer allocation. The program therefore leaks memory. What almost certainly should be happening is that the thing that captures the value of the getX function in the main program (f in this case, but f is used for multiple things, so I'll call it f_ptr...) itself should be a pointer, and it should be pointer assigned - f_ptr => getX(f1). After the value of f_ptr has been used in the subsequent setX call and write statement, it can then be explicitly deallocated.
The potential for accidental use of normal assignment when pointer assignment is intended is one of the reasons that use of functions with pointer results is discouraged. If you need to return a pointer - then use a subroutine.
Fortran 95 simplifies management of pointer components by allowing default initialization of those components to NULL. (Note that you are using default initialization in your type definition - so your code isn't Fortran 90 anyway!)
Fortran 2003 (or Fortran 95 + the allocatable TR - which is a language level supported by most maintained compilers) introduces allocatable function results - which remove many of the potential errors that can otherwise be made using pointer functions.
Fortran 95 + allocatable TR support is so ubiquitous these days and the language improvements and fixes made to that point are so useful that (unless you are operating on some sort of obscure platform) limiting the language level to Fortran 90 is frankly ridiculous.

Passing functions in R as .Fortran arguments

After spending some days already searching for something like this on the internet, I still couldn't manage to find anything describing this problem. Reading through the (otherwise quite recommendable) 'Writing R Extensions' dind't offer a solution as well. Thus, here's my most urgent question:
Is it possible to pass functions (for simplicity's sake, assume a simple R function - in reality, the problem is even uglier) as function/subroutine parameters to Fortran via .Fortran(...) call - and if so, how?
I wrote two simple functions in order to test this, first a Fortran subroutine (tailored to use the function I originally intended to pass, thus the kinda weird dimensions in the interface):
subroutine foo(o, x)
implicit none
interface
subroutine o(t, y, param, f)
double precision, intent(in) :: t
double precision, dimension(58), intent(in) :: y, param
double precision, dimension(22), intent(out) :: f
end subroutine
end interface
double precision, dimension(22), intent(out) :: x
double precision, dimension(58) :: yt, paramt
integer :: i
do i = 1, 58
yt(i) = rand(0)
paramt(i) = rand(1)
end do
call o(dble(4.2), yt, paramt, x)
end subroutine
and a simple R function to pass to the above function:
asdf <- function(a, s, d, f){x <- c(a, s, d, f)}
Calling .Fortran("foo", asdf, vector(mode="numeric", length=22)) yields
Error: invalid mode (closure) to pass to Fortran (arg 1) and passing "asdf" (as a string) results in a segfault, as the argument obviously doesn't fit the expected type (namely, a function).
FYI, I don't expect the code to do anything meaningful (that would be the task of another function), I mainly would like to know, whether passing functions (or function pointers) from R is possible at all or wether I better give up on this approach instantly and look for something that might work.
Thanks in advance,
Dean
You can't pass R objects via .Fortran. You would need to use the .Call or .External interface to pass the R objects to C/C++ code.
You could write a C/C++ wrapper for your R function, which you could then call from your Fortran code (see Calling-C-from-FORTRAN-and-vice-versa in Writing R Extensions).

Resources