2015-07-20 2 views
1

У меня есть последовательность вызовов подпрограмм, которые мне нужно сделать для разных имен типов данных. Например:Функция макроса фортрана для литеральной строки?

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!' 

, и я хотел бы определить макрос, который будет принимать значение #define, так что я могу обернуть эту последовательность вызовов. Например, определение макроса mymacro, я хотел бы быть в состоянии назвать просто

mymacro(Matrix1) 
mymacro(Matrix2) 
mymacro(OtherMat) 

, чтобы сделать то же самое. Это возможно?

+2

Что вы пытаетесь до сих пор? –

+0

Я пробовал поиск по Google для того, чтобы сделать это, и не придумал ничего :) – drjrm3

ответ

2

Мне потребовалось некоторое время, чтобы получить эту работу за gfortran, так как она не поддерживает #expr.

Идея состоит в том, чтобы использовать ;, чтобы получить несколько команд в одну строку. Конечно, для этого требуется отключить обычный лимит. С gfortran это достигается -ffree-line-length-0.

Затем препроцессор gfortran использует "x" вместо #s (как это делает любой другой компилятор). Вот результат: он работает на ifort и 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 
2

Что о написании подпрограммы, как это:

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 

Это не совсем то, что получит название вашей матрицы для вас, но достаточно близко.

mymacro(matrix) 

становится

call mymacro(matrix,'matrix') 

Не очень разные, вы не думаете?

+0

К сожалению, я пробовал это, но мне нужен макрос, потому что 'size' не вызывается правильно. – drjrm3

+1

Эта проблема размера немного странная. Что происходит точно с размером? – innoSPG

+0

Я бы предпочел не решить проблему «размер» прямо сейчас, так как это не ответит на мой первоначальный вопрос. Я ищу макрос/директив препроцессора. – drjrm3

0

Макросы сами по себе не являются частью Фортрана. Они реализуются большинством (если не всех) компиляторов, просто повторно используя препроцессор C. Я узнал здесь: https://gcc.gnu.org/onlinedocs/cpp/Macros.html

Это может сделать трюк: (не проверено!)

#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!" ; 

Обратите внимание, что вам придется использовать соответствующие флаги компилятора, чтобы компилятор запустить препроцессор.

+0

К сожалению, это не будет работать с 'gfortran', так как оно не поддерживает' # m'. Мне потребовалось довольно много времени, чтобы понять это - см. Мой ответ ниже ... –

Смежные вопросы