Interval Arithmetic Package
Douglas Wilhelm Harder 2001/10/17
This package is meant to give a front end package to Maple's already existing interval arithmetic tools, including the interval object and the command . It over-rides the operations +, -, *, /, ^, and the functions and and the various trigonometric, hyperbolic and their inverse functions, and the exponential and logrithmic functions. It solves two problems: the need to call evalr on the result of operations, and cancelation of equal objects. The obscure name simply ensures that if any new package in Maple associated with intervals is introduced then no name collision will occur.
The Source Code
> restart; INTERVALs := module() export `+`, `-`, `*`, `/`, `^`, eval, ln, exp, sin, cos, tan, sec, csc, cot, arcsin, arccos, arctan, arcsec, arccsc, arccot, sinh, cosh, tanh, sech, csch, coth, arcsinh, arccosh, arctanh, arcsech, arccsch, arccoth, signum; local combine, i; `+` := proc(x, y) if nargs = 0 then 0; elif nargs = 1 then x; elif nargs = 2 then if type( x, 'specfunc'('`..`', 'INTERVAL') ) or type( y, 'specfunc'('`..`', 'INTERVAL') ) then evalr( x + y ); else x + y; end if; else procname( procname( x, y ), args[3..-1] ); end if; end proc; `-` := proc(x, y) if nargs = 1 then if type( x, 'specfunc'('`..`', 'INTERVAL') ) then INTERVAL( seq( -op( 2, i )..-op( 1, i ), i = x ) ); else -x; end if; elif nargs = 2 then `+`( x, `-`(y) ); else error "expecting 1 or 2 arguments, but got %1", nargs; end if; end proc; `*` := proc(x, y) if nargs = 0 then 1; elif nargs = 1 then x; elif nargs = 2 then if type( x, 'specfunc'('`..`', 'INTERVAL') ) or type( y, 'specfunc'('`..`', 'INTERVAL') ) then evalr( x * y ); else x * y; end if; else procname( procname( x, y ), args[3..-1] ); end if; end proc; `/` := proc(x, y) if nargs = 1 then if type( x, 'specfunc'('`..`', 'INTERVAL') ) then evalr( 1/x ); else 1/x; end if; elif nargs = 2 then `*`( x, `/`(y) ); else error "expecting 1 or 2 arguments, but got %1", nargs; end if; end proc; `^` := proc(x, y) if nargs = 2 then if type( x, 'specfunc'('`..`', 'INTERVAL') ) or type( y, 'specfunc'('`..`', 'INTERVAL') ) then evalr( x ^ y ); else x ^ y; end if; else error "expecting 2 arguments, but got %1", nargs; end if; end proc; eval := proc( x::uneval, y ) if nargs = 1 then :-eval( ':-eval'( x ) ); elif type( y, 'posint' ) then :-eval( ':-eval'( x, y ) ); elif type( y, {'`=`', 'list'('`=`')} ) then try combine( :-eval(x), y ); catch: error; end try; else error "wrong number (or type) of parameters in function eval"; end if; end proc; combine := proc(x, y) local M, i, result; if type( x, atomic ) then :-eval( x, y ); elif type( x, 'specfunc'('`..`', INTERVAL) ) then :-eval( x, y ); elif type( x, ':-`*`' ) then result := seq( procname( i, args[2..-1] ), i = x ); `*`( result ); elif type( x, ':-`+`' ) then result := seq( procname( i, args[2..-1] ), i = x ); `+`( result ); elif type( x, ':-`^`' ) then result := seq( procname( i, args[2..-1] ), i = x ); `^`( result ); elif type( x, 'function' ) then evalr( :-eval( op( 0, x ), y )( seq( procname( i, args[2..-1] ), i = x ) ) ); else map( procname, x, args[2..-1] ); end if; end proc; for i in [ ln, exp, sin, cos, tan, sec, csc, cot, arcsin, arccos, arctan, arcsec, arccsc, arccot, sinh, cosh, tanh, sech, csch, coth, arcsinh, arccosh, arctanh, arcsech, arccsch, arccoth ] do assign( i = FromInert( _Inert_PROC( _Inert_PARAMSEQ( _Inert_NAME("x") ), _Inert_LOCALSEQ(), _Inert_OPTIONSEQ(), _Inert_EXPSEQ(), _Inert_STATSEQ( _Inert_FUNCTION( _Inert_NAME("evalr"), _Inert_EXPSEQ( _Inert_FUNCTION( _Inert_MEMBER( _Inert_EXPSEQ(), _Inert_NAME(convert(i, 'string')) ), _Inert_EXPSEQ( _Inert_PARAM(1) ) ) ) ) ), _Inert_DESCRIPTIONSEQ(), _Inert_GLOBALSEQ(), _Inert_LEXICALSEQ() ) ) ); end do; signum := proc(x) local result; if nargs = 1 then result := evalr( Signum( x ) ); if result = FAIL then undefined; else result; end if; else error "not yet implemented"; end if; end proc; end module:
> with(INTERVALs);
Warning, these protected names have been redefined and unprotected: *, +, -, /, ^, arccos, arccosh, arccot, arccoth, arccsc, arccsch, arcsec, arcsech, arcsin, arcsinh, arctan, arctanh, cos, cosh, cot, coth, csc, csch, eval, exp, ln, sec, sech, signum, sin, sinh, tan, tanh
Subtraction Problem: INTERVAL(1..2) - INTERVAL(1..2) = 0
> INTERVAL(1..2) - INTERVAL(1..2);
> eval( a - b, [a = INTERVAL(1..2), b = INTERVAL(1..2)] );
Division Problem: INTERVAL(1..2) / INTERVAL(1..2) = 1
> INTERVAL(1..2) / INTERVAL(1..2);
> eval( a / b, [a = INTERVAL(1..2), b = INTERVAL(1..2)] );
Problems Which Exist Despite this Package
You must either assign names beforehand, or you must use the eval command. The following shows how assigning an expression to a name and then re-evaluating that expressions results in unexpected output.
> c := a - b;
> d := a / b;
> a := INTERVAL(1..2);
> b := INTERVAL(1..2);
> c;
> d;
> a - b;
> a / d;
Functions
> sin(INTERVAL(1..2));
> signum(INTERVAL(1..3));
In the case of taking a signum of an interval which crosses , instead of is returned.
> signum(INTERVAL(-1..3));
>