Application Center - Maplesoft

App Preview:

INTERVALs Package

You can switch back to the summary page by clicking here.

Learn about Maple
Download Application


 

INTERVALs.mws

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 INTERVAL and the command evalr . It over-rides the operations +, -, *, /, ^, and the functions eval and signum 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 INTERVAL 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

[`*`, `+`, `-`, `/`, `^`, arccos, arccosh, arccot, ...
[`*`, `+`, `-`, `/`, `^`, arccos, arccosh, arccot, ...

Subtraction Problem: INTERVAL(1..2) - INTERVAL(1..2) = 0

> INTERVAL(1..2) - INTERVAL(1..2);

INTERVAL(-1 .. 1)

> eval( a - b, [a = INTERVAL(1..2), b = INTERVAL(1..2)] );

INTERVAL(-1 .. 1)

Division Problem: INTERVAL(1..2) / INTERVAL(1..2) = 1

> INTERVAL(1..2) / INTERVAL(1..2);

INTERVAL(1/2 .. 2)

> eval( a / b, [a = INTERVAL(1..2), b = INTERVAL(1..2)] );

INTERVAL(1/2 .. 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;

c := a-b

> d := a / b;

d := a/b

> a := INTERVAL(1..2);

a := INTERVAL(1 .. 2)

> b := INTERVAL(1..2);

b := INTERVAL(1 .. 2)

> c;

0

> d;

1

> a - b;

INTERVAL(-1 .. 1)

> a / d;

INTERVAL(1 .. 2)

Functions

> sin(INTERVAL(1..2));

INTERVAL(sin(1) .. 1)

> signum(INTERVAL(1..3));

1

In the case of taking a signum of an interval which crosses 0 , undefined instead of FAIL is returned.

> signum(INTERVAL(-1..3));

undefined

>