00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "cinterval.hpp"
00027 #include "cidot.hpp"
00028 #include "dot.hpp"
00029 #include "rmath.hpp"
00030 #include "imath.hpp"
00031
00032 namespace cxsc {
00033
00034 #define CXSC_Zero 0.0
00035
00036 cinterval::cinterval(const dotprecision &a) throw() : re(a),im(0) {}
00037 cinterval::cinterval(const idotprecision &a) throw() : re(a),im(0) {}
00038 cinterval::cinterval(const cdotprecision &a) throw() : re(Re(a)),im(Im(a)) {}
00039 cinterval::cinterval(const cidotprecision &a) throw() :
00040 re(rnd(InfRe(a),RND_DOWN),rnd(SupRe(a),RND_UP)),
00041 im(rnd(InfIm(a),RND_DOWN),rnd(SupIm(a),RND_UP))
00042 {
00043 }
00044
00045 cinterval operator *(const cinterval & a,const cinterval & b) throw()
00046 {
00047 cidotprecision akku;
00048 akku=0.0;
00049 accumulate(akku,a,b);
00050 return rnd(akku);
00051 }
00052
00053
00054 void product (real, real, real, real, int&, real&, interval&);
00055 real quotient (real, interval, real, interval, int, int, int);
00056
00057
00058
00059 bool cxsc_complex_division_p[5];
00060
00061 real cxsc_complex_division_f(real a, real b, real c, real d, int round)
00062 {
00063 int zoverfl,noverfl;
00064 real z1,n1;
00065 interval z2,n2;
00066
00067
00068
00069 product( a, c, b, d, zoverfl, z1,z2 );
00070 product( c, c, d, d, noverfl, n1,n2 );
00071
00072 return quotient( z1,z2, n1,n2, round, zoverfl, noverfl );
00073 }
00074
00075 static real minmax(int minimum, real a, real b, real y0,
00076 interval x, int i, int j)
00077
00078
00079
00080
00081 {
00082 real q1,q2,w1,w2,t1,t2,x1,x2,ay0, minmax;
00083 dotprecision akku;
00084 bool scaling = false;
00085
00086 if (minimum)
00087 minmax = MaxReal;
00088 else
00089 minmax = -MaxReal;
00090
00091 if (Inf(x) == Sup(x))
00092 {
00093 if (cxsc_complex_division_p[i] && cxsc_complex_division_p[j])
00094 minmax = cxsc_complex_division_f( a, b, Inf(x), y0, 1-2*minimum );
00095
00096 cxsc_complex_division_p[i] = false;
00097 cxsc_complex_division_p[j] = false;
00098 } else
00099 if (a == 0.0)
00100 {
00101 if ( b == CXSC_Zero || y0 == CXSC_Zero )
00102 {
00103 minmax = 0.0;
00104 cxsc_complex_division_p[i] = false;
00105 cxsc_complex_division_p[j] = false;
00106 } else
00107 {
00108 if (0.0 < x) {
00109 if (minimum && sign(b) != sign(y0) )
00110 {
00111 minmax = divd(b, y0);
00112 cxsc_complex_division_p[i] = false;
00113 cxsc_complex_division_p[j] = false;
00114 } else
00115 if (!minimum && sign(b) == sign(y0) )
00116 {
00117 minmax = divu(b, y0);
00118 cxsc_complex_division_p[i] = false;
00119 cxsc_complex_division_p[j] = false;
00120 }
00121 }
00122 }
00123 } else
00124 {
00125
00126 if (y0 == 0.0)
00127 {
00128 if (minimum)
00129 {
00130 if (a > 0.0)
00131 minmax = divd(a, Sup(x));
00132 else
00133 minmax = divd(a, Inf(x));
00134 } else
00135 {
00136 if (a > 0.0)
00137 minmax = divu(a, Inf(x));
00138 else
00139 minmax = divu(a, Sup(x));
00140 }
00141 cxsc_complex_division_p[i] = false;
00142 cxsc_complex_division_p[j] = false;
00143 } else
00144 {
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 real invf2=1, a_skal;
00155 int exf1=0, exf2=0, exinf1=0, exinf2=0;
00156
00157 if (sign(b)==0) { t1 = 1; t2 = 0; }
00158 else
00159 {
00160 if (a>0.0)
00161 q2 = abs(b);
00162 else
00163 q2 = -abs(b);
00164
00165
00166 int expo_diff = expo(b)-expo(a), ex;
00167 if (expo_diff >= 512)
00168 {
00169 int exdiff5 = expo_diff - 500;
00170 scaling = true;
00171 if (exdiff5 > 1024)
00172 {
00173 ex = exdiff5 / 2;
00174 exf1 = ex-1;
00175 exf2 = exdiff5 - ex;
00176 exinf1 = -exf1;
00177 invf2 = comp(0.5,1-exf2);
00178 exinf2 = -exf2;
00179 a_skal = a;
00180 times2pown(a_skal,exf1);
00181 times2pown(a_skal,exf2);
00182 }
00183 else
00184 {
00185 exf2 = exdiff5-1;
00186 invf2 = comp(0.5,2-exdiff5);
00187 exinf2 = -exf2;
00188 a_skal = a;
00189 times2pown(a_skal,exf2);
00190 }
00191 }
00192 else
00193 { a_skal = a; }
00194
00195 q1 = q2/a_skal;
00196 akku = q2;
00197 accumulate(akku, -q1, a_skal);
00198 q2 = rnd(akku) / a_skal;
00199
00200 akku = 0.0;
00201 if (exinf1 == 0) accumulate(akku, invf2, invf2);
00202 accumulate(akku, q1, q1);
00203 accumulate(akku, q1, q2);
00204 accumulate(akku, q1, q2);
00205 accumulate(akku, q2, q2);
00206
00207 w1 = sqrt(rnd(akku));
00208
00209 accumulate(akku, -w1, w1);
00210 w2 = rnd(akku) / (2.0*w1);
00211
00212 akku = q1;
00213 akku += q2;
00214 akku += w1;
00215 akku += w2;
00216
00217 t1 = rnd(akku);
00218
00219 akku -= t1;
00220 t2 = rnd(akku);
00221 }
00222 if (a<0.0)
00223 {
00224 t1 = -t1;
00225 t2 = -t2;
00226 }
00227
00228
00229 ay0 = abs(y0);
00230 if (( sign(b) == sign(y0) ) == minimum)
00231 {
00232
00233 akku = 0.0;
00234 accumulate(akku,ay0,t1);
00235 accumulate(akku,ay0,t2);
00236 x1 = rnd(akku);
00237 if (expo(x1) == 2147483647) goto Ende;
00238 akku -= x1;
00239 x2 = rnd(akku);
00240 if (scaling)
00241 {
00242 if (expo(x1)+exf1 > 1023) goto Ende;
00243 times2pown(x1,exf1);
00244 if (expo(x1)+exf2 > 1023) goto Ende;
00245 times2pown(x1,exf2);
00246 times2pown(x2,exf1);
00247 times2pown(x2,exf2);
00248 }
00249 } else
00250 {
00251
00252 x1 = ay0 / t1;
00253 akku = ay0;
00254 accumulate(akku, -t1, x1);
00255 accumulate(akku, -t2, x1);
00256 x2 = rnd(akku) / t1;
00257 if (scaling)
00258 {
00259 if (expo(x1)+exinf1 > 1023) goto Ende;
00260 times2pown(x1,exinf1);
00261 if (expo(x1)+exinf2 > 1023) goto Ende;
00262 times2pown(x1,exinf2);
00263 times2pown(x2,exinf1);
00264 times2pown(x2,exinf2);
00265 }
00266 }
00267 if (minimum)
00268 {
00269 x1 = -x1;
00270 x2 = -x2;
00271 }
00272
00273 if (x1 < x)
00274 {
00275
00276 q1 = a/(2*x1);
00277 akku = 0.0;
00278 accumulate(akku, -x1, q1);
00279 accumulate(akku, -x2, q1);
00280
00281
00282 akku += akku;
00283 akku += a;
00284 q2 = rnd(akku) / (2.0*x1);
00285 if (minimum)
00286 {
00287 if (sign(q2)==0 && sign(akku)!=0) minmax = pred(q1);
00288 else minmax = addd(q1, q2);
00289 }
00290 else
00291 {
00292 if (sign(q2)==0 && sign(akku)!=0) minmax = succ(q1);
00293 else minmax = addu(q1, q2);
00294 }
00295
00296 cxsc_complex_division_p[i] = false;
00297 cxsc_complex_division_p[j] = false;
00298 }
00299 Ende:;
00300 }
00301 }
00302 return minmax;
00303 }
00304
00305 cinterval cidiv(const cinterval& A, const cinterval& B)
00306 {
00307 real realteilINF, realteilSUP,
00308 imagteilINF, imagteilSUP;
00309
00310 real a0,b0;
00311 bool a_repeat,b_repeat;
00312 int i, rep, j;
00313 real AREINF, ARESUP, AIMINF, AIMSUP,
00314 BREINF, BRESUP, BIMINF, BIMSUP;
00315 interval ARE, AIM, BRE, BIM;
00316
00317
00318
00319
00320
00321
00322
00323
00324 AREINF = Inf(Re(A));
00325 ARESUP = Sup(Re(A));
00326 AIMINF = Inf(Im(A));
00327 AIMSUP = Sup(Im(A));
00328 BREINF = Inf(Re(B));
00329 BRESUP = Sup(Re(B));
00330 BIMINF = Inf(Im(B));
00331 BIMSUP = Sup(Im(B));
00332 ARE = Re(A);
00333 AIM = Im(A);
00334 BRE = Re(B);
00335 BIM = Im(B);
00336
00337 a_repeat = ( BREINF < CXSC_Zero ) && ( CXSC_Zero < BRESUP );
00338 b_repeat = ( BIMINF < CXSC_Zero ) && ( CXSC_Zero < BIMSUP );
00339
00340 if (a_repeat || b_repeat)
00341 rep = 2;
00342 else
00343 rep = 1;
00344
00345 if (BREINF >= 0.0)
00346 a0 = ARESUP;
00347 else
00348 a0 = AREINF;
00349
00350 if (BIMINF >= 0.0)
00351 b0 = AIMSUP;
00352 else
00353 b0 = AIMINF;
00354
00355 realteilSUP = -MaxReal;
00356
00357 for (j=1; j<=rep; j++)
00358 {
00359 for (i=1; i<=4; cxsc_complex_division_p[i++] = true);
00360
00361 realteilSUP =
00362 max( realteilSUP,
00363 max( max( minmax( false, a0, b0, BIMINF, BRE, 1,2 ),
00364 minmax( false, a0, b0, BIMSUP, BRE, 3,4 ) ),
00365 max( minmax( false, b0, a0, BREINF, BIM, 1,3 ),
00366 minmax( false, b0, a0, BRESUP, BIM, 2,4 ) ) )
00367
00368 );
00369
00370 if (cxsc_complex_division_p[1])
00371 realteilSUP = max( realteilSUP, cxsc_complex_division_f( a0, b0, BREINF, BIMINF, +1 ) );
00372 if (cxsc_complex_division_p[2])
00373 realteilSUP = max( realteilSUP, cxsc_complex_division_f( a0, b0, BRESUP, BIMINF, +1 ) );
00374 if (cxsc_complex_division_p[3])
00375 realteilSUP = max( realteilSUP, cxsc_complex_division_f( a0, b0, BREINF, BIMSUP, +1 ) );
00376 if (cxsc_complex_division_p[4])
00377 realteilSUP = max( realteilSUP, cxsc_complex_division_f( a0, b0, BRESUP, BIMSUP, +1 ) );
00378
00379 if (a_repeat)
00380 a0 = ARESUP;
00381 else if (b_repeat)
00382 b0 = AIMSUP;
00383 }
00384
00385 if (BREINF >= 0.0)
00386 a0 = AREINF;
00387 else
00388 a0 = ARESUP;
00389 if (BIMINF >= 0.0)
00390 b0 = AIMINF;
00391 else
00392 b0 = AIMSUP;
00393
00394 realteilINF = MaxReal;
00395
00396 for (j=1; j<=rep; j++)
00397 {
00398 for (i=1; i<=4; cxsc_complex_division_p[i++] = true);
00399
00400 realteilINF =
00401 min( realteilINF,
00402 min( min( minmax( true, a0, b0, BIMINF, BRE, 1,2 ),
00403 minmax( true, a0, b0, BIMSUP, BRE, 3,4 ) ),
00404 min( minmax( true, b0, a0, BREINF, BIM, 1,3 ),
00405 minmax( true, b0, a0, BRESUP, BIM, 2,4 ) ) )
00406 );
00407 if (cxsc_complex_division_p[1])
00408 realteilINF = min( realteilINF, cxsc_complex_division_f( a0, b0, BREINF, BIMINF, -1 ) );
00409 if (cxsc_complex_division_p[2])
00410 realteilINF = min( realteilINF, cxsc_complex_division_f( a0, b0, BRESUP, BIMINF, -1 ) );
00411 if (cxsc_complex_division_p[3])
00412 realteilINF = min( realteilINF, cxsc_complex_division_f( a0, b0, BREINF, BIMSUP, -1 ) );
00413 if (cxsc_complex_division_p[4])
00414 realteilINF = min( realteilINF, cxsc_complex_division_f( a0, b0, BRESUP, BIMSUP, -1 ) );
00415
00416 if (a_repeat)
00417 a0 = AREINF;
00418 else if (b_repeat)
00419 b0 = AIMINF;
00420 }
00421
00422
00423
00424
00425
00426 a_repeat = ( BIMINF < CXSC_Zero ) && ( CXSC_Zero < BIMSUP );
00427 b_repeat = ( BREINF < CXSC_Zero ) && ( CXSC_Zero < BRESUP );
00428
00429
00430
00431 if (BREINF >= 0.0)
00432 b0 = AIMSUP;
00433 else
00434 b0 = AIMINF;
00435
00436 if (BIMINF >= 0.0)
00437 a0 = AREINF;
00438 else
00439 a0 = ARESUP;
00440
00441 imagteilSUP = -MaxReal;
00442
00443 for (j=1; j<=rep; j++)
00444 {
00445 for (i=1; i<=4; cxsc_complex_division_p[i++] = true) ;
00446
00447 imagteilSUP =
00448 max( imagteilSUP,
00449 max( max( minmax( false, b0, -a0, BIMINF, BRE, 1,2 ),
00450 minmax( false, b0, -a0, BIMSUP, BRE, 3,4 ) ),
00451 max( minmax( false, -a0, b0, BREINF, BIM, 1,3 ),
00452 minmax( false, -a0, b0, BRESUP, BIM, 2,4 ) ) )
00453 );
00454
00455 if (cxsc_complex_division_p[1])
00456 imagteilSUP = max( imagteilSUP, cxsc_complex_division_f( b0, -a0, BREINF, BIMINF, +1 ) );
00457 if (cxsc_complex_division_p[2])
00458 imagteilSUP = max( imagteilSUP, cxsc_complex_division_f( b0, -a0, BRESUP, BIMINF, +1 ) );
00459 if (cxsc_complex_division_p[3])
00460 imagteilSUP = max( imagteilSUP, cxsc_complex_division_f( b0, -a0, BREINF, BIMSUP, +1 ) );
00461 if (cxsc_complex_division_p[4])
00462 imagteilSUP = max( imagteilSUP, cxsc_complex_division_f( b0, -a0, BRESUP, BIMSUP, +1 ) );
00463
00464 if (b_repeat)
00465 b0 = AIMSUP;
00466 else if (a_repeat)
00467 a0 = AREINF ;
00468 }
00469
00470 if (BREINF >= 0.0)
00471 b0 = AIMINF;
00472 else
00473 b0 = AIMSUP;
00474
00475 if (BIMINF >= 0.0)
00476 a0 = ARESUP;
00477 else
00478 a0 = AREINF;
00479
00480 imagteilINF = MaxReal;
00481
00482 for (j=1; j<=rep; j++)
00483 {
00484 for (i=1; i<=4; cxsc_complex_division_p[i++] = true) ;
00485
00486 imagteilINF =
00487 min( imagteilINF,
00488 min( min( minmax( true, b0, -a0, BIMINF, BRE, 1,2 ),
00489 minmax( true, b0, -a0, BIMSUP, BRE, 3,4 ) ),
00490 min( minmax( true, -a0, b0, BREINF, BIM, 1,3 ),
00491 minmax( true, -a0, b0, BRESUP, BIM, 2,4 ) ) )
00492 );
00493
00494 if (cxsc_complex_division_p[1])
00495 imagteilINF = min( imagteilINF, cxsc_complex_division_f( b0, -a0, BREINF, BIMINF, -1 ) );
00496 if (cxsc_complex_division_p[2])
00497 imagteilINF = min( imagteilINF, cxsc_complex_division_f( b0, -a0, BRESUP, BIMINF, -1 ) );
00498 if (cxsc_complex_division_p[3])
00499 imagteilINF = min( imagteilINF, cxsc_complex_division_f( b0, -a0, BREINF, BIMSUP, -1 ) );
00500 if (cxsc_complex_division_p[4])
00501 imagteilINF = min( imagteilINF, cxsc_complex_division_f( b0, -a0, BRESUP, BIMSUP, -1 ) );
00502
00503 if (b_repeat)
00504 b0 = AIMINF;
00505 else if (a_repeat)
00506 a0 = ARESUP;
00507 }
00508
00509 return cinterval(interval(realteilINF, realteilSUP),
00510 interval(imagteilINF, imagteilSUP));
00511 }
00512
00513 cinterval C_point_div(const cinterval& z, const cinterval& n)
00514
00515
00516
00517 {
00518 complex a,b,q1,q2;
00519 a = complex(InfRe(z),InfIm(z));
00520 b = complex(InfRe(n),InfIm(n));
00521 q1 = divd(a,b);
00522 q2 = divu(a,b);
00523
00524 interval re, im;
00525 re = interval( Re(q1),Re(q2) );
00526 im = interval( Im(q1),Im(q2) );
00527
00528 return cinterval(re,im);
00529 }
00530
00531 cinterval operator / (const cinterval & a, const cinterval & b) throw(DIV_BY_ZERO)
00532 {
00533 if (0.0 <= b.re && 0.0 <= b.im ) {
00534 cxscthrow(DIV_BY_ZERO("cinterval operator / (const cinterval&, const cinterval&)"));
00535 return a;
00536 }
00537 bool a_point, b_point;
00538 a_point = InfRe(a)==SupRe(a) && InfIm(a)==SupIm(a);
00539 b_point = InfRe(b)==SupRe(b) && InfIm(b)==SupIm(b);
00540 if(a_point && b_point) return C_point_div(a,b);
00541 else return cidiv(a,b);
00542 }
00543
00544 interval abs(const cinterval &a) throw()
00545 {
00546
00547
00548
00549
00550 return sqrtx2y2(a.re,a.im);
00551 }
00552
00553
00554
00555
00556 std::ostream & operator << (std::ostream &s, const cinterval& a) throw()
00557 {
00558 s << '('
00559 << a.re << ','
00560 << a.im
00561 << ')';
00562 return s;
00563 }
00564 std::string & operator << (std::string &s, const cinterval &a) throw()
00565 {
00566 s+='(';
00567 s << a.re;
00568 s+=',';
00569 s << a.im;
00570 s+=')';
00571 return s;
00572 }
00573
00574 std::istream & operator >> (std::istream &s, cinterval &a) throw(ERROR_CINTERVAL_EMPTY_INTERVAL)
00575 {
00576 char c;
00577 skipeolnflag = inpdotflag = true;
00578 c = skipwhitespacessinglechar (s, '(');
00579 if (inpdotflag) s.putback(c);
00580 c = skipwhitespacessinglechar (s, '[');
00581 if (inpdotflag) s.putback(c);
00582 s >> SaveOpt >> RndDown >> Inf(a.re);
00583 skipeolnflag = inpdotflag = true;
00584 c = skipwhitespacessinglechar (s, ',');
00585 if (inpdotflag) s.putback(c);
00586 s >> RndUp >> Sup(a.re);
00587 c = skipwhitespacessinglechar (s, ']');
00588 if (inpdotflag) s.putback(c);
00589 c = skipwhitespacessinglechar (s, ',');
00590 if (inpdotflag) s.putback(c);
00591
00592 c = skipwhitespacessinglechar (s, '[');
00593 if (inpdotflag) s.putback(c);
00594 s >> RndDown >> Inf(a.im);
00595 skipeolnflag = inpdotflag = true;
00596 c = skipwhitespacessinglechar (s, ',');
00597 if (inpdotflag) s.putback(c);
00598 s >> RndUp >> Sup(a.im) >> RestoreOpt;
00599
00600 if (!waseolnflag)
00601 {
00602 skipeolnflag = false, inpdotflag = true;
00603 c = skipwhitespaces (s);
00604 if (inpdotflag && c != ']')
00605 s.putback(c);
00606 }
00607 if (!waseolnflag)
00608 {
00609 skipeolnflag = false, inpdotflag = true;
00610 c = skipwhitespaces (s);
00611 if (inpdotflag && c != ')')
00612 s.putback(c);
00613 }
00614 if (Inf(a.re) > Sup(a.re) || Inf(a.im) > Sup(a.im))
00615 cxscthrow(ERROR_CINTERVAL_EMPTY_INTERVAL("std::istream & operator >> (std::istream &s, cinterval &a)"));
00616
00617 return s;
00618 }
00619
00620 std::string & operator >> (std::string &s, cinterval &a) throw(ERROR_CINTERVAL_EMPTY_INTERVAL)
00621 {
00622 s = skipwhitespacessinglechar (s, '(');
00623 s = skipwhitespacessinglechar (s, '[');
00624 s = s >> SaveOpt >> RndDown >> Inf(a.re);
00625 s = skipwhitespacessinglechar (s, ',');
00626 s = s >> RndUp >> Sup(a.re);
00627 s = skipwhitespacessinglechar (s, ']');
00628 s = skipwhitespacessinglechar (s, ',');
00629 s = skipwhitespacessinglechar (s, '[');
00630 s = s >> RndDown >> Inf(a.im);
00631 s = skipwhitespacessinglechar (s, ',');
00632 s = s >> RndUp >> Sup(a.im) >> RestoreOpt;
00633 s = skipwhitespaces (s);
00634 if (s[0] == ']')
00635 s.erase(0,1);
00636 s = skipwhitespaces (s);
00637 if (s[0] == ')')
00638 s.erase(0,1);
00639
00640 if (Inf(a.re) > Sup(a.re) || Inf(a.im) > Sup(a.im))
00641 cxscthrow(ERROR_CINTERVAL_EMPTY_INTERVAL("std::string & operator >> (std::string &s, cinterval &a)"));
00642
00643 return s;
00644 }
00645
00646 void operator >>(const std::string &s,cinterval &a) throw(ERROR_CINTERVAL_EMPTY_INTERVAL)
00647 {
00648 std::string r(s);
00649 r>>a;
00650 }
00651 void operator >>(const char *s,cinterval &a) throw(ERROR_CINTERVAL_EMPTY_INTERVAL)
00652 {
00653 std::string r(s);
00654 r>>a;
00655 }
00656
00657 int in ( const cinterval& x, const cinterval& y )
00658 {
00659 return ( in(Re(x),Re(y)) && in(Im(x),Im(y)) );
00660 }
00668 cinterval Blow ( cinterval x, const real& eps )
00669 {
00670 return cinterval(Blow(Re(x),eps),Blow(Im(x),eps));
00671 }
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687