Массив Fortran автоматически увеличивается при добавлении значения

Есть ли способ эмулировать растущий массив в Fortran? Как вектор в C++. Я был очень удивлен, когда не нашел ничего на эту тему в Интернете.

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


person DartLenin    schedule 04.08.2016    source источник
comment
связанные или возможный дубликат? stackoverflow.com/questions/8384406/   -  person solalito    schedule 04.08.2016
comment
Чтобы процитировать ответ из упомянутого выше сообщения: добавление одного элемента за раз путем увеличения массива не является эффективным подходом. Увеличение массива с N элементов до N+1 в Фортране, скорее всего, будет означать создание нового массива и копирование всех существующих элементов. Более подходящей структурой данных может быть связанный список.   -  person solalito    schedule 04.08.2016
comment
Вы отмечены как fortran90. Вам действительно нужно игнорировать изменения в языке за последние 25 лет? Например, очень простое a=[a,5] не является F90. (Или эффективно.)   -  person francescalus    schedule 04.08.2016
comment
RESHAPE, UBOUND и некоторые другие, по сути, ваши друзья.   -  person Holmz    schedule 04.08.2016
comment
Умный ответ Алека - MOVE_ALLOC, который, я думаю, из F2003.   -  person Holmz    schedule 04.08.2016
comment
Я не вижу, как RESHAPE или UBOUND могут помочь здесь. Даже не только MOVE_ALLOC. F2003 a=[a,5] — простой пример того, что можно сделать легко, но что будет медленно.   -  person Vladimir F    schedule 04.08.2016
comment
@solalito Да, этот пост о реализации. Я знаю, как это реализовать. Я новичок в фортране, поэтому мне было интересно, есть ли для него существующая структура данных или синтаксис, возможно, добавленный в какой-то более поздний стандарт, о котором я не знаю, чтобы я мог не изобретать велосипед. .   -  person DartLenin    schedule 04.08.2016
comment
@francescalus Нет, мне не нужно придерживаться fortran90, я удалил лишний тег   -  person DartLenin    schedule 04.08.2016


Ответы (1)


Я уверен, что это было показано где-то на этом сайте раньше, но я не могу найти его.

Во-первых, в Fortran 2003 вы можете добавить один элемент простым

a = [a, item]

как прокомментировал francescalus. Это может привести к перераспределению массива очень часто и будет медленным.

Вы можете сохранить свой массив для выделения несколько большего размера, чем ваше количество элементов n. Когда количество ваших элементов n превысит размер массива size(a), вы можете выделить новый массив в несколько раз больше (здесь в 2 раза) и скопировать туда старые элементы. К сожалению, в Фортране нет realloc().

module growing_array
  implicit none

  real, allocatable :: a(:)

  integer :: n

contains

  subroutine add_item(item)
    real, allocatable :: tmp(:)
    real, intent(in) :: item

    if (n == size(a)) then
      !this statement is F2003, it can be avoided, but I don't see why in 2016
      call move_alloc(a, tmp)

      allocate(a(n*2))
      a(1:n) = tmp
    end if

    n = n + 1

    a(n) = item
  end subroutine
end module

Я пропустил начальное распределение, оно достаточно простое.

Все это можно поместить в производный тип с процедурами, связанными с типом, и использовать его как структуру данных, но это чистый Фортран 2003, а вы хотели 90. Итак, я показываю Фортран 95, потому что Фортран 90 во многих отношениях несовершенен для размещения массивов и безнадежно устарел и по существу мертв.

person Vladimir F    schedule 04.08.2016
comment
спасибо, я надеялся, что это уже реализовано в фортране, чтобы я мог не изобретать велосипед, но чем больше я использую фортран, тем больше понимаю: фортран не любит делать вашу жизнь проще. - person DartLenin; 04.08.2016
comment
FWIW векторный тип С++, на который делается ссылка, делает что-то подобное, выделяя блоки за раз. Возможно, стоит посмотреть, что именно представляет собой алгоритм. - person agentp; 04.08.2016
comment
@HighPerformanceMark К сожалению, это не мое решение. Давайте проведем более честное сравнение. C++ имеет широкий спектр различных функций и структур данных в стандартной библиотеке, что не мешает ему превосходить фортран во многих задачах. У Фортрана может быть такая же стандартная библиотека, но никто ее еще не написал (насколько мне известно), поэтому я сказал, что Фортран не любит упрощать вашу жизнь :) - person DartLenin; 04.08.2016
comment
Так что используйте C++, проблема решена. Они, наконец, представили пригодные для использования динамически выделяемые смежные 3D-массивы? С любым стартовым индексом? Создание такой библиотеки не так просто, как может показаться, и потребуется дополнительная поддержка со стороны языка groups.google.com/forum/#!topic/comp.lang.fortran/ - person Vladimir F; 04.08.2016
comment
@VladimirF Как часто вам нужны трехмерные массивы с нестандартным начальным индексом? В любом случае, это относительно легко реализовать по сравнению со всей стандартной библиотекой. Возможно, синтаксис будет не таким красивым, как в фортране, но его можно будет использовать. И я не говорил, что реализовать стандартную библиотеку легко, но это необходимо, если вы хотите сделать свой язык удобным и простым. - person DartLenin; 04.08.2016
comment
Намного чаще, чем растущий массив. - person Vladimir F; 04.08.2016
comment
В примере, где IF (n==SIZE(A))... я думаю, SIZE следует заменить на UBOUND ? - person Holmz; 05.08.2016
comment
@Holmz не имеет значения, если вы начнете с 1. - person Vladimir F; 05.08.2016