Variable Precision Arithmetic

Version 3.0a

(June 2009)

A Fortran Module

By

J.L.Schonfelder


Contents

1.       Introduction  3

2.       Specification  4

2.1       The Module  4

2.2       The Type  4

2.3           Precision manipulation. 5

2.4           Format inquiry and manipulation. 5

2.4.1               Inquiry on NUMBER exponent 6

2.4.2               Inquiry on NUMBER fraction  6

2.4.3               Set the NUMBER exponent 6

2.5       Type conversion procedures. 7

2.5.1               Conversion to type(NUMBER) by NUM  7

2.5.2               Conversion to INTEGER by INT  7

2.5.3               Conversion to CHARACTER string by CHAR  7

2.5.4               Conversion to a formatted CHARACTER string by EFCHAR  8

2.5.5               Conversion to a formatted CHARACTER string by FFCHAR  8

2.6           Arithmetic operations. 9

2.6.1               Addition and Subtraction. 9

2.6.2               Multiplication  9

2.6.3               Division  10

2.6.4               Raising to a power 11

2.7           Relational operations. 11

2.8           Overloads for numeric intrinsic procedures. 13

2.8.1               Absolute value (ABS) 13

2.8.2               Transfer of the sign (SIGN) 13

2.8.3               Square root (SQRT) 14

3.     The Module. 14

 

 


1.     Introduction

This module, written in standard conforming Fortran 95, but making use of the Fortran 2003 extension that allows ALLOCATABLE components, provides a set of facilities for the support of floating-point style of arithmetic that is of variable, and in principle, arbitrary precision. The range of numbers handled is very large.  It has been produced to enable applications that require very high and possibly varying numeric precision to be implemented easily. It exploits the semantic-extension data-abstraction capabilities of the Fortran 95 language to define a suitable number data-type and the fundamental arithmetic operations to manipulate numbers of this type.  Thus application programs can work with such numbers in ways that are similar to those needed if they were normal REAL values.

The set of facilities provided by this version (3.0) is extended to allow elemental as well as scalar overloads of the basic operations.  The set of type conversion routines necessary to allow values to be created and results displayed is slightly extended over those provided in previous versions.  The six logical comparison operators are also provided and the most basic of the intrinsic functions are overloaded.

As in version 2 the radix used is chosen to more fully exploit the range of the default integer thus reducing the number of digits necessary to provide a given decimal precision.  This improves the efficiency of operations at the expense of some extra complexity in the algorithms.  To enable the elemental extension of the operations, the number system is defined so as to have representations for positive and negative overflow, positive and negative underflow, zero, and indeterminate values. The algorithms used for all operations are also defined to propagate such values.  Thus operations have no failure conditions and can therefore be made elemental.  The occurrence of a numeric exception can only be detected by the occurrence of an unexpected exceptional result.

The major change in this version is in the number representation.  This version does not employ an explicit exponent field.  Instead the absolute bounds of the stored mantissa are adjusted so that a value is represented as

A = Σ ai R-i  for  i=e:n

That is the lower bound effectively carries the exponent information and the number of retained digits the precision.  This change was made partly to prove that Fortran 95 provided enough control over absolute bounds for them to be used in this way and partly that this representation provides a marginal improvement in both storage and execution efficiency; the latter appears to be approximately 5% at 100D. This 3.0a version employs an allocatable component instead of a pointer. This it is hoped will be both more efficient and less prone to memory leaks.

This version also adds an overload for the SQRT function.  This is not elemental for two reasons, SQRT of a negative value has no valid or reasonable exception value so a failure condition must be indicated and this is can not be done within the constraints of an elemental function, and the algorithm used is based on Heron’s rule. This starts with a low accuracy approximation with each iteration doubling the number of correct digits.  Efficiency requires the working precision to be varied during the process and again this cannot be done within the elemental rules.

The copyright in both the source code of the module and in this explanatory document rests with the author. However, the module and its documentation may be used freely by any individual or group for charitable, educational or research purposes, provided that such use is acknowledged.  If the package is used by a commercial organisation or for commercial gain, this use must be notified to the author in advance.  In such cases the author reserves the right to negotiate appropriate terms for such use. 

