У меня странная проблема с кодом на Фортране - PullRequest
0 голосов
/ 23 ноября 2018

Я довольно новичок в программировании на Фортране, так что это может быть очевидной проблемой, так что терпите меня.Вот код, с которым я работаю:

program A1H

! Householder transformation

implicit none
integer,parameter::dp=selected_real_kind(15,307) ! Double precision kind

real(kind=dp), dimension(6,3)::A
real(kind=dp), dimension(6,1)::b
integer, dimension(6,6)::Pglobal ! Global identity matrix
integer::i,j,g
g = size(A,1)
do j=1,g
   do i=1,g
       Pglobal(i,j) = (i/j)*(j/i)
   end do
end do
b(:,1) = [1237,1941,2417,711,1177,475]
A(1,:) = [1,0,0]
A(2,:) = [0,1,0]
A(3,:) = [0,0,1]
A(4,:) = [-1,1,0]
A(5,:) = [-1,0,1]
A(6,:) = [0,-1,1]
call mat_print('A',A)
call mat_print('b',b)
call mat_print('Pglobal',Pglobal)
call householder(A,b)

contains

subroutine householder(A,b)
real(kind=dp), intent(in)::A(:,:),b(:,:)
real(kind=dp)::alpha,gamma,beta
real(kind=dp), dimension(6,6)::H
real(kind=dp), dimension(6,3)::y,aa
real(kind=dp), dimension(6,1)::yy,v,dglobal,ek,bb
real(kind=dp), dimension(1,6)::d
integer::k,m,n,j
m = size(A,1)
n = size(A,2)
aa = A
bb = b
do k=1,n
   dglobal(:,k) = [0,0,0,0,0,0]
   alpha = -sign(aa(k,k),aa(k,k))*norm2(aa(k:m,k))
   ek(:,1) = Pglobal(:,k) 
   dglobal(k:m,k) = aa(k:m,k)
   v(:,k) = (dglobal(:,k)) - alpha*ek(:,1) 
   d(k,:) = v(:,k)
   beta = dot_product(d(k,:),v(:,k))
   if (beta==0) then
       continue
   end if
   H = Pglobal - (2/beta)*(matmul(reshape(v(:,k),(/m,1/)),reshape(d(k,:),(/1,m/)))) 
   y = matmul(H,aa)
   yy = matmul(H,bb)
   aa = y
   bb = yy
   call mat_print('aa',y)
   call mat_print('bb',yy)
end do

end subroutine

! Matrix print subroutine

subroutine mat_print(b,a)
    character(*), intent(in)::b
    class(*), intent(in)::a(:,:)
    integer::i
    print*,' '
    print*,b
    do i=1,size(a,1)
        select type (a)
        type is (real(kind=dp)) ; print'(100f9.4)',a(i,:)
        type is (integer) ; print'(100i9  )',a(i,:)
        end select
    end do
    print*,' '
 end subroutine

 end program

Проблема, с которой я сталкиваюсь, заключается в том, что когда я изменяю переменную aa на другое имя, я получаю неверный результат для переменной y;если я оставлю это как есть, это правильно;однако, оставляя переменную bb как есть, результат yy неверен, но если я изменю переменную bb на другое другое имя, я получу правильный результат для yy, но затем мой ответ для y меняется!Я очень запутался, как это может произойти, так как мой опыт написания кода говорит мне, что ответ не должен меняться в зависимости от простого изменения имени переменной, и если вы посмотрите на код, переменные y и yy даже несвязано в алгоритме.Это не единственный код на Фортране, с которым я столкнулся ранее.Любая помощь будет высоко ценится.

1 Ответ

0 голосов
/ 24 ноября 2018

Я смог воспроизвести вашу ошибку с GNU Fortran (Homebrew GCC 8.2.0) 8.2.0.В вашей программе действительно есть ошибка.Вы можете найти эту ошибку, скомпилировав с параметром -fbounds_check.Когда вы запустите его, вы обнаружите, что некоторые из ваших массивов доступа не имеют смысла.Например, вы получаете доступ к dglobal(:,k) = [0,0,0,0,0,0], но второе измерение dglobal - только 1. Используйте этот флаг, чтобы исправить ваш код, и я уверен, что эта ошибка исчезнет.

Для всех, кто хочетЧтобы глубже понять, почему внешний вид этой ошибки зависит от имени переменной, я смог воспроизвести ее с именем массива test_array, но не с другими более короткими именами.Я также смог получить правильный ответ, используя имя test_array, если я установил -fmax-stack-var-size=100, и другие значения появились с разными размерами.Я предполагаю, что gfortran помещает эти массивы в стек, а порядок основан на имени.Некоторые имена помещают его в «безопасное» место, чтобы значения не перезаписывались переполнением буфера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...