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
00027 #include "complex.hpp"
00028 #include "dot.hpp"
00029 #include "cdot.hpp"
00030 #include "real.hpp"
00031 #include "rmath.hpp"
00032 #include "idot.hpp"
00033 #include "interval.hpp"
00034
00035 #include "cinterval.hpp"
00036
00037 namespace cxsc {
00038
00039 complex::complex(const cdotprecision & a) throw()
00040 {
00041 *this=rnd(a);
00042 }
00043
00044 complex & complex::operator =(const cdotprecision & a) throw()
00045 {
00046 return *this=rnd(a);
00047 }
00048
00049 bool operator== (const complex & a, const dotprecision & b) throw() { return !a.im && a.re==b; }
00050 bool operator== (const dotprecision & a, const complex & b) throw() { return !b.im && a==b.re; }
00051 bool operator!= (const complex & a, const dotprecision & b) throw() { return !!a.im || a.re!=b; }
00052 bool operator!= (const dotprecision & a, const complex & b) throw() { return !!b.im || a!=b.re; }
00053
00054 complex operator *(const complex &a,const complex &b) throw()
00055 {
00056 complex tmp;
00057 dotprecision dot(0.0);
00058
00059 accumulate (dot, a.re, b.re);
00060 accumulate (dot, -a.im, b.im);
00061 rnd (dot, tmp.re, RND_NEXT);
00062
00063 dot = 0.0;
00064 accumulate (dot, a.re, b.im);
00065 accumulate (dot, a.im, b.re);
00066 rnd (dot, tmp.im, RND_NEXT);
00067
00068 return tmp;
00069 }
00070
00071 complex muld(const complex &a, const complex &b) throw()
00072 {
00073 complex tmp;
00074 dotprecision dot(0.0);
00075
00076 accumulate (dot, a.re, b.re);
00077 accumulate (dot, -a.im, b.im);
00078 rnd (dot, tmp.re, RND_DOWN);
00079
00080 dot = 0.0;
00081 accumulate (dot, a.re, b.im);
00082 accumulate (dot, a.im, b.re);
00083 rnd (dot, tmp.im, RND_DOWN);
00084
00085 return tmp;
00086 }
00087
00088 complex mulu(const complex &a, const complex &b) throw()
00089 {
00090 complex tmp;
00091 dotprecision dot(0.0);
00092
00093 accumulate (dot, a.re, b.re);
00094 accumulate (dot, -a.im, b.im);
00095 rnd (dot, tmp.re, RND_UP);
00096
00097 dot = 0.0;
00098 accumulate (dot, a.re, b.im);
00099 accumulate (dot, a.im, b.re);
00100 rnd (dot, tmp.im, RND_UP);
00101
00102 return tmp;
00103 }
00104
00105
00106 static const int Min_Exp_ = 1074, minexpom = -914,
00107 maxexpo1 = 1022, MANT_W = 52;
00108
00109 void product(real a, real b, real c, real d,
00110 int& overfl, real& p1, interval& p2)
00111
00112
00113
00114
00115
00116
00117
00118
00119 {
00120 int exa, exb, exc, exd;
00121 dotprecision dot;
00122 int inexact;
00123
00124 overfl = 0;
00125 inexact = 0;
00126
00127 dot = 0.0;
00128 exa = expo(a);
00129 exb = expo(b);
00130 exc = expo(c);
00131 exd = expo(d);
00132
00133 if ( sign(a) == 0 || sign(b) == 0 )
00134 if ( sign(c) == 0 || sign(d) == 0 )
00135
00136 ;
00137 else
00138 {
00139
00140 if (exc+exd > maxexpo1)
00141 {
00142
00143 if ( exc > exd ) c = comp( mant(c), exc-Min_Exp_ );
00144 else d = comp( mant(d), exd-Min_Exp_ );
00145 overfl = 1;
00146 } else
00147 if ( exc+exd < minexpom )
00148 {
00149
00150 if (exc < exd) c = comp( mant(c), exc+Min_Exp_ );
00151 else d = comp( mant(d), exd+Min_Exp_ );
00152 overfl = -1;
00153 }
00154 accumulate(dot,c,d);
00155 } else
00156 if ( sign(c) == 0 || sign(d) == 0 )
00157 {
00158
00159 if (exa+exb > maxexpo1)
00160 {
00161
00162 if ( exa > exb ) a = comp( mant(a), exa-Min_Exp_ );
00163 else b = comp( mant(b), exb-Min_Exp_ );
00164 overfl = 1;
00165 } else
00166 if (exa+exb < minexpom)
00167 {
00168
00169 if (exa < exb) a = comp( mant(a), exa+Min_Exp_ );
00170 else b = comp( mant(b), exb+Min_Exp_ );
00171 overfl = -1;
00172 }
00173 accumulate(dot,a,b);
00174 } else
00175 {
00176
00177 if (exa+exb > maxexpo1)
00178 {
00179 if ( exa > exb ) a = comp( mant(a), exa-Min_Exp_ );
00180 else b = comp( mant(b), exb-Min_Exp_ );
00181 if (exc > MANT_W) c = comp( mant(c), exc-Min_Exp_ );
00182 else if (exd > MANT_W)
00183 d = comp( mant(d), exd-Min_Exp_ );
00184 else
00185 {
00186
00187 c = 0.0;
00188 inexact = 1;
00189 }
00190 overfl = 1;
00191 } else if (exc+exd > maxexpo1)
00192 {
00193
00194 if ( exc > exd ) c = comp( mant(c), exc-Min_Exp_ );
00195 else d = comp( mant(d), exd-Min_Exp_ );
00196 if (exa > MANT_W) a = comp( mant(a), exa-Min_Exp_ );
00197 else if (exb > MANT_W)
00198 b = comp( mant(b), exb-Min_Exp_ );
00199 else
00200 {
00201
00202 a = 0.0;
00203 inexact = 1;
00204 }
00205 overfl = 1;
00206 } else
00207 if ( exa+exb < minexpom && exc+exd < minexpom )
00208 {
00209
00210 if (exa < exb) a = comp( mant(a), exa+Min_Exp_ );
00211 else b = comp( mant(b), exb+Min_Exp_ );
00212 if (exc < exd) c = comp( mant(c), exc+Min_Exp_ );
00213 else d = comp( mant(d), exd+Min_Exp_ );
00214 overfl = -1;
00215 }
00216 accumulate(dot, a, b);
00217 accumulate(dot, c, d);
00218 }
00219
00220 p1 = rnd(dot);
00221 dot -= p1;
00222 rnd(dot,p2);
00223
00224 if (inexact)
00225 p2 = _interval( pred(Inf(p2)), succ(Sup(p2)) );
00226
00227 }
00228
00229 real quotient (real z1, interval z2, real n1,
00230 interval n2, int round, int zoverfl, int noverfl)
00231
00232
00233
00234
00235
00236
00237
00238 {
00239 real q1=0, scale;
00240 interval q2, nh;
00241 idotprecision id;
00242 int vorz, anz_scale, ex = 0;
00243
00244 vorz = sign(z1);
00245
00246 if ( zoverfl == -1 && noverfl == 1 )
00247 {
00248
00249 switch (round)
00250 {
00251 case RND_DOWN:
00252 if (vorz >= 0)
00253 q1 = 0.0;
00254 else
00255 q1 = -minreal;
00256 break;
00257 case RND_NEXT:
00258 q1 = 0.0;
00259 break;
00260 case RND_UP:
00261 if (vorz <= 0)
00262 q1 = 0.0;
00263 else
00264 q1 = minreal;
00265 break;
00266 }
00267 } else if ( zoverfl==1 && noverfl==-1 )
00268 {
00269
00270 if (vorz >= 0) q1 = MaxReal+MaxReal;
00271 else q1 = -MaxReal-MaxReal;
00272 } else
00273 {
00274 q1 = divd(z1, n1);
00275 nh = _interval(addd(n1, Inf(n2)),
00276 addu(n1, Sup(n2)));
00277
00278
00279 id = z1;
00280 accumulate(id, -q1, n1);
00281 id += z2;
00282 accumulate(id, -q1, n2);
00283 q2 = rnd(id);
00284
00285 switch (round)
00286 {
00287 case RND_DOWN:
00288 q1 = adddown(q1, divd(Inf(q2), Sup(nh)));
00289 break;
00290 case RND_NEXT:
00291 q1 = q1 + (Inf(q2)+Sup(q2))*0.5/n1;
00292 break;
00293 case RND_UP:
00294 q1 = addup(q1, divu(Sup(q2), Inf(nh)));
00295 break;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 anz_scale = zoverfl - noverfl;
00307 if (anz_scale > 0)
00308 {
00309 scale = comp(0.5, +1024);
00310 ex = MANT_W-1;
00311 }
00312 else if (anz_scale < 0)
00313 {
00314 scale = comp(0.5, -1022);
00315 ex = -MANT_W+1;
00316 }
00317 else scale = 1.0;
00318
00319
00320 if (ex) times2pown(q1,ex);
00321 switch (round)
00322 {
00323 case RND_DOWN:
00324 q1 = multdown(q1, scale);
00325 break;
00326 case RND_NEXT:
00327 q1 = q1 * scale;
00328 break;
00329 case RND_UP:
00330 q1 = multup(q1, scale);
00331 break;
00332 }
00333 }
00334 return q1;
00335 }
00336
00337 complex _c_division(complex a, complex b, int round) throw(DIV_BY_ZERO)
00338 {
00339 if (0.0 == (sqr(Re(b))+sqr(Im(b)))) {
00340 cxscthrow(DIV_BY_ZERO("complex operator / (const complex&,const complex&)"));
00341 }
00342
00343 int zoverflow, noverflow;
00344 real z1, n1;
00345 interval z2, n2;
00346 complex tmp;
00347
00348 product (Re(b), Re(b), Im(b), Im(b), noverflow, n1, n2);
00349 product (Re(a), Re(b), Im(a), Im(b), zoverflow, z1, z2);
00350 SetRe (tmp, quotient (z1, z2, n1, n2, round, zoverflow, noverflow));
00351 product (Im(a), Re(b), -Re(a), Im(b), zoverflow, z1, z2);
00352 SetIm (tmp, quotient (z1, z2, n1, n2, round, zoverflow, noverflow));
00353 return tmp;
00354 }
00355
00356 complex divn (const complex & a, const complex & b)
00357 {
00358 return _c_division(a, b, RND_NEXT);
00359 }
00360
00361 complex divd (const complex & a, const complex & b)
00362 {
00363 return _c_division(a, b, RND_DOWN);
00364 }
00365
00366 complex divu (const complex & a, const complex & b)
00367 {
00368 return _c_division(a, b, RND_UP);
00369 }
00370
00371 complex operator / (const complex &a,const complex &b) throw()
00372 {
00373 return divn(a,b);
00374 }
00375
00376 real abs2(const complex &a) throw()
00377 {
00378 dotprecision dot(0.0);
00379 accumulate(dot,a.re,a.re);
00380 accumulate(dot,a.im,a.im);
00381 return rnd(dot);
00382 }
00383
00384 real abs (complex z) throw()
00385 {
00386 return sqrtx2y2(Re(z),Im(z));
00387 }
00388
00389
00390
00391
00392 std::ostream & operator << (std::ostream &s, const complex& a) throw()
00393 {
00394 s << '('
00395 << a.re << ','
00396 << a.im
00397 << ')';
00398 return s;
00399 }
00400 std::string & operator << (std::string &s, const complex &a) throw()
00401 {
00402 s+='(';
00403 s << a.re;
00404 s+=',';
00405 s << a.im;
00406 s+=')';
00407 return s;
00408 }
00409
00410 std::istream & operator >> (std::istream &s, complex &a) throw()
00411 {
00412 char c;
00413
00414 skipeolnflag = inpdotflag = true;
00415 c = skipwhitespacessinglechar (s, '(');
00416 if (inpdotflag)
00417 s.putback(c);
00418
00419 s >> a.re;
00420
00421 skipeolnflag = inpdotflag = true;
00422 c = skipwhitespacessinglechar (s, ',');
00423 if (inpdotflag) s.putback(c);
00424
00425 s >> a.im >> RestoreOpt;
00426
00427 if (!waseolnflag)
00428 {
00429 skipeolnflag = false, inpdotflag = true;
00430 c = skipwhitespaces (s);
00431 if (inpdotflag && c != ')')
00432 s.putback(c);
00433 }
00434
00435
00436
00437
00438 return s;
00439 }
00440
00441 std::string & operator >> (std::string &s, complex &a) throw()
00442 {
00443 s = skipwhitespacessinglechar (s, '(');
00444 s >> SaveOpt >> RndDown >> a.re;
00445 s = skipwhitespacessinglechar (s, ',');
00446 s >> RndUp >> a.im >> RestoreOpt;
00447 s = skipwhitespaces (s);
00448
00449 if (s[0] == ')')
00450 s.erase(0,1);
00451
00452
00453
00454
00455 return s;
00456 }
00457
00458 void operator >>(const std::string &s,complex &a) throw()
00459 {
00460 std::string r(s);
00461 r>>a;
00462 }
00463 void operator >>(const char *s,complex &a) throw()
00464 {
00465 std::string r(s);
00466 r>>a;
00467 }
00468
00469 complex exp(const complex& x) throw() { return mid(exp(cinterval(x))); }
00470 complex expm1(const complex& x) throw() { return mid(expm1(cinterval(x))); }
00471 complex exp2(const complex& x) throw() { return mid(exp2(cinterval(x))); }
00472 complex exp10(const complex& x) throw() { return mid(exp10(cinterval(x))); }
00473 complex cos(const complex& x) throw() { return mid(cos(cinterval(x))); }
00474 complex sin(const complex& x) throw() { return mid(sin(cinterval(x))); }
00475 complex cosh(const complex& x) throw() { return mid(cosh(cinterval(x))); }
00476 complex sinh(const complex& x) throw() { return mid(sinh(cinterval(x))); }
00477
00478 complex tan(const complex& x) throw() { return mid(tan(cinterval(x))); }
00479 complex cot(const complex& x) throw() { return mid(cot(cinterval(x))); }
00480 complex tanh(const complex& x) throw() { return mid(tanh(cinterval(x))); }
00481 complex coth(const complex& x) throw() { return mid(coth(cinterval(x))); }
00482
00483 real arg(const complex& x) throw() { return mid(arg(cinterval(x))); }
00484 real Arg(const complex& x) throw() { return mid(Arg(cinterval(x))); }
00485
00486 complex ln(const complex& x) throw() { return mid(ln(cinterval(x))); }
00487 complex lnp1(const complex& x) throw() { return mid(lnp1(cinterval(x))); }
00488 complex log2(const complex& x) throw() { return mid(log2(cinterval(x))); }
00489 complex log10(const complex& x) throw() { return mid(log10(cinterval(x))); }
00490
00491 complex sqr(const complex& x) throw() { return mid(sqr(cinterval(x))); }
00492
00493 complex sqrt(const complex& x) throw() { return mid(sqrt(cinterval(x))); }
00494 complex sqrtp1m1(const complex& x) throw() { return mid(sqrtp1m1(cinterval(x))); }
00495 complex sqrt1px2(const complex& x) throw() { return mid(sqrt1px2(cinterval(x))); }
00496 complex sqrtx2m1(const complex& x) throw() { return mid(sqrtx2m1(cinterval(x))); }
00497 complex sqrt1mx2(const complex& x) throw() { return mid(sqrt1mx2(cinterval(x))); }
00498 complex sqrt(const complex& x, int d) throw()
00499 { return mid(sqrt(cinterval(x),d)); }
00500
00501 std::list<complex> sqrt_all( const complex& c )
00502 {
00503 complex z;
00504 z = sqrt(c);
00505
00506 std::list<complex> res;
00507 res.push_back( z );
00508 res.push_back( -z );
00509
00510 return res;
00511 }
00512
00513 std::list<complex> sqrt_all( const complex& z, int n )
00514
00515
00516
00517
00518
00519
00520
00521
00522 {
00523 std::list<complex> res;
00524
00525 if( n == 0 )
00526 {
00527 res.push_back( complex(1,0) );
00528 return res;
00529 }
00530 else if( n == 1 )
00531 {
00532 res.push_back(z);
00533 return res;
00534 }
00535 else if( n == 2 ) return sqrt_all( z );
00536 else
00537 {
00538 real
00539 arg_z = arg( z ), root_abs_z = sqrt( abs( z ), n );
00540
00541 for(int k = 0; k < n; k++)
00542 {
00543 real arg_k = ( arg_z + 2 * k * mid(Pi_interval) ) / n;
00544
00545 res.push_back( complex( root_abs_z * cos( arg_k ),
00546 root_abs_z * sin( arg_k ) ) );
00547 }
00548 return res;
00549 }
00550 }
00551
00552
00553
00554 complex power_fast(const complex& x,int d) throw()
00555 { return mid(power_fast(cinterval(x),d)); }
00556 complex power(const complex& x,int d) throw()
00557 { return mid(power(cinterval(x),d)); }
00558 complex pow(const complex& x, const real& r) throw()
00559 { return mid(pow(cinterval(x),interval(r))); }
00560 complex pow(const complex& x, const complex& y) throw()
00561 { return mid(pow(cinterval(x),cinterval(y))); }
00562
00563 complex asin(const complex& x) throw() { return mid(asin(cinterval(x))); }
00564 complex acos(const complex& x) throw() { return mid(acos(cinterval(x))); }
00565 complex asinh(const complex& x) throw() { return mid(asinh(cinterval(x))); }
00566 complex acosh(const complex& x) throw() { return mid(acosh(cinterval(x))); }
00567 complex atan(const complex& x) throw() { return mid(atan(cinterval(x))); }
00568 complex acot(const complex& x) throw() { return mid(acot(cinterval(x))); }
00569 complex atanh(const complex& x) throw() { return mid(atanh(cinterval(x))); }
00570 complex acoth(const complex& x) throw() { return mid(acoth(cinterval(x))); }
00571
00572 }
00573