Numeric Computations: Events, Status Flags, and Traps
Maple's numeric computation environment provides direct support for handling numeric events. There are six possible types of events, each described below, which are signaled when detected. When an event is signaled, it can be controlled in the following ways.
A trap may be installed for the event, indicating a routine to be invoked to determine the action to be taken. For information on how events are signaled and traps are installed, see NumericEventHandler and NumericEventLocation.
A status flag (that is, the corresponding component of the status vector) can be raised. For more information on how status flags are set and queried, see NumericStatus.
In the absence of an enabled trap, a default action is taken.
EventsTraps and Status Flags
<Text-field style="Heading 2" layout="Heading 2" bookmark="bkmrk0">Events</Text-field>
The six types of events are described below.
1. invalid_operation
The invalid_operation event is signaled if an operation is attempted on arguments not in its domain (but not, for example, for an incorrect number of arguments). The invalid operations include (with the default result indicated in square brackets):
a. 0 * infinity, 0/0, infinity - infinity, or infinity/infinity [undefined]. Maple's evaluation of 0/0 is a two stage process: 0/0 -> 0 x 0^(-1). Thus, 0/0 may not signal invalid_operation if the division_by_zero event is caught.
b. Various powers of 0 and infinity and various infinite powers.
c. frem(x, y) (irem(x, y)) when
x is any kind of infinity [undefined] or y = 0 [undefined], or
y is a complex numeric [undefined].
d. iquo(x, 0) where x <> 0 [signum(x) infinity]. (Note:This signals invalid_operation rather than division_by_zero because iquo and irem must be viewed as two sides of the same coin, particularly as each can take a third argument which returns what the other would have computed on the same inputs.)
e. CopySign(x, y) when y is not a real undefined but is unordered with 0 (that is, Unordered(y, 0) returns true (not unevaluated)) [undefined].
f. NextAfter(x, y) when y is unordered with x (but neither is undefined) (again, if Unordered(x, y) returns unevaluated this event is not signaled) [undefined].
More generally, any Maple function should signal invalid_operation whenever it receives an argument provably not in its domain, but should not signal invalid_operation for infinite or removable singularities. See division_by_zero below.
2. division_by_zero
A division of a non-0 number by 0 should signal a division_by_zero event. The default action is to return a correctly signed infinity, if possible, and otherwise an undefined. This event is also properly signaled when an attempt is made to evaluate a function at an infinite singularity, e.g., ln(0).
3. overflow
The overflow event is signaled if the correctly rounded infinitely precise result of the computation (including a conversion operation) exceeds, in absolute value, the largest representable number in the current computation environment. If no trap is enabled for this event, the result returned in the exact integer and exact rational environments is undefined. In the software float environment, the default result on overflow is the correspondingly signed infinity.
4. underflow
The underflow event is signaled if the correctly rounded result of an operation (including a conversion operation) would be non-0 and strictly smaller, in absolute value, than the smallest positive representable number in the given format.
In the exact integer environment, underflow cannot occur.
In the exact rational environment, the default result on underflow is always 0 (of the appropriate type).
In the software float environment, the default value is 0.
5. inexact
The inexact event is signaled if the rounded result of a computation is not the same as the infinitely precise result, or if overflow occurs without an enabled trap, or if underflow occurs without an enabled trap. (It is not signaled on overflow if there is an enabled corresponding trap, or on underflow if there is an enabled corresponding trap.) The default result is the value of the computation.
Note: The condition for which the inexact exception is signaled is checked for only if the corresponding status flag is not set. In this particular, the signaling of this event differs from that of the other events.
6. real_to_complex
The real_to_complex event is signaled when the input to an operation (which may be a procedure) is real and the output is complex. For example, this is signaled by sqrt(-4) and by arcsin( 2.3 ). The event is not signaled for a multivariate procedure when at least one of the input arguments is complex. The default result will usually be the value of the computation.
Note: It is the responsibility of each procedure to determine if it should signal this event.
The real_to_complex event is provided for three reasons.
1. Maple's natural mathematical domain of computation is the complex numbers;
2. Elementary and transcendental functions are considered atomic operations by Maple; and
3. This event facilitates the implementation of a real computation context.
The following Maple procedure illustrates how the real_to_complex event can be used to keep Maple computing over the reals unless instructed to otherwise, by the explicit introduction of Complex(x, y) expressions (see the section on Traps).
RealToComplex_Trap := proc( F :: name, operands :: list, default :: anything )
'F'( op( operands ) );
end proc;
The real_to_complex event is an extension to the IEEE/754 Standard.
<Text-field style="Heading 2" layout="Heading 2" bookmark="bkmrk1">Traps and Status Flags</Text-field>
Traps
An event is "handled" by specifying a procedure, called a trap (or trap handler), and associating it with the appropriate flag ("enabling (or installing) the trap"). A previously associated trap can be replaced or stored. When an event with an enabled trap is signaled, that trap is immediately invoked, and the result returned by that trap is used in lieu of the default value for that event.
It is the trap's responsibility to set the state of the corresponding status flag before returning. Note:It is the event itself that results in the signal which is caught by the trap, if enabled, not the fact that the status flag is set.
The environment variable NumericEventHandlers stores the current trap handler values for each event class.
If no trap is desired for a particular event, NumericEventHandler should be invoked to set the corresponding trap to default. For example, NumericEventHandler(division_by_zero = default). To set all event handlers to their defaults, use NumericEventHandler(default).
The keyword exception can be used to cause a numeric event to trigger an exception. For example, after NumericEventHandler(division_by_zero = exception) the operation 1. / 0. will cause Maple to send an error message. This error can be caught by the catch clause of a try-catch block. To set all event handlers to raise exceptions, use NumericEventHandler(exception).
The six error message strings associated to the six numeric events are:
"numeric exception: invalid operation"
"numeric exception: division by zero"
"numeric exception: inexact"
"numeric exception: overflow"
"numeric exception: underflow"
"numeric exception: real to complex "
To catch all numeric events in a catch clause, therefore, use catch "numeric exception: ". The routine NumericException can be used to obtain the error string corresponding to a given event.
The possibility that more than one event can be signaled as the result of a particular operation is precluded. However, there is nothing that prevents an invoked trap from signaling another event itself. This is the expected behavior of the default overflow and underflow traps, for example. Similarly, the default action for a particular event can involve the signaling of a different event.
While the IEEE Standards suggest that the trap should be provided with the format of the desired result, the fact that Maple's numeric events can occur in different computational environments means that more information than this must be supplied. Thus, Maple's traps are provided with the actual expected default value, from which the format of the desired result can be deduced if it is required.
If a Maple procedure signals an event (e.g., if ln() signals a division_by_zero event) the corresponding trap, if one is enabled, is passed the name of that procedure as well as its arguments. More generally, the name of the most recent Maple procedure in which an event was signaled is always stored in the system global variable NumericEventLocation.
If it is the Maple kernel which signals an event (that is, the event is signaled as the result of an explicit numerical computation) Maple may require that the value returned from your trap be of a type which is compatible with the current computation context. If this return type is not compatible, the kernel will produce an error message to that effect. To deal with this situation, you may be able to query the value of the global variable NumericEventLocation to more finely control the output from your trap.
Status Flags
When a numeric event is signaled, the corresponding status flag is set.
You can inspect, change, save, and restore the status flags, individually or all at once (see NumericStatus), and can enable and disable traps (see NumericEventHandler). At most, one event can result from any given operation (see NumericEvent). However, it is possible that the trap for a signaled event can signal other events. Similarly, the default action for a particular event can involve the signaling of a different event.
Status flags are independent of the computation environment.
Once a status flag is set, it remains set until explicitly cleared. (Status flags are not environment variables.)
See AlsoDefaultOverflowinfinityNumericEventNumericEventHandlerNumericEventLocationNumericStatusRoundingtryundefined