- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The following (almost) minimal code triggers a strange bug with ifort & ifx 2021.2:
module mod1
implicit none
real, parameter :: z = sqrt (0.0)
end module mod1
module mod2
implicit none
type t
real :: a = 0.
end type
interface sqrt
module procedure sqrt
end interface
contains
function sqrt (a)
type(t), intent(in) :: a
type(t) :: sqrt
sqrt% a = a% a
end function sqrt
end module mod2
program test
use mod1
use mod2
implicit none
type(t) :: x, y
y = sqrt (x)
y% a = sqrt (x% a)
end program test
I obtain the following error:
% ifort intel-sqrt-ifc.f90
intel-sqrt-ifc.f90(28): error #6284: There is no matching specific function for this generic function reference. [SQRT]
y% a = sqrt (x% a)
---------^
compilation aborted for intel-sqrt-ifc.f90 (code 1)
The code compiles flawlessly with NAG and with Nvidia.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please submit a support request with Intel online service center if you are able to.
In the meantime, if you need to work your code with Intel Fortran in addition to other compilers, you can try this workaround which I expect will work with those other compilers as well:
program test
use mod1
use mod2
implicit none
type(t) :: x, y
y = sqrt (x)
block
intrinsic :: sqrt
y% a = sqrt (x% a)
end block
end program test
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@IanH wrote:
Alternatively, rename the specific procedure.
Or make it PRIVATE.
module mod2
implicit none
private
type, public :: t
real :: a = 0.
end type
generic, public :: sqrt => sqrt
contains
function sqrt (a)
type(t), intent(in) :: a
type(t) :: sqrt
sqrt% a = a% a
end function sqrt
end module mod2
C:\Temp>ifort /c /standard-semantics /warn:all /stand:f18 intel-sqrt-ifc.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.2.0 Build 20210228_000000
Copyright (C) 1985-2021 Intel Corporation. All rights reserved.
C:\Temp>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My contribution should fix your problem but maybe in not the most helpful. Please consider overloading intrinsics as a similar activity as juggling with chain saws.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@andrew_4619 : I strongly disagree. I overload intrinsics for use with derived types all the time. This makes programming much easier.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The overloading is perfectly legal and may generate some benefits, each to their own. My problem is that I understand Fortran, when you overload you have changed the meaning of an intrinsic. A third party starting to look at the code reads "apple" and expects it to be an apple when in fact it may now be a pear. If you made a unique thing e.g sqrt_t than you can still have the same functionality whilst being clearer.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You cannot replace an intrinsic (for standard argument types) with generic extension. I recall there was a case recently where the Intel compiler was improperly allowing this in some circumstances. The only thing you can do with extension of a generic intrinsic is to define it for argument lists not specified by the standard.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Steve_Lionel wrote:
You cannot replace an intrinsic (for standard argument types) with generic extension. I recall there was a case recently where the Intel compiler was improperly allowing this in some circumstances. The only thing you can do with extension of a generic intrinsic is to define it for argument lists not specified by the standard.
I don't understand what this means. The standard, per section 15.4.3 Specification of the procedure interface, suggests it is indeed possible to override an intrinsic procedure in the case of "standard argument types".
The confusion that can come about is with the programmer choice of specific procedure names in a generic interface, the standard asks that it be a nonintrinsic procedure with an explicit interface. Compiler implementations (e.g., gfortran) have had problems with this from what I've seen. To the extent a coder doesn't make it too confusing, a conforming processor can be expected to handle overrides such as this: as to whether it's advisable is a different matter altogether.
module m
private
generic, public :: sqrt => sqrt
contains
function sqrt( x ) result( r )
real, intent(in) :: x
real :: r
print *, "Using pocket calculator method:"
r = exp( 0.5*log(x) )
end function
end module
use m
print *, "sqrt(2.0) = ", sqrt(2.0)
end
C:\Temp>ifort /standard-semantics /warn:all /stand:f18 q.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.2.0 Build 20210228_000000
Copyright (C) 1985-2021 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 14.28.29337.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:q.exe
-subsystem:console
q.obj
C:\Temp>q.exe
Using pocket calculator method:
1.414214
C:\Temp>
The case where Intel compiler was non-conforming had to do with intrinsic operations, not intrinsic procedures. The standard never intended an override of intrinsic operations but that is different from intrinsic procedures.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@FortranFan , would you please point to the specific paragraph or lines of the standard that, according to you, allows one to replace an intrinsic procedure through generic extension? I don't think this is correct, especially as it would violate 15.4.3.4.1p2, which says (in part), "The rules specifying how any two procedures with the same generic identifier shall differ are given in 15.4.3.4.5. They ensure that any generic invocation applies to at most one specific procedure."
The same applies to generic operators. You can extend them by adding meanings the standard does not provide, but you can't, for example, make "2+2" call your own addition routine, just as you can't replace SQRT(REAL) unless you completely replace the standard intrinsic name in a scope.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Steve_Lionel wrote:
.. would you please point to the specific paragraph or lines of the standard that, according to you, allows one to replace an intrinsic procedure through generic extension? ..
It will be more helpful if you first explain what you meant by, "You cannot replace an intrinsic (for standard argument types) with generic extension." By this statement, did you meant the following code does not conform to the standard? (note: it's a variant of the snippet upthread but the Fortran 2018 GENERIC statement has been replaced by the Fortran 90 and later INTERFACE block to allow parsing with different compilers). If that is what you meant, then you will find the standard and almost all the compilers disagree.
module m
interface sqrt
module procedure sqrt
end interface
public :: sqrt !<-- superfluous; included for one compiler's sake
contains
function sqrt( x ) result(r)
real, intent(in) :: x
real :: r
write(*,*) "Using pocket calculator method:"
r = exp( 0.5*log(x) )
end function
end module
use m, only : sqrt
real :: x
x = sqrt(2.0)
write(*, "('sqrt(2.0) = ', f14.6)") x
end
Here the generic interface identifier is "overriding" the intrinsic SQRT procedure; one then has to employ the INTRINSIC attribute to reference the intrinsic SQRT.
Arguably what the standard does is effectively permission-by-omission here. Unlike with defined operations where in section 15.4.3.4.2 Defined operations, paragraph 1, lines 10 thru' 13 (page 305) where the standard states, "If the operator is an intrinsic-operator (R608), the number of dummy arguments shall be consistent with the intrinsic uses of that operator, and the types, kind type parameters, or ranks of the dummy arguments shall differ from those required for the intrinsic operation (10.1.5)," there is no corresponding stipulation with intrinsic procedures and my take is it's by design.
The notion of allowing an override of an intrinsic procedure is then spread subtly across section 15.4.3. And statements such as, "If a generic invocation is consistent with both a specific procedure from an interface and an accessible intrinsic procedure, it is the specific procedure from the interface that is referenced," provide a gentle hint toward its support. One will be hard-pressed to find a processor conformant to Fortran 90 even that does not compile the code posted in this thread to a program giving the following output:
C:\Temp>f90 q.f90
Compaq Visual Fortran Optimizing Compiler Version 6.6 (Update C)
Copyright 2003 Compaq Computer Corp. All rights reserved.
q.f90
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
/subsystem:console
..
/out:q.exe
C:\Temp>q.exe
Using pocket calculator method:
sqrt(2.0) = 1.414214
C:\Temp>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are correct. I was confusing the rule for operators with that for intrinsics.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A generic interface (replacing an intrinsic interface) does not extend the interface with alternate arguments (as is done with C++). It replaces it.
You may have luck defining the interface sqrt to use, for example, three interface functions:
sqrt_t(ArgOfType_t)
sqrt_real(ArgOfType_real)
sqrt_double(ArgOfType_double)
In the case of the implementation of the last two, you would have to hide your generic interface from the intrinsic interface (as mentioned by earlier post or by other means).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@jimdempseyatthecove wrote:
A generic interface (replacing an intrinsic interface) does not extend the interface with alternate arguments (as is done with C++). It replaces it. ..
Jim, I don't understand what you mean here.
Fortran standard document only seems to mention the "replaces it" aspect i.e., an override semantics when a generic invocation is consistent with a specific procedure in a generic interface and an intrinsic procedure. This is not the case with the original post where the generic interface can be viewed as "extending" the interface.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim, I do not see any replacement of an intrinsic. It was always legal to add interfaces to an existing one, which is sort of implicit for the intrinsics.
Let me note that replacing in the main the line
use mod1
by
use mod1, only: z
makes the code compile. Thus module mod1 is the/a troublemaker.
My question is: how can that happen?
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page