R studio crashing when calling a Fortran module


R studio crashing when calling a Fortran module



I am trying to call a module written in Fortran in R studio, but the latter unexpectedly crashes.



I have tried with other Fortran examples (factorial and MC estimation of pi) and these worked well.



The only difference I see between my code that don't work and those examples is that I used a subroutine wrapper for my pure function (calling other pure function) whereas these examples were only relying on subroutines and the fact my function has a vector as input.



Here is the procedure I have followed (or code typed in):


R CMD SHLIB mypath/myfile.f90 #this compiles without problem; code supplied below.


dyn.load('ptoh') #This is just the given name of the wrapper subroutine


.Fortran('ptoh', dimen=as.integer(dimen), p=as.matrix(p), m=as.integer(m), h=integer(1) )



where I arbitrarily set in R: dimen<-3; p<-c(4,6,7); m=3;


dimen<-3; p<-c(4,6,7); m=3;



Do you have any idea of why is it crashing? Is the way of building my wrapper correct? Is it a problem linked to bind(C, name="ptoh_") ?


bind(C, name="ptoh_")



I already thank you very much for your help.



Gilles



I am working on a Mac running HighSierra with latest version of R.
The code in 'myfile.90' is the following :


module hilbert
implicit none

contains
pure function rotate_right(x, d, dimen)
integer, intent(in) :: x, d, dimen
integer :: rotate_right, tmp, mask

mask = 2 ** dimen - 1
rotate_right = shiftr(x, d)
tmp = shiftl(x, dimen - d)
rotate_right = iand(ior(rotate_right, tmp), mask)
end

pure function rotate_left(x, d, dimen)
integer, intent(in) :: x, d, dimen
integer :: rotate_left, tmp, mask

mask = 2 ** dimen - 1
rotate_left = shiftl(x, d)
tmp = shiftr(x, dimen - d)
rotate_left = iand(ior(rotate_left, tmp), mask)
end

pure function gc(i)
integer, intent(in) :: i
integer :: gc

gc = ieor(i, shiftr(i, 1))
end

pure function entry_point(i)
integer, intent(in) :: i
integer :: entry_point

if(i == 0) then
entry_point = 0
else
entry_point = gc(2 * ((i - 1) / 2))
end if
end

pure function exit_point(i, dimen)
integer, intent(in) :: i, dimen
integer :: exit_point, mask

mask = 2 ** dimen - 1
exit_point = ieor(entry_point(mask - i), 2 ** (dimen - 1))
end

pure function inverse_gc(g, dimen)
integer, intent(in) :: g, dimen
integer :: inverse_gc, j

inverse_gc = g
j = 1
do while(j < dimen)
inverse_gc = ieor(inverse_gc, shiftr(g, j))
j = j + 1
end do
end

pure function intercube_g(i) result(g)
integer, intent(in) :: i
integer :: g

g = trailz(ieor(gc(i), gc(i + 1)))
end

pure function intracube_d(i, dimen) result(d)
integer, intent(in) :: i, dimen
integer :: d

if(i == 0) then
d = 0
else if(modulo(i, 2) == 0) then
d = modulo(intercube_g(i - 1), dimen)
else
d = modulo(intercube_g(i), dimen)
end if
end

pure function transform(e, d, b, dimen) result(t)
integer, intent(in) :: e, d, b, dimen
integer :: t

t = rotate_right(ieor(b, e), d + 1, dimen)
end

pure function inverse_transform(e, d, b, dimen) result(t)
integer, intent(in) :: e, d, b, dimen
integer :: t

t = transform(rotate_right(e, d + 1, dimen), dimen - d - 2, b, dimen)
end

pure function ptoh(dimen, p, m) result(h)
integer, intent(in) :: dimen, p(dimen), m
integer :: h, e, d, i, j, l, w

h = 0
e = 0
d = 2
do i = m - 1, 0, -1
l = 0
do j = 1, dimen
l = l + 2 ** (j - 1) * ibits(p(j), i, 1)
end do
l = transform(e, d, l, dimen)
w = inverse_gc(l, dimen)
e = ieor(e, rotate_left(entry_point(w), d + 1, dimen))
d = modulo(d + intracube_d(w, dimen) + 1, dimen)
h = ior(shiftl(h, dimen), w)
end do
end

