Reputation: 4718
I have a sequence of subroutine calls I need to make on various datatype names. For example:
print*, 'Now giving information about Matrix1'
call mysub(Matrix1, size(Matrix1,1), size(Matrix1,2))
print*, 'About to do function on Matrix1'
call dofunction(Matrix1)
print*, 'Matrix1 is a nice matrix! Huzzah!'
print*, 'Now giving information about Matrix2'
call mysub(Matrix2, size(Matrix2,1), size(Matrix2,2))
print*, 'About to do function on Matrix2'
call dofunction(Matrix2)
print*, 'Matrix2 is a nice matrix! Huzzah!'
print*, 'Now giving information about OtherMat'
call mysub(OtherMat, size(OtherMat,1), size(OtherMat,2))
print*, 'About to do function on OtherMat'
call dofunction(OtherMat)
print*, 'OtherMat is a nice matrix! Huzzah!'
and I would like to define a macro that will take a #define
value so that I can wrap this sequence of calls. For example, defining a macro mymacro
, I would like to be able to call simply
mymacro(Matrix1)
mymacro(Matrix2)
mymacro(OtherMat)
to accomplish the same thing. Is this possible?
Upvotes: 2
Views: 2416
Reputation: 4656
What about writing a subroutine like this:
subroutine mymacro(matrix, matrixName)
! declare matrix, precision should be declare somewhere as a constant
real(precision), dimension(:,:) :: matrix
character(*), intent(in) :: matrixname
print*, 'Now giving information about '//matrixname
call mysub(matrix, size(matrix,1), size(matrix,2))
print*, 'About to do function on '//matrixname
call dofunction(matrix)
print*, matrixname//' is a nice matrix! Huzzah!'
end subroutine mymacro
It is not exactly the thing that will get the name of your matrix for you but close enough.
mymacro(matrix)
becomes
call mymacro(matrix,'matrix')
Not very different, don't you think?
Upvotes: 2
Reputation: 858
Macros themselves are not part of Fortran. They are implemented by most (if not all) compilers by just reusing the C preprocessor. I learned from here: https://gcc.gnu.org/onlinedocs/cpp/Macros.html
This might do the trick: (not tested!)
#define MYSUB(m) write(*,*) "Now giving information about ", #m; \
call mysub(m, size(m,1), size(m,2) ); \
write(*,*) "About to do function on ",#m; \
call dofunction(m) ; \
write(*,*) #m , "is a nice matrix! Huzzah!" ;
Note that you will have to use the appropriate compiler flags to have the compiler run the preprocessor.
Upvotes: 0
Reputation: 18118
It took me a while to get this working for gfortran
, since it doesn't support #expr
.
The idea is to use ;
to get multiple commands into one line. Of course, this requires to disable the usual line limit. With gfortran
, this is achieved by -ffree-line-length-0
.
Then, gfortran
's preprocessor uses "x"
instead of #s
(as every other compiler does).
Here is the result: it is working on ifort
and gfortran
:
#ifdef __GFORTRAN__
#define mymacro(x) print *, "Now giving information about ", "x" ; \
call mysub( x, size(x,1), size(x,2) ) ; \
print *, "About to do function on ", "x"; \
call dofunction(x) ; \
print *, "x"," is a nice matrix! Huzzah!"
#else
#define mymacro(x) print *, "Now giving information about ", #x ; \
call mysub( x, size(x,1), size(x,2) ) ; \
print *, "About to do function on ", #x; \
call dofunction(x) ; \
print *, #x," is a nice matrix! Huzzah!"
#endif
program main
implicit none
integer :: i(2,2)
i = 123
mymacro(i)
contains
subroutine mysub(ii, N, M)
integer,intent(in) :: ii(:,:), N, M
print *,'in mysub:', ii(1,1)
end subroutine
subroutine dofunction(ii)
integer,intent(in) :: ii(:,:)
print *,'in dofunction:', ii(1,1)
end subroutine
end program main
Upvotes: 4