C++ Interval Arithmetic Programming Reference


Using the Interval Arithmetic Library

1.1 What Is Interval Arithmetic?
Interval arithmetic is a system for computing with intervals of numbers. Because interval arithmetic always produces intervals that contain the set of all possible result values, interval algorithms have been developed to perform surprisingly difficult computations. For more information on interval applications, see the Interval Arithmetic Readme.
1.2 C++ Interval Support Goal: Implementation Quality
The goal of interval support in C++ is to stimulate development of commercial interval solver libraries and applications by providing program developers with:
 Quality interval code
 Narrowwidth interval results
 Rapidly executing interval code
 An easytouse software development environment
Support and features are components of implementation quality. Not all possible quality of implementation features have been implemented. Throughout this book, various unimplemented quality of implementation opportunities are described. Additional suggestions from users are welcome.
1.2.1 Quality Interval Code
As a consequence of evaluating any interval expression, a valid intervalsupporting compiler must produce an interval that contains the set of all possible results. The set of all possible results is called the containment set (cset) of the given expression. The requirement to enclose an expression's cset is the containment constraint of interval arithmetic. The failure to satisfy the containment constraint is a containment failure. A silent containment failure (with no warning or documentation) is a fatal error in any interval computing system. By satisfying this single constraint, intervals provide otherwise unprecedented computing quality.
Given the containment constraint is satisfied, implementation quality is determined by the location of a point in the twodimensional plane whose axes are runtime and interval width. On both axes, small is better. How to trade runtime for interval width depends on the application. Both runtime and interval width are obvious measures of intervalsystem quality. Because interval width and runtime are always available, measuring the accuracy of both interval algorithms and implementation systems is no more difficult than measuring their speed.
The Sun Studio tools for performance profiling can be used to tune interval programs. However, in C++, no intervalspecific tools exist to help isolate where an algorithm may gain unnecessary interval width. Quality of implementation opportunities include adding additional intervalspecific code development and debugging tools.
1.2.2 NarrowWidth Interval Results
All the normal language and compiler quality of implementation opportunities exist for intervals, including rapid execution and ease of use.
Valid interval implementation systems include a new additional quality of implementation opportunity: Minimize the width of computed intervals while always satisfying the containment constraint.
If an interval's width is as narrow as possible, it is said to be sharp. For a given floatingpoint precision, an interval result is sharp if its width is as narrow as possible.
The following statements apply to the width of intervals produced by the interval class:
 Individual intervals are sharp approximations of their external representation.
 Individual interval arithmetic functions produce sharp results.
 Mathematical functions usually produce sharp results.
1.2.3 Rapidly Executing Interval Code
By providing compiler optimization and hardware instruction support, interval operations are not necessarily slower than their floatingpoint counterparts. The following can be said about the speed of interval operators and mathematical functions:
 Arithmetic operations are reasonably fast.
 The speed of interval<double> mathematical functions is generally less than half the speed of their double counterparts. interval<float> math functions are provided, but are not tuned for speed (unlike their interval<double> counterparts). The interval<long double> mathematical functions are not provided in this release. However, other interval<long double> functions are supported.
1.2.4 EasytoUse Development Environment
The C++ interval class facilitates interval code development, testing, and execution.
Sun Studio C++ includes the following interval extensions:
 interval template specializations for intervals using float, double, and long double scalar types.
 interval arithmetic operations and mathematical functions that form a closed mathematical system. (This means that valid results are produced for any possible operatoroperand combination, including division by zero and other indeterminate forms involving zero and infinities.)
 Three types of interval relational functions:
 intervalspecific functions, such as intersect and interval_hull.
 intervalspecific functions, such as inf, sup, and wid.
 interval input/output, including singlenumber input/output.
For examples and more information on these and other interval functions, see CODE EXAMPLE 28 through CODE EXAMPLE 210 and Section 2.9.4, Functions That Accept Interval Arguments.
Chapter 2 contains detailed descriptions of these and other interval features.
1.2.5 The C++ Interval Class Compilation Interface
The compilation interface consists of the following:
 A new value, interval, for the library flag, which expands to the appropriate libraries.
 A new value, interval, for the staticlib flag, which at present is ignored because only static libraries are currently supported.
 A new flag, xia, which expands to fsimple=0 ftrap=%none fns=no library=interval. This flag is the same flag that is used with the Fortran compilers, though the expansion is different.