The module is made available in source form and hence it can be freely modified and enhanced by the user.  The author requests that any such enhancements that may be generally useful, either by improving the performance of the package, correcting errors or by providing additional functionality, should be communicated to the author.  All such enhancements will be considered for possible incorporation in subsequent releases of the package.

The module has been subject to reasonably careful testing by the author and no errors have been found in the released module.  However, no guarantee is given or implied that the released module is without fault or is fit for any specific purpose.  The author accepts no liability for any damages howsoever caused resulting from any use of this package.

2.     Specification

2.1     The Module

The module is named

VARIABLE_PRECISION_ARITHMETIC

and the facilities of the module can be accessed by the inclusion of the statement

USE VARIABLE_PRECISION_ARITHMETIC

2.2     The Type

The type is

TYPE NUMBER

    INTEGER,ALLOCATABLE :: sig(:) ! holds the significand 

ENDTYPE NUMBER

The interpretation of the type depends on the values of a small number of integer parameters. In the distributed version these are set as appropriate for an IEEE arithmetic system where the default integer is 32 bit, with a range of 9, and HUGE=2147483647. The necessary parameters are declared as

INTEGER,PARAMETER :: maxdecdig=9 ! max number of decimal digits that

                                 ! can be represented in a default integer

                                 ! maxdecdig=RANGE(0)

INTEGER,PARAMETER :: radd=8 ! number of decimal digits representable in the

                            ! number radix, radd<maxdecdig and even

INTEGER,PARAMETER :: rad=100000000 ! number system radix chosen so that

                                   ! rad=10**radd is representable in a

                                   ! default integer

INTEGER,PARAMETER :: rtrad=10000   ! rtrad=SQRT(rad)=10**radd/2

A radix commensurate with 10 is used to simplify conversions to and from a representation of numeric values by character strings in the form of normal decimal notation. The radix is chosen so that it is exactly  representable as a default INTEGER and the root of the radix is also an exact power of ten.  This enables relatively simple algorithms to be employed for multiplication and division without causing integer overflows. 

The value represented by an object of the type(NUMBER) is given by

SUM(sig(i)*rad**(-i)) for i=ex:nx

where: rad is the number system radix, and ex & nx are the lower and upper bounds of the significand; the number of digits retained in the significand nd is nx-ex+1. 

The value is normalised so that;

sig(ex)/=0, ABS(sig(i))<rad

and all digits are of the same sign.

For i>nd either sig(i)=0 exactly or the significand has been truncated to retain only nx-ex+1 digits.  The truncation length is set by a global variable ndig.  Thus the working precision is varied by changing the value of this global variable, ndig.  The default working precision set initially guarantees at least 100D accuracy. Values that can be represented exactly with fewer than ndig digits will not carry the extra redundant zero digits.

It should be noted that the maximum allowed exponent is maxexp, (initially set to rad). Numbers larger than this, though in some cases representable are considered too large to be useful.  With the above values for the parameters this gives a range of usable normalised values of approximately 10**(-800000000) to 10**(+800000000).

The number system is closed by defining a set of unnormalised values to represent numeric exceptions.  These are :

N.B. although the exponent is strictly irrelevant for a zero value it is convenient to give it a defined exponent and an exponent smaller than any normalised or underflowing value has proved sensible.  The indeterminant and unknown values all have an exponent larger than any valid or overflowing value.  The signed unknown values are defined to represent situations where the result of an operation has no predictable magnitude but the sign is defined.  The indeterminant value, which has the same representation as a yet to be defined value, is used to represent results where no valid value can be returned or there is no predictable sign or magnitude for the result; this is effectively a NaN value.  All operations are defined to produce either a normalised result or one of these exceptional values.  They are also designed to accept any of these values as valid operands and to propagate them as is shown below into the result.

2.3     Precision manipulation

The working precision can be changed or determined at anytime by invoking the procedure

