Passing characters/strings from R to Fortran - r

I have a Fortran subroutine that selects a function based on the value of a string and then executes that function.
!! file:select.f90
module funcs
contains
subroutine add(x, y, xy)
real :: x, y, xy
xy = x + y
return
end subroutine
subroutine diff(x, y, xy)
real :: x, y, xy
xy = x - y
return
end subroutine
end module
subroutine simple(modname)
use funcs
procedure(), pointer :: model => null()
character(10) :: modname
real :: x, y, xy
print *, "-",modname,"-"
select case (modname)
case("add")
model => add
case("diff")
model => diff
case default
print *, "No model with that name!"
stop
end select
x = 4
y = 3
call model(x, y, xy)
print *, xy
end subroutine
I would like to call this subroutine from an R script.
# file:select.R
dyn.load("select.so")
.Fortran("simple", "add")
.Fortran("simple", "diff")
As a standalone Fortran program that takes a command line argument, this runs perfectly fine. It's even insensitive to spaces before or after modname. However, when I try to pass in a character as an argument from R, it correctly re-prints the character (without any extra spaces), but then doesn't recognize it as a case and skips to the default. What is going on here? Is there some encoding issue with R characters that makes them incompatible with Fortran?

I believe your select case statement is not properly matching because the modname is 10 characters long, and none of your cases cover a string of that length. The best thing to do is to also pass in the length of the string to your Fortran function, then use this to slice your character array.
subroutine simple(modname,length)
then select case (modname(1:length))
Fortran strings are not zero terminated like the C language. It's an array based language.
Also when passing a string from R to .Fortran, it might be better to pass it as raw bytes. Simple example below. First is the Fortran code, then the R wrapper code.
subroutine print_this ( str, length )
integer :: length
character(length) :: str
print *, str(1:length)
end subroutine print_this
test <- function(str) {
l <- nchar(str)
str_raw <- character(l)
str_raw <- charToRaw(str)
.Fortran("print_this",str_raw,l)
l #returns length
}

Related

Problem calling BLAS from julia directly (could not find function :zgemm_64_ in library libopenblas64_)

