Передать производный тип как массив

В Fortran можно работать с массивами, но как можно рассматривать индексы производного типа как часть массива? Код объяснил бы, что я хочу сделать лучше всего:

type mytype
    integer :: b(3,3)
    real :: c(4)
endtype

integer :: a(3,3)
real :: d(2,4)
type(mytype) :: mat(2)

!do stuff so that 'mat' gets values
....

!usually one does this
a = matmul(mat(1)%b, transpose(mat(2)%b))

!multiplying two 3x3 matrices

!but how does one do this? Note the "array"
d = matmul(mat(:)%c, mat(:)%c)

Я предположил, что последняя строка аналогична матрице 2x4, умноженной сама на себя. Однако, когда я пытаюсь скомпилировать, gfortran жалуется

Ошибка: нельзя указывать две или более ссылок на детали с ненулевым рангом

Возможно ли это сделать на Фортране?


person Samuel Tan    schedule 11.01.2012    source источник


Ответы (2)


Вы хотите, чтобы компилятор рассматривал mat(:)%c как матрицу 2 x 4? Это не работает таким образом. mat и c это разные объекты и их ранги не сливаются в один массив. mat — это определяемый пользователем тип, а c — реальная матрица. Тот факт, что вы используете только c-компонент mat, не означает, что компилятор преобразует c в реальный массив большей размерности на основе размерности mat.

Вы можете создать новый массив через X = [ mat(1)%c, mat(2)%c ]. Вы можете использовать reshape для управления формой.

person M. S. B.    schedule 11.01.2012

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

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

Можно сослаться на матрицу с помощью небольшого хака FORTRAN STYLE (эквивалентность и последовательность, предполагая одинаковый размер хранилища для целых чисел по умолчанию и действительных). Этот компилируется :))))

type mytype
    !!!
    sequence
    integer :: b(3,3)
    real :: c(4)
endtype

integer :: a(3,3)
real :: d(4,4)

type(mytype) :: mat(2)
real,dimension(13,2) :: newmat

!!!
equivalence (mat,newmat)

!do stuff so that 'mat' gets values
! ....

!usually one does this
a = matmul(mat(1)%b, mat(2)%b)

!multiplying two 3x3 matrices

!but how does one do this? Note the "array"
 d = matmul(reshape(newmat(10:13,:),(/4,2/)),transpose(reshape(newmat(10:13,:),(/4,2/))))

end
person Vladimir F    schedule 11.01.2012
comment
Программист на Фортране должен быть готов найти подобные вещи в унаследованных кодах :). Тем не менее, первые два сообщения были более важными и актуальны до сих пор. Код просто для удовольствия. - person Vladimir F; 11.01.2012
comment
Спасибо, что указали на ошибки. Я исправил их. Однако суть вопроса остается прежней. - person Samuel Tan; 11.01.2012
comment
Вы поместили транспонирование не в ту строку. Первое умножение в порядке. Также проверьте правильность размерности результата. Правильный ответ - MSB, мой пример ничего не сохраняет с точки зрения памяти, все равно изменяет форму и транспонирует временный массив. Это было просто для иллюстрации эквивалентности. - person Vladimir F; 11.01.2012