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

Strange result with MAXLOC/MINLOCK and the BACK argument

290 views
Skip to first unread message

Arjen Markus

unread,
Nov 9, 2016, 9:52:17 AM11/9/16
to
Hello,

I was dabbling a bit with the new Fortran 2008 feature for MINLOC and MAXLOC, that is, using a last argument to control what happens if the extreme value occurs in several places.

Here is the program:

program chk_maxloc_backward
implicit none

integer, dimension(10) :: array = (/ 1, 5, 3, 4, 5, 1, 2, 3, 4, 5 /)

write( *, '(a)' ) 'Location of minimum and maximum values - with duplicates'

write( *, '(a,i5)' ) ' Minimum (first): ', minloc(array)
write( *, '(a,i5)' ) ' Minimum (first): ', minloc(array, .false.)
write( *, '(a,i5)' ) ' Minimum (last): ', minloc(array, .true.)
write( *, '(a,i5)' ) ' Maximum (first): ', maxloc(array)
write( *, '(a,i5)' ) ' Maximum (first): ', maxloc(array, .false.)
write( *, '(a,i5)' ) ' Maximum (last): ', maxloc(array, .true.)

end program chk_maxloc_backward

To my astonishment the output was:

Location of minimum and maximum values - with duplicates
Minimum (first): 1
Minimum (first): 0
Minimum (last): 1
Maximum (first): 2
Maximum (first): 0
Maximum (last): 2

consistently with Intel Fortran and gfortran.

I had expected: 1, 1, 6, 2, 2, 10 as values.

I think I know what is happening: the second argument is the mask, not the backward option. But shouldn't the mask be an array of the same shape as the first argument?

To get this right, I need to use the name of the last argument, I guess, but what is that exactly?

Regards,

Arjen

michael...@compuserve.com

unread,
Nov 9, 2016, 10:41:29 AM11/9/16
to
The mask has to conformable with the array, and a scalar is conformable with any array (MFE, bottom of p. 46).

Regards,

Mike Metcalf

Steve Lionel

unread,
Nov 9, 2016, 11:04:19 AM11/9/16
to
On 11/9/2016 9:52 AM, Arjen Markus wrote:

>
> To my astonishment the output was:
>
> Location of minimum and maximum values - with duplicates
> Minimum (first): 1
> Minimum (first): 0
> Minimum (last): 1
> Maximum (first): 2
> Maximum (first): 0
> Maximum (last): 2
>
> consistently with Intel Fortran and gfortran.

I'll note for those who may try this on their own - the Intel Fortran
compiler's default for MAXLOC or MINLOC where the mask is all false
isn't conforming with the current standard. Use -assume noold_maxinloc
or -standard-semantics to get standard behavior (which will be a bit
slower.) Arjen evidently used one of these options with ifort.

--
Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/
Intel Software Development Products Support
http://software.intel.com/sites/support/
My Fortran blog
http://www.intel.com/software/drfortran

Refer to http://software.intel.com/en-us/articles/optimization-notice
for more information regarding performance and optimization choices in
Intel software products.

Arjen Markus

unread,
Nov 9, 2016, 11:10:56 AM11/9/16
to
Thank you both for the information - it took me by surprise yesterday and I never realised that a logical scalar fits neatly in the slot for the mask.

What is the name of the last argument, so that I can do:

write(*,*) minloc( array, proper-name = .true. )

I have not found it so far.

Regards,

Arjen

michael...@compuserve.com

unread,
Nov 9, 2016, 11:47:12 AM11/9/16
to
proper-name is back (MFE 20.11.4).

Mike

herrman...@gmail.com

unread,
Nov 9, 2016, 1:20:21 PM11/9/16
to
On Wednesday, November 9, 2016 at 6:52:17 AM UTC-8, Arjen Markus wrote:

> I was dabbling a bit with the new Fortran 2008 feature for MINLOC
> and MAXLOC, that is, using a last argument to control what happens
> if the extreme value occurs in several places.

(snip)