I'm trying to call BLAS in Julia using ccall like this
ccall((BLAS.#blasfunc(:zgemm_), BLAS.libblas),...other arguments)
For as far as I can tell, this is the same way the LinearAlgebra package calls BLAS (link to source)
I get the following error however:
ccall: could not find function :zgemm_64_ in library libopenblas64_
Anyone have any idea what could be the problem?
EDIT: found out that using :zgemm_64_ directly instead of BLAS.#blasfunc(:zgemm_) solved the error, but I'd still like to know why.
In case it becomes necessary, here is the full function where I make the BLAS call.
import LinearAlgebra: norm, lmul!, rmul!, BlasInt, BLAS
# Preallocated version of A = A*B
function rmul!(
A::AbstractMatrix{T},
B::AbstractMatrix{T},
workspace::AbstractVector{T}
) where {T<:Number}
m,n,lw = size(A,1), size(B,2), length(workspace)
if(size(A,2) !== size(B,1))
throw(DimensionMismatch("dimensions of A and B don't match"))
end
if(size(B,1) !== n)
throw(DimensionMismatch("A must be square"))
end
if(lw < m*n)
throw(DimensionMismatch("provided workspace is too small"))
end
# Multiplication via direct blas call
ccall((BLAS.#blasfunc(:zgemm_), BLAS.libblas), Cvoid,
(Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt},
Ref{BlasInt}, Ref{T}, Ptr{T}, Ref{BlasInt},
Ptr{T}, Ref{BlasInt}, Ref{T}, Ptr{T},
Ref{BlasInt}),
'N', 'N', m, n,n, 1.0, A, max(1,stride(A,2)),B, max(1,stride(B,2)), 0.0, workspace, n)
# Copy temp to A
for j=1:n
for i=1:m
A[i,j] = workspace[j+*(i-1)*n]
end
end
end
function test_rmul(m::Integer, n::Integer)
BLAS.set_num_threads(1)
A = rand(ComplexF64, m,n)
Q = rand(ComplexF64, n,n)
workspace = similar(A, m*n)
A_original = copy(A)
Q_original = copy(Q)
rmul!(A,Q,workspace)
#show norm(A_original*Q_original - A)
#show norm(Q_original - Q)
end
test_rmul(100,50)
BLAS.#blasfunc(:zgemm_) returns Symbol(":zgemm_64_"), and not :zgemm_64_, which looks rather strange in the first place... it's hygienic in the technical sense, but admittedly confusing. The reason it works in the original implementation is because there, the symbol with the name is always spliced into #eval; compare:
julia> #eval begin
BLAS.#blasfunc(:zgemm_)
end
Symbol(":zgemm_64_")
julia> #eval begin
BLAS.#blasfunc($(:zgemm_))
end
:zgemm_64_
So, #blasfunc expects its argument to be a name (i.e., a symbol in the AST), not a symbol literal (a quoted symbol in the AST). You could equivalently write it like a variable name:
julia> #eval begin
BLAS.#blasfunc zgemm_
end
:zgemm_64_
(without zgemm_ being actually defined in this scope!)

Fortran pointer to parameter array target

I have a few parameter arrays with different names in a module:
real*8, parameter :: para1(*) = [43.234, 34.0498, ...
real*8, parameter :: para2...
In a routine in this module
subroutine sub(n,...
...
end
I want to use para1 when n=1, para2 when n=2, etc. There are some solutions to that, one is to make an array paras=[para1,para2...] and index properly which works fine. But I want to try using a pointer
real*8, pointer :: ptr(:)
and assign it to different parameter arrays depending on n, but the problem is that "PARAMETER attribute conflicts with TARGET attribute at (1)". If I remove the parameter attribute, the routine is less safe and the SAVE attribute is assumed.
Am I missing something or why can we not combine parameter and target? And is there a good way around it for this purpose?
The parameter and target attributes indeed conflict. An object with the target attribute must be a variable (Fortran 2018 8.5.17, C861); a named constant (object with the parameter attribute) is not a variable (F2018, 8.5.13, C850).
To use target arrays you must, then, use variables. It is tricky to have a variable which is "safe" from having its value modified by a programming mistake or such. There are several considerations which prohibit a variable from appearing in a variable definition context. If you can arrange such a state, then the compiler may have a chance of detecting your mistake. Can that happen easily?
Outside a pure procedure and an intent(in) dummy argument, the most tempting prohibition is with a protected module variable:
module pars
real, save, target, protected :: para1(74) = [...]
real, save, target, protected :: para2(1) = [6]
end module
subroutine sub (...)
use pars
real, pointer :: p
p => para1
end subroutine sub
Being protected, the values are safe from modification outside the module pars? Alas, even if this were true it isn't helpful: being protected, we can't even point a pointer to module variables.
In summary, your compiler isn't going to find it easy to detect a programming mistake which modifies the variable target array, so if you want to use an array as a target, you'll have to be careful.
Following the suggestion by #ja72 in the comment, this is an attempt to use a single 2D array for the parameters. This works nicely with gfortran-8.2 (on MacOS10.11).
program main
implicit none
integer i
integer, parameter :: para1(*) = [1, 2, 3, 4, 5]
integer, parameter :: para2(*) = [6, 7]
integer, parameter :: N1 = size(para1), N2 = size(para2), N = max(N1, N2)
integer, parameter :: params(N, 2) = &
reshape( [ para1, (0, i = 1, N - N1), &
para2, (0, i = 1, N - N2) ], [N, 2] )
print *, "para1 = ", params( :, 1 )
print *, "para2 = ", params( :, 2 )
print *, "Input i"
read *, i
print *, params( :, i )
end
$ gfortran-8 test.f90 && ./a.out
para1 = 1 2 3 4 5
para2 = 6 7 0 0 0
Input i
1
1 2 3 4 5
However, because the code becomes a bit complicated (because of reshape) and may not work with old compilers, things may be more straightforward to just use non-parameter arrays...

Evaluate expression with local variables

I'm writing a genetic program in order to test the fitness of randomly generated expressions. Shown here is the function to generate the expression as well a the main function. DIV and GT are defined elsewhere in the code:
function create_single_full_tree(depth, fs, ts)
"""
Creates a single AST with full depth
Inputs
depth Current depth of tree. Initially called from main() with max depth
fs Function Set - Array of allowed functions
ts Terminal Set - Array of allowed terminal values
Output
Full AST of typeof()==Expr
"""
# If we are at the bottom
if depth == 1
# End of tree, return function with two terminal nodes
return Expr(:call, fs[rand(1:length(fs))], ts[rand(1:length(ts))], ts[rand(1:length(ts))])
else
# Not end of expression, recurively go back through and create functions for each new node
return Expr(:call, fs[rand(1:length(fs))], create_single_full_tree(depth-1, fs, ts), create_single_full_tree(depth-1, fs, ts))
end
end
function main()
"""
Main function
"""
# Define functional and terminal sets
fs = [:+, :-, :DIV, :GT]
ts = [:x, :v, -1]
# Create the tree
ast = create_single_full_tree(4, fs, ts)
#println(typeof(ast))
#println(ast)
#println(dump(ast))
x = 1
v = 1
eval(ast) # Error out unless x and v are globals
end
main()
I am generating a random expression based on certain allowed functions and variables. As seen in the code, the expression can only have symbols x and v, as well as the value -1. I will need to test the expression with a variety of x and v values; here I am just using x=1 and v=1 to test the code.
The expression is being returned correctly, however, eval() can only be used with global variables, so it will error out when run unless I declare x and v to be global (ERROR: LoadError: UndefVarError: x not defined). I would like to avoid globals if possible. Is there a better way to generate and evaluate these generated expressions with locally defined variables?
Here is an example for generating an (anonymous) function. The result of eval can be called as a function and your variable can be passed as parameters:
myfun = eval(Expr(:->,:x, Expr(:block, Expr(:call,:*,3,:x) )))
myfun(14)
# returns 42
The dump function is very useful to inspect the expression that the parsers has created. For two input arguments you would use a tuple for example as args[1]:
julia> dump(parse("(x,y) -> 3x + y"))
Expr
head: Symbol ->
args: Array{Any}((2,))
1: Expr
head: Symbol tuple
args: Array{Any}((2,))
1: Symbol x
2: Symbol y
typ: Any
2: Expr
[...]
Does this help?
In the Metaprogramming part of the Julia documentation, there is a sentence under the eval() and effects section which says
Every module has its own eval() function that evaluates expressions in its global scope.
Similarly, the REPL help ?eval will give you, on Julia 0.6.2, the following help:
Evaluate an expression in the given module and return the result. Every Module (except those defined with baremodule) has its own 1-argument definition of eval, which evaluates expressions in that module.
I assume, you are working in the Main module in your example. That's why you need to have the globals defined there. For your problem, you can use macros and interpolate the values of x and y directly inside the macro.
A minimal working example would be:
macro eval_line(a, b, x)
isa(a, Real) || (warn("$a is not a real number."); return :(throw(DomainError())))
isa(b, Real) || (warn("$b is not a real number."); return :(throw(DomainError())))
return :($a * $x + $b) # interpolate the variables
end
Here, #eval_line macro does the following:
Main> #macroexpand #eval_line(5, 6, 2)
:(5 * 2 + 6)
As you can see, the values of macro's arguments are interpolated inside the macro and the expression is given to the user accordingly. When the user does not behave,
Main> #macroexpand #eval_line([1,2,3], 7, 8)
WARNING: [1, 2, 3] is not a real number.
:((Main.throw)((Main.DomainError)()))
a user-friendly warning message is provided to the user at parse-time, and a DomainError is thrown at run-time.
Of course, you can do these things within your functions, again by interpolating the variables --- you do not need to use macros. However, what you would like to achieve in the end is to combine eval with the output of a function that returns Expr. This is what the macro functionality is for. Finally, you would simply call your macros with an # sign preceding the macro name:
Main> #eval_line(5, 6, 2)
16
Main> #eval_line([1,2,3], 7, 8)
WARNING: [1, 2, 3] is not a real number.
ERROR: DomainError:
Stacktrace:
[1] eval(::Module, ::Any) at ./boot.jl:235
EDIT 1. You can take this one step further, and create functions accordingly:
macro define_lines(linedefs)
for (name, a, b) in eval(linedefs)
ex = quote
function $(Symbol(name))(x) # interpolate name
return $a * x + $b # interpolate a and b here
end
end
eval(ex) # evaluate the function definition expression in the module
end
end
Then, you can call this macro to create different line definitions in the form of functions to be called later on:
#define_lines([
("identity_line", 1, 0);
("null_line", 0, 0);
("unit_shift", 0, 1)
])
identity_line(5) # returns 5
null_line(5) # returns 0
unit_shift(5) # returns 1
EDIT 2. You can, I guess, achieve what you would like to achieve by using a macro similar to that below:
macro random_oper(depth, fs, ts)
operations = eval(fs)
oper = operations[rand(1:length(operations))]
terminals = eval(ts)
ts = terminals[rand(1:length(terminals), 2)]
ex = :($oper($ts...))
for d in 2:depth
oper = operations[rand(1:length(operations))]
t = terminals[rand(1:length(terminals))]
ex = :($oper($ex, $t))
end
return ex
end
which will give the following, for instance:
Main> #macroexpand #random_oper(1, [+, -, /], [1,2,3])
:((-)([3, 3]...))
Main> #macroexpand #random_oper(2, [+, -, /], [1,2,3])
:((+)((-)([2, 3]...), 3))
Thanks Arda for the thorough response! This helped, but part of me thinks there may be a better way to do this as it seems too roundabout. Since I am writing a genetic program, I will need to create 500 of these ASTs, all with random functions and terminals from a set of allowed functions and terminals (fs and ts in the code). I will also need to test each function with 20 different values of x and v.
In order to accomplish this with the information you have given, I have come up with the following macro:
macro create_function(defs)
for name in eval(defs)
ex = quote
function $(Symbol(name))(x,v)
fs = [:+, :-, :DIV, :GT]
ts = [x,v,-1]
return create_single_full_tree(4, fs, ts)
end
end
eval(ex)
end
end
I can then supply a list of 500 random function names in my main() function, such as ["func1, func2, func3,.....". Which I can eval with any x and v values in my main function. This has solved my issue, however, this seems to be a very roundabout way of doing this, and may make it difficult to evolve each AST with each iteration.

Recursive Combination on Fortran

I wrote a recursive program on Fortran to calculate the combinations of npoints of ndim dimensions as follows. I first wrote this program on MATLAB and it was perfectly running. But in Fortran, my problem is that after the first iteration it is assigning absurd values for the list of points, with no explanation. Could somebody give me a hand?
PROGRAM MAIN
IMPLICIT NONE
INTEGER :: ndim, k, npontos, contador,i,iterate, TEST
integer, dimension(:), allocatable :: pontos
print*, ' '
print*, 'npoints?'
read *, npontos
print*, 'ndim?'
read *, ndim
k=1
contador = 1
open(450,file= 'combination.out',form='formatted',status='unknown')
write(450,100) 'Comb ','stat ',(' pt ',i,' ',i=1,ndim)
write(450,120) ('XXXXXXXXXX ',i=1,ndim+1)
allocate(pontos(ndim))
do i=1,4
pontos(i)=i
end do
TEST = iterate(pontos, ndim, npontos,k,contador)
end program MAIN
recursive integer function iterate(pontos, ndim, npontos, k,contador)
implicit NONE
integer, intent(in) :: ndim, k, npontos
integer,dimension(:) :: pontos
integer contador,inic,i,j,m
if (k.eq.ndim) then
inic=pontos(ndim)
do i = pontos(ndim),npontos
pontos(k)= i
write(*,*) pontos(:)
contador=contador+1
end do
pontos(ndim)= inic + 1
else
inic = pontos (k)
do j = pontos(k),(npontos-ndim+k)
pontos(k)=j
pontos= iterate(pontos, ndim, npontos, k+1,contador)
end do
end if
pontos(k)=inic+1;
if (pontos(k).gt.(npontos-ndim+k+1)) then
do m =k+1,ndim
pontos(m)=pontos(m-1)+1
end do
end if
end function iterate
There are too many issues in that code... I stopped debugging it. This is what I got so far, it's too much for a comment.
This doesn't make sense:
pontos= iterate(pontos, ndim, npontos, k+1,contador)
You are changing pontos inside iterate, and never set a return value within the function.
You need to a) provide a result statement for recursive functions (and actually set it) or b) convert it to a subroutine. Since you are modifying at least one dummy argument, you should go with b).
Since you are using assumed-shape dummy arguments, you need to specify an interface to the function/subroutine, either explicitly or with a module.
Neither format 100 nor format 120 are specified in your code.

