GNU Info

Info Node: (g77-295.info)Generics and Specifics

(g77-295.info)Generics and Specifics


Next: REAL() and AIMAG() of Complex Prev: %DESCR() Up: Functions and Subroutines
Enter node , (file) or (file)node

Generics and Specifics
----------------------

   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).


automatically generated by info2www version 1.2.2.9