> write( *, '(a,i5)' ) ' Minimum (first): ', minloc(array)
> write( *, '(a,i5)' ) ' Minimum (first): ', minloc(array, .false.)
> write( *, '(a,i5)' ) ' Minimum (last): ', minloc(array, .true.)
> write( *, '(a,i5)' ) ' Maximum (first): ', maxloc(array)
> write( *, '(a,i5)' ) ' Maximum (first): ', maxloc(array, .false.)
> write( *, '(a,i5)' ) ' Maximum (last): ', maxloc(array, .true.)

Looks to me that for two arguments it should be ARRAY and DIM:

MAXLOC (ARRAY, DIM [, MASK, KIND, BACK])

and of course DIM shouldn't be LOGICAL.

There is also: MAXLOC (ARRAY [, MASK, KIND, BACK])

which looks to me like the one or four argument form.

Richard Maine

unread,
Nov 9, 2016, 2:15:54 PM11/9/16
to
No. That's not the way the optionality notation works. It is not like
the use of [] in BNF. The [] around a set of arguments means that those
arguments are optional. When the brackets surround multiple arguments,
it does *NOT* mean that it is an all-or-none thing. If you look at the
intrinsics, you will see several that would obviously be ludicrous if
that were the meaning. For a great example, look at date_and_time. Do
you really think that the only two valid forms for date_and_time are to
specify all of the arguments or none of them? (Slightly amusing that
specifying none is actually a valid option, though I can imagine useful
cases of that). Plenty of other examples; that's just a particularly
ludicrous one. But in short, just no; that's not the meaning of that
syntax. See f2003 Note 13.2 for specific examples of how to interpret
the syntax.

You really can't catch all the possibilities for arguments using BNF, so
the standard doesn't try. It could have used overly verbose syntax like

MAXLOC(ARRAY [, MASK [, KIND], BACK]]])

which at least would describe the purely positional cases, but that
still wouldn't describe the possibilities with keyword arguments. In the
words of the standard (f2003 13.2) "the names of the optional arguments
are enclosed in square brackets in the description headings and in lists
of procediures." Nothing about having to use all of them if you use any.
Again, this is *NOT* bnf; it is just a concise way to indicate which
arguments are optional.

You can call MAXLOC with 2 positional arguments and have the 2nd
argument be either MASK or DIM. Which it is depends on the type.

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

herrman...@gmail.com

unread,
Nov 9, 2016, 2:32:34 PM11/9/16
to
On Wednesday, November 9, 2016 at 11:15:54 AM UTC-8, Richard Maine wrote:

(snip, I wrote)

> > Looks to me that for two arguments it should be ARRAY and DIM:

> > MAXLOC (ARRAY, DIM [, MASK, KIND, BACK])

> > and of course DIM shouldn't be LOGICAL.

> > There is also: MAXLOC (ARRAY [, MASK, KIND, BACK])

> > which looks to me like the one or four argument form.

> No. That's not the way the optionality notation works. It is not like
> the use of [] in BNF. The [] around a set of arguments means that those
> arguments are optional. When the brackets surround multiple arguments,
> it does *NOT* mean that it is an all-or-none thing.

I think I knew that, but was still confused for this case.

> If you look at the
> intrinsics, you will see several that would obviously be ludicrous if
> that were the meaning. For a great example, look at date_and_time. Do
> you really think that the only two valid forms for date_and_time are to
> specify all of the arguments or none of them? (Slightly amusing that
> specifying none is actually a valid option, though I can imagine useful
> cases of that). Plenty of other examples; that's just a particularly
> ludicrous one. But in short, just no; that's not the meaning of that
> syntax. See f2003 Note 13.2 for specific examples of how to interpret
> the syntax.

> You really can't catch all the possibilities for arguments using BNF, so
> the standard doesn't try. It could have used overly verbose syntax like

> MAXLOC(ARRAY [, MASK [, KIND], BACK]]])

Yes, that is what I would have liked to see.

Well, the other thought which I didn't mention, and Steve also
didn't mention, is, as far as I know the Intel compiler still has
the DEC Fortran feature of converting between INTEGER and
LOGICAL, such that .FALSE. could be converted to INTEGER.

He didn't explain what -assume noold_maxinloc does.

