Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Logical indexing in Fortran

533 views
Skip to first unread message

Lichtenberg

unread,
Jun 13, 2014, 11:36:54 AM6/13/14
to
Happy Friday the 13th everyone,

what do you think about introducing logical indexing of Fortran arrays, similar to Matlab and R?
The 'where' construct lacks the expressiveness of logical mask arrays.
Any objections agains it?

Thomas Koenig

unread,
Jun 13, 2014, 2:39:05 PM6/13/14
to
Lichtenberg <tent...@gmail.com> schrieb:

> what do you think about introducing logical indexing of Fortran arrays, similar to Matlab and R?

It can be done with a helper function, but that is not elegant.
I also don't really see where this helps. Why not use 0 and 1 as
array indices?

> The 'where' construct lacks the expressiveness of logical mask arrays.

This I don't understand. What would you want to do?

Lichtenberg

unread,
Jun 13, 2014, 3:16:43 PM6/13/14
to
Assignments similar to
A(A < 0) = -1
without using pack/unpack.
I find this notation very convenient in those languages.

Dick Hendrickson

unread,
Jun 13, 2014, 3:59:11 PM6/13/14
to
Can you give a better example of what's hard to do with WHERE? Your
example is easy,

WHERE (A<0) A = -1

More verbose, but also clearer (to me).

In your notation something like

A(B) = -1

is mildly ambiguous to the code reader.

Dick Hendrickson

Lichtenberg

unread,
Jun 13, 2014, 4:27:03 PM6/13/14
to
How about

...
integer :: N
real :: A(N),B(N),x
...
x = maxval(A(A<0 | B<0)) ?

I disagree on A(B)-=1 being ambiguous if B is a logical mask array.
To me it seems more intuitive especially when Fortran code is a write-up of a Matlab/R/Numpy prototype.

Dick Hendrickson

unread,
Jun 13, 2014, 5:04:06 PM6/13/14
to
On 6/13/14, 3:27 PM, Lichtenberg wrote:
> How about
>
> ...
> integer :: N
> real :: A(N),B(N),x
> ...
> x = maxval(A(A<0 | B<0)) ?
>
OK, I see what you're getting at now. You confused me at first by
talking abut WHERE. I think of WHERE as a masked assignment statement.
But

x = maxval(A, A<0 .OR. B<0)

is reasonably close to what you have above. I think all of the
reduction functions have an optional mask argument.

> I disagree on A(B)-=1 being ambiguous if B is a logical mask array.

What I actually said was "is mildly ambiguous to the code reader". How
does the reader know that B is logical and not integer? Sure, they
should read the declarations and remember than, but ....

Dick Hendrickson

Richard Maine

unread,
Jun 13, 2014, 5:55:37 PM6/13/14
to
Dick Hendrickson <dick.hen...@att.net> wrote:

> On 6/13/14, 3:27 PM, Lichtenberg wrote:
> > How about
> >
> > ...
> > integer :: N
> > real :: A(N),B(N),x
> > ...
> > x = maxval(A(A<0 | B<0)) ?
> >
> OK, I see what you're getting at now. You confused me at first by
> talking abut WHERE. I think of WHERE as a masked assignment statement.
> But
>
> x = maxval(A, A<0 .OR. B<0)
>
> is reasonably close to what you have above. I think all of the
> reduction functions have an optional mask argument.
>
> > I disagree on A(B)-=1 being ambiguous if B is a logical mask array.
>
> What I actually said was "is mildly ambiguous to the code reader". How
> does the reader know that B is logical and not integer? Sure, they
> should read the declarations and remember than, but ....

I might also imagine that people used to some nonstandard Fortran
features might be further confused by it, as might the compilers that
implement those features. In particular, compilers with DEC heritage
often get a bit "sloppy" (my term for it) about intermixing integers and
logicals. So some people and compilers might essentially cast the
logical array to an integer one, which would then mean something, but
something different from the proposal here.

Yes, its a nonstandard feature, and I'm not sure of the details of its
application to this case anyway, but I'd bet on it confusing at least
some readers.

Heck, my first thought on seeing a noninteger used as an array index
would be that it looked like an associative array (which people have
also asked for in Fortran and which seems to me to have a lot bigger
impact than just looking a little better to some people).