PRECISION(dec_acc)

Description: Sets the working precision or inquires as to its current value in terms of equivalent significant decimal digits.

Class: Transformational function

Argument:

dec_acc shall be of type INTEGER

Result characteristics: the result shall be of type INTEGER

Result value: if dec_acc > 0, the number of digits to be retained, ndig, is set so that the working precision is greater than or equal to dec_acc. If dec_acc <=0, no change is made to the current working precision. In both cases the value returned is the current working precision defined as (ndig-1)*radd.

N.B. Since the leading digit may contain values less than 10 it may only represent a single decimal figure.  Hence the ndig-1 in the above formular.

Examples: PRECISION(30) will set the working precision to at least 30D and with the parameters above will return the value 32 and ndig will be set to the value 5.

2.4     Format inquiry and manipulation

There are three functions designed to provide information about the detailed representation of a value and to manipulate a value by direct changes to the representation.  These are:

      EXPONENT(val)

      FRACTION(val)

      SET_EXPONENT(val,ex)

These routines assume a standard floating point representation such that

            val = rad**exp * f

where f is a pure fraction.  That is

            1/rad  ≤ |f| <1

This means that

      FRACTION(val) = f = NUMBER(val%sig(1:nx-ex+1))

      EXPONENT(val) = 1-ex

       EXPONENT(FRACTION(val)) = 0

          SET_EXPONENT(FRACTION(val),EXPONENT(val)) = val

2.4.1     Inquiry on NUMBER exponent

EXPONENT(val)

Description: Inquires as to the effective exponent of a type(NUMBER) value

Class: Generic elemental

Argument: val shall be of type(NUMBER)

Result characteristics: The result shall be of type INTEGER

Result value: The result is the effective exponent of the number value. If val is represented by the component array val%sig(ex:nx), EXPONENT(val) returns the value 1-ex

Examples: EXPONENT(NUM(10)) will produce the value one

2.4.2     Inquiry on NUMBER fraction

FRACTION(val)

Description: Inquires as to the effective pure fraction mantissa of a type(NUMBER) value

Class: Generic elemental

Argument: val shall be of type(NUMBER)

Result characteristics: The result shall be of type(NUMBER)

Result value: The result is the effective fraction mantissa of the number value. If val is represented by the component array val%sig(ex:nx), FRACTION(val) has a component array val%sig(1:nx-ex+1)

Examples: FRACTION(NUM(10)) will produce the NUMBER value equal to 10**(-7)=10/rad

2.4.3     Set the NUMBER exponent

SET_EXPONENT(val,ex)

Description: Sets the effective exponent of a type(NUMBER) value

Class: Generic elemental

Argument:  

val shall be of type(NUMBER)

ex shall be of type INTEGER

Result characteristics: The result shall be of type(NUMBER)

Result value: The result has the same mantissa as val but with the effective exponent set to ex

Examples: SET_EXPONENT(NUM(10),2) will produce the NUMBER value equivalent to 10*10**rad

 

2.5     Type conversion procedures

There are procedures for converting between INTEGER and NUMBER, and between CHARACTER and NUMBER.

2.5.1      Conversion to type(NUMBER) by NUM

NUM(val)

Description: Converts the value represented by its argument to the equivalent representation as a NUMBER

Class: Generic elemental

Argument:

val shall be of type INTEGER or CHARACTER In the case of a CHARACTER value the character string must denote a decimal value with the following format possibly with leading or trailing blanks

sdddd.ddddEsdddd  or  sdddd.dddd

where s denotes +,-, or nothing

dddd denotes a string of one or more decimal digits

Result characteristics: The result shall be of type NUMBER

Result value: In both cases the result is the equivalent value to that of the argument represented as a NUMBER. The number of digits in the return value is the minimum number required to exactly represent the value. If a string argument fails to denote a correctly formatted value, an ind result is returned.  If it denotes a value that is too big or too small to be represented as a valid NUMBER, an overflow or an underflow value is returned.

Examples: NUM(10) will produce the value ten as a NUMBER. NUM("-1.0E+1") will produce the value -ten as a NUMBER.