It is a fatal error if at the end of command line processing xia is set, and either fsimple, fns, or ftrap is set to any value other than
fsimple=0
fns=no
ftrap=no
ftrap=%none
To use the C++ interval arithmetic features, add the following header file to the code.
#include <suninterval.h>
An example of compiling code using the xia commandline option is shown here.
math% CC o filename xia filename.cc

The C++ interval library supports the following common C++ compilation modes:
 Compatibility mode (ARM) using compat
 Standard mode (ISO) with the standard library, which is the default
 Standard mode with the traditional iostream library (library=iostream)
See the C++ Migration Guide and the C++ User's Guide for more information on these modes.
The following sections describe the ways that these compilation modes affect compilation of applications using the interval library.
1.2.5.1 namespace SUNW_interval
In standard mode only, all interval types and symbols are defined within the namespace SUNW_interval. To write applications that compile in both standard mode and compatibility mode, use the following code.
#if __cplusplus >= 199711
using namespace SUNW_interval;
#endif

1.2.5.2 Boolean Return Values
Some interval functions return boolean values. Because compatibility mode does not support boolean types by default, these functions are defined returning a type interval_bool, which is a typedef to an int (compatibility mode) or a bool (standard mode). Client code should use whatever type appropriate for boolean values and rely on the appropriate conversions from interval_bool to the client's boolean type. The library does not support explicit use of features=bool or features=no%bool.
1.2.5.3 Input and Output
The interval library requires the I/O mechanisms supplied in one of the three compilation modes listed in Section 1.2.5, The C++ Interval Class Compilation Interface. In particular, the flag library=iostream must be specified on all compile and link commands if the application is using the standard mode with the traditional iostream library.
1.3 Writing Interval Code for C++
The examples in this section are designed to help new interval programmers to understand the basics and to quickly begin writing useful interval code. Modifying and experimenting with the examples is strongly recommended.
1.3.1 Hello Interval World
CODE EXAMPLE 11 is the interval equivalent of "hello world."
CODE EXAMPLE 11 Hello Interval World
math% cat ce11.cc
#include <suninterval.h>
#if __cplusplus >= 199711
using namespace SUNW_interval;
#endif
int main() {
cout <<"[2,3]+[4,5]="
<< (interval<double>("[2,3]") +
interval<double>("[4,5]"));
cout << endl;
}
math% CC xia o ce11 ce11.cc
math% ce11
[2,3]+[4,5]=[0.6000000000000000E+001,0.8000000000000000E+001]

CODE EXAMPLE 11 uses standard output streams to print the labeled sum of the intervals [2, 3] and [4, 5].
1.3.2 interval External Representations
The integer and floatingpoint numbers that can be represented in computers are referred to as internal machine representable numbers. These numbers are a subset of the entire set of extended (including  and +) real numbers. To make the distinction, machine representable numbers are referred to as internal and any number as external. Let x be an external (decimal) number or an interval endpoint that can be read or written in C++. Such a number can be used to represent either an external interval or an endpoint. There are three displayable forms of an external interval:
 [X_inf,X_sup]represents the mathematical interval
 [X] represents the degenerate mathematical interval [x, x], or [x]
 X represents the nondegenerate mathematical interval [x] + [1,+1]_{uld} (unit in the last digit). This form is the singlenumber representation, in which the last decimal digit is used to construct an interval. See Section 1.3.4, interval Input/Output and Section 2.8.2, SingleNumber Output. In this form, trailing zeros are significant. Thus 0.10 represents interval [0.09, 0.11], 100E1 represents interval [9.9, 10.1], and 0.10000000 represents the interval [0.099999999, 0.100000001].
A positive or negative infinite interval endpoint is input/output as a caseinsensitive string inf or infinity prefixed with a minus sign or an optional plus sign.
The empty interval is input/output as the caseinsensitive string empty enclosed in square brackets, [...]. The string, "empty", can be preceded or followed by blank spaces.
See Section 2.4.1, Arithmetic Operators +, , *, /, for more details.
Note  If an invalid interval such as [2,1] is converted to an internal interval, [inf, inf] is stored internally.

