> Here is a more generic find() you could use. It will work on any valid
> logical expression.
>
> Usage Example:
> integer,allocatable :: i(:)
>
> allocate( i(count(x>3.0) )
>
> i = find(x > 3.0)
>
> .... do stuff with i...
>
> deallocate(i)
> ...
>
> Matlab does some of this for you behind the scenes. Fortran is more like
> C -- you get to deal with the wonderful :-) allocations yourself.
>
> function find(mask) result(f)
> logical,intent(in) :: mask(:)
>
> ! Note x and mask are of the same size by definition. The > operator is
> ! broadcast along the rank of x and a vector of boolean values is created.
>
> integer :: f(size(count(mask==.true.)) ! or just count(mask).
I lost count of who wrote this ^^^^^^^^^^^^
Anayway, to compare logicals == should be replaced by .EQV. :-()
I am astonished that compilers often don't flag this error.
And, indeed, COUNT(MASK) is the way to write it.
> integer :: i,k
> i = 1
> do k = 1,size(mask)
> if (mask(k)) then
> f(i) = k
> i = i + 1
> end if
> end do
>
> end function find
> I just dashed this off, so please let me know if I goofed this up. :-)
>
> Somebody who knows more F90 than I, tell me: could I do this:
>
> i(1:n) = find(x>3.0,n) ???
>
> I think not, but it would simplify the usage.
>
>
> Alvaro Fernandez
> Vice President
> Athena Technology Consultants, Inc.
> WWW: www.athena-eng.com
> Email: [log in to unmask]
> Voice: 281-648-3994
> Fax: 281-648-4015
>
> |
> ||-----Original Message-----
> ||From: Fortran 90 List [mailto:[log in to unmask]]On Behalf
> ||Of Malcolm Cohen
> ||Sent: Thursday, January 24, 2002 9:02 AM
> ||To: [log in to unmask]
> ||Subject: Re: Find indices of nonzero elements
> ||
> ||
> ||Choru 'n Moru said:
> ||> I am wondering if there is a way in F90 to get the indices of non-zero
> ||> elements.
> ||
> ||Hmm, why do you want the indices?
> ||
> ||You can operate on the non-zero elements without knowing the indices,
> ||by using the WHERE statement or construct. You can also operate on
> ||corresponding elements of other arrays (the same way).
> ||
> ||E.g.
> ||
> || REAL A(...),B(...)
> || ...
> || WHERE (A.NE.0)
> || B = 1/A
> || A = SQRT(A)
> || ELSEWHERE
> || B = 0
> || ENDWHERE
> ||
> ||> For those familiar with MATLAB, there is function called find.
> ||> For example, I = FIND(A>100), returns the indices of A where A
> |is greater
> ||> than 100. The caveat to this is that I'd like to do it without loops or
> ||> IF-THEN_ELSE statements.
> ||
> ||The most efficient way is probably to use loops and IF-THEN.
> ||Something like:
> ||
> ||FUNCTION find(a)
> || REAL a(:)
> || REAL find(COUNT(a.NE.0))
> || j = 1
> || DO i=1,SIZE(a)
> || IF (a(i).NE.0) THEN
> || find(j) = i
> || j = j + 1
> || END IF
> || END DO
> ||END FUNCTION
> ||
> ||> I'd like to exploit F90's vector operations. Is
> ||> this even possible in F90?
> ||
> ||Sure, but why would you want to?
> ||
> ||Here is an obfuscated but "vector" version of FIND:
> ||
> || PACK((/(i,i=LBOUND(a,1),UBOUND(a,1))/),a.NE.0)
> ||
> ||This will probably be slower than the procedure using loops, as many
> ||compilers will manifest the array constructor before masking and packing
> ||it down. [Yes, I'm sure some compilers can optimise it ok, but not all.]
> ||
> ||But mostly you can just use WHERE to operate on masked vectors already,
> ||rather than manifesting a index for the mask.
> ||
> ||Cheers,
> ||--
> ||...........................Malcolm Cohen, NAG Ltd., Oxford, U.K.
> || ([log in to unmask])
> ||
> ||_____________________________________________________________________
> ||This message has been checked for all known viruses by Star Internet
> ||delivered through the MessageLabs Virus Scanning Service. For further
> ||information visit http://www.star.net.uk/stats.asp or alternatively call
> ||Star Internet for details on the Virus Scanning Service.
> ||
> |
>
|