2.5.2     Conversion to INTEGER by INT

INT(val)

Description: Converts the value represented by its argument to the equivalent representation as an INTEGER

Class: Generic transformational

Argument:

Val shall be of type NUMBER

Result characteristics: The result shall be of type INTEGER

Result value: The result the equivalent value to that of the argument represented as a INTEGER. If the argument denotes a value that is too big to represent as a valid INTEGER a fault is reported and execution is terminated.

Examples: INT(NUM(10)) will produce the value 10.

2.5.3     Conversion to CHARACTER string by CHAR

CHAR(val)

Description: Converts the value represented by its argument to a CHARACTER string representing the value as a standard floating point decimal.

Class: Generic transformational

Argument: Val shall be of type NUMBER

Result characteristics: The result shall be of type CHARACTER

Result value: The result is a CHARACTER string representing the equivalent value to that of the argument in a format:

^^si.ddddEsdddd

where ^^ represents zero or more blanks

s is the sign, -,or +

i is exactly one digit

dddd is one or more digits

Examples: CHAR(NUM(10)) will produce the value string " +1.0000E+1"

2.5.4      Conversion to a formatted CHARACTER string by EFCHAR

EFCHAR(val,w,d)

Description: Converts the value represented by its first argument to a CHARACTER string representing the value as a standard floating point decimal correctly truncated to 1PEw.d format.

Class: Generic transformational

Argument:

val shall be of type NUMBER

w,d shall be of type INTEGER

Result characteristics: The result shall be of type CHARACTER

Result value: The result is a CHARACTER string representing the equivalent value to that of the argument, val, in a format equivalent to 1PEw.d. This function is provided to enable formatted output.

Examples: EFCHAR(NUM(10),9,2) will produce the value string " +1.00E+1"

2.5.5     Conversion to a formatted CHARACTER string by FFCHAR

FFCHAR(val,w,d)

Description: Converts the value represented by its first argument to a CHARACTER string representing the value as a standard floating point decimal correctly truncated to Fw.d format.

Class: Generic transformational

Argument:

val shall be of type NUMBER

w,d shall be of type INTEGER

Result characteristics: The result shall be of type CHARACTER

Result value: The result is a CHARACTER string representing the equivalent value to that of the argument, val, in a format equivalent to Fw.d. This function is provided to enable formatted output.

Examples: FFCHAR(NUM(10),9,2) will produce the value string "   +10.00"

2.6     Arithmetic operations

The basic operations of arithmetic (+,-,*,/) are provided for NUMBER arguments and producing NUMBER results.  The operation of raising a NUMBER to an INTEGER power (**) is also provided.  All five operations are defined elementally for conformant array arguments.

If an exact result is possible within the current precision, the result will be exact and only the significant digits returned. Otherwise a result properly truncated to the current precision is returned.

2.6.1     Addition and Subtraction

The algorithms for both addition and subtraction employ a register that has two guard digits.  The basic algorithm is the same for both operations; subtraction simply being addition with the sign of the digits for the second operand inverted.  For normalised operands the only exceptional results that can occur are overflow, underflow, or exact cancellation to zero.  The operations are defined to propagate exceptional value operands as shown in the following table.

 Exceptional value propagation by addition and subtraction operation

  A+B

-unk

-ovf

-num

-unf

zero

+unf

+num

+ovf

+unk

ind

 -unk

-unk

-ovf

-unk

-unk

-unk

ind

ind

ind

ind

ind

 -ovf

-ovf

-ovf

-ovf

-ovf

-ovf

-ovf

-ovf

ind

ind

ind

 -num

-unk

-ovf

ALG

-num

-num

-num

ALG

+ovf

ind

ind

 -unf

-unk

-ovf

-num

-unf

-unf

zero

+num

+ovf

ind

ind

 zero

-unk

-ovf

-num

-unf

zero

+unf

+num

+ovf

+unk

ind

 +unf

  ind

-ovf

-num

zero

+unf

+unf

+num