I'd also be concerned about the impact on diagnosing errors. That's one
of the things I don't like about the DEC extension mentioned above; some
simple errors in coding turn into code that compiles but does the wrong
thing.

So I guess I'm seeing a claim that some readers used to the notation in
matlab might find it a little more clear, while others might find it
confusing. Seems to me like a wash at best. One might debate which camp
would be more numerous, but I don't see that the benefit is clear enough
to have much chance.

--
Richard Maine
email: last name at domain . net
domain: summer-triangle

Lichtenberg

unread,
Jun 13, 2014, 5:57:10 PM6/13/14
to
But user-defined reduction functions still require optional mask arguments to mimick similar behavior.
Logical indexing (or packing) eliminates that need.

Thanks for the hint anyway,
I overlooked those mask arguments in my copy of MFE/MRC (2011).

Lichtenberg

unread,
Jun 13, 2014, 6:05:31 PM6/13/14
to
Btw, does F-2008's norm2 support a mask argument?
I can't find any traces of it in my book.
This would make it at least inconsistent with the other functions.

JWM

unread,
Jun 13, 2014, 9:54:43 PM6/13/14
to
No, only DIM. But you can always use PACK as the first argument to
NORM2.

Actually it's better if the function has the optional MASK argument only
when it makes sense, instead of going for the theoretical "consistency
pattern". What should NORM2 return if all the elements in the MASK are
false? The euclidean norm of "nothing" is not defined, is it?

--
John.


Richard Maine

unread,
Jun 13, 2014, 10:08:26 PM6/13/14
to
JWM <jwmw...@gmail.com> wrote:

> Actually it's better if the function has the optional MASK argument only
> when it makes sense, instead of going for the theoretical "consistency
> pattern". What should NORM2 return if all the elements in the MASK are
> false? The euclidean norm of "nothing" is not defined, is it?

I abstain on the question of whether norm2 should have a mask argument.
But I don't see any particular problem relating to all elements of such
a mask being false. That would seem to be the same thing as having the
argument be an array of size zero. That's already allowed and, as far as
I can see, well-defined to give zero as a result.

Dick Hendrickson

unread,
Jun 13, 2014, 10:27:29 PM6/13/14
to
On 6/13/14, 9:08 PM, Richard Maine wrote:
> JWM <jwmw...@gmail.com> wrote:
>
>> Actually it's better if the function has the optional MASK argument only
>> when it makes sense, instead of going for the theoretical "consistency
>> pattern". What should NORM2 return if all the elements in the MASK are
>> false? The euclidean norm of "nothing" is not defined, is it?
>
> I abstain on the question of whether norm2 should have a mask argument.
> But I don't see any particular problem relating to all elements of such
> a mask being false. That would seem to be the same thing as having the
> argument be an array of size zero. That's already allowed and, as far as
> I can see, well-defined to give zero as a result.
>
My recollection is that a whole bunch of math functions were added to
F2008, all from a common C library. There were added into the intrinsic
list "as is". That was essentially a no cost options to the vendors
since they were almost for sure already supporting the functions for
their C compiler.

Dick Hendrickson

Arjen Markus

unread,
Jun 17, 2014, 5:48:08 AM6/17/14
to
Op vrijdag 13 juni 2014 22:27:03 UTC+2 schreef Lichtenberg:
You may get closer - at least with one-dimensional arrays using something like:

x = maxval( A( indices(A<0 .or. B<0) )

where the function indices could be defined as:

function indices( mask ) result(idx)
logical, dimension(:) :: mask

integer, dimension(:), allocatable :: idx
integer :: i, j

allocate( idx(count(mask)) )

j = 0
do i = 1,size(mask)
if ( mask(i) ) then
j = j + 1
idx(j) = i
endif
enddo
end function indices

Regards,

Arjen

Beliavsky

unread,
Jun 17, 2014, 8:27:59 AM6/17/14
to
On Friday, June 13, 2014 4:27:03 PM UTC-4, Lichtenberg wrote:
> How about
>
>
>
> ...
>
> integer :: N
>
> real :: A(N),B(N),x
>
> ...
>
> x = maxval(A(A<0 | B<0)) ?

You can write

x = maxval(pack(A,A < 0 .or. B < 0))

or

x = maxval(A,A < 0 .or. B < 0)

since maxval has an optional mask argument.
0 new messages