Detection of Math Errors
The following sections describe common math errors that may occur on some systems.
On Windows Systems
PV-WAVE detects the following six mathematical errors conditions:
Integer divide by zero.
Integer overflow.
Floating-point divide by zero.
Floating-point underflow.
Floating-point overflow.
Floating-point operand error. (An illegal operand was encountered, such as a negative operand to the SQRT or ALOG functions; or an attempt to convert to integer a number whose absolute value is greater than 2
31–1.)
When an error is detected, PV-WAVE prints an error message indicating the source of the statement that caused the error and continues program execution. Up to eight messages are printed before program execution stops.
On UNIX Systems
The detection of math errors, such as division by 0, overflow, and attempting to take the logarithm of a negative number, is hardware dependent. Some machines trap on all math errors, while others never trap.
On machines that handle floating-point exceptions and integer math errors properly, PV-WAVE prints an error message indicating the source statement that caused the error and continues program execution. Up to eight error messages are printed.
Checking the Accumulated Math Error Status
PV-WAVE maintains an accumulated math error status. This status, which is implemented as a longword, contains a bit for each type of math error that is detected by the hardware. PV-WAVE checks and clears this indicator each time the interactive prompt is issued, and if it is non-zero, prints an error message. A typical message is:
% Program caused arithmetic error: Floating divide by 0
This means that a floating division by 0 occurred since the last interactive prompt.
The CHECK_MATH function, described below, allows you to check and clear this accumulated math error status when desired. It is used to control how PV-WAVE treats floating-point exceptions on machines that don’t properly support them. It can also disable printing of math error messages.
Special Values for Undefined Results
Under Windows, and on any machine which implements the IEEE standard for binary floating-point arithmetic, such as the Sun, there are two special values for undefined results, NaN (Not A Number), and Infinity. Infinity results when a result is larger than the largest representation. NaN is the result of an undefined computation such as zero divided by zero, taking the square-root of a negative number, or the logarithm of a non-positive number. These special operands propagate throughout the evaluation process. The result of any term involving these operands is one of these two special values.
Check the Validity of Operands
Use the FINITE function to explicitly check the validity of floating-point or double-precision operands. this works under Windows and on machines which use the IEEE floating-point standard. For example, to check the result of the EXP function for validity:
; Perform exponentiation.
a = EXP(expression)
; Print error message, or if a is an array do the following:
IF NOT FINITE(a) THEN PRINT, 'overflow occurred'
IF FINITE(a) NE N_ELEMENTS(a) THEN error
Check for Overflow in Integer Conversions
When converting from floating to byte, short integer or longword types, if overflow is important, you must explicitly check to be sure the operands are in range. Conversions to the above types from floating-point, double-precision, complex, and string types do not check for overflow; they convert the operand to longword integer and extract the low 8, 16, or 32 bits (on 64-bit systems, this is 8, 16, and 64 bits).
note | When run on a Sun workstation, the program: |
a = 2.0 ^ 31 + 2
PRINT, LONG(a), LONG(-a), FIX(a), FIX(-a), $
BYTE(a), BYTE(-a)
which creates a floating-point number two larger than the largest positive longword integer, will print the following incorrect results:
2147483647 -2147483648 -1 0 255 0
% Program caused arithmetic error: Floating illegal operand
note | No error message will appear if you attempt to convert a floating number whose absolute value is between 215 and 231–1 to short integer even though the result is incorrect. Similarly, converting a number in the range of 256 to 231–1 from floating, complex or double to byte type produces an incorrect result but no error message. Furthermore, integer overflow is usually not detected. If integer overflow is a problem, your programs must guard explicitly against it. |
Trap Math Errors with the CHECK_MATH Function
As mentioned previously, the CHECK_MATH function lets you test the accumulated math error status. It is also used to enable or disable traps. Each call to this function returns and clears the value of this status.
note | CHECK_MATH does not properly maintain an accumulated error status on machines that do not implement the IEEE standard for floating-point math. |
It is good programming practice to bracket segments of code which might produce an arithmetic error with calls to CHECK_MATH to properly handle ill-conditioned results.
Its call is:
result = CHECK_MATH([print_flag, message_inhibit])
If an error condition has been detected, and the first optional parameter is present and non-zero, an error message is printed and program execution continues. Otherwise, the routine runs silently.
If the second optional parameter, message_inhibit, is present and non-zero, error messages are disabled for subsequent math errors. The accumulated math error status is maintained, even when error messages are disabled. When the program completes and exits back to the PV-WAVE prompt, accumulated math error messages which have been suppressed are printed. To suppress this final message, call CHECK_MATH to clear the accumulated error status before returning to the interactive mode.
The error status is encoded as an integer, where each binary bit represents an error, as shown in
Table 11-3: Error Status Code Values:
note | Not all machines detect all errors. |
Enable and Disable Math Traps
To enable trapping:
junk = CHECK_MATH(TRAP = 1)
To disable trapping:
junk = CHECK_MATH(TRAP = 0)
Examples Using the CHECK_MATH Function
For example, assume that there is a critical section of code that is likely to produce an error. The following code shows how to check for errors, and if one is detected to repeat the code with different parameters:
; Clear error status from previous operations and print error
; messages if error exists. Also, disable automatic printing of
; subsequent math errors.
junk = CHECK_MATH(1,1)
again ...
; Critical section goes here.
; Did an arithmetic error occur? Also, re-enable the printing of
; subsequent math errors.
IF CHECK_MATH(0,0) NE 0 THEN BEGIN
PRINT, 'Math error occurred in critical ' + 'section'
; Input new parameters from user.
READ, 'Enter new values: ', ...
; And retry.
GOTO, again
ENDIF