Как объявить точность числа регулируемым параметром?

В 2013 году встал вопрос о преобразовании большого рабочего кода из двойной точности в четверную: to-quadruple-precision-how-to-r">Преобразование рабочего кода из двойной точности в четырехкратную: как читать числа с четырехкратной точностью в FORTRAN из входного файла", и консенсус состоял в том, чтобы объявить переменные с помощью регулируемого параметра «WP», который указывает «рабочую точность», вместо того, чтобы иметь отдельную версию программы с переменными, объявленными с помощью D + 01, и другую версию с использованием Q + 01. Таким образом, мы можем легко переключаться туда и обратно, определяя WP=real128 или WP=real64 вверху, а остальное менять не нужно.

Но как мы это делаем?

Я попробовал предложение в ответе на этот вопрос, сделав простой код TEST.F90:

  PROGRAM TEST
  use ISO_FORTRAN_ENV
  WP= real128
  IMPLICIT NONE
  real (WP) ::  X
  X= 5.4857990945E-4_WP
  END PROGRAM TEST

скомпилировано с:

~/gcc-4.6/bin/gfortran -o tst.x TEST.F90

Но это дает:

      IMPLICIT NONE
                   1
Error: Unexpected IMPLICIT NONE statement at (1)
QLEVEL16.F90:5.12:

      real (WP) ::  MEL 
            1
Error: Parameter 'wp' at (1) has not been declared or is a variable, which does not reduce to a constant expression
QLEVEL16.F90:6.29:

      MEL= 5.4857990945E-4_WP
                             1
Error: Missing kind-parameter at (1)

person user1271772    schedule 16.07.2016    source источник


Ответы (2)


Спецификатор вида должен быть целочисленным параметром, и вы не объявляете его надлежащим образом. Кроме того, implicit none должен стоять перед любым объявлением.

Вот рабочая версия, решающая обе проблемы:

PROGRAM TEST
  use ISO_FORTRAN_ENV
  IMPLICIT NONE
  integer, parameter :: WP= real128
  real (WP) ::  X

  X= 5.4857990945E-4_WP
END PROGRAM TEST
person Alexander Vogt    schedule 16.07.2016
comment
Превосходно! Ответ в другом потоке показал, что WP=real128 должен быть сразу после использования ISO_FORTRAN_ENV, и не показывал целое число, параметр :: часть. Это было источником моей проблемы. Спасибо! - person user1271772; 17.07.2016
comment
Возможно, более заманчиво иметь use, intrinsic :: iso_fortran_env, wp=>real128, не так ли? - person francescalus; 17.07.2016
comment
Спасибо @francescalus. Каковы преимущества и недостатки двух альтернативных вариантов? - person user1271772; 17.07.2016
comment
@ user1271772, честно говоря, они имеют примерно одинаковое влияние. Моя предложенная версия, возможно, ближе к намерению, поскольку оно есть в вопросе (т.е. часть использования). По сути, это говорит о том, что нужно взять значение real128 из модуля, но здесь назвать его wp. Другой — новая константа wp, которая имеет то же значение, что и real128 из модуля. Если вы все еще хотите ссылаться на real128, вам понадобится второй подход. - person francescalus; 17.07.2016
comment
В своих кодах я предпочитаю использовать константы из ISO_Fortran_env напрямую, то есть real(REAL128) :: ... и 1.0_REAL128. Это значительно облегчает чтение. - person Alexander Vogt; 17.07.2016

На самом деле многие коды используют этот подход WP. Многие со встроенной функцией select_*_kind. Но я думаю, что есть «более простой» способ. Это использование точности по умолчанию без указания какого-либо ключевого слова и использование флага компилятора для выбора точности по умолчанию.

Плюс в том, что этот метод проще, если вам не нужен точный контроль точности для каждой переменной. Минус в том, что это будет сильно зависеть от флагов компилятора, которые различаются для каждого компилятора или даже могут быть недоступны.

Для gfortran существует больше флагов -freal4-real8 или -freal4-real16 для повышения точности каждой явно указанной переменной с более низкой точностью.

person Francium    schedule 17.07.2016
comment
На самом деле это предпочтительный подход, я думаю. Но я не знаю, как это сделать. - person user1271772; 18.07.2016