2010-01-27 5 views
2

J'ai un p p tableau n en Fortran, et je veux extraire k * k de cette sous-tableau plus grand tableau. J'ai essayé comme ça, mais pas sûr ça marche:Sélection k * k * p de sous-tableau tableau p * n dans Fortran

do i=1,p 
    vp(i)=i 
end do 
help=y(1:p,t)*vp 
do t = 1, n 
    A(1:k,1:k,t) = B(pack(help,help>0), pack(help,help>0), t) 
end do 

où y contient des valeurs 0 et 1, 1 signifiant que la ligne/colonne est voulu sous-tableau. Est-ce que cela fonctionne, et sinon, comment cette même chose pourrait-elle être exploitée? Merci.

Répondre

0

Si je comprends ce que vous voulez faire, voici un exemple de programme qui extrait les colonnes et les lignes sélectionnées, mais n'utilise pas beaucoup de notation de tableau.

program test 

integer, parameter :: Adim = 2 
integer, parameter :: Bdim = 3 
integer, dimension (Adim,Adim) :: A 
integer, dimension (Bdim,Bdim) :: B 
logical, dimension (Bdim) :: good_row = [.true., .false., .true.] 
logical, dimension (Bdim) :: good_col = [.false., .true., .true.] 
integer :: i, j, ia, ja, ib, jb 


if (count (good_row) /= Adim .or. count (good_col) /= Adim) then 
    write (*, *) 'selection arrays not setup correctly.' 
    stop 
end if 

do i=1, Bdim 
    do j=1, Bdim 
     B (i,j) = i + i*j**2 ! test values 
    end do 
end do 

do i=1, Bdim 
    write (*, *) (B (i, j), j=1, Bdim) 
end do 

ia = 0 
do ib=1, Bdim 
    if (good_row (ib)) then 
    ia = ia + 1 
    ja = 0 
    do jb=1, Bdim 
     if (good_col (jb)) then 
      ja = ja + 1 
      !write (*, *) ia, ja, ib, jb 
      A(ia,ja) = B(ib,jb) 
     end if 
    end do 
    end if 
end do 

write (*, *) 
do i=1, Adim 
    write (*, *) (A (i, j), j=1, Adim) 
end do 

stop 
end program test 
0

solution à deux, en utilisant des opérations de réseau au vecteur de niveau (tableau 1D) - remplacer la boucle principale avec:

ia = 0 
do ib=1, Bdim 
    if (good_row (ib)) then 
    ia = ia + 1 
    A (ia,:) = pack (B(ib,:), good_col) 
    end if 
end do 

Solution trois, en utilisant entièrement les opérations de tableau:

program test 

integer, parameter :: Adim = 2 
integer, parameter :: Bdim = 3 
integer, dimension (Adim,Adim) :: A 
integer, dimension (Bdim,Bdim) :: B 
logical, dimension (Bdim,Bdim) :: mask 
integer :: i, j 

mask (1,:) = [.false., .true., .true.] 
mask (2,:) = .false. 
mask (3,:) = [.false., .true., .true.] 


do i=1, Bdim 
    do j=1, Bdim 
     B (i,j) = i + i*j**2 ! test values 
    end do 
end do 

do i=1, Bdim 
    write (*, *) (B (i, j), j=1, Bdim) 
end do 

A = reshape (pack (B, mask), [Adim, Adim]) 

write (*, *) 
do i=1, Adim 
    write (*, *) (A (i, j), j=1, Adim) 
end do 

stop 
end program test 
0

Vous ne savez pas si ces fragments de non-code vous sont utiles, mais; Ne pas oublier les caractéristiques de sectionnement de tableau de Fortran.

  • N'oubliez pas que vous pouvez utiliser des indices de vecteur pour obtenir des sections de tableau, par exemple, vous pouvez sélectionner des éléments d'un v comme vecteur ceci:

    v ((/ 1, 3, 6, 5, 10 /))

subscripting vecteur peut être appliqué à des tableaux de rang supérieur à 1. il serait mal la tête pour comprendre vos besoins de subscripting cette façon, mais vous pourriez vouloir essayer.

0

Oui il devrait fonctionner, et vous même ne pas besoin de la boucle do t = ...

program main 
    integer,dimension(3,3,2):: a 
    integer,dimension(4,4,2):: b 
    integer,dimension(4):: y 
    integer,dimension(4):: idx 
    integer:: i,j,k 

    y = (/ 1 , 0 , 1 , 1 /) 
    idx = (/ (i,i=1,4) /) 
    b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/)) 
    a(:,:,:) = b(pack(idx,y>0) , pack(idx,y>0) , :) 

    print '(A2/,(4I4))','b=',b 
    print '(A2/,(3I4))','a=',a 

    end 

compilé avec gfortran 4.2.3 correctement me donne

b= 
111 112 113 114 
121 122 123 124 
131 132 133 134 
141 142 143 144 
211 212 213 214 
221 222 223 224 
231 232 233 234 
241 242 243 244 
a= 
111 113 114 
131 133 134 
141 143 144 
211 213 214 
231 233 234 
241 243 244 

Vous pouvez également utiliser

k = count(y> 0) 
    a(1:k,1:k,:) = b(pack(idx,y>0) , pack(idx,y>0) , :) 

Ou pensez en utilisant LOGICAL .true. et .false. au lieu de 1 et 0 ...

program main 
    integer,dimension(3,3,2):: a 
    integer,dimension(4,4,2):: b 
    logical,dimension(4):: y 
    integer,dimension(4):: idx 
    integer:: i,j,k 

    idx = (/ (i,i=1,4) /) 
    y = idx /= 2 
    b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/)) 

    k = count(y) 
    a(1:k,1:k,:) = b(pack(idx,y) , pack(idx,y) , :) 

    print '(A2/,(4I4))','b=',b 
    print '(A2/,(3I4))','a=',a 

    end 
Questions connexes