[fortran] вопрос знатокам
как вариант, можно хранить массив ранга 1 и по мере необходимости работать с ним как с 3-х мерным, воспользовавшись фичей 2003 фортрана 'pointer rank remapping' (правда gfortran (4.4.1) и ifort (11.1.038) ее не поддерживают).
program alloc
use memory_allocator
implicit none
integer, parameter :: n = 3
real(8 dimension( allocatable, target :: foo
real(8 dimension(:,:, pointer :: foo3d
integer :: i, j, k
print *, "main: before memory: ", allocated(foo)
call memory(foo, n*n*n)
foo3d(1:n,1:n,1:n) => foo
print *, "main: after memory: ", allocated(foo)
forall (i=1:n, j=1:n, k=1:n) foo3d(i, j, k) = real(i*j*k,kind=8)
print *, foo
print *, "main: before freem: ", allocated(foo)
call freem(foo)
print *, "main: after freem: ", allocated(foo)
end program alloc
Но проблема в том, что мне приходится указывать число размерностей массива в интерфейсе функции, поэтому она работает только для массивов определеного ранга.
А что мешает передать размерность массивом?
Ну вот а как это сделать?..
Я так понимаю, что этот массив должен быть описан как deferred shape, т.е. a(:,..., потому что он allocatable. Т.е. про него известен только ранг, а как его передать параметром?
Я так понимаю, что этот массив должен быть описан как deferred shape, т.е. a(:,..., потому что он allocatable. Т.е. про него известен только ранг, а как его передать параметром?
Самый простой вариант передать всё явно: ранг, массив размерностей размера ранг (это если все размерности начинаются с 1 и того же числа - если надо использовать отрезки - немного сложнее) и сам массив.
Что-то вроде такого:
Что-то вроде такого:
subroutine memory(array, length, range)
implicit none
integer, intent(in) :: range, length(range)
...
Я не понимаю, array в этом случае как описать?
Вот так не получится, потому что allocatable массив array должен быть описан как deferred shape
Вот так не получится, потому что allocatable массив array должен быть описан как deferred shape
subroutine memory(array, dims)
integer, intent(in) :: dims(:)
real(8 intent(inout allocatable :: array(dims)
alloc.f90:7.47:
real(8 allocatable, intent(out) :: array(dims)
1
Error: Expression at (1) must be scalar
alloc.f90:4.25:
subroutine memory(array, dims)
1
Error: Allocatable array 'array' at (1) must have a deferred shape
Действительно, с рангом массива сложнее - сконструировать не проблема, но вот описать такой параметр?..
Так сразу непонятно как.
Имхо это одна из недоделок фортрана, но мб и можно извернуться через символьные константы (описывая ими сечения, но у меня не получилось, а мб и нельзя).
Как вариант - можно действительно всё делать одномерными массивами (как тут уже и советовали).
Тогда в минимальном варианте надо будет лишь написать свой метод доступа к ячейке (но он будет конечно не такой же универсальный, как и в стандарте, но мб и хватит ну или написать фабрику.
Но конечно всё это не очень удобно, и в этом основной минус фортрана - как только хочется что-нибудь сделать красиво - язык не пускает
Так сразу непонятно как.
Имхо это одна из недоделок фортрана, но мб и можно извернуться через символьные константы (описывая ими сечения, но у меня не получилось, а мб и нельзя).
Как вариант - можно действительно всё делать одномерными массивами (как тут уже и советовали).
Тогда в минимальном варианте надо будет лишь написать свой метод доступа к ячейке (но он будет конечно не такой же универсальный, как и в стандарте, но мб и хватит ну или написать фабрику.
Но конечно всё это не очень удобно, и в этом основной минус фортрана - как только хочется что-нибудь сделать красиво - язык не пускает

Оставить комментарий
mazamaza2008
Я хочу написать функцию, которая на вход получает массив и размерности, выделяет память allocate-ом, и возвращает массив. Причем функция должна уметь выделять память для массивов разного ранга. По существу мне нужна просто обертка для allocate, которая будет еще кое-что делать.В Fortran 2003 есть возможность передавать allocatable объекты как параметры. Но проблема в том, что мне приходится указывать число размерностей массива в интерфейсе функции, поэтому она работает только для массивов определеного ранга.
Код, приведенный ниже, не компилируется, так как subroutine memory на вход принимает массив ранга 1, а я ему даю массив ранга 3.
Можно ли как-нибудь все-таки такую функцию реализовать? Писать отдельно функции для массивов ранга 1, 2, 3 и т.д. как-то не хочется...
Спасибо!