Processing math: 100%

14 PRIMDAT – Primitive data processing

The PRIMDAT package (see SUN/39) provides a range of symbolic constants, functions and subroutines which aid in the processing of numeric data. Facilities to cope with all HDS numeric data types are included; manipulation involving the non-numeric types, _LOGICAL and _CHAR can be done using the CHR routines as described in Section 11.

The names of the routines and constants described below usually end with a one or two letter code appropriate to the data type to which they apply. These codes are R, D, I, W, UW, B or UB corresponding to the HDS data types _REAL, _DOUBLE, _INTEGER, _WORD, _UWORD, _BYTE, and _UBYTE respectively. For example, VAL__BADR is the symbolic constant which represents the bad data value for _REAL data, whereas VAL__BADUB represents the bad data value for _UBYTE data.

VAL, NUM and VEC routines.

The example program in Section 12 contained a subroutine which simply calculated the square root of the input data array and dealt correctly with bad data values. However the PRIMDAT package contains a set of general purpose routines which includes just such a subroutine. There are three sets of routines, which can be summarised as follow:

VAL_ functions – these perform arithmetic operations and type conversion on scalar values. Bad data handling is incorporated.
NUM_ functions – these are like the VAL routines except that bad data handling is not incorporated; numerical errors can cause these routines to crash and bad input values are interpreted literally.
VEC_ routines – these are subroutines which perform the same operations as the VAL functions but operate on arrays of numbers.

The name of a routine consists of one of the above prefixes, plus an indication of the function it performs and the type of data it expects. For example, the name of the subroutine which takes the square root of a double-precision input data array is VEC_SQRTD. There are also type conversion routines. For example, VEC_RTOI converts a real array to an integer one. A list of the formats of the routines is shown in the table on the following page.

The tables below indicate the range of arithmetic operations available. The functions in the left-hand table are implemented for all the HDS numeric types. The trigonometric functions in the right-hand table are implemented only for types _REAL and _DOUBLE; those trigonometric functions whose name ends with D operate in degrees; the others use radians.




Func Narg Operation performed



ADD 2 addition: ARG1 + ARG2
SUB 2 subtraction: ARG1 ARG2
MUL 2 multiplication: ARG1 ARG2
DIV 2 *(floating) division: ARG1 / ARG2
IDV 2 **(integer) division: ARG1 / ARG2
PWR 2 raise to power: ARG1 ARG2
NEG 1 negate (change sign): ARG
SQRT 1 square root: ARG
LOG 1 natural logarithm: ln(ARG)
LG10 1 common logarithm: log10(ARG)
EXP 1 exponential: exp(ARG)
ABS 1 absolute value: |ARG|
NINT 1 nearest integer value to ARG
INT 1 Fortran AINT (truncation to integer) fn.
MAX 2 maximum: max(ARG1,ARG2)
MIN 2 minimum: min(ARG1,ARG2)
DIM 2 Fortran DIM (positive difference) fn.
MOD 2 Fortran MOD (remainder) fn.
SIGN 2 Fortran SIGN (transfer of sign) fn.



       



Func Narg Operation performed



SIN 1 sin(ARG)
SIND 1 sin(ARG)
COS 1 cos(ARG)
COSD 1 cos(ARG)
TAN 1 tan(ARG)
TAND 1 tan(ARG)
ASIN 1 sin1(ARG)
ASND 1 sin1(ARG)
ACOS 1 cos1(ARG)
ACSD 1 cos1(ARG)
ATAN 1 tan1(ARG)
ATND 1 tan1(ARG)
ATN2 2 Fortran ATAN2
(inverse tangent) function
AT2D 2 VAX Fortran ATAN2D
(inverse tangent) function
SINH 1 sinh(ARG)
COSH 1 cosh(ARG)
TANH 1 tanh(ARG)



The following table gives the format of the routines as described above;



Format of routine Example


