[fortran] вопрос знатокам
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. Т.е. про него известен только ранг, а как его передать параметром?
Что-то вроде такого:
subroutine memory(array, length, range)
implicit none
integer, intent(in) :: range, length(range)
...
Вот так не получится, потому что 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 и т.д. как-то не хочется...
Спасибо!