User Errors

IMSL functions attempt to detect user errors and handle them in a way that provides as much information to the user as possible. To do this, we recognize various levels of severity of errors, and we also consider the extent of the error in the context of the purpose of the function; a trivial error in one situation may be serious in another. Functions attempt to report as many errors as they can reasonably detect. Multiple errors present a difficult problem in error detection because input is interpreted in an uncertain context after the first error is detected.

What Determines Error Severity

In some cases, the user’s input may be mathematically correct, but because of limitations of the computer arithmetic and of the algorithm used, it is not possible to compute an answer accurately. In this case, the assessed degree of accuracy determines the severity of the error. In cases where the function computes several output quantities, if some are not computable but most are, an error condition exists; and its severity depends on an assessment of the overall impact of the error.

Kinds of Errors and Default Actions

Five levels of severity of errors are defined in the PyIMSL Stat Library. Upon return from a PyIMSL function, exactly one error state exists. Even if more than one informational error occurs, only one message is printed. Multiple errors for which no corrective action within the calling program is reasonable or necessary result in the printing of multiple messages. Errors of any of the severity levels except TERMINAL may be informational errors. The include file, imsl.h, defines NOTE, ALERT, WARNING, FATAL, TERMINAL, WARNING_IMMEDIATE, and FATAL_IMMEDIATE.

NOTE. A note is issued to indicate the possibility of a trivial error or simply to provide information about the computations.

ALERT. An alert indicates that a function value has been set to 0 due to underflow.

WARNING. A warning indicates the existence of a condition that may require corrective action by the user or calling routine. A warning error may be issued because the results are accurate to only a few decimal places, because some of the output may be erroneous, but most of the output is correct, or because some assumptions underlying the analysis technique are violated. Usually no corrective action is necessary, and the condition can be ignored.

FATAL. A fatal error indicates the existence of a condition that may be serious. In most cases, the user or calling routine must take corrective action to recover.

TERMINAL. A terminal error is serious. It usually is the result of an incorrect specification, such as specifying a negative number as the number of equations. These errors may also be caused by various programming errors impossible to diagnose correctly in C. The resulting error message may be perplexing to the user. In such cases, the user is advised to compare carefully the actual arguments passed to the function with the dummy argument descriptions given in the documentation. Special attention should be given to checking argument order and data types.

A terminal error is not an informational error, because corrective action within the program is generally not reasonable. In normal usage, execution is terminated immediately when a terminal error occurs. Messages relating to more than one terminal error are printed if they occur.

WARNING_IMMEDIATE. An immediate warning error is identical to a warning error, except it is printed immediately.

FATAL_IMMEDIATE. An immediate fatal error is identical to a fatal error, except it is printed immediately.

Errors in Lower-Level Functions

It is possible that a user’s program may call an PyIMSL Stat Library function that in turn calls a nested sequence of lower-level functions. If an error occurs at a lower level in such a nest of functions, and if the lower-level function cannot pass the information up to the original user-called function, then a traceback of the functions is produced. The only common situation in which this can occur is when an PyIMSL Stat Library function calls a user-supplied routine that in turn calls another PyIMSL Stat Library function.

Functions for Error Handling

When an exceptional condition (FATAL, TERMINAL, or FATAL_IMMEDIATE) is encountered in a PyIMSL Stat Library function, an exception will be raised. All other errors are captured in an error stack.

If an exception is raised, it will be an instance of class pyimsl.util.ImslError. Each ImslError object contains three attributes:

  1. type = The severity of the error. This value will be one of the kinds of errors described above, for example WARNING, FATAL, or TERMINAL.
  2. code = A numeric code that provides more information about the error. If a PyIMSL Stat Library routine may raise an error, that error is described in the documentation for the function. Error names and their integer equivalents are defined in
  3. message = A string describing the error.

An example of code which will trap an IMSLError exception and programmatically trap details on it is shown below:

from pyimsl.util.ImslError import ImslError
from pyimsl.math.gamma import gamma
from pyimsl.math.errorOptions import FATAL, TERMINAL, FATAL_IMMEDIATE
from pyimsl.math.mathErrors import IMSL_ARG_ZERO

try:
    gamma(0.0)
except ImslError,e:
   if e.type == FATAL:
      print "Fatal error encountered"
   elif e.type == TERMINAL:
      print "Terminal error encountered"
   elif e.type == FATAL_IMMEDIATE:
      print "Fatal Immediate error encountered"
   if e.code == IMSL_ARG_ZERO: print "Caught argument zero error"
      print "Error Message: ", e.message

If no exception has been raised, it is still possible to find out more information about errors or warnings that have been encountered. Error information is managed by class pyimsl.util.ImslErrorHandler. The ImslErrorHandler class contains these static methods:

  1. getErrorCode() – returns the error code for the most recent error.
  2. getErrorType() – returns the severity of the most recent error.
  3. getErrorMessage() – returns the message string for the most recent error.
  4. getErrorStack() – returns a deque containing all errors that have been encountered. Errors on the stack will be instances of class ImslError. Errors can be removed from the stack (deque) by calling pop().
  5. clear() – clears the stack of error messages.

An example of code to programmatically trap non-fatal warning messages is shown below:

from pyimsl.util.ImslErrorHandler import ImslErrorHandler
from pyimsl.math.zerosFcn import zerosFcn
from pyimsl.math.mathErrors import IMSL_NO_CONVERGE_MAX_ITER

# Clear all errors in case any previous errors were queued
ImslErrorHandler.clear()

def fcn(x):
   return x*x*x - 3.0*x*x - 3.0*x - 1.0

x = zerosFcn (fcn)

# Test for non-fatal warnings
errtype = ImslErrorHandler.getErrorType()
if errtype:
   errcode = ImslErrorHandler.getErrorCode()
   errmesg = ImslErrorHandler.getErrorMessage()
   if errcode == IMSL_NO_CONVERGE_MAX_ITER:
      print("Did not converge")
   print("Error message: ", errmesg)