Fortran equivalent to Matlab find - matrix slicing application without duplicating memory

I use the command to search quite a lot in matlab, and I am wondering how to translate this cleverly into fortran to extract a slice of an array. In Matlab, you can slice with either logic or indexes, but in fortran you need indexes to slice. I know about the built-in routines of pack, etc., but have never used them. In addition, since I am dealing with large matrices, I would like to avoid duplication of memory. I want the sliced ​​matrix to be controlled as part of a subroutine. I read somewhere that the fragments of the array are not duplicated. I do not know how to do this in Matlab. I am also puzzled that at Matlab some appropriations are transparent to you.

I would like to know how to reproduce the examples below and make sure that I am not duplicating the material in memory and that it is actually elegant. Otherwise, I would forget about slicing and just send the whole matrix (since it is by reference) and pass through the index array I ...

Matlab example 1: find simple playback

  v=[1 2 3 4];
  I=find(v==3);

Matlab 2 example:

m=rand(4,4);
bools=logical([ 1 0 0 1]);
I=find(bools==1); 
% which I could also do like: 
I=1:size(m,1); 
I=I(bools);

  for i=1:length(I)
      % here dealing with m(I(i)),:)  and do some computation
      % etc.

Example 3: just call the subroutine on m (I, :), but using direct booleans for slicing

   foo( m(bools, :) , arg2, arg3 )

Thank you in advance for your help!

+5
source share
3 answers

Fortran does not have an exact match for Matlab find, but you can usually use either where, or forall, or sometimes both, to replace its functionality.

For example, for an array vlike you in the first example, the Fortran statement

where (v==3) do_stuff

v, 3. , find, find , where.

v, , ix, Fortran , :

[.true., .false., .false., .true.]

ix, , v, ,

where (ix) v = some_value

ix , , , ,

where (ix>=0.0) v = some_value

, Fortran where. forall.

, Fortran,

v([1,3]) = 0

1 3 v 0. , , , 1.

, ( , ). , , -

call my_subroutine(array(1:12:3, 2:12:4))

, , , .

+9

Bellow, FORTRAN CODE, , matlab scilab. () , 22 ()

     PROGRAM Principal
     REAL*8 A(8)
     INTEGER n, npos, pos(8)
     n=8
     A = (/ 19, 20, 21, 22, 23, 24, 25, 26 /)
     ! Find the positions of vector A that is equal to 22 
     CALL FindInVector(n,A==22,npos,pos)
     WRITE(*,*) pos(1:npos)

     ! Find the positions of vector A that contains even numbers 
     CALL FindInVector(n,ABS(A/2.d0-INT(A/2.d0))<1.d-2,npos,pos)
     WRITE(*,*) pos(1:npos)

     END PROGRAM Principal

! ________________________________________________________________

! , TF (True False). npos .

     SUBROUTINE FindInVector(n,TF,npos,pos)
    ! Inlet variables
    INTEGER,INTENT(IN):: n      ! Dimension of logical vector
    LOGICAL,INTENT(IN):: TF(n)  ! Logical vector (True or False)
    ! Outlet variables
    INTEGER npos                ! number of "true" conditions
    INTEGER pos(n)              ! position of "true" conditions
    ! Internal variables
    INTEGER i                   ! counter
    INTEGER v(n)                ! vector of all positions

    pos = 0                     ! Initialize pos
    FORALL(i=1:n)   v(i) = i    ! Enumerate all positions
    npos  = COUNT(TF)           ! Count the elements of TF that are .True.
    pos(1:npos)= pack(v, TF)    ! With Pack function, verify position of true conditions

    ENDSUBROUTINE FindInVector
+1

"pack" do:

I = pack([(j,j=1,size(v))],v==3)
+1

All Articles