1.3.3 Interval Declaration and Initialization
The interval declaration statement performs the same functions for interval data items as the double and int declarations do for their respective data items. CODE EXAMPLE 12 uses interval variables and initialization to perform the same operation as CODE EXAMPLE 11.
CODE EXAMPLE 12 Hello Interval World With interval Variables
math% cat ce12.cc
#include <suninterval.h>
#if __cplusplus >= 199711
using namespace SUNW_interval;
#endif
int main() {
interval<double> X("[2,3]");
interval<double> Y("3"); // interval [2,4] is represented
cout <<"[2,3]+[2,4]=" << X + Y;
cout << endl;
}
math% CC xia o ce12 ce12.cc
math% ce12
[2,3]+[2,4]=[0.4000000000000000E+001,0.7000000000000000E+001]

Variables X and Y are declared to be of type interval<double> variables and are initialized to [2, 3] and [2, 4], respectively. The standard output stream is used to print the labeled interval sum of X and Y.
Note  To facilitate codeexample readability, all interval variables are shown as uppercase characters. Interval variables can be uppercase or lowercase in code.

1.3.4 interval Input/Output
Full support for reading and writing intervals is provided. Because reading and interactively entering interval data can be tedious, a singlenumber interval format is introduced. The singlenumber convention is that any number not contained in brackets is interpreted as an interval whose lower and upper bounds are constructed by subtracting and adding 1 unit to the last displayed digit.
Thus
2.345 = [2.344, 2.346],
2.34500 = [2.34499, 2.34501],
and
23 = [22, 24].
Symbolically,
[2.34499, 2.34501] = 2.34500 + [1, +1]_{uld }
where [1, +1]_{uld} means that the interval [1, +1] is added to the last digit of the preceding number. The subscript, uld, is a mnemonic for "unit in the last digit."
To represent a degenerate interval, a single number can be enclosed in square brackets. For example,
[2.345] = [2.345, 2.345] = 2.345000000000.....
This convention is used both for input and constructing intervals out of an external character string representation. Thus, type [0.1] to indicate the input value is an exact decimal number, even though 0.1 is not machine representable.
During input to a program, [0.1,0.1] = [0.1] represents the point, 0.1, while using singlenumber input/output, 0.1 represents the interval
0.1 + [1, +1]_{uld} = [0, 0.2].
The input conversion process constructs a sharp interval that contains the input decimal value. If the value is machine representable, the internal machine approximation is degenerate. If the value is not machine representable, an interval having width of 1ulp (unitinthelastplace of the mantissa) is constructed.
Note  A uld and an ulp are different. A uld is a unit in the last displayed decimal digit of an external number. An ulp is the smallest possible increment or decrement that can be made to an internal machine number.

The simplest way to read and print interval data items is with standard stream input and output.
CODE EXAMPLE 13 is a simple tool to help users become familiar with interval arithmetic and singlenumber interval input/output using streams.
Note  The interval containment constraint requires that directed rounding be used during both input and output. With singlenumber input followed immediately by singlenumber output, a decimal digit of accuracy can appear to be lost. In fact, the width of the input interval is increased by at most 1ulp, when the input value is not machine representable. See Section 1.3.5, SingleNumber Input/Output and CODE EXAMPLE 16.

