- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've found that if I have overloaded the intrinsic MAX function with any arbitrary function, I am no longer able to use the intrinsic MAX function with 10 or more arguments, but it still works for 2 to 9 arguments.
For a simple example consider a program that simply attempts to call the intrinsic MAX function twice, once with 9 arguments and once with 10 arguments. Now, assume we have a module max_mod that overloads the intrinsic MAX function with a dummy function that accepts a single integer input and returns it. If I modify the original program to add a USE max_mod statement it will no longer compile. Code for this example is below:
program prog1 implicit none real :: a a = max(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0) write (*, *) 'max of 9 numbers, expecting 9: ', a a = max(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) write (*, *) 'max of 10 numbers, expecting 10: ', a end program
This program compiles and works as expected. Next the module and the program using it:
module max_mod implicit none interface max module procedure max_dummy end interface max contains function max_dummy (i) integer, intent(in) :: i integer :: max_dummy max_dummy = i end function max_dummy end module max_mod program prog2 use max_mod implicit none real :: a a = max(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0) write (*, *) 'max of 9 numbers, expecting 9: ', a a = max(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) write (*, *) 'max of 10 numbers, expecting 10: ', a end program
This program will not compile, giving the error message
prog2.f90(20): error #6284: There is no matching specific function for this generic function reference. [MAX] a = max(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) --------^ compilation aborted for prog2.f90 (code 1)
I found it odd that there is no error when only 9 arguments are specified, but for 10 or more I see this compilation error. I had expected this to compile. Am I misunderstanding something or is this a bug?
I'm using Intel Fortran ifort (IFORT) 15.0.2 20150121. I have also tested with 14.0.0 20130728 and 12.0.0 20101006.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Looks like a bug to me. I will let the developers know - thanks. Issue ID DPD200379258. Affects MIN as well.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve. I forgot to mention MIN has this problem too, glad you spotted that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I know that the compiler has to "stand on its head" to support MAX and MIN with their variable argument lists - especially if you use the keyword form. The language doesn't have anything like this elsewhere. If I recall correctly, there's a bit of a separate code path for 10 or more arguments and this is probably where the issue lies. When I get any info on a fix I will let you know here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve, Andrew,
This is entering an area that I have yet to explore...
Can you clarify what you expect to happen in light of the fact that your interface max, which appears to be a generic interface to an interface max_dummy taking a single integer argument is to work with a max(...) statement taking multiple real arguments? (as used in your sample program)
IOW does the declaration in your code extend the intrinsic max function such that max(123) calls your function, max(123 ,456) calls the default max function (two args not specified in your definition), max(123.0) calls the default max function,...
Then, follow-up, how does one define a Fortran interface containing a variable number of arguments? (an argument equivalent to ellipsis in other languages)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Andrew's extension would come into effect only if one called MAX with a single integer argument. Since his program always calls MAX with multiple real arguments the calls are not "consistent with" the extension.
Section 12.5 of F2008 covers how name resolution works, and 12.5.5.2 in particular. There is an order to the consideration:
- Nonelemental reference to a specific interface of the generic
- Elemental reference to a specific interface of the generic
- If declared INTRINSIC in this scoping unit or USE makes accessible the name declared INTRINSIC, then that intrinsic
- Apply these rules to the next outer scoping unit (with a condition about whether the current and host scoping unit agree as to whether the name is a subroutine or a function - remember that you can't mix these in a generic (except that we sort-of allow this as a limited extension.))
- Otherwise, if it's an intrinsic, that intrinsic
How do you define a Fortran interface like MAX or MIN? You can't - that's why it's so weird.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
.. how does one define a Fortran interface containing a variable number of arguments? (an argument equivalent to ellipsis in other languages) ..
Jim,
Fyi, you'll see a note along the following lines in Fortran standard documents, the particular text below from draft Fortran 2015:
The C language allows specification of a C function that can take a variable number of arguments (ISO/IEC 9899:2011, 7.16). This part of ISO/IEC 1539 does not provide a mechanism for Fortran procedures to interoperate with such C functions.
As mentioned in another thread a while ago (by R.O.?), one might be able to get the variadic argument stuff o work with !DEC$ ATTRIBUTE VARYING.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am fairly certain that ATTRIBUTES VARYING is not of help here. Variadic functions typically pass the address of a list as corresponding to the "...". Regardless, there is no syntax for declaring a Fortran procedure that takes an unspecified number of arguments.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Intel) wrote:
I am fairly certain that ATTRIBUTES VARYING is not of help here. Variadic functions typically pass the address of a list as corresponding to the "...". Regardless, there is no syntax for declaring a Fortran procedure that takes an unspecified number of arguments.
Steve,
See this thread, especially Message #18 where R.O. shows a working example:
https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/544720
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I saw that, but I am still uncertain how well this works with variadic functions, or maybe my understanding of how they work is wrong. ATTRIBUTES VARYING can be used in an interface, as RO showed, to be able to pass "extra" arguments, but you had better get the types right.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Intel) wrote:
I saw that, but I am still uncertain how well this works with variadic functions, or maybe my understanding of how they work is wrong. ATTRIBUTES VARYING can be used in an interface, as RO showed, to be able to pass "extra" arguments, but you had better get the types right.
Makes sense - I personally prefer to avoid compiler directives for anything other with the necessary interfaces for OS-specific APIs and when it comes to variadic functions in C/C++, wrapper functions with a fixed set of arguments for interoperation with Fortran seems to keep it simple enough for me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For varying number of like arguments you could use an array constructor
! max_dummy.f90 module max_mod implicit none interface max module procedure max_dummy1 module procedure max_dummy2 module procedure max_dummyn end interface max contains function max_dummy1 (i) integer, intent(in) :: i integer :: max_dummy1 max_dummy1 = i end function max_dummy1 function max_dummy2 (i,j) integer, intent(in) :: i,j integer :: max_dummy2 if ( i .ge. j ) then max_dummy2 = i else max_dummy2 = j endif end function max_dummy2 recursive function max_dummyn (ia) integer, intent(in) :: ia(:) integer :: max_dummyn if( size(ia) .eq. 1 ) then max_dummyn = ia(lbound(ia,1)) else max_dummyn = max_dummy2(ia(lbound(ia,1)), max_dummyn(ia(lbound(ia,1)+1:ubound(ia,1)))) endif end function max_dummyn end module max_mod program prog2 use max_mod implicit none integer :: a a = max([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) write (*, *) 'max of 10 numbers, expecting 10: ', a end program
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
BTW line 30 can also read
max_dummyn = max(ia(lbound(ia,1)), max(ia(lbound(ia,1)+1:ubound(ia,1))))
Jim Dempsey

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page