Next: REAL() and AIMAG() of Complex, Previous: %DESCR(), Up: Functions and Subroutines

The ANSI FORTRAN 77 language defines generic and specific intrinsics. In short, the distinctions are:

*Specific*intrinsics have specific types for their arguments and a specific return type.*Generic*intrinsics are treated, on a case-by-case basis in the program's source code, as one of several possible specific intrinsics.Typically, a generic intrinsic has a return type that is determined by the type of one or more of its arguments.

The GNU Fortran language generalizes these concepts somewhat,
especially by providing intrinsic subroutines and generic
intrinsics that are treated as either a specific intrinsic subroutine
or a specific intrinsic function (e.g. `SECOND`

).

However, GNU Fortran avoids generalizing this concept to the point where existing code would be accepted as meaning something possibly different than what was intended.

For example, `ABS`

is a generic intrinsic, so all working
code written using `ABS`

of an `INTEGER`

argument
expects an `INTEGER`

return value.
Similarly, all such code expects that `ABS`

of an `INTEGER*2`

argument returns an `INTEGER*2`

return value.

Yet, `IABS`

is a *specific* intrinsic that accepts only
an `INTEGER(KIND=1)`

argument.
Code that passes something other than an `INTEGER(KIND=1)`

argument to `IABS`

is not valid GNU Fortran code, because
it is not clear what the author intended.

For example, if ``J`' is `INTEGER(KIND=6)`

, ``IABS(J)`'
is not defined by the GNU Fortran language, because the programmer
might have used that construct to mean any of the following, subtly
different, things:

- Convert `
`J`' to`INTEGER(KIND=1)`

first (as if ``IABS(INT(J))`' had been written). - Convert the result of the intrinsic to
`INTEGER(KIND=1)`

(as if ``INT(ABS(J))`' had been written). - No conversion (as if `
`ABS(J)`' had been written).

The distinctions matter especially when types and values wider than
`INTEGER(KIND=1)`

(such as `INTEGER(KIND=2)`

), or when
operations performing more “arithmetic” than absolute-value, are involved.

The following sample program is not a valid GNU Fortran program, but might be accepted by other compilers. If so, the output is likely to be revealing in terms of how a given compiler treats intrinsics (that normally are specific) when they are given arguments that do not conform to their stated requirements:

PROGRAM JCB002 C Version 1: C Modified 1999-02-15 (Burley) to delete my email address. C Modified 1997-05-21 (Burley) to accommodate compilers that implement C INT(I1-I2) as INT(I1)-INT(I2) given INTEGER*2 I1,I2. C C Version 0: C Written by James Craig Burley 1997-02-20. C C Purpose: C Determine how compilers handle non-standard IDIM C on INTEGER*2 operands, which presumably can be C extrapolated into understanding how the compiler C generally treats specific intrinsics that are passed C arguments not of the correct types. C C If your compiler implements INTEGER*2 and INTEGER C as the same type, change all INTEGER*2 below to C INTEGER*1. C INTEGER*2 I0, I4 INTEGER I1, I2, I3 INTEGER*2 ISMALL, ILARGE INTEGER*2 ITOOLG, ITWO INTEGER*2 ITMP LOGICAL L2, L3, L4 C C Find smallest INTEGER*2 number. C ISMALL=0 10 I0 = ISMALL-1 IF ((I0 .GE. ISMALL) .OR. (I0+1 .NE. ISMALL)) GOTO 20 ISMALL = I0 GOTO 10 20 CONTINUE C C Find largest INTEGER*2 number. C ILARGE=0 30 I0 = ILARGE+1 IF ((I0 .LE. ILARGE) .OR. (I0-1 .NE. ILARGE)) GOTO 40 ILARGE = I0 GOTO 30 40 CONTINUE C C Multiplying by two adds stress to the situation. C ITWO = 2 C C Need a number that, added to -2, is too wide to fit in I*2. C ITOOLG = ISMALL C C Use IDIM the straightforward way. C I1 = IDIM (ILARGE, ISMALL) * ITWO + ITOOLG C C Calculate result for first interpretation. C I2 = (INT (ILARGE) - INT (ISMALL)) * ITWO + ITOOLG C C Calculate result for second interpretation. C ITMP = ILARGE - ISMALL I3 = (INT (ITMP)) * ITWO + ITOOLG C C Calculate result for third interpretation. C I4 = (ILARGE - ISMALL) * ITWO + ITOOLG C C Print results. C PRINT *, 'ILARGE=', ILARGE PRINT *, 'ITWO=', ITWO PRINT *, 'ITOOLG=', ITOOLG PRINT *, 'ISMALL=', ISMALL PRINT *, 'I1=', I1 PRINT *, 'I2=', I2 PRINT *, 'I3=', I3 PRINT *, 'I4=', I4 PRINT * L2 = (I1 .EQ. I2) L3 = (I1 .EQ. I3) L4 = (I1 .EQ. I4) IF (L2 .AND. .NOT.L3 .AND. .NOT.L4) THEN PRINT *, 'Interp 1: IDIM(I*2,I*2) => IDIM(INT(I*2),INT(I*2))' STOP END IF IF (L3 .AND. .NOT.L2 .AND. .NOT.L4) THEN PRINT *, 'Interp 2: IDIM(I*2,I*2) => INT(DIM(I*2,I*2))' STOP END IF IF (L4 .AND. .NOT.L2 .AND. .NOT.L3) THEN PRINT *, 'Interp 3: IDIM(I*2,I*2) => DIM(I*2,I*2)' STOP END IF PRINT *, 'Results need careful analysis.' END

No future version of the GNU Fortran language
will likely permit specific intrinsic invocations with wrong-typed
arguments (such as `IDIM`

in the above example), since
it has been determined that disagreements exist among
many production compilers on the interpretation of
such invocations.
These disagreements strongly suggest that Fortran programmers,
and certainly existing Fortran programs, disagree about the
meaning of such invocations.

The first version of `JCB002`

didn't accommodate some compilers'
treatment of ``INT(I1-I2)`' where ``I1`' and ``I2`' are
`INTEGER*2`

.
In such a case, these compilers apparently convert both
operands to `INTEGER*4`

and then do an `INTEGER*4`

subtraction,
instead of doing an `INTEGER*2`

subtraction on the
original values in ``I1`' and ``I2`'.

However, the results of the careful analyses done on the outputs
of programs compiled by these various compilers show that they
all implement either ``Interp 1`' or ``Interp 2`' above.

Specifically, it is believed that the new version of `JCB002`

above will confirm that:

- Digital Semiconductor (“DEC”) Alpha OSF/1, HP-UX 10.0.1, AIX 3.2.5
`f77`compilers all implement ``Interp 1`'. - IRIX 5.3
`f77`compiler implements ``Interp 2`'. - Solaris 2.5, SunOS 4.1.3, DECstation ULTRIX 4.3,
and IRIX 6.1
`f77`compilers all implement ``Interp 3`'.

If you get different results than the above for the stated compilers, or have results for other compilers that might be worth adding to the above list, please let us know the details (compiler product, version, machine, results, and so on).