RESULT = VAL_funcx (BAD, ARG, STATUS) PROOT = VAL_SQRTR (BAD, P, STATUS)
RESULT = VAL_funcx (BAD, ARG, ARG1, STATUS) BSUM = VAL_ADDUB (BAD, B1, B2, STATUS)
RESULT = VAL_xTOy (BAD, ARG, STATUS) IP = VAL_RTOI (BAD, P, STATUS)
RESULT = NUM_funcx (ARG) PLOG = NUM_LOGR (P)
RESULT = NUM_funcx (ARG, ARG1) ICUBE = NUM_PWRI (I, 3)
RESULT = NUM_xTOy (ARG) P = NUM_DTOR (D)
CALL VEC_funcx (BAD, ARG, RESULT, IERR, NERR, STATUS) CALL VEC_SINR (BAD, P, SINP, I, N, STATUS)
CALL VEC_funcx (BAD, ARG, ARG1, RESULT, IERR, NERR, STATUS) CALL VEC_ADDD (BAD, A, B, C, I, N, STATUS)
CALL VEC_xTOy (BAD, ARG, RESULT, IERR, NERR, STATUS) CALL VEC_RTOI (BAD, P, IP, I, N, STATUS)


The arguments are summarised below. BAD is a logical value specifying whether bad input arguments are to be recognised; N is the number of elements in the case of VAL routines; ARG, ARG1 and ARG2 are the input arguments, and RESULT is the result. (In the case of the VEC routines the input arguments ARG, ARG1, ARG2 and the RESULT are vectorised arrays, whereas they represent single values in the cases of the VAL and NUM routines.) IERR is an integer output argument which identifies the first array element to generate a numerical error, NERR is an integer output argument which returns a count of the number of numerical errors which occur, and finally STATUS is the usual integer status.

Thus the subroutine call in ADAM_EXAMPLES:SQROOT.FOR could be replaced with the call below:

        CALL VEC_SQRTR (.TRUE., NELM, %VAL(PTR1), %VAL(PTR2), IERR, NBAD, STATUS)

The program SQROOT.FOR assumes that the input array is of REAL type – a safe assumption as the NDF_MAP routine used type ’_REAL’ which means that the array will be mapped as _REAL regardless of the actual type in the NDF. An obvious improvement would be to test the actual type of the data array, map with that type, and use an appropriate subroutine to take the square root12. ADAM_EXAMPLES:SQROOTGEN.FOR contains these modifications.

The PRIMDAT routines are linked using the options file PRM_LINK as shown below:

  $ ALINK prog,PRM_LINK/OPT

Symbolic constants.

The set of symbolic constants provided within the PRIMDAT package is made available to a program by including the file with logical name PRM_PAR. These constants relate to machine-specific numeric quantities – for example, the range of values which can be represented for a particular data type or the number of bytes per value used for each data type. Programs must use such symbolic constants rather than the numbers which they represent. For example, the largest integer which can be represented on a VAX is 2147483647 (i.e. 2311). A program which uses this number in arithmetic checks etc. will not be portable to a machine with different arithmetic capabilities. However, software which uses the appropriate symbolic constant (called VAL__MAXI) can be ported simply by providing an appropriate version of PRM_PAR.

The complete set of symbolic constants is represented in the table below, where the final x in the name is one of R, D, I, W, UW, B or UB as indicated above. The data type of each symbolic constant matches that of the data type to which it applies, except in the cases of VAL__NBx and VAL__SZx which are, of course, integers.



Constant Quantity


VAL__BADx Bad data value
VAL__EPSx Machine precision – minimum ϵ such that 1 is distinguishable from (1+ϵ)
VAL__MAXx Maximum (most positive) non-bad value
VAL__MINx Minimum (most negative) non-bad value
VAL__NBx Number of bytes used by a value
VAL__SMLx Smallest positive non-zero value
VAL__SZx Number of characters needed to format value as a decimal string


12The general problem of producing and maintaining a set of subroutines which perform the same function for different data types is addressed by the GENERIC package described in SUN/7.