// copyright (c) 1997, Thomas C. Hales, all rights reserved. // interval (TCH Jan 1996) /* This gives a new data type interval, with controlled precision (interval) arithmetic. If the interval contains zero, division by the interval is NaN. */ #include extern "C" { #include #include #include #include #include } #include "error.h" #include "notPortable.h" #include "interval.h" interval interMath::min(interval a,interval b) { double t; t = ((inf(a) > inf(b)) ? inf(b) : inf(a)); return interval(t,t); } interval interMath::min(interval a,interval b,interval c) { return interMath::min(a,interMath::min(b,c)); } interval interMath::min(interval a,interval b,interval c,interval d) { return interMath::min(a,b,interMath::min(c,d)); } interval interMath::max(interval a,interval b) { double t; t = ((sup(a) < sup(b)) ? sup(b) : sup(a) ); return interval(t,t); } interval interMath::max(interval a,interval b,interval c) { return interMath::max(a,interMath::max(b,c)); } interval interMath::max(interval a,interval b, interval c,interval d) { return interMath::max(a,b,interMath::max(c,d)); } // rounding modes: volatile void interMath::nearest() { ROUND_NEAR; } // It is not intended for the output to accurately reflect // the actual interval. We merely give a rough approximation. // User beware! ostream &operator<< (ostream & stream,interval c) { //interMath::nearest(); // if (c.hi-c.lo<1.0e-10) stream << c.hi; //stream.precision(18); stream << "{" << c.lo << "," << c.hi << "}"; if (c.hi0.0) { if (t2.lo>0.0) { interMath::up(); t.hi=hi*t2.hi; interMath::down(); t.lo=lo*t2.lo; return t; } else if (t2.hi<0.0) { interMath::up(); t.hi= lo*t2.hi; interMath::down(); t.lo = hi*t2.lo; return t; } else { interMath::up(); t.hi = hi*t2.hi; interMath::down(); t.lo = hi*t2.lo; return t; } } else if (hi<0.0) { if (t2.hi<0.0) { interMath::up(); t.hi=lo*t2.lo; interMath::down(); t.lo=hi*t2.hi; return t; } else if (t2.lo>0.0) { interMath::up(); t.hi=hi*t2.lo; interMath::down(); t.lo=lo*t2.hi; return t; } else { interMath::up(); t.hi= lo*t2.lo; interMath::down(); t.lo = lo*t2.hi; return t; } } else { if (t2.lo>0.0) { interMath::up(); t.hi = hi*t2.hi; interMath::down(); t.lo = lo*t2.hi; return t; } else if (t2.hi<0.0) { interMath::up(); t.hi = lo*t2.lo; interMath::down(); t.lo = hi*t2.lo; return t; } else { double tt; interMath::up(); t.hi = hi*t2.hi; tt= lo*t2.lo; if (tt>t.hi) t.hi=tt; interMath::down(); t.lo = lo*t2.hi; tt = hi*t2.lo; if (tt=0.0) { if (x< tanpi_16) return( Atan1(x) ); else if (x < tan3pi_16) return Atan1(tan6pi_16 - c2pi_16/(x+tan6pi_16))+ pi2_16; else if (x < tan5pi_16) return Atan1(1.0 - 2.0/(x+1.0))+ pi4_16; else if (x < tan7pi_16) return Atan1(tan2pi_16 - c6pi_16/(x+tan2pi_16))+ pi6_16; else return Atan1(-1.0/x) + pi8_16; } else return -Atan(-x); } interval interMath::atan(interval a) { interMath::nearest(); static double arctan_error = 1.0e-10; return interval( Atan(inf(a))-arctan_error, Atan(sup(a))+arctan_error ); } interval interMath::combine(interval x,interval y) { return interval(inf(min(x,y)),sup(max(x,y))); } static double rand01() { static int w =0; if (w==0) { srand(time(0)); w = 1; } double u = double(rand()); double v = double(/*stdlib.h*/RAND_MAX); return u/v; } void interMath::selfTest() { static int intervalTestCount =0; if (intervalTestCount>0) return; intervalTestCount++; cout << " -- loading interval routines $Revision: 1.5 $\n" << flush; /* underflow and overflow tests */ { double t = DBL_MAX; interMath::down(); t = 2*t; assert(t==t); interMath::up(); t = DBL_MIN; for (int i=0;i<1000;i++) t = t/2; assert(t==t); assert(t>0); } /* multiplication test */ { assert(interval(2.0,4.0)*interval(3.0,4.0)==interval(6.0,16.0)); assert(interval(-1.0,4.0)*interval(3.0,7.0)==interval(-7.0,28.0)); } /* rounding mode test */ { interval v(DBL_MIN,DBL_MIN); v = v+interval("1"); assert(interMath::inf(v)==1.0); assert(interMath::sup(v)==1.0+DBL_EPSILON); } /* divison test */ { interval v = interval("1")/interval("6"); v = v*interval("6"); assert(interMath::inf(v)<1.0); assert(interMath::sup(v)>1.0); } /* square root test*/ { interval v = interMath::sqrt("2"); v = v*v; assert(interMath::inf(v)<2.0); assert(interMath::sup(v)>2.0); assert((interMath::sup(v)-interMath::inf(v))/DBL_EPSILON <= 12); } /* rand01 test */ { double t = 0,u =0; for (int i=0;i<500;i++) { u=rand01(); t = (u>t?u:t); } assert(t>0.9); assert(t<=1.0); } /* interval multiplication */ { for (int i=0;i<5;i++) { cout.precision(30); double t1=rand01()-0.5,t2=rand01()-0.5,s1=rand01()-0.5,s2=rand01()-0.5; double t; if (t2t) t = t1*s2; if (t2*s1>t) t = t2*s1; if (t2*s2>t) t = t2*s2; if ( interMath::sup(z) != t) { cout << t1 << " " << t2 << " " << s1 << " " << s2 << endl << flush; cout << z << endl << flush; cout << " "<< t << endl << endl << flush; } interMath::down(); t = t1*s1; if (t1*s2