Silverfrost Forums

Welcome to our forums

Bug with maxloc, minloc

8 Aug 2011 4:57 (Edited: 9 Sep 2011 3:54) #8754

Maxloc and minloc intrinsics should return a scalar when the array has rank of 1 and DIM=1 is used. In the following code, the call at (A) returns an integer scalar which is assigned to the value of max_index. At (B) the value of the array element max_index is printed out.

However, when the two operations are combined at (C) (using maxloc to get the index but without using an intermediate variable) I get a compiler error. The compiler thinks the RHS is an array.

I know this seems a rather convoluted way to get the maximum (I could just use maxval), but actually in my application I am using maxloc and minloc to get indices of doubly indexed array sections like.

ind = ix(maxloc(x(ix(lower:upper)),1)+lower-1)

which exhibits the same bug but is harder to follow.

The example below is simpler.

program maxim
   implicit none
   
   integer :: max_index
   real :: x(5), max_val

   x = (/1.0, 2.0, 5.0, 4.0, 3.0/)

   ! (A) Maximum index should be 3
   max_index = maxloc(x(1:5), 1)
   print *,'Maximum is at location ', max_index, ' (should be 3)'

   ! (B) Max value should be 5.0
   print *, 'Maximum value is ', x(max_index), ' (should be 5.0)'

   ! (C) This line should compile should also give 5.0, but the compiler
   ! thinks that the RHS is an array and issues an error 945.

   !*****************************
   max_val = x(maxloc(x(1:5), 1))
   !*****************************

   print *, 'Maximum value is ', max_val, ' (should be 5.0)'

end program maxim
9 Aug 2011 12:40 (Edited: 11 Aug 2011 3:34) #8758

I'm no wiser than you are in terms of what goes on within the compiler and machine during conversion from array to scalar data when the rank is specified to be 1. But it is clear than when maxloc(x(1:5), 1) is used an an index to an array-typed variable, it is not 'seen' by the compiler as a 'normal' integer.

So you need a workaround.

INT function does not change the typing of the offending argument either. It is still seen as an array . . .

10 Aug 2011 5:35 #8765

I have noted this issue and logged it for investigation.

6 Sep 2011 3:06 #8913

This turns out to be a programming error. i.e. the error report is correct.

maxloc always returns an array even when its size is one hence the type miss-match.

You can assign the result of maxloc to a scalar in order to generate the type conversion etc.

7 Sep 2011 9:13 #8914

Quoted from PaulLaidler This turns out to be a programming error. i.e. the error report is correct.

maxloc always returns an array even when its size is one hence the type miss-match.

Thanks for investigating. But I don't quite understand.

Do you mean

It's my programming error, and the compilers error report is correct?

Or.

Its a programming error in the compiler, and my report is correct?

If the latter, I hope it can be fixed.

David.

7 Sep 2011 2:46 #8917

I meant to say that it is your programming error.

7 Sep 2011 7:59 #8920

OK I think you are right. If you have DIM = 1 then the result is supposed to be a scalar.

7 Sep 2011 9:05 #8921

Quoted from PaulLaidler I meant to say that it is your programming error.

OMG! It's not 😛 . It should be an integer scalar for rank 1 arrays when DIM is supplied.

If it was supposed to return an array, the compiler should be complaining when I assign the result to a scalar in (A) in my code example above.

Thank's brucebowler for checking the draft standard.

It is also clearly stated by Jeanne Adams et.al in 'The Fortran 2003 Handbook' :

'If DIM is absent it [the Result] is a rank-one array of size equal to the rank of n of ARRAY; if DIM is present and ARRAY is of rank-one, it is a scalar; otherwise, it is a rank one array of size n-1.'

To my mind this is self consistent. It just says that when DIM is given the result is an integer array of size one less than the array argument; and one less than 1 is 0, and the closest thing to an 'array of zero rank' in Fortran is a scalar.