subroutine ptoh_R_wrapper(dimen, p, m, h) bind(C, name="ptoh_")
integer :: dimen, p(dimen), m, h, ptoh
external ptoh

h = ptoh(dimen, p, m)
end
end





I would open an R session from the console and run above commands. Typically R will give some sort of error message why it is exiting.
– Ralf Stubner
Jun 29 at 11:43





might the EXTERNAL ptoh be the problem as the function is already in the module?
– albert
Jun 29 at 11:45


EXTERNAL ptoh





Unfortunately, removing EXTERNAL did not solve the problem. Thank you very much for your time though.
– Gilles Mordant
Jun 29 at 11:56





Maybe do a nm on the myfile.o to see which symbols are present. Other alternative compile the Fortran part with -g, -Wall and -traceback (when available) to see where it does crash. Maybe add some 'good old' print statements to see where it crashes.
– albert
Jun 29 at 12:23


nm


myfile.o





Does your code work when called from other Fortran unit?
– Rodrigo Rodrigues
Jun 29 at 23:05





1 Answer
1



You exposed your wrapper subroutine with the name "ptoh_" in your module, but you are calling it with 'ptoh' in R Studio. Actually, 'ptoh' is the name of the wrapped (but also exposed) function.


subroutine


"ptoh_"


'ptoh'


'ptoh'


function



So, the error may be coming from passing the argument h=integer(1), once that the function is not expecting this argument.


h=integer(1)



If that is the cause, to fix it you change your calling in R Studio to:


.Fortran('ptoh_', dimen=as.integer(dimen), p=as.matrix(p), m=as.integer(m), h=integer(1))



Edit:



Another thing that may be causing the error is that you are overriding the name ptoh inside your wrapper subroutine.


ptoh


subroutine ptoh_R_wrapper(dimen, p, m, h) bind(C, name="ptoh_")
integer :: dimen, p(dimen), m, h, ptoh
external ptoh

h = ptoh(dimen, p, m)
end



The function ptoh is already accesible inside all the module, including inside the wrapper subroutine (the external ptoh statement should be removed too).


ptoh


external ptoh



Change the declaration to this:


subroutine ptoh_R_wrapper(dimen, p, m, h) bind(C, name="ptoh_")
integer :: dimen, p(dimen), m, h

h = ptoh(dimen, p, m)
end



And check if the error persists, please.



As a last note, as you are making the subroutine interoperable with C, consider using kind parameters from the intrinsic module iso_c_binding in your interoperable arguments (and maybe the value attribute if applicable).


iso_c_binding


value



I don't know enough of R to be sure that it is necessary, but it doesn't hurt. The final code would look like this:


subroutine ptoh_R_wrapper(dimen, p, m, h) bind(C, name="ptoh_")
use, intrinsic :: iso_c_binding, only: c_int
integer(c_int) :: dimen, p(dimen), m, h

h = ptoh(dimen, p, m)
end





This shouldn't be it, the .Fortran should handle the name mangling itself. But not the module name mangling. See, for example, stackoverflow.com/questions/31631239/…
– Vladimir F
Jun 30 at 6:32


.Fortran





Yeah, I don't know R enough to be sure that is the problem. But the external and the overriding should certainly be issues from the Fortran side of the history. I edited the answer to include that.
– Rodrigo Rodrigues
Jun 30 at 7:27






Yes, I think that is it, not to remove just external, but also integer ptoh. The value would likely just spoil it. We have some questions with the same problem, but without R. I think, that also just moving the wrapper ou of the module and using the module in it would fix it as well.
– Vladimir F
Jun 30 at 7:49



integer ptoh


value





Thank you so much for your help. I confess that I have very limited experience in Fortran. I will try your suggestions out. Have a good day.
– Gilles Mordant
2 days ago





So, could you test it? Did it work?
– Rodrigo Rodrigues
yesterday






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

.

Delphi Android file open failure with API 26

How to generate build files in next js