+ovf

+unk

ind

 +num

  ind

-ovf

ALG

+num

+num

+num

ALG

+ovf

+unk

ind

 +ovf

ind

ind

+ovf

+ovf

+ovf

+ovf

+ovf

+ovf

+ovf

ind

 +unk

ind

ind

ind

ind

+unk

+unk

+unk

+ovf

+unk

ind

  ind

ind

ind

ind

ind

ind

ind

ind

ind

ind

ind

 

Where normalised values are represented by ±num and ALG represents the application of the basic algorithm.

The cost of these operations increases linearly with precision. 

2.6.2     Multiplication

Multiplication is done by a straight forward school-book digit by digit multiply and accumulate algorithm, with partial normalisation of digits done as part of the running calculation. The potential integer overflow in the digit*digit calculation is avoided by decomposing each digit modulo rtrad and by performing the multiply, accumulate and carry modulo rad. An exponent fault will occur if an attempt is made to produce an exponent greater than rad in absolute value.  Such cases will result in an underflow or overflow value being returned.  The operation is defined to propagate exceptional value operands as shown in the following table.

 

 

 

 

 Exceptional value propagation by multiplication operation

  A*B

-unk

-ovf

-num

-unf

Zero

+unf

+num

+ovf

+unk

 ind

 -unk

+unk

+unk

+unk

+unk

 Ind

-unk

-unk

-unk

-unk

 ind

 -ovf

+unk

+ovf

+ovf

+unk

Zero

-unk

-ovf

-ovf

-unk

 ind

 -num

+unk

+ovf

 ALG

+unf

Zero

-unf

 ALG

-ovf

-unk

 ind

 -unf

+unk

+unk

+unf

+unf

Zero

-unf

-unf

-unk

-unk

 ind

 zero

 ind

zero

zero

zero

Zero

zero

zero

zero

 ind

 ind

 +unf

-unk

-unk

-unf

-unf

Zero

+unf

+unf

+unk

+unk

 ind

 +num

-unk

-ovf

 ALG

-unf

Zero

+unf

 ALG

+ovf

+unk

 ind

 +ovf

-unk

-ovf

-ovf

-unk

Zero

+unk

+ovf

+ovf

+unk

 ind

 +unk

-unk

-unk

-unk

-unk

 Ind

+unk

+unk

+unk

+unk

 ind

  ind

 ind

 ind

 ind

 ind

 Ind

 ind

 ind

 ind

 ind

 ind

 

The cost of multiplication using this algorithm increases quadratically with precision.  The true dependence is on the product of the lengths, na*nb.  The algorithm automatically adjusts for operands that can be represented with fewer than ndig digits.  In particular, the important special case where one of the operands is a simple integer automatically has a linear dependence of the precision of the full-length operand.  For this reason no special overload for the multiplication of a NUMBER by an integer is provided.

2.6.3     Division

Division employs a variation on the school-book long division algorithm.  Real arithmetic is used to determine a value for the next quotient digit.  The dividend is updated by multiplication of the divisor by this and subtracting.  This process is done by the same algorithm as used for the multiply and accumulation in the multiplication algorithm.  An exponent fault will occur if an attempt is made to produce an exponent greater than rad in absolute value.  In this case underflow or overflow values will be returned.  Divide by zero will be handled by returning an indeterminant value.  The operation is defined to propagate exceptional value operands as shown in the following table.

Exceptional value propagation by division operation

  A/B

-unk

-ovf

-num

-unf

zero

+unf

+num

+ovf

+unk

 ind

 -unk

+unk

+unk

+unk

+unk

 ind

-unk

-unk

-unk

-unk

 ind

 -ovf

+unk

+unk

+ovf

+ovf

 ind

-ovf

-ovf

-unk

-unk

 ind

 -num

+unk

+unf

 ALG

+ovf

 ind

-ovf

 ALG

-unf

-unk

 ind

 -unf

+unk

+unf

+unf

+unk

 ind

-unk

-unf

-unf

-unk

 ind

 zero

zero

zero

zero

