Fortran 90 with C/C++ style macro (e.g. # define SUBNAME(x) s ## x) - macros

I am recently working with a F90 code project. I am using gfortran (linux and MinGW) to compile it. There is something interesting in file loct.F90.
# define TYPE real(4)
# define SUBNAME(x) s ## x
# include "loct_inc.F90"
# undef SUBNAME
# undef TYPE
# define TYPE real(8)
# define SUBNAME(x) d ## x
# include "loct_inc.F90"
# undef SUBNAME
# undef TYPE
...
The loct_inc.F90 file looks like this:
subroutine SUBNAME(loct_pointer_copy_1)(o, i)
...
end subroutine SUBNAME(loct_pointer_copy_1)
subroutine SUBNAME(loct_pointer_copy_2)(o, i)
...
end subroutine SUBNAME(loct_pointer_copy_2)
...
I think in the file loct.F90 the author used sets of macros (C/C++ style). Each set is used to define a data type (e.g. real(4), real(8), character, etc). The file loct_inc.F90 provide a set of function which is the same except the type of the variables.
These two files works together as a template of c++ in my opinion.
In the end one should have a set of subroutines:
sloct_pointer_copy_1(o, i)
sloct_pointer_copy_2(o, i)
...
dloct_pointer_copy_1(o, i)
dloct_pointer_copy_2(o, i)
...
But when I tried to compile loct.F90 (gfortran -c loct.F90), I get some errors.
basic/loct_inc.F90:21.13:
Included at basic/loct.F90:256:
subroutine s ## loct_pointer_copy_1(o, i)
1 Error: Syntax error in SUBROUTINE statement at (1)
It seems gfortran replace SUBNAME(loct_pointer_copy_1)(o, i) with s ## loct_pointer_copy_1(o, i). But according to c++ macro, the correct replace should be sloct_pointer_copy_1(o, i).
Could anyone tell me why this happened?

GNU Fortran uses the GNU C Preprocessor in traditional mode, in which mode the macro pasting operator ## is not available. That's why Fortran projects which were written to also compile with the GNU toolchain perform explicit preprocessing in additional Makefile targets, e.g. all *.F90 are first preprocessed with cpp to temporary .f90 files which are then compiled.

Related

Fortran substitute subroutine name using macro

I am writing a module that allows users to log information. I want to provide an interface that logs a string message, which can be called as
call m_log(msg)
So in file m_logger.f90, I will have
module m_logger
..
subroutine m_log(msg)
..
end module
In file main.f90, a user will have
program main
use m_logger
call m_log(msg)
end program
Now how can I substitute call m_log(msg) with call m_log(msg, __FILE__, __LINE__) ?
Because of this substitution, a different subroutine subroutine m_log(msg, filename, linenum) in the logger module will be called instead.
If I use a macro like #define m_log(msg) m_log(msg,__FILE__,__LINE__) , it will have to be added to every user file that uses the logger.
Also, I do not want to enforce the user to pass __FILE__ and __LINE__ explicitly.
Is there a way I can do this? Or are there any other alternatives altogether?
Thanks in advance
Edit:
I had a discussion on comp.lang.fortran. Adding a link for reference.
here
In this case you would have to use the same approach C uses. Define the macro you proposed
#define log(msg) m_log(msg,__FILE__,__LINE__)
in a separate file (possibly with other useful macros) and include it using #include "file.inc" (standard Fortran include won't suffice).
If the macro has a different name, than the subroutine it actually calls, you can ensure that the user has to use the include and cannot forget it.
If you don't want to force __file__ and __line__ explicitly, then you can use the optional flag, such that your subroutine looks like:
subroutine m_log(msg, filename, linenum)
character(len=*) :: msg
character(len=*), optional :: filename
integer, optional :: linenum
if(present(filename)) then
<something with filename>
endif
if(present(linenum)) then
<something with linenume>
endif
<normal stuff with msg>
end subroutine
The intrinsic function present returns a true value if filename or linenum have any values attached to it, returning false otherwise.
Since you want them to be passed as compiler macros by the user, you would first have to choose different names for your macros. __FILE__ and __LINE__ are both predefined macros. These two macros are defined by preprocessor, not passed by the user. I think that might have cause some confusion.
If you would like to allow users to optionally supply the macros through compiler options, it is probably best to include #ifdef directive in your subroutine:
subroutine m_log(msg)
implicit none
character(len=*) :: msg
character(len=something) :: file
integer ::line
!Initialize file and line to some default value
file=...
line=...
#ifdef __KVM_FILE__
file=__KVM_FILE__
#endif
#ifdef __KVM_LINE__
line=__KVM_LINE__
#endif
...
This way the user will always call the subroutine with the same syntax call m_log(something), but the effect will change according to your compilation macros. Of course, that would also require the user to recompile your code every time they change this macro. If this is too costly to do, you can set up a subroutine with optional argument (as in Kyle's answer), then enclose #define macro in #ifdef blocks, and put them into an .h file, and have your user always include that file. (similar to Vladimir's answer)

inline iPython call to system

I really like to use system shell commands in iPython. But I was wondering if it is possible to loop over the returned values from a call to e.g. !ls. This works:
files = !ls ./*_subcell_cooc.txt
for f in files:
print f
But this does not:
for f in ( !ls ./*_subcell_cooc.txt):
print f
Error is:
File "<ipython-input-1-df2bc72907d7>", line 5
for f in ( !ls $ROOT/*_subcell_cooc.txt):
^
SyntaxError: invalid syntax
No it is not possible, the syntax var = !something is special cased in IPython. It is not valid python syntax, and we will not extend for loops and so on to work with it.
You can do assignment as you show in your first example, but using glob,os and other real python module to do that will be more robust, not much harder, and also work outside of IPython...
For the anecdote Guido was really not happy with IPython half-shell syntax when he saw it last time at SciPy2013.
(Also it uppercase I in IPython please.)

How to use command line arguments in Fortran?

GCC version 4.6
The Problem: To find a way to feed in parameters to the executable, say a.out, from the command line - more specifically feed in an array of double precision numbers.
Attempt: Using the READ(*,*) command, which is older in the standard:
Program test.f -
PROGRAM MAIN
REAL(8) :: A,B
READ(*,*) A,B
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
The execution -
$ gfortran test.f
$ ./a.out 3.D0 1.D0
This did not work. On a bit of soul-searching, found that
$./a.out
3.d0,1.d0
4.0000000000000000 0
does work, but the second line is an input prompt, and the objective of getting this done in one-line is not achieved. Also the COMMAND_ARGUMENT_COUNT() shows that the numbers fed into the input prompt don't really count as 'command line arguments', unlike PERL.
If you want to get the arguments fed to your program on the command line, use the (since Fortran 2003) standard intrinsic subroutine GET_COMMAND_ARGUMENT. Something like this might work
PROGRAM MAIN
REAL(8) :: A,B
integer :: num_args, ix
character(len=12), dimension(:), allocatable :: args
num_args = command_argument_count()
allocate(args(num_args)) ! I've omitted checking the return status of the allocation
do ix = 1, num_args
call get_command_argument(ix,args(ix))
! now parse the argument as you wish
end do
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
Note:
The second argument to the subroutine get_command_argument is a character variable which you'll have to parse to turn into a real (or whatever). Note also that I've allowed only 12 characters in each element of the args array, you may want to fiddle around with that.
As you've already figured out read isn't used for reading command line arguments in Fortran programs.
Since you want to read an array of real numbers, you might be better off using the approach you've already figured out, that is reading them from the terminal after the program has started, it's up to you.
The easiest way is to use a library. There is FLAP or f90getopt available. Both are open source and licensed under free licenses.
The latter is written by Mark Gates and me, just one module and can be learned in minutes but contains all what is needed to parse GNU- and POSIX-like command-line options. The first is more sophisticated and can be used even in closed-source projects. Check them out.
Furthermore libraries at https://fortranwiki.org/fortran/show/Command-line+arguments
What READ (*,*) does is that it reads from the standard input. For example, the characters entered using the keyboard.
As the question shows COMMAND_ARGUMENT_COUNT() can be used to get the number of the command line arguments.
The accepted answer by High Performance Mark show how to retrieve the individual command line arguments separated by blanks as individual character strings using GET_COMMAND_ARGUMENT(). One can also get the whole command line using GET_COMMAND(). One then has to somehow parse that character-based information into the data in your program.
I very simple cases you just need the program requires, for example, two numbers, so you read one number from arg 1 and another form arg 2. That is simple. Or you can read a triplet of numbers from a single argument if they are comma-separated like 1,2,3 using a simple read(arg,*) nums(1:3).
For general complicated command line parsing one uses libraries such as those mentioned in the answer by Hani. You have set them up so that the library knows the expected syntax of the command line arguments and the data it should fill with the values.
There is a middle ground, that is still relatively simple, but one already have multiple arguments, that correspond to Fortran variables in the program, that may or may not be present. In that case one can use the namelist for the syntax and for the parsing.
Here is an example, the man point is the namelist /cmd/ name, point, flag:
implicit none
real :: point(3)
logical :: flag
character(256) :: name
character(1024) :: command_line
call read_command_line
call parse_command_line
print *, point
print *, "'",trim(name),"'"
print *, flag
contains
subroutine read_command_line
integer :: exenamelength
integer :: io, io2
command_line = ""
call get_command(command = command_line,status = io)
if (io==0) then
call get_command_argument(0,length = exenamelength,status = io2)
if (io2==0) then
command_line = "&cmd "//adjustl(trim(command_line(exenamelength+1:)))//" /"
else
command_line = "&cmd "//adjustl(trim(command_line))//" /"
end if
else
write(*,*) io,"Error getting command line."
end if
end subroutine
subroutine parse_command_line
character(256) :: msg
namelist /cmd/ name, point, flag
integer :: io
if (len_trim(command_line)>0) then
msg = ''
read(command_line,nml = cmd,iostat = io,iomsg = msg)
if (io/=0) then
error stop "Error parsing the command line or cmd.conf " // msg
end if
end if
end subroutine
end
Usage in bash:
> ./command flag=T name=\"data.txt\" point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
or
> ./command flag=T name='"data.txt"' point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
Escaping the quotes for the string is unfortunately necessary, because bash eats the first quotes.

Error message when trying to create a module in fortran 90

I am trying to create a module for a fortran 90 program. The file is called epath.f90. When I try to create the file epath.mod by running an object-only compile on the file by way of the commad f95 -c epath.f90 it gives me the following error message:
epath.f90:1:
MODULE euler-path
1
Error: Unclassifiable statement at (1)
epath.f90:8.3:
END MODULE euler-path
1
Error: Expecting END PROGRAM statement at (1)
Error: Unexpected end of file in 'epath.f90'
The code for epath.f90 is:
MODULE euler-path
INTEGER, PARAMETER :: NSTEPS=10
REAL, PARAMETER :: A=0.0, B=1.0, YSTART=0.0
REAL, DIMENSION(0:NSTEPS) :: x,y
END MODULE euler-path
I took the same steps for another module and it worked fine. Any help is appreciated.
In Fortran, names - module names, variable names, etc - have to start with a letter and contain only letters, digits, or underscores. (Fortran in particular forbids using special characters like operators, eg, -/+/*/(/) in names because it's historically taken a very cavalier approach to the use of spaces, or for that matter explicitly defined variable names, which would make it very difficult to distinguish between a-b as a name and the expression a - b.) See, eg, section 3.2.2 ("Names") of the recent Fortran standard.
So euler_path is ok, euler_path123 is ok, but euler-path isn't.

Equivalent of Matlab "whos" command for Lua interpreter?

What is the Lua equivalent of the Octave/Matlab/IPython "whos" command? I'm trying to learn Lua interactively and would like to see what variables are currently defined.
All global variables in Lua reside in a table available as global variable _G (yes, _G._G == _G). Therefore if you want to list all global variable, you can iterate over the table using pairs():
function whos()
for k,v in pairs(_G) do
print(k, type(v), v) -- you can also do more sophisticated output here
end
end
Note that this will also give you all the Lua base functions and modules. You can filter them out by checking for a value in a table which you can create on startup when no global variables other than Lua-provided are defined:
-- whos.lua
local base = {}
for k,v in pairs(_G) do
base[k] = true
end
return function()
for k,v in pairs(_G) do
if not base[k] then print(k, type(v), v) end
end
end
Then, you can use this module as follows:
$ lua
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
> whos = require 'whos'
> a = 1
> b = 'hello world!'
> whos()
a number 1
b string hello world!
whos function function: 0x7f986ac11490
Local variables are a bit tougher - you have to use Lua's debug facilities - but given that you want to use it interactively, you should only need globals.