module Interval:Interval library in OCAML. ONLY FOR INTEL PROCESSORS.sig..end
All operations use correct rounding.
It is not mandatory, but still wise, to read the documentation of the
Fpu module
WARNING: even if some functions have been associated with operators, such as
the interval addition which is associated with the +$ operator, the
priority order between +, * and functions is not maintained. You HAVE to
use parenthesis if you want to be sure that a +$ b *$ c is properly
computed as a +$ (b *$ c).
This library has been mainly designed to be used in a branch and bound optimization algorithm. So, some choices have been made:
{low=2.;high=3.} /$ {low=0.;high=2.} returns {low=1.;high=Inf}, while {low=2.;high=3.} /$ {low=0.;high=0.} or {low=0.;high=0.} /$ {low=0.;high=0.} raise a failure.log, sqrt, acos or asin are restricted to their definition domain but raise an exception rather than returning an empty interval: for example sqrt_I {low=-4;high=4} returns {low=0;high=2} while sqrt_I {low=-4;high=-2} will raise an exception.Another design choice was to have non mutable elements in interval structure, and to maintain an "ordinary" syntax for operations, such as ''let a = b+$c in'' thus mapping interval computation formula on airthmetic formula. We could have instead chosen to have mutable elements, and to write for example (add_I_I a b c) to perform ''a=b+$c''. The first choice is, to our point of view, more elegant and easier to use. The second is more efficient, especially when computing functions with many temporary results, which force the GC to create and destroy lot of intervals when using the implementation we chose. Nothing's perfect.
The library is implemented in x87 assembly mode and is quite efficient (see below).
Intel Atom 230 Linux 32 bits:
Intel 980X Linux 64 bits:
type interval = {
|
low : |
(* | low bound | *) |
|
high : |
(* | high bound | *) |
let a = {low=1./.3.;high=1./.3.} creates an interval which does NOT contain the mathematical object 1/3.
If you want to create an interval representing 1/3, you have to write let a = 1. /.$ {low=3.0;high=3.0}
because rounding will then be properly set
val zero_I : intervalval one_I : intervalval pi_I : intervalpi with bounds properly roundedval e_I : intervale with bounds properly roundedval printf_I : (float -> string, unit, string) Pervasives.format ->
interval -> unitval fprintf_I : Pervasives.out_channel ->
(float -> string, unit, string) Pervasives.format ->
interval -> unitval sprintf_I : (float -> string, unit, string) Pervasives.format ->
interval -> stringval float_i : int -> intervalval compare_I_f : interval -> float -> intcompare_I_f a x returns 1 if a.high<x, 0 if a.low<=x<=a.high and -1 if x<a.lowval size_I : interval -> floatsize_I a returns a.high-a.lowval sgn_I : interval -> intervalsgn_I a returns {low=float (compare a.low 0.);high=float (compare a.high 0.)}val truncate_I : interval -> intervaltruncate_I a returns {low=floor a.low;high=ceil a.high}val abs_I : interval -> intervalabs_I a returns {low=a.low;high=a.high} if a.low>=0., {low=-a.high;high=-a.low} if a.high<=0., and {low=0.;high=max -a.low a.high}
otherwiseval union_I_I : interval -> interval -> intervalunion_I_I a b returns {low=min a.low b.low;high=max a.high b.high}val max_I_I : interval -> interval -> intervalmax_I_I a b returns {low=max a.low b.low;high=max a.high b.high}val min_I_I : interval -> interval -> intervalmin_I_I a b returns {low=min a.low b.low;high=min a.high b.high}val (+$) : interval -> interval -> intervala +$ b returns {low=a.low+.b.low;high=a.high+.b.high}val (+$.) : interval -> float -> intervala +$. x returns {low=a.low+.x;high=a.high+.x}val (+.$) : float -> interval -> intervalx +.$ a returns {low=a.low+.x;high=a.high+.x}val (-$) : interval -> interval -> intervala -$ b returns {low=a.low-.b.high;high=a.high-.b.low}val (-$.) : interval -> float -> intervala -$. x returns {low=a.low-.x;high=a.high-.x}val (-.$) : float -> interval -> intervalx -.$ a returns {low=x-.a.high;high=x-.a.low}val (~-$) : interval -> interval~-$ a returns {low=-a.high;high=-a.low}val ( *$. ) : interval -> float -> intervala *$. x multiplies a by x according to interval arithmetic and returns the proper result.
If x=0. then zero_I is returnedval ( *.$ ) : float -> interval -> intervalx *$. a multiplies a by x according to interval arithmetic and returns the proper result.
If x=0. then zero_I is returnedval ( *$ ) : interval -> interval -> intervala *$ b
multiplies a by b according to interval arithmetic and returns the proper result.
If a=zero_I or b=zero_I then zero_I is returnedval (/$.) : interval -> float -> intervala /$. x divides a by x according to interval arithmetic and returns the proper result.
Raise Failure "/$." if x=0.val (/.$) : float -> interval -> intervalx /.$ a divides x by a according to interval arithmetic and returns the result.
Raise Failure "/.$" if a=zero_Ival (/$) : interval -> interval -> intervala /$ b divides the first interval by the second according to interval arithmetic and returns the proper result.
Raise Failure "/$" if b=zero_Ival mod_I_f : interval -> float -> intervalmod_I_f a f returns a mod f according to interval arithmetic et ocaml mod_float definition.
Raise Failure "mod_I_f" if f=0.val inv_I : interval -> intervalinv_I a returns 1. /.$ a.
Raise Failure "inv_I" if a=zero_Ival sqrt_I : interval -> intervalsqrt_I a returns {low=sqrt a;high=sqrt b} if a>=0., {low=0.;high=sqrt b} if a<0.<=b.
Raise Failure "sqrt_I" if b<0.val pow_I_i : interval -> int -> intervalPow_I_i a n with n integer returns interval a raised to nth power according to interval arithmetic.
If n=0 then {low=1.;high=1.} is returned. Raise Failure "pow_I_f" if n<=0 and a=zero_I.
Computed with exp-log in base2val ( **$. ) : interval -> float -> intervala **$. f returns interval a raised to f power according to interval arithmetic.
If f=0. then {low=1.;high=1.} is returned. Raise Failure "**$." if f<=0. and a=zero_I or if f is not an integer value and a.high<0..
Computed with exp-log in base2val ( **$ ) : interval -> interval -> intervala **$ b returns interval a raised to b power according to interval arithmetic, considering the restriction of x power y to x >= 0.
Raise Failure "**$" if a.high < 0 or (a.high=0. and b.high<=0.)val ( **.$ ) : float -> interval -> intervalx **.$ a returns float x raised to interval a power according to interval arithmetic, considering the restiction of x power y to x >= 0.
Raise Failure "**.$" if x < 0 and a.high <= 0val log_I : interval -> intervallog_I a returns {low=log a.low; high=log a.high} if a.low>0., {low=neg_infinity; high=log a.high} if a.low<0<=a.high. Raise Failure "log_I" if a.high<=0.val exp_I : interval -> intervalexp_I a returns {low=exp a.high;high=exp b.high}val cos_I : interval -> intervalcos_I a returns the proper extension of cos to arithmetic interval
Returns [-1,1] if one of the bounds is greater or lower than +/-2**53val sin_I : interval -> intervalsin_I a returns the proper extension of sin to arithmetic interval
Returns [-1,1] if one of the bounds is greater or lower than +/-2**53val tan_I : interval -> intervaltan_I a returns the proper extension of tan to arithmetic interval
Returns [-Inf,Inf] if one of the bounds is greater or lower than +/-2**53val acos_I : interval -> intervalacos_I a raise Failure "acos_I" if a.low>1. or a.high<-1., else returns {low=if a.high<1. then acos a.high else 0; high=if a.low>-1. then acos a.low else pi}. All values are in [0,pi].val asin_I : interval -> intervalasin_I a raise Failure "asin_I" if a.low>1. or a.high<-1. else returns {low=if a.low>-1. then asin a.low else -pi/2; high=if a.low<1. then asin a.high else pi/2}. All values are in [-pi/2,pi/2].val atan_I : interval -> intervalatan_I a returns {low=atan a.low;high=atan a.high}val atan2mod_I_I : interval -> interval -> intervalatan2mod_I_I y x returns the proper extension of interval arithmetic to atan2 but with values in [-pi,2 pi] instead of [-pi,pi]. This can happen
when y.low<0 and y.high>0 and x.high<0: then the returned interval is
{low=atan2 y.high x.high;high=(atan2 y.low x.high)+2 pi}. This preserves the best inclusion function possible but is not compatible with
the standard definition of atan2val atan2_I_I : interval -> interval -> intervalval cosh_I : interval -> intervalval sinh_I : interval -> intervalval tanh_I : interval -> intervalval size_max_X : interval array -> floatval size_mean_X : interval array -> floatval printf_X : (float -> string, unit, string) Pervasives.format ->
interval array -> unitval fprintf_X : Pervasives.out_channel ->
(float -> string, unit, string) Pervasives.format ->
interval array -> unitval sprintf_X : (float -> string, unit, string) Pervasives.format ->
interval array -> stringval print_X : interval array -> unitval print_I : interval -> unitval size_X : interval array -> floatval size2_X : interval array -> floatval (<$.) : interval -> float -> intval pow_I_f : interval -> float -> intervalval pow_I_I : interval -> interval -> interval