0

I'm trying to write Fortran 95 code to mimic what I did in MATLAB but I'm struggling to access the array indices. code is much more complex than what is shown below, but this is the gist. I'd prefer to avoid do loops.

e.g. --> Matlab commands. Assume a,b,c are same size.

    indx=find(a<0);  % find all negative values of "a"
    b(indx)=30.;  %  set those same elements in different array "b" to 30.
    c(indx)=b(indx)./a(indx)
    etc.
    etc.

How can I store and use those indices from "a" array and operate on the same indices from other arrays in fortran?

B Laub
  • 1
  • Possible duplicate of [Fortran equivalent of numpy.where() function?](https://stackoverflow.com/questions/21435589/fortran-equivalent-of-numpy-where-function) – francescalus Sep 29 '17 at 21:02
  • it's close, but it returns a logical array which isn't useful to generate the indices to apply to other arrays. – B Laub Sep 29 '17 at 21:35
  • You use `pack` and the logical mask to give you an array of indexes which act as a vector subscript, or use a `where` statement/construct with the mask. – francescalus Sep 29 '17 at 21:41

2 Answers2

1

You want something like

$ cat pack.f90
Program pack_test

  Implicit None

  Real, Dimension( 1:5 ) :: a
  Real, Dimension( 1: 5) :: b, c

  Integer, Dimension( : ), Allocatable :: indx

  Integer :: i

  a = [ 1, -2, 3, -4, 5 ]
  b = a
  c = a

  indx = Pack( [ ( i, i = Lbound( a, Dim = 1 )    , &
                          Ubound( a, Dim = 1 ) ) ], &
                a < 0 )

  b( indx ) = 30.0
  c( indx ) = b( indx ) / a( indx )

  Write( *, * ) c

End Program pack_test

ian-standard@barleybarber ~
$ gfortran -O -Wall -Wextra -fcheck=all -std=f2003 pack.f90

ian-standard@barleybarber ~
$ ./a.exe
   1.00000000      -15.0000000       3.00000000      -7.50000000       5.00000000
Ian Bush
  • 6,996
  • 1
  • 21
  • 27
1

It's not always necessary to create the index array and if it isn't where may be the right tool to use. For example, the code from @IanBush's answer could be modified like this:

Program where_test

  Implicit None

  Real, Dimension( 1:5 ) :: a
  Real, Dimension( 1: 5) :: b, c

  Integer :: i

  a = [ 1, -2, 3, -4, 5 ]
  b = a
  c = a

  WHERE(a<0) b = 30.0
  WHERE(a<0) c = b/a

  Write( *, * ) c

End Program where_test
High Performance Mark
  • 77,191
  • 7
  • 105
  • 161