CODE EXAMPLE 13 Interval Input/Output
math% cat ce13.cc
#include <suninterval.h>
#if __cplusplus >= 199711
using namespace SUNW_interval;
#endif
int main() {
interval <double> X, Y;
cout << "Press Control/C to terminate!"<< endl;
cout <<" X,Y=?";
cin >>X >>Y;
for (;;){
cout <<endl <<"For X =" <<X <<endl<<", and Y=" <<Y <<endl;
cout <<"X+Y=" << (X+Y) <<endl;
cout <<"XY=" << (XY) <<endl;
cout <<"X*Y=" << (X*Y) <<endl;
cout <<"X/Y=" << (X/Y) <<endl;
cout <<"pow(X,Y)=" << pow(X,Y) <<endl;
cout <<" X,Y=?";
cin >>X>>Y;
}
}
math% CC ce13.cc xia o ce13
math% ce13
Press Control/C to terminate!
X,Y=?[1,2][3,4]
For X =[0.1000000000000000E+001,0.2000000000000000E+001]
, and Y=[0.3000000000000000E+001,0.4000000000000000E+001]
X+Y=[0.4000000000000000E+001,0.6000000000000000E+001]
XY=[.3000000000000000E+001,.1000000000000000E+001]
X*Y=[0.3000000000000000E+001,0.8000000000000000E+001]
X/Y=[0.2500000000000000E+000,0.6666666666666668E+000]
pow(X,Y)=[0.1000000000000000E+001,0.1600000000000000E+002]
X,Y=?[1,2] inf
For X =[0.1000000000000000E+001,0.2000000000000000E+001]
, and Y=[ Infinity,.1797693134862315E+309]
X+Y=[ Infinity,.1797693134862315E+309]
XY=[0.1797693134862315E+309, Infinity]
X*Y=[ Infinity,.1797693134862315E+309]
X/Y=[.1112536929253602E307,0.0000000000000000E+000]
pow(X,Y)=[0.0000000000000000E+000, Infinity]
X,Y=? ^c

1.3.5 SingleNumber Input/Output
One of the most frustrating aspects of reading interval output is comparing interval infima and suprema to count the number of digits that agree. For example, CODE EXAMPLE 14 and CODE EXAMPLE 15 shows the interval output of a program that generates different randomwidth interval data.
CODE EXAMPLE 14 [inf, sup] Interval Output
math% a.out
Press Control/C to terminate!
Enter number of intervals (less then 10), then 4  for float,8  for double, or
16  for long double, and then 0 for [inf,sup] output and 1 for singlenumber
output: 5 4 0
5 intervals, output mode [inf,sup], KIND = 4:
[.22382161E001,0.88642842E+000]
[.14125850E+000,0.69100440E+000]
[.19697744E+000,0.60414422E+000]
[.35070375E+000,0.29852561E+000]
[.50582356E+000,0.84647579E+000]
Enter number of intervals (less then 10), then 4  for float,8  for double, or
16  for long double, and then 0 for [inf,sup] output and 1 for singlenumber
output: 5 8 0
5 intervals, output mode [inf,sup], KIND = 8:
[.2564517726079477E+000,0.9827522631010304E+000]
[.2525155427945818E+000,0.3510597363485733E+000]
[.3133963062586074E+000,0.6036160987815685E+000]
[.4608920508962374E+000,0.9438903393544678E+000]
[.7237777863955990E001,0.5919545024378117E+000]
Enter number of intervals (less then 10), then 4  for float,8  for double, or
16  for long double, and then 0 for [inf,sup] output and 1 for singlenumber
output: 5 16 0
5 intervals, output mode [inf,sup], KIND = 16:
[.7372694179875272420263966037179573E0001,0.8914952196721550592428684467449785
E+0000]
[.5003665785136456882479176712464738E+0000,0.9596355623810595147915591951459647
E+0000]
[0.5034039683817009896795857135003379E0002,0.6697658316807206801968277432024479
E+0000]
[.2131331913859165562121330770531887E+0000,0.8440084600454227370391890872269869
E+0000]
[.1771294604939292809903937013979606E+0000,0.9135081692043627299426589161157609
E+0000]
Enter number of intervals (less then 10), then 4  for float,8  for double, or
16  for long double, and then 0 for [inf,sup] output and 1 for singlenumber
output: ?<ControlC>

