Использование Iso_Fortran_Env для установки значения Kind функции

Как можно использовать внутреннюю функцию ISO Fortran Env для установки возвращаемого значения KIND функции способом, который является идиоматическим для Fortran 2008?

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

program name here
    use iso_fortran_env
    implicit none
    integer, parameter :: double=REAL64
    real(kind=double) :: some_variable
end program name here

Но, похоже, нет удобного способа использовать эти встроенные функции для внешних функций, поскольку REAL64 и double были бы определены только внутри основной функции, указанной выше. Попытка определить KIND функции в main следующим образом:

program name here
    use iso_fortran_env
    implicit none
    integer, parameter :: double=REAL64
    real(kind=double) :: some_function
    ! Do stuff
end program name here
real function some_function()
    ! Do stuff
end some_function

По крайней мере, в моей системе выдает ошибку несоответствия типа (double определяется как KIND = 8, а реальное значение по умолчанию определяется как KIND = 4 в моей системе). Я всегда мог бы просто использовать real(kind=8) function some_function(), но я бы предпочел не использовать в интересах переносимости. Кроме того, просто кажется грязным использовать REAL64 из iso_fortran_env в одном месте, только чтобы развернуться и использовать KIND = 8 в другом месте.

Есть ли простой (или, по крайней мере, читаемый) способ сделать это, например, ниже?

real(kind=REAL64) function some_function()

person AmphotericLewisAcid    schedule 30.05.2018    source источник


Ответы (3)


Вы начинаете свой вопрос, предлагаете решение на том, и это решение работает хорошо. Как указывает IanH, в стандартной формулировке есть некоторая двусмысленность, но я прочитал ее так, как будто это разрешено, и компиляторы принимают этот синтаксис:

fundef.f90:

real(kind=REAL64) function some_function()
  use iso_fortran_env
  some_function = 1._real64
end

компилировать:

> gfortran -c funkind.f90 
> 

Вы можете использовать тип, определенный в модуле, используемом внутри функции. Протестировано также с Intel Fortran и Oracle Studio.

В современном Фортране все функции в любом случае должны быть определены в модуле, но если вы хотите, чтобы вид модуля использовался только внутри функции, такая возможность есть.

person Vladimir F    schedule 30.05.2018
comment
Этим занимается Interp F90 / 0145. Он не решен, и так было уже более двух десятилетий. Учитывая это, я думаю, что описание этого как полностью законного может быть немного спорным. - person IanH; 30.05.2018
comment
На самом деле я не был уверен в этом слове и даже подумал, что упустил его, но, видимо, нет. - person Vladimir F; 30.05.2018
comment
Я активно избегаю использования этого подхода из-за того, как проявляются эти противоречия. Просто не стоит выяснять, как компилятор обрабатывает это, даже если кажется, что он принимает синтаксис. - person francescalus; 30.05.2018
comment
Я открыл интерп, но я прочитал его как относящийся к более тонким деталям, в основном непостоянным сущностям и функциям запроса, действующим на них. А именно, похоже, это согласуется с правильностью этого A named constant can appear in a <type-spec> of a function statement if it is accessible within the function by host or use association. ответа на пункт а) в F90 / 0145 в j3-fortran.org/doc/year/17/17-006.txt - person Vladimir F; 30.05.2018
comment
Этот промежуточный ответ был отклонен по какой-либо причине. Дальнейшая работа над интерполяцией может изменить этот ответ, или, возможно, его можно будет выдвинуть и принять без изменений - мы просто не знаем. Я могу понять, почему нужна осторожность с этим интерп, поскольку требования к последовательности в языке и так достаточно сложны. А пока я придерживаюсь того же подхода, что и francescalus. - person IanH; 31.05.2018
comment
Этот подход, кажется, работает в Gfortran как для Fortran 2008, так и для Fortran 90. Я знаю, что определение функций в модулях - правильный способ решения задач, но в любом случае это был всего лишь короткий сценарий для личного использования. Спасибо! - person AmphotericLewisAcid; 02.06.2018

Расширение ответа @chw21:

У вас всегда есть возможность объявить тип результата функции в части спецификации функции и получить доступ к параметрам из модулей через ассоциацию с хостом внутри.

Изменить: «Как указывает @Vladimir F, вы также можете получить доступ к переменным по ассоциации с хостом из модуля, объявленного внутри тела функции».

Фактически, это единственный способ применить атрибуты к результату функции, такие как указатель, выделяемый объект, измерение и т. Д.

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

pure function some_other_function_with_a_long_name() result(out)
    use, intrinsic :: iso_fortran_env, only: rk => real64
    implicit none
    real(rk), dimension(5) :: out
    out = 1.0_rk
    ! (...)
end
person Rodrigo Rodrigues    schedule 30.05.2018
comment
Изначально я планировал спросить о чистых функциях, но решил, что свожу это к простой грязной функции. Я действительно рад слышать, что это все еще возможно с pures. - person AmphotericLewisAcid; 02.06.2018

Обычно я пробую это перед публикацией, но думаю, это должно сработать:

function some_function()
    use iso_fortran_env, only: real64
    implicit none
    real(kind=real64) :: some_function
    some_function = 1.0_real64
end function some_function

Или внутри модуля

module some_module
    use iso_fortran_env, only: real64
    implicit none
contains
    real(kind=real64) function some_function()
        some_function=1.0_real64
    end function some_function
end module some_module
person chw21    schedule 30.05.2018