> which at least would describe the purely positional cases, but that
> still wouldn't describe the possibilities with keyword arguments. In the
> words of the standard (f2003 13.2) "the names of the optional arguments
> are enclosed in square brackets in the description headings and in lists
> of procediures." Nothing about having to use all of them if you use any.
> Again, this is *NOT* bnf; it is just a concise way to indicate which
> arguments are optional.

> You can call MAXLOC with 2 positional arguments and have the 2nd
> argument be either MASK or DIM. Which it is depends on the type.

Seems that they could have made that more obvious.

Richard Maine

unread,
Nov 9, 2016, 3:03:00 PM11/9/16
to
<herrman...@gmail.com> wrote:

> On Wednesday, November 9, 2016 at 11:15:54 AM UTC-8, Richard Maine wrote:

> > You really can't catch all the possibilities for arguments using BNF, so
> > the standard doesn't try. It could have used overly verbose syntax like
>
> > MAXLOC(ARRAY [, MASK [, KIND], BACK]]])
>
> Yes, that is what I would have liked to see.

> > You can call MAXLOC with 2 positional arguments and have the 2nd
> > argument be either MASK or DIM. Which it is depends on the type.
>
> Seems that they could have made that more obvious.

Lots of people tried pretty hard, with the result being what we have
now. Its not as though someone just threw this in without debate. There
was quite a lot of discussion on it. I can pretty much guarantee that no
matter what syntax you opted for, some people would have found it
confusing. I know that because a lot of those options were looked at and
people did in fact find them confusing.

For example, the notation above that you say you would have liked leads
to the "obvious" conclusion that you can't specify BACK unless you also
specify MASK and KIND. Maybe it doesn't imply that to you, but it did to
some people. That conclusion, by the way, would be wrong; you can
specify it using a keyword, but the syntax misses that. Trying too hard
to make it look like BNF can make people read it too literally as BNF
and forget about all those other syntax options. These abbreviated
headers are to describe the intrinsic in general - not just the
positional syntax.

Anyway, regardless of what you might have preferred, that's the way it
is. There are also things I would have preferred to be different.

Tim Prince

unread,
Nov 9, 2016, 3:09:06 PM11/9/16
to
This might be one more reason why that old DEC extension should come
into play only when specifically requested.
>
> He didn't explain what -assume noold_maxinloc does.
noold_maxminloc produces a different result (compliant with standard)
for zero-length argument. It also prevents simd parallel reduction
optimization.
>
>> which at least would describe the purely positional cases, but that
>> still wouldn't describe the possibilities with keyword arguments. In the
>> words of the standard (f2003 13.2) "the names of the optional arguments
>> are enclosed in square brackets in the description headings and in lists
>> of procediures." Nothing about having to use all of them if you use any.
>> Again, this is *NOT* bnf; it is just a concise way to indicate which
>> arguments are optional.
>
>> You can call MAXLOC with 2 positional arguments and have the 2nd
>> argument be either MASK or DIM. Which it is depends on the type.
>
> Seems that they could have made that more obvious.
>
I had thought that it would be necessary always to use keyword names
when skipping any optional arguments or changing the order. But I think
others have recommended using DIM= etc. since it's not so easy to
remember what it means without the keyword.

Richard Maine

unread,
Nov 9, 2016, 3:31:13 PM11/9/16
to
Tim Prince <tpr...@computer.org> wrote:

> I had thought that it would be necessary always to use keyword names
> when skipping any optional arguments or changing the order. But I think
> others have recommended using DIM= etc. since it's not so easy to
> remember what it means without the keyword.

I forget all the details, it having been about 25 years ago, but part of
the messiness of maxloc/minloc comes from a historical compatibility
issue. MAXlLOCand MINLOC were introduced in f90 without the DIM
argument, so of course, MASK was the 2nd argument and could be specified
as such positionally. (I'd think it clearer to use the keyword form, but
positional was valid). Then when DIM was added in f95, there was a
desire to make it be the 2nd argument. Darned if I recall why, sorry
about my failure to recall that. Describing it as two separate forms,
much like generics can work in general, allowed DIM to be put as a 2nd
positional argument without invalidating f90 code that used MASK as the
2nd positional argument.