Compare the output readability in CODE EXAMPLE 14 with CODE EXAMPLE 15.
CODE EXAMPLE 15 SingleNumber Output
math%: a.out
Press Control/C to terminate!
Enter number of intervals (less then 10), then 4  for float,8  for double, or
16  for long double, and then 0 for [inf,sup] output and 1 for singlenumber
output: 5 4 1
5 intervals, output mode SINGLE NUMBER, KIND = 4:
[.2239E001,0.8865 ]
[0.1413 ,0.6911 ]
[0.1970 ,0.6042 ]
[0.3508 ,0.2986 ]
[0.5059 ,0.8465 ]
Enter number of intervals (less then 10), then 4  for float,8  for double, or
16  for long double, and then 0 for [inf,sup] output and 1 for singlenumber
output: 5 8 1
5 intervals, output mode SINGLE NUMBER, KIND = 8:
[0.25646 ,0.98276 ]
[0.25252 ,0.35106 ]
[0.31340 ,0.60362 ]
[0.46090 ,0.94390 ]
[.72378E001,0.59196 ]
Enter number of intervals (less then 10), then 4  for float,8  for double, or
16  for long double, and then 0 for [inf,sup] output and 1 for singlenumber
output: 5 16 1
5 intervals, output mode SINGLE NUMBER, KIND = 16:
[0.737269418E001, 0.891495220 ]
[ 0.500366579 , 0.959635563 ]
[ 0.503403968E002, 0.669765832 ]
[ 0.213133192 , 0.844008461 ]
[ 0.177129461 , 0.913508170 ]
Enter number of intervals (less then 10), then 4  for float,8  for double, or
16  for long double, and then 0 for [inf,sup] output and 1 for singlenumber
output: ?<ControlC>

In the singlenumber display format, trailing zeros are significant. See Section 2.8, Input and Output for more information.
Intervals can always be entered and displayed using the traditional [inf, sup] display format. In addition, a single number in square brackets denotes a point. For example, on input, [0.1] is interpreted as the number 1/10. To guarantee containment, directed rounding is used to construct an internal approximation that is known to contain the number 1/10.
CODE EXAMPLE 16 Character Input With Internal Data Conversion
math% cat ce16.cc
#include <suninterval.h>
#if __cplusplus >= 199711
using namespace SUNW_interval;
#endif
int main() {
char BUFFER[128];
cout << "Press Control/C to terminate!"<< endl;
cout << "X=?";
cin >>BUFFER;
for(;;) {
interval<double> X(BUFFER);
cout << endl << "Your input was:" <<BUFFER << endl;
cout << "Resulting stored interval is:" << endl << X << endl;
cout << "Single number interval output is: ";
single_number_output(X, cout);
cout <<endl <<"X=?" ;
cin >>BUFFER;
}
}
math% CC xia ce16.cc o ce16
math% ce16
Press Control/C to terminate!
X=?1.37
Your input was:1.37
Resulting stored interval is:
[0.1359999999999999E+001,0.1380000000000001E+001]
Single number interval output is: 0.13 E+001
X=?1.444
Your input was:1.444
Resulting stored interval is:
[0.1442999999999999E+001,0.1445000000000001E+001]
Single number interval output is: 0.144 E+001
X=? ^c

CODE EXAMPLE 16 notes:
 Single numbers in square brackets represent degenerate intervals.
 When a nonmachine representable number is read using singlenumber input, conversion from decimal to binary (radix conversion) and the containment constraint force the number's interval width to be increased by 1ulp (unit in the last place of the mantissa). When this result is displayed using singlenumber output, it can appear that a decimal digit of accuracy has been lost. This is not so. To echo singlenumber interval inputs, use character input together with an interval constructor with a character string argument, as shown in CODE EXAMPLE 16.
1.3.6 Arithmetic Expressions
Writing arithmetic expressions that contain interval data items is simple and straightforward. Except for intervalspecific functions and constructors, interval expressions look like floatingpoint arithmetic expressions, such as in CODE EXAMPLE 17.
CODE EXAMPLE 17 Simple interval Expression Example
math% cat ce17.cc
#include <suninterval.h>
#if __cplusplus >= 199711
using namespace SUNW_interval;
#endif
int main() {
interval <double> X1("[0.1]");
interval <double> N(3);
interval <double> A (5.0);
interval <double> X = X1 * A / N;
cout << "[0.1]*[A]/[N]=" <<X <<endl;
}
math% CC xia o ce17 ce17.cc
math% ce17
[0.1]*[A]/[N]=[0.1666666666666666E+000,0.1666666666666668E+000]

Note  Not all mathematically equivalent interval expressions produce intervals having the same width. Additionally, it is often not possible to compute a sharp result by simply evaluating a single interval expression. In general, interval result width depends on the value of interval arguments and the form of the expression.