zero

 ind

zero

zero

zero

zero

zero

 +unf

-unk

-unf

-unf

-unk

 ind

+unk

+unf

+unf

+unk

 ind

 +num

-unk

-unf

 ALG

-ovf

 ind

+ovf

 ALG

+unf

+unk

 ind

 +ovf

-unk

-unk

-ovf

-ovf

 ind

+ovf

+ovf

+unk

+unk

 ind

 +unk

-unk

-unk

-unk

-unk

 ind

+unk

+unk

+unk

+unk

 ind

  ind

 ind

 ind

 ind

 ind

 ind

 ind

 ind

 ind

 ind

 ind

 

The cost of division increases quadratically with precision.  The true dependence is on the product of the lengths, na*nb.  The algorithm automatically adjusts for operands that can be represented with fewer than ndig digits.  In particular, the important special case where the divisor is a simple integer automatically has a linear dependence of the precision of the full-length operand.  For this reason no special overload for the division of a NUMBER by an integer is provided.

 

2.6.4     Raising to a power

The operation (val**n) is provided where a NUMBER value is raised to an INTEGER power. An algorithm is used based on repeated squaring of val and multiplying the value into the result if the corresponding bit is set in the binary representation of ABS(n). If n is positive this gives the final result with a near minimum number of multiplications. If n is negative the final result is produced by dividing NUM(1) by the positive power.  This operation may cause overflow or underflow.  Also raising a zero value to a negative power returns an indeterminant value.  The propagation of the exception values by this operation is shown in the following table.  Note, the different propagation for odd and even powers.

Exceptional value propagation by power operation

A**N

 -2n

-2n-1

   0

+2n+1

  2n

-unk

+unk

-unk

+1.0

-unk

+unk

-ovf

+unf

-unf

+1.0

-ovf

+ovf

-num

 ALG

 ALG

+1.0

 ALG

 ALG

-unf

+ovf

-ovf

+1.0

-unf

+unf

zero

 ind

 ind

+1.0

zero

zero

+unf

+ovf

+ovf

+1.0

+unf

+unf

+num

 ALG

 ALG

+1.0

 ALG

 ALG

+ovf

+unf

+unf

+1.0

+ovf

+ovf

+unk

+unk

+unk

+1.0

+unk

+unk

 ind

 ind

 ind

+1.0

 ind

 ind

2.7     Relational operations

The relational operations (==,/=,<,<=,>=,>) are provided for NUMBER arguments producing LOGICAL results. The algorithms used do not rely on subtraction of the arguments and there is no danger of arithmetic errors being caused by these comparisons.  Since there are only two possible results of type LOGICAL there is no available representation for situations where it not strictly possible to determine a true or false result.  There is no representation for the, in principle, unknown result of comparing two unknown (unk) NUMBER values.  Therefore to enable elemental extension of these operators, purely conventional true/false values are defined for such comparisons.  These definitions are shown in the following tables.

Exceptional value comparison by relational operation ==

A==B

-unk

-ovf

-num

-unf

zero

+unf

+num

+ovf

+unk

 ind

-unk

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

-ovf

FALSE

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

-num

FALSE

FALSE

 ALG

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

-unf

FALSE

FALSE

FALSE

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

zero

FALSE

FALSE

FALSE

FALSE

TRUE

FALSE

FALSE

FALSE

FALSE

TRUE

+unf

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

FALSE

FALSE

FALSE

FALSE

+num

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

 ALG

FALSE

FALSE

FALSE

+ovf

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

FALSE

FALSE

+unk

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

FALSE

 ind

FALSE

FALSE

FALSE

FALSE

TRUE

FALSE

FALSE

FALSE

FALSE

TRUE

 

 

 

 

 

Exceptional value comparison by relational operation /=

A/=B

-unk

-ovf

-num

-unf

zero

+unf

+num

+ovf

+unk

 ind

-unk

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

-ovf

TRUE

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

-num

TRUE

TRUE

 ALG

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

-unf

TRUE

TRUE

TRUE

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

zero

TRUE

