home *** CD-ROM | disk | FTP | other *** search
-
- (* :Name: NumericalMath`IntervalArithmetic` *)
-
- (* :Title: Approximate Interval Arithmetic *)
-
- (* :Author: Jerry B. Keiper *)
-
- (* :Summary:
- Implements a simple form of interval arithmetic in which the
- endpoints of the intervals are calculated correctly, but with
- standard machine-precision arithmetic. In particular, no effort
- is made to round results outward. It is not intended for
- rigorous calculation, but rather for educational purposes.
- *)
-
- (* :Context: NumericalMath`IntervalArithmetic` *)
-
- (* :Package Version: Mathematica 2.0 *)
-
- (* :Copyright: Copyright 1990, Wolfram Research, Inc.
- Permission is hereby granted to modify and/or make copies of
- this file for any purpose other than direct profit, or as part
- of a commercial product, provided this copyright notice is left
- intact. Sale, other than for the cost of media, is prohibited.
-
- Permission is hereby granted to reproduce part or all of
- this file, provided that the source is acknowledged.
- *)
-
- (* :History:
- Revised by Jerry B. Keiper, December, 1990.
- Originally by Jerry B. Keiper, May, 1990.
- *)
-
- (* :Keywords: interval arithmetic *)
-
- (* :Source:
- R. E. Moore, Interval Analysis, Prentice-Hall, Englewood Cliffs,
- NJ, 1966
-
- Germund Dahlquist and Ake Bjorck (Translated by Ted Anderson),
- Numerical Methods, Prentice-Hall, Englewood Cliffs, NJ, 1974,
- pp. 37-39
- *)
-
- (* :Mathematica Version: 2.0 *)
-
- (* :Limitation:
- This package cannot be used to provide rigorous bounds on a
- result, since the rounding is provided by the hardware and
- occasionally may give smaller intervals than are justified.
- *)
-
- (* :Discussion:
- A simple form of interval arithmetic is implemented to provide
- students with some (albeit limited) experience with the ideas
- of interval arithmetic. It is assumed that the intervals
- overestimate the error sufficiently that incorrect rounding
- in calculation of the endpoints of the intervals will not
- significantly affect the result. It is undoubtedly the case
- that examples can be found where this asumption is violated.
- Basic arithmetic on intervals is automatic."
-
- The basic data object used is Interval[a, x, b], where a and b
- are the left and right endpoints of the interval, respectively,
- and x is the value of the number that the interval represents.
- Of course x is not correct either; it is simply the result of
- machine arithmetic used in evaluating x.
-
- Interval[a, b] is converted to Interval[a, x, b] where x is
- the midpoint of the interval (a, b). Interval[x] is converted
- to Interval[x - fuzz, x, x + fuzz] where fuzz is determined
- by the magnitude of x and a constant, which can be set with
- the function SetEpsilon[ ].
-
- SetEpsilon[dig] sets a constant that is used in converting
- simple numbers to intervals. When Interval[x]is converted
- to Interval[x - fuzz, x, x + fuzz], the value of fuzz used is
- Abs[x] * epsilon, where epsilon is 10^(-dig). The value of
- dig must be between 1 and 10, inclusive, and the default value
- is 6."
- *)
-
- (* :Examples:
-
- In[1]:= << NumericalMath`IntervalArithmetic` (* read in the package *)
-
- Out[1]= NumericalMath`IntervalArithmetic`
-
- In[2]:= a = Interval[-1,3]
-
- Out[2]= Interval[-1, 1, 3]
-
- In[3]:= b = Interval[1,5]
-
- Out[3]= Interval[1, 3, 5]
-
- In[4]:= a b
-
- Out[4]= Interval[-5, 3, 15]
-
- In[5]:= a a
-
- Out[5]= Interval[-3, 1, 9]
-
- In[6]:= a^2
-
- Out[6]= Interval[0, 1, 9]
-
- In[7]:= a-a
-
- Out[7]= Interval[-4, 0, 4]
-
- In[8]:= 3b
-
- Out[8]= Interval[3, 9, 15]
-
- In[9]:= Interval[Pi] (* inexact arithmetic is used when necessary *)
-
- Out[9]= Interval[3.14159, 3.14159, 3.1416]
-
- (* Note that the interval has positive length: *)
-
- In[10]:= SetPrecision[SetPrecision[%,20],10]
-
- Out[10]= Interval[3.141589512, 3.141592654, 3.141595795]
-
- (* We want a larger epsilon (i.e., more fuzz, fewer digits): *)
-
- In[11]:= SetEpsilon[3]
-
- In[12]:= sum = 0; Do[sum += 1/Interval[i], {i, 1., 500.}]; sum
-
- Out[12]= Interval[6.78604, 6.79282, 6.79962]
-
- (* exact interval arithmetic is not affected by the order of a sum.
- inexact interval is slightly affected by order, but not
- significantly if the intervals are much bigger than
- rounding errors. *)
-
- In[13]:= sum = 0; Do[sum += 1/Interval[i], {i, 500., 1., -1}]; sum
-
- Out[13]= Interval[6.78604, 6.79282, 6.79962]
- *)
-
- BeginPackage["NumericalMath`IntervalArithmetic`"];
-
- SetEpsilon::usage =
- "SetEpsilon[dig] sets a constant that is used in converting simple numbers
- to intervals. When Interval[x] gives Interval[x - fuzz, x, x + fuzz], the
- fuzz used is Abs[x] * epsilon, where epsilon is 10^(-dig). The value of
- dig must be between 1 and 10, inclusive, and the default value is 6."
-
- Interval::usage =
- "Interval[lowerbound, x, upperbound] is a data object that represents a
- number in interval arithmetic. The second argument is the value that the
- number would have in ordinary machine arithmetic, and lowerbound and
- upperbound are the bounds of the interval. Interval[x] gives
- Interval[x - fuzz, x, x + fuzz] where fuzz is Abs[x] * epsilon and epsilon
- is set using SetEpsilon[]. Interval[a,b] gives Interval[a,(a+b)/2,b].
- Basic arithmetic on intervals is automatic."
-
- Begin["NumericalMath`IntervalArithmetic`Private`"];
-
- SetEpsilon::digs = "The argument `1` to SetEpsilon is not between 1 and 10."
-
- SetEpsilon[n_Integer] :=
- (If[1 <= n <= 10, $epsilon = 10^(-n), Message[SetEpsilon::digs, n]];)
-
- If[!NumberQ[$epsilon], SetEpsilon[6]];
-
- Interval[x_] :=
- Module[{nx = N[x]}, If[NumberQ[nx], Interval[nx], x]] /; !NumberQ[x]
-
- Interval[x_] :=
- Module[{fuzz}, fuzz = Abs[x] $epsilon; Interval[x - fuzz, x, x + fuzz]] /;
- (NumberQ[x] && (Head[x] =!= Complex))
-
- Interval[a_, b_] :=
- Module[{na = a, nb = b},
- Interval[na, (na+nb)/2, nb] /;
- (If[!NumberQ[na], na = N[a]];
- If[!NumberQ[nb], nb = N[b]];
- (NumberQ[na] && NumberQ[nb] && na <= nb))];
-
- Interval /:
- Plus[x_Interval, y_Interval] :=
- Interval[x[[1]]+y[[1]], x[[2]]+y[[2]], x[[3]]+y[[3]]] /;
- ((Length[x] == 3) && (Length[y] == 3))
-
- Interval /:
- Plus[x_Interval, y_] :=
- Interval[x[[1]] + y, x[[2]] + y, x[[3]] + y] /;
- (NumberQ[y] && (Head[y] =!= Complex))
-
- Interval /:
- Times[s_, Interval[a_,x_,b_]] :=
- If[s >= 0,
- Interval[a s, x s, b s],
- (* else *)
- Interval[b s, x s, a s]
- ] /; (NumberQ[s] && (Head[s] =!= Complex))
-
- Interval /:
- Times[x_Interval, y_Interval] :=
- Module[{a1, a2, a3, a4},
- a1 = x[[1]] y[[1]];
- a2 = x[[1]] y[[3]];
- a3 = x[[3]] y[[1]];
- a4 = x[[3]] y[[3]];
- Interval[Min[a1,a2,a3,a4], x[[2]] y[[2]], Max[a1,a2,a3,a4]]
- ] /; (Length[x] == 3 && Length[y] == 3)
-
- Interval /: Power[x_Interval, 0] := Interval[1, 1, 1]
-
- Interval /:
- Power[x_Interval, n_Integer] :=
- Module[{min, max, a1, a3},
- If[x[[1]] <= 0 <= x[[3]],
- If[n <= 0, Return[Indeterminate]];
- a1 = x[[1]]^n;
- a3 = x[[3]]^n;
- min = Min[a1, 0, a3];
- max = Max[a1, 0, a3],
- (* else *)
- a1 = x[[1]]^n;
- a3 = x[[3]]^n;
- min = Min[a1, a3];
- max = Max[a1, a3]
- ];
- Interval[min, x[[2]]^n, max]
- ] /; (Length[x] == 3)
-
- End[ ] (* "NumericalMath`IntervalArithmetic`Private`" *)
-
- Protect[SetEpsilon, Interval];
-
- EndPackage[ ] (* "NumericalMath`IntervalArithmetic`" *)
-