What is the result for an array argument of rank 2 with DIM=1? Is it an array of rank 1 (as it should be) or an array of rank 2 (which would be incorrect)? Is there a more general bug here whereby the result is always one rank too many? (I haven't checked).

8 Sep 2011 12:13 #8922

My reading of this is that Paul was right the first time. I have extracted the description of MAXLOC from the Lahey fortran documentation, which indicates that the result is an array. Assuming the Lahey documentation is correct Fortran 95 syntax ( it always has been in the past)

MAXLOC Function

Description
Location of the first element in array having the maximum value of the elements identified 
by mask.

Syntax
MAXLOC (array, dim, mask)

Required Arguments
array must be of type INTEGER or REAL.  It must not be scalar.

Optional Arguments
dim must be a scalar INTEGER in the range 1 ≤ dim ≤ n , where n is the rank of array.  The 
corresponding dummy argument must not be an optional dummy argument.
mask must be of type LOGICAL and must be conformable with array.

Result
The result is of type default INTEGER. If dim is present, the result is an array of rank n-1 
where n is the rank of array.  The result values are the locations having the maximum value 
along dimension dim.
If dim is absent, the result is an array of rank one whose element values are the values of the 
subscripts of the first element in array to have the maximum value of all of the elements of 
array.  
If mask is present, the elements of array for which mask is false are not considered.

Example
integer, dimension(1) :: i
i = maxloc ((/3,0,4,4/)) ! i is assigned the value [3]

While 'maxloc' is returned as an array, it is possible to declare i as a scaler for the statement i = maxloc (...). It is not possible to use maxloc as an array subscript, which is the programing error. It is not a very friendly definition, as David's expectation shows, although using a function as an array subscript is not something I would try. David, you've deserted your F77 roots.

John

As a postscript, I find this definition a bit annoying. What does an array of dimension 1 and size 1 provide, apart from cleaning up a poor language definition. Indeed if 'i' is an array and 'j' is a scaler, what does j = i mean?

j = i(1) ! this would be correct i = j ! array filled with a scaler is ok, but j = i ! scaler filled with an array could only mean j = i(1)

If i was dimensioned as (2), and i(1) /= i(2), then how would we interpret j = i then. Somewhere along this line of thought something is wrong. As I have observed in the past, the Fortran Standard has been taken over by non Fortranites.

8 Sep 2011 5:48 #8923

Sorry guys for this confusion. With the volume of work that I get through, I do occasionally make mistakes, hopefully not too often.

The result in this particular case needs to be a scalar and both FTN95 and Lahey have sliped up on this detail.

If I can fix the bug, I will and hopefully no ones existing code will be broken.

8 Sep 2011 7:52 #8924

Thank you Paul.

I checked a few other compilers, NAG, Gfortran, open64 all return a scalar if DIM=1 and the array has rank 1 and comply with the draft standard.

8 Sep 2011 7:59 #8925

Quoted from JohnCampbell

David, you've deserted your F77 roots.

Only temporarily . F77 was my first language (well I did a bit of F66). 😄

8 Sep 2011 8:07 #8926

I have now looked in the latest standard that I have, and it shows 3 cases for MAXLOC, with case (iii) result being a scalar, as David has used and Bruce has indicated. However, if DIM is omitted (case (i)) then the result reverts to an array!

It's interesting to note that the standard shows the examples as Case (i) is: The value of MAXLOC ((/ 2,6,4,6 /)) is [2], while for Case(iii) is: The value of MAXLOC ((/ 5,-9,3 /), DIM=1) is 1

Can we take from this that '[2]' and '[2,1,2]' can be used as a valid alternative array syntax for '(/2/)' and '(/ 2,1,2 /)', as they are listed in the standard !! If it was good enough for those who wrote the standard, why not for us users ?

John

9 Sep 2011 3:52 #8937

Quoted from JohnCampbell I have now looked in the latest standard that I have, and it shows 3 cases for MAXLOC, with case (iii) result being a scalar, as David has used and Bruce has indicated. However, if DIM is omitted (case (i)) then the result reverts to an array!

It's interesting to note that the standard shows the examples as Case (i) is: The value of MAXLOC ((/ 2,6,4,6 /)) is [2], while for Case(iii) is: The value of MAXLOC ((/ 5,-9,3 /), DIM=1) is 1 John

Yes, this is the correct behaviour. The result is only a scalar in the special case of a rank 1 array when the DIM argument is provided and is 1. In all other valid cases you get an array.

, while for

Case(iii) is: The value of MAXLOC ((/ 5,-9,3 /), DIM=1) is 1 John

Yes, this is the correct behaviour. The result is only a scalar in the special case of a rank 1 array when the DIM argument is provided and is 1. In all other valid cases you get an array.

[quote:88b60fac06="JohnCampbell"]Can we take from this that '[2]' and '[2,1,2]' can be used as a valid alternative array syntax for '(/2/)' and '(/ 2,1,2 /)', as they are listed in the standard !! If it was good enough for those who wrote the standard, why not for us users ?

John

The array delimiters [ ] may be used instead of (/ and /) in Fortran 2003. But not in Fortran 95. (I am not sure if its an extension option in FTN95). It's certainly implemented in Gfortran, intel and NAG.

[u:88b60fac06]Edit[/u:88b60fac06]: I just tried it and [ ] is in fact an allowed F2003 extension in FTN95. I just ticked the F2003 extensions option in Plato, which is the /F2K option on the command line.

9 Sep 2011 8:51 #8945

One further point of interest, the values returned always assume a starting index of 1 so the following code should print 2 (not 4).

a = (/ 1.0, 2.0, 1.0, 5.0, 4.0, 2.0 /)
print *, maxloc(a(3:),1) !< should print 2
8 Mar 2012 11:11 #9773

The original bug in this thread has now been fixed for the next release.

The code immediately above now gives the expected result. I don't know if this was intended as a bug report but if it was a problem then it has got fixed along the way.

8 Mar 2012 6:13 #9775

Thank you for very much for fixing this. 😃

The code immediately above wasn't a bug report, just an observation that the maxloc function assumes that arrays start at 1 and doesn't account for the actual lower bound when taking an array section. In my original application (the 'quick select' algorithm using indices to an array) I need to take this fact into account when calculating the index into the array using maxloc.

Best Regards, David.

Please login to reply.