How to use inteface blocks to pass a function to a subroutine?

I understand the interface command can be used to pass a a function into a subroutine. So for example in the main program I'd define some function and then pass it to some subroutine like:
MainProgran
Use ....
Implicit None
Type decorations etc
Interface
Function test(x,y)
REAL, INTENT(IN) :: x, y
REAL :: test
END function
End Interface
Call Subroutine( limit1, limit2, test, Ans)
End MainProgram
Is this the correct way of doing this? I'm quite stuck! Also within the Subroutine is there anything I need to put to let it know that a function is coming in? The Subroutine in this case will be a library so I don't want to have to keep recompiling it to change the function.
Module:
module fmod
interface
function f_interf(x,y)
real, intent(in) :: x, y
real :: f_interf
end function
end interface
contains
function f_sum(x,y)
real, intent(in) :: x, y
real f_sum
f_sum = x + y
end function
function f_subst(x,y)
real, intent(in) :: x, y
real f_subst
f_subst = x - y
end function
subroutine subr(limit1, limit2, func, ans)
real limit1, limit2
procedure(f_interf) func
real ans
ans = func(limit1, limit2)
end subroutine
end module
main program:
program pass_func
use fmod
Implicit None
real ans, limit1, limit2
limit1 = 1.0
limit2 = 2.0
call subr( limit1, limit2, f_subst, ans)
write(*,*) ans
call subr( limit1, limit2, f_sum, ans)
write(*,*) ans
end program pass_func
and output:
-1.000000
3.000000
A simple way to do this is to go old school and just leave the function external:
program main
real f,z
external f
call subr(f,z)
write(*,*)z
end
real function f(x)
real x
f=x**2
end
! below possibly in a precompiled library:
subroutine subr(f,y)
real f,y
y=f(2.)
end
out: 4
Of course with this approach you can not use advanced language features that require an explicit interface. **
On the other hand if you are interfacing with standard libraries that need function arguments this is I think the only way.
** per MSB's comment you can handle that issue with an interface block in the subroutine,
for example if we want to pass a function that returns an array:
function f(x)
real x,f(2)
f(1)=x
f(2)=x**2
end
as in the first example f is an external function, and the sub can be in
a precompiled library:
subroutine subr(g,y)
interface
function g(x)
real x,g(2)
end function
end interface
real y,z(2)
z=g(2.)
y=z(1)+z(2)
end
out: 6
As noted, this is only strictly necessary if relying on language features that need the interface.
The most elegant way I know of right now is to put your functions into a module so that you don't have to do construct interface but simply use 'external'. Here is a example to do that.
It covers different situations using subroutine or function as arguments for subroutine or function.
Notice if you want to pass array as argument without receiving null arraies, here is a tip to do that.
Module part:
module func_arg_test
!I used ifort to compile but other compilers should also be fine.
!Written by Kee
!Feb 20, 2017
contains
!-------------------------
real function func_func(f, arg)
!========================================
!This shows how to pass number as argument
!========================================
implicit none
real, external::f !Use external to indicate the f is a name of a function
real::arg
func_func=f(arg)
end function func_func
real function func_sub(subr, arg)
!========================================
!This shows how to pass subroutine as arg to function
!========================================
implicit none
external::subr !Use external to indicate subr is a subroutine
real::arg
call sub(arg)
func_sub = arg
end function func_sub
subroutine sub_func(f,arg)
!========================================
!This shows how to pass function as argument
!in subroutine
!========================================
real::arg
real,external::f
arg = f(arg)
end subroutine sub_func
subroutine sub_sub(subr,arg)
!========================================
!This shows how to pass subroutine as argument
!in subroutine
!========================================
real::arg
external::subr
call subr(arg)
end subroutine sub_sub
real function funcmat(f, mat)
!========================================
!This shows how to pass matrix as argument
!========================================
implicit none
real, external::f
real,dimension(:)::mat!Here memory for mat is already allocated when mat is
!passed in, so don't need specific size
integer::sizeinfo
sizeinfo = size(mat)
funcmat = f(mat,sizeinfo)
end function funcmat
!--------------------------
real function f1(arg)
!This test function double the number arg
implicit none
real::arg
f1 = arg*2
return
end function f1
real function f2(arg)
!This test function square the number arg
implicit none
real::arg
f2 = arg*arg
return
end function f2
real function fmat(mat,sizeinfo)
!This test function sum up all elements in the mat
implicit none
integer::sizeinfo!This is the method I come up with to get around the
!restriction.
real,dimension(sizeinfo)::mat!This mat cannot be undetermined, otherwise it
!won't recevie mat correctly. I don't know why yet.
fmat = sum(mat)
end function fmat
subroutine sub(arg)
real::arg
arg = arg*3
end subroutine sub
end module
Main program:
program main
use func_arg_test
implicit none
real::a = 5d0
real::output
real, dimension(:),allocatable::mat
write(*,*) 'value of a=',a
output = func_func(f1,a)
write(*,*) 'a is doubled'
write(*,*) output
output = func_func(f2,a)
write(*,*) 'a is squared'
write(*,*) output
output = func_sub(sub,a)
write(*,*) 'a is tripled and overwritten'
write(*,*) output
call sub_func(f2,a)
write(*,*) 'a is squared and overwritten'
write(*,*) a
call sub_sub(sub,a)
write(*,*) 'a is tripled and overwritten'
write(*,*) a
allocate(mat(3))
mat = (/1d0,10d0,1d0/)!The allocatable arrray has to have a determined shape before
!pass as arguemnt
write(*,*) '1D matrix:',mat
write(*,*) 'Summation of the matrix:'
output = funcmat(fmat,mat)!elements of mat are summed
write(*,*) output
end program
And the result is:
value of a= 5.000000
a is doubled
10.00000
a is squared
25.00000
a is tripled and overwritten
15.00000
a is squared and overwritten
225.0000
a is tripled and overwritten
675.0000
1D matrix: 1.000000 10.00000 1.000000
Summation of the matrix:
12.00000

Resources