Do note that it is not described as skipping the MASK argument; it is a
separate form. Think of it as if it were 2 specifics for the same
generic. (It isn't completely accurate to describe them as specifics, as
they are actually both generic and the intrinsics aren't otherwise
described as collections of specifics anyway, but it gives you the
general idea).

Steve Lionel

unread,
Nov 9, 2016, 4:17:07 PM11/9/16
to
On 11/9/2016 2:32 PM, herrman...@gmail.com wrote:
> He didn't explain what -assume noold_maxinloc does.

The default, old_maxminloc, initializes the result to 1 and then
replaces it as it goes through the array if it finds a value larger
(MAX) or smaller (MIN) than the first element. (If BACK=.TRUE. then
substitute index of last element - keep in mind that these intrinsics
ignore lower bounds and always start at 1.)

If noold_maxminloc is specified and MASK is present, extra code keeps
track if any MASK elements were true, and if not, the result is zero.
This extra code inhibits vectorization.

Arjen Markus

unread,
Nov 10, 2016, 2:44:58 AM11/10/16
to
Well, I tried that with both gfortran and Intel Fortran, both complain that BACK is invalid (just checked it to be certain).

Regards,

Arjen

Arjen Markus

unread,
Nov 10, 2016, 2:47:09 AM11/10/16
to
Here are the messages:

(gfortran 5.4.0)
chk_maxloc_backward.f90:12:49:

write( *, '(a,i5)' ) ' Minimum (first): ', minloc(array, back = .false.)
1
Error: Can't find keyword named ‘back’ in call to ‘minloc’ at (1)

(Intel Fortran)
Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.1.148 Build 20141023
Copyright (C) 1985-2014 Intel Corporation. All rights reserved.

chk_maxloc_backward.f90(12): error #6503: This keyword is invalid for this intrinsic procedure reference. [BACK]
write( *, '(a,i5)' ) ' Minimum (first): ', minloc(array, back = .false.)
----------------------------------------------------------------^
compilation aborted for chk_maxloc_backward.f90 (code 1)


Regards,

Arjen

michael...@compuserve.com

unread,
Nov 10, 2016, 3:28:01 AM11/10/16
to
On Thursday, 10 November 2016 08:47:09 UTC+1, Arjen Markus wrote:
> >
> > Well, I tried that with both gfortran and Intel Fortran, both complain that BACK is invalid (just checked it to be certain).
> >
> > Regards,
> >
> > Arjen
>
> Here are the messages:
>
> (gfortran 5.4.0)
> chk_maxloc_backward.f90:12:49:
>
> write( *, '(a,i5)' ) ' Minimum (first): ', minloc(array, back = .false.)
> 1
> Error: Can't find keyword named ‘back’ in call to ‘minloc’ at (1)
>
> (Intel Fortran)
> Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.1.148 Build 20141023
> Copyright (C) 1985-2014 Intel Corporation. All rights reserved.
>
> chk_maxloc_backward.f90(12): error #6503: This keyword is invalid for this intrinsic procedure reference. [BACK]
> write( *, '(a,i5)' ) ' Minimum (first): ', minloc(array, back = .false.)
> ----------------------------------------------------------------^
> compilation aborted for chk_maxloc_backward.f90 (code 1)
>
>
> Regards,
>
> Arjen

According to the document at http://www.fortranplus.co.uk/fortran-information/, only Cray and IBM have implemented this feature.

Regards,

Mike

Arjen Markus

unread,
Nov 10, 2016, 3:36:24 AM11/10/16
to
Ah, that explains the problem! My mistake - I assumed it worked with these two compilers because the program was accepted by both, even if the results were unexpected :). Just shows how you can allow yourself to be fooled and to travel along the wrong road because of that.

Regards,

Arjen

Tim Prince

unread,
Nov 10, 2016, 7:27:20 AM11/10/16
to
Intel has said that f2008 intrinsics including findloc (presumably
including BACK) would be introduced in their next major release (within
a year).
0 new messages