6 Data Type Conversions—the DCV Routines

 6.1 Introduction
 6.2 An Example of Data Type Conversion
 6.3 Range Checking

6.1 Introduction

Occasionally, it may be necessary to convert data passed into a generic routine in a generic variable into another data type. A general set of conversion functions was originally provided within GENERIC to make this possible. However, new code requiring such conversions should invoke the PRIMDAT  library of functions. PRIMDAT also provides many other instrinsic functions that are amenable to inclusion in generic code. This section remains only to interpret legacy code that still calls DCV routines.

A naming convention is used so that the function DCV_<T1>TO<T2> converts data type <T1> into <T2>.

The functions which can be are defined using Fortran statement functions in a file which may be included in a program by

  INCLUDE ’DCV_FUN’

which should come after any data type definitions, but before any DATA initialisation or executable code. In the standard prologue of SGP/16, it should go in the “Internal References” section.

Conversions which cannot be defined as statement functions are provided as external functions in an object library (/star/lib/dcv.a on a Starlink system). Programs requiring these functions should be compiled

  % f77 prog.f -L/star/lib ‘dcv_link‘

on Unix.

The types of these functions can be declared in a program by including

  INCLUDE ’DCV_EXT’

(in the “External References” section of the standard prologue).

NOTE: Statement functions are considerably faster than external functions, so programs which use the common conversions defined in ‘DCV_FUN’ will execute a lot faster.

Only numeric conversions are supported at present, and there are no DCV_ functions for conversions involving CHARACTER and LOGICAL data types. A full list of the functions, the conversion performed, and their location and restrictions, is given in Appendix B.

6.2 An Example of Data Type Conversion

As an example, a generic subroutine for finding the mean of the data contained in an array, where the array is of varying type but the mean is always REAL, might look like the following routine.

            SUBROUTINE MEAN<T>( N, ARRAY, MEAN )
      *+
      *  Name:
      *     MEAN<T>
      *  Purpose:
      *     Calculate the mean value contained in a <COMM> array.
      *  Invocation :
      *     CALL MEAN<T>( N, ARRAY, MEAN )
      *  Description :
      *     This calculates the mean value of then data contained in the given
      *     <COMM> array, and returns the value in the REAL variable MEAN.
      *  Arguments:
      *     N = INTEGER( Given )
      *        The dimension of the array.
      *     ARRAY( N ) = <TYPE>( Given )
      *        The array containing the data to be averaged.
      *     MEAN = REAL( Returned )
      *        The mean of the values contained in the array.
      *                   "
      *     (the rest of the standard prologue)
      *                   "
      *  Type Definitions:
            IMPLICIT NONE
      *  Arguments Given:
            INTEGER N
            <TYPE> ARRAY( N )
      *  Arguments Returned:
            REAL MEAN
      *  External References:
            INCLUDE ’DCV_EXT’          ! Data conversion external functions
      *  Local Variables:
            INTEGER I                  ! Array index
            <LTYPE> SUM                ! Sum of the data in the array
      *  Internal References:
            INCLUDE ’DCV_FUN’          ! Data conversion statement functions
      *-
  
      *  Initialise the sum to zero.
            SUM = 0<CONST>
  
      *  Accumulate the sum of the contents of the array.
            DO I = 1, N
              SUM = SUM + ARRAY( N )
            END DO
  
      *  Divide by the dimension of the array to obtain the mean, using
      *  DCV_<T>TOR to convert from <COMM> into REAL.
            MEAN = DCV_<T>TOR( SUM ) / REAL( N )
  
            END

In the above example, for the INTEGER version of the routine for instance, the DCV_ITOR( SUM ) statement will be converted to REAL( SUM ) by the statement function in DCV_FUN.

6.3 Range Checking

The DCV_<T1>TO<T2> functions will not check the range of the values given to them, and overflow errors are possible from some conversions (e.g. INTEGER to BYTE). It is recommended that an application check the range of any value given to a DCV function, to ensure it is within the allowed range. Global parameters of the form DCV__<T>MIN and DCV__<T>MAX are available for this purpose, which give the allowed range for type <T> (e.g. − 128 to + 127 for a BYTE). These by may included in a program using the following line.

  INCLUDE ’DCV_PAR’

(in the “Global Parameters” section of the standard prologue).

Here is an example of the use of these parameters (for instance converting an INTEGER to another type).

      *             "
      *     (standard prologue)
      *             "
      *  Global Parameters:
            INCLUDE ’DCV_PAR’          ! DCV global parameters giving allowed
                                       ! ranges
      *             "
      *  External References:
            INCLUDE ’DCV_EXT’          ! DCV external function definitions
      *             "
      *  Local Variables:
            INTEGER IVAL               ! Integer value to be converted
            <TYPE> VAL                 ! Destination variable of type <COMM>
                      "
      *  Internal References:
            INCLUDE ’DCV_FUN’          ! DCV in-line statement functions
      *-
                    "
                    "
            IF ( ( IVAL .GE. DCV__<T>MIN ) .AND.
           :     ( IVAL .LE. DCV__<T>MAX ) ) THEN
  
      *  Value within range. The conversion is allowed.
               VAL = DCV_ITO<T>( IVAL )
  
            ELSE
  
      *  Error. Value out of range ...
               <take appropriate action>
            END IF
                    "
                    "

Note that ranges are only provided for numeric data types.

An alternative (and easier) way of preventing numerical overflow from causing problems is to use the PRIMDAT routines instead of the DCV ones. The PRIMDAT routines will not crash your program if an overflow occurs. See SUN/39 for details.