Значение по умолчанию для компонентов параметризованных производных типов Fortran

Вот минимальная программа для воспроизведения моей проблемы:

program test

  use iso_fortran_env, only: REAL32

  implicit none

  type :: matrix (rows, cols, kind)
     integer, len                             :: rows
     integer, len                             :: cols
     integer, kind                            :: kind = REAL32
     real (kind=kind), dimension (rows, cols) :: values
     real (kind=kind)                         :: small = 1.0e-9
  end type matrix

end program test

Когда я скомпилировал эту программу с помощью gfortran 14.1, я получил следующую ошибку:

test.f90:12:56:

   12 |      real (kind=kind)                         :: small = 0.0e-9
      |                                                        1
Error: Cannot convert REAL(4) to REAL(0) at (1)

Когда я удаляю = 0.0e-9, код успешно компилируется.

  1. Я что-то пропустил? или это глюк gfortran?
  2. Если возможно инициализировать компоненты параметризованных производных типов, как в приведенном выше коде, как я могу установить тип литерала в назначении инициализации (например, small = 1.0e-9_kind, когда kind получен из параметров производного типа)?

Обновлено:

Работает с AOCC 4.1 (фланец 16.0)! Так что я думаю, что это ошибка gfortran (аналогично этому багу).

Поэтому, не удаляя исходный вопрос, я изменил его на:

Учитывая следующий параметризованный производный тип:

program test

  use iso_fortran_env, only: REAL32, REAL64, REAL128

  implicit none

  type :: mytype (kind)
     integer, kind    :: kind = REAL32
     real (kind=kind) :: small = 1.0e-9
  end type mytype

  type (mytype (kind=REAL32))  :: s
  type (mytype (kind=REAL64))  :: d
  type (mytype (kind=REAL128)) :: q

end program test

Здесь для всех реальных видов (кроме реального вида по умолчанию) литерал 1.0e-9, назначенный компоненту small компонента mytype, потеряет точность. Как я могу использовать параметр kind в назначении значения по умолчанию small = 1.0e-9 (что-то вроде small = 1.0e-9_kind)?

Функция параметризованного производного типа в Fortran 2018 в gfortran практически не работает. К сожалению, в настоящее время никто не занимается решением проблем. Лучше не использовать PDT с gfortran или использовать другой компилятор, например компиляторы Intel ifx и/или ifort.

steve 29.05.2024 07:02

@ Стив Фортран 2003?

Scientist 29.05.2024 08:28

@Ученый: Я думаю, это f2003.

Ghorban M. Tavakoly 29.05.2024 09:47

@steve: Спасибо за ответ. Я отредактировал свой вопрос. Пожалуйста, прочитайте добавленный раздел РЕДАКТИРОВАНИЯ.

Ghorban M. Tavakoly 29.05.2024 09:48

Как вы думаете, что не так с small = 1.0e-9_kind?

francescalus 29.05.2024 09:56

@francescalus: и gfortran, и flang выдают мне ошибку. Я думаю, что в 1.0e-9_kindkind должна быть целочисленной константой (например, integer, parameter :: kind = REAL32). Это нормально в стандарте Фортрана? К сожалению, у меня нет компиляторов Intel, nvhpc и/или pgi.

Ghorban M. Tavakoly 29.05.2024 10:01
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
104
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В буквальной реальной константе, такой как 1.0e-9_kind, параметр kind должен быть именованной константой.

Напротив, некоторые другие спецификации параметра типа требуют просто постоянного выражения.

В определении производного типа, например

type t(kind)
   integer, kind :: kind
   real(kind) :: x=1._kind
end type

параметр kind для объявления типа (real(kind)) — это требование «постоянного выражения», тогда как 1._kind — это требование «именованной константы».

В определении производного типа параметр вида производного типа может использоваться в константном выражении, но это не именованная константа. То есть real(kind) у нас может быть, а 1._kind нет.

kind будучи постоянным выражением, однако, мы можем иметь

type t(kind)
   integer, kind :: kind
   real(kind) :: x=TINY(REAL(1., kind))  ! Not TINY(1._kind)
end type

Вы можете указать «наиболее точную» литеральную константу и использовать kind для ее преобразования:

type t(kind)
   integer, kind :: kind
   real(kind) :: x=REAL(1._real128, kind)
end type

но это всего лишь

type t(kind)
   integer, kind :: kind
   real(kind) :: x=1._real128
end type

за исключением случаев, когда в компиляторах есть ошибки.

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

Я знаю, что REAL128 не портативен (у меня есть устройство M68K максимум REAL80 типа). Фортран гарантирует, что на один реальный вид точнее, чем реальный вид по умолчанию (double precision). На самом деле REAL64 достаточно для моих нужд. Итак, мне приходится использовать явное или неявное приведение из наиболее точного реального вида. Спасибо.

Ghorban M. Tavakoly 29.05.2024 22:57

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

francescalus 29.05.2024 23:41

Я читал (во многих местах) об использовании целочисленного литерального типа и мнемонических типов (например, 1.0_4 против 1.0_REAL32), которые не являются переносимыми. Например, gfortran использует размер хранилища для вида (REAL32=4, REAL64=8, REAL128=16), но процессоры могут использовать другие значения. Поэтому лучше использовать добрые константы из iso_fortran_env или использовать select_real_kind. Мое намерение использовать kind в качестве параметра PDT состоит в том, чтобы разработать библиотеку моделирования океана и позволить пользователям выбирать точность с плавающей запятой (какая-то общая модель). Я знаю, что есть и другие способы сделать это, но я предпочитаю этот метод.

Ghorban M. Tavakoly 29.05.2024 23:57
1._4 всегда ошибается; 1._real32 возможно, неправильно. Стремление к переносимости в Фортране (и во всем остальном) — это хорошо, но «переносимость» в Фортране широко понимается неправильно. (Я не говорю, что вы неправы, но это гораздо более широкая тема, чем можно справедливо выразить в комментариях; я приветствую дальнейшие вопросы.)
francescalus 30.05.2024 00:23

Другие вопросы по теме