1.3.7 intervalSpecific Functions
A variety of intervalspecific functions are provided. See Section 2.9.4, Functions That Accept Interval Arguments. Use CODE EXAMPLE 18 to explore how specific interval functions behave.
CODE EXAMPLE 18 interval Specific Functions
math% cat ce18.cc
#include <suninterval.h>
#if __cplusplus >= 199711
using namespace SUNW_interval;
#endif
int main() {
interval <double> X;
cout << "Press Control/C to terminate!"<< endl;
cout <<"X=?";
cin >>X;
for(;;){
cout <<endl << "For X =" <<X << endl;
cout <<"mid(X)=" << (mid(X)) <<endl;
cout <<"mig(X)=" << (mig(X)) <<endl;
cout <<"mag(X)=" << (mag(X)) <<endl;
cout <<"wid(X)=" << (wid(X)) <<endl;
cout <<"X=?";
cin >>X;
}
}
math% CC xia o ce18 ce18.cc
math% ce18
Press Control/C to terminate!
X=? [1.23456,1.234567890]
For X =[0.1234559999999999E+001,0.1234567890000001E+001]
mid(X)=1.23456
mig(X)=1.23456
mag(X)=1.23457
wid(X)=7.89e06
X=? [1,10]
For X =[0.1000000000000000E+001,0.1000000000000000E+002]
mid(X)=5.5
mig(X)=1
mag(X)=10
wid(X)=9
X=? ^c

1.3.8 Interval Versions of Standard Functions
Use CODE EXAMPLE 19 to explore how some standard mathematical functions behave.
CODE EXAMPLE 19 interval Versions of Mathematical Functions
math% cat ce19.cc
#include <suninterval.h>
#if __cplusplus >= 199711
using namespace SUNW_interval;
#endif
int main() {
interval <double> X;
cout << "Press Control/C to terminate!"<< endl;
cout <<"X=?";
cin >>X;
for (;;) {
cout <<endl << "For X =" <<X << endl;
cout <<"abs(X)=" << (fabs(X)) <<endl;
cout <<"log(X)=" << (log(X)) <<endl;
cout <<"sqrt(X)=" << (sqrt(X)) <<endl;
cout <<"sin(X)=" << (sin(X)) <<endl;
cout <<"acos(X)=" << (acos(X)) <<endl;
cout <<"X=?";
cin >>X;
}
}
math% CC xia o ce19 ce19.cc
math% ce19
Press Control/C to terminate!
X=? [1.1,1.2]
For X =[0.1099999999999999E+001,0.1200000000000001E+001]
abs(X)=[0.1099999999999999E+001,0.1200000000000001E+001]
log(X)=[0.9531017980432472E001,0.1823215567939548E+000]
sqrt(X)=[0.1048808848170151E+001,0.1095445115010333E+001]
sin(X)=[0.8912073600614351E+000,0.9320390859672266E+000]
acos(X)=[EMPTY ]
X=? [0.5,0.5]
For X =[.5000000000000000E+000,0.5000000000000000E+000]
abs(X)=[0.0000000000000000E+000,0.5000000000000000E+000]
log(X)=[ Infinity,.6931471805599452E+000]
sqrt(X)=[0.0000000000000000E+000,0.7071067811865476E+000]
sin(X)=[.4794255386042031E+000,0.4794255386042031E+000]
acos(X)=[0.1047197551196597E+001,0.2094395102393196E+001]
X=? ^c

1.4 Code Development Tools
Information on interval code development tools is available online. See the Interval Arithmetic Readme for a list of interval web sites and other online resources.
To report a suspected interval error, send email to the following address:
sundpcomments@Sun.COM
Include the following text in the Subject line of the email message:
FORTEDEV "7.0 mm/dd/yy" Interval
where mm/dd/yy is the month, day, and year of the message.
1.4.1 Debugging Support
In Sun Studio, interval data types are supported by dbx to the following extent:
 The values of individual interval variables can be printed using the print command.
 The value of all interval variables can be printed using the dump command.
 New values can be assigned to interval variables using the assign command.
 All generic functionality that is not data type specific should work.
For additional details on dbx functionality, see Debugging a Program With dbx.
C++ Interval Arithmetic Programming Reference

819050510


Copyright © 2004, Sun Microsystems, Inc. All Rights Reserved.