TRUE

TRUE

TRUE

FALSE

TRUE

TRUE

TRUE

TRUE

FALSE

+unf

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

TRUE

TRUE

TRUE

TRUE

+num

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

 ALG

TRUE

TRUE

TRUE

+ovf

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

TRUE

TRUE

+unk

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

TRUE

 ind

TRUE

TRUE

TRUE

TRUE

FALSE

TRUE

TRUE

TRUE

TRUE

FALSE

 

Exceptional value comparison by relational operation <

 A<B

-unk

-ovf

-num

-unf

zero

+unf

+num

+ovf

+unk

 ind

-unk

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

-ovf

FALSE

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

-num

FALSE

FALSE

 ALG

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

-unf

FALSE

FALSE

FALSE

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

zero

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

TRUE

TRUE

TRUE

FALSE

+unf

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

TRUE

TRUE

FALSE

+num

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

 ALG

TRUE

TRUE

FALSE

+ovf

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

FALSE

+unk

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

 ind

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

TRUE

TRUE

TRUE

FALSE

 

Exceptional value comparison by relational operation <=

A<=B

-unk

-ovf

-num

-unf

zero

+unf

+num

+ovf

+unk

 ind

-unk

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

-ovf

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

-num

FALSE

FALSE

 ALG

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

-unf

FALSE

FALSE

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

zero

FALSE

FALSE

FALSE

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

+unf

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

TRUE

TRUE

TRUE

FALSE

+num

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

 ALG

TRUE

TRUE

FALSE

+ovf

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

TRUE

FALSE

+unk

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

FALSE

 ind

FALSE

FALSE

FALSE

FALSE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

 


Exceptional value comparison by relational operation >=

A>=B

-unk

-ovf

-num

-unf

zero

+unf

+num

+ovf

+unk

 ind

-unk

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

-ovf

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

-num

TRUE

TRUE

 ALG

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

-unf

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

zero

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

TRUE

+unf

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

TRUE

+num

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

 ALG

FALSE

FALSE

TRUE

+ovf

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

TRUE

+unk

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

 ind

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

TRUE

 

Exceptional value comparison by relational operation >

 A>B

-unk

-ovf

-num

-unf

zero

+unf

+num

+ovf

+unk

 ind

-unk

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

-ovf

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

-num

TRUE

TRUE

 ALG

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

-unf

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

zero

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

+unf

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

TRUE

+num

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

 ALG

FALSE

FALSE

TRUE

+ovf

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

TRUE

+unk

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

TRUE

 ind

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

FALSE

 

2.8     Overloads for numeric intrinsic procedures

2.8.1     Absolute value (ABS)

ABS(A)

Description: Returns the absolute value of its argument.

Class: Generic elemental

Argument: A shall be of type NUMBER

Result characteristics: The result shall be of type NUMBER

Result value: The result is the same as A if A is positive. The result is –A if A is negative.

Examples: ABS(NUM(-10)) will produce the value NUM(10)

2.8.2     Transfer of the sign (SIGN)

SIGN(A,B)

Description: Returns the absolute value A times the sign of B.

Class: Generic elemental

Arguments: A & B shall be of type NUMBER

Result characteristics: The result shall be of type NUMBER

Result value: If B>=0, the result is the same as ABS(A). If B<0, the result is –ABS(A).

Examples: SIGN(NUM(10),NUM(-1)) will produce the value NUM(-10)

2.8.3     Square root (SQRT)

SQRT(A)

Description: Returns the square root of A.

Class: Generic transformational

Argument: A shall be of type NUMBER

Result characteristics: The result shall be of type NUMBER

Result value: If A>=0, the result is the square root of A correct to the current precision. If A<0, there is no valid result and the function fails causing the program to terminate execution.  SQRT(unf) returns unf, SQRT(ovf) returns ovf, SQRT(unk) returns unk, SQRT(ind) returns ind.

Examples: SQRT(NUM(9) will produce the value NUM(3)

 

3.     The Module

The source code for the module VPA30A.F95 is available via this link.