C-XSC - A C++ Class Library for Extended Scientific Computing
2.5.4
|
00001 /* 00002 ** CXSC is a C++ library for eXtended Scientific Computing (V 2.5.4) 00003 ** 00004 ** Copyright (C) 1990-2000 Institut fuer Angewandte Mathematik, 00005 ** Universitaet Karlsruhe, Germany 00006 ** (C) 2000-2014 Wiss. Rechnen/Softwaretechnologie 00007 ** Universitaet Wuppertal, Germany 00008 ** 00009 ** This library is free software; you can redistribute it and/or 00010 ** modify it under the terms of the GNU Library General Public 00011 ** License as published by the Free Software Foundation; either 00012 ** version 2 of the License, or (at your option) any later version. 00013 ** 00014 ** This library is distributed in the hope that it will be useful, 00015 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 ** Library General Public License for more details. 00018 ** 00019 ** You should have received a copy of the GNU Library General Public 00020 ** License along with this library; if not, write to the Free 00021 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 */ 00023 00024 /* CVS $Id: cimath.cpp,v 1.31 2014/01/30 17:23:43 cxsc Exp $ */ 00025 00026 /* 00027 ** 00028 ** COmplex interval STandard functions LibrarY, CoStLy Version 1.0.3 00029 ** 00030 ** Copyright (C) Markus Neher, markus.neher@math.uni-karlsruhe.de 00031 ** Ingo Eble, ingoeble@web.de 00032 ** Frithjof Blomquist, Blomquist@math.uni-wuppertal.de 00033 ** 00034 ** The complex interval elementary functions in C-XSC are based on the 00035 ** CoStLy library written by Markus Neher. Additional improvements have 00036 ** been done by Frithjof Blomquist. 00037 ** 00038 ** References: 00039 ** - Neher, M: "Complex Standard Functions and their Implementation in 00040 ** the CoStLy Library", Preprint Nr. 04/18, Fakultaet fuer Mathematik, 00041 ** Universitaet Karlsruhe, 2004. 00042 ** - Blomquist, F.; Hofschuster, W.; Kraemer, W.: "Complex Interval Functions 00043 ** in C-XSC", Preprint BUW-WRSWT 2005/2, Universitaet Wuppertal, 2005. 00044 ** - Neher, M: "Complex Standard Functions and their Implementation in 00045 ** the CoStLy Library", to appear in ACM Transactions on Mathematical 00046 ** Software (TOMS). 00047 ** 00048 */ 00049 00050 00051 //Include header files 00052 #include "cimath.hpp" // Declaration of the complex functions 00053 #include "rmath.hpp" // "real" standard functions 00054 #include "imath.hpp" // "interval" standard functions 00055 #include "dot.hpp" // "dotprecision" standard functions 00056 00057 namespace cxsc{ 00058 00059 const real Inf_Pi = 7074237752028440.0 / 2251799813685248.0; // Inf_Pi < Pi 00060 // succ(Inf_Pi) > Pi is guaranteed! 00061 00062 const real pi2 = 4967757600021510.0 / 40564819207303340847894502572032.0; 00063 const interval Pi2 = interval(pi2,succ(pi2)); 00064 // Inf_Pi+pi2 < pi; Inf_Pi+succ(pi2) > pi; 00065 00066 00067 inline const interval& ZERO_INTERVAL() 00068 { 00069 static const interval zero = interval(0.0); 00070 return zero; 00071 } 00072 00073 inline const interval& ONE_INTERVAL() 00074 { 00075 static const interval one = interval(1.0); 00076 return one; 00077 } 00078 00079 inline const interval& PI() // Blomquist; 00080 { 00081 static const interval pi = interval(Inf_Pi,succ(Inf_Pi)); 00082 return pi; 00083 } 00084 00085 inline const interval& HALFPI() // Blomquist; 00086 { 00087 interval hp = PI(); 00088 times2pown(hp,-1); // division by 2 00089 static const interval hpi = hp; 00090 return hpi; 00091 } 00092 00093 bool disjoint(const interval& x,const interval& y) 00094 { 00095 real ix( Inf(x) ),iy( Inf(y) ),sx( Sup(x) ), sy( Sup(y) ); 00096 real inf( ( ix > iy )? ix : iy ); 00097 real sup( ( sx < sy )? sx : sy ); 00098 00099 return ( inf > sup ); 00100 } 00101 00102 //-- SQRT_2 --- INV_SQRT_2 --- LN(4) ------------------------------------------ 00103 // 00104 const real Inf_rev_sqrt_2 = 6369051672525772.0 / 9007199254740992.0; 00105 // Inf_rev_sqrt_2 < 1/sqrt(2); 00106 00107 inline const interval& INV_SQRT_2() 00108 { // optimal inclusion of 1/sqrt(2); 00109 static const interval t = interval(Inf_rev_sqrt_2,succ(Inf_rev_sqrt_2)); 00110 return t; 00111 } 00112 00113 const real Inf_U_atan = 6243314768165359.0 / 4503599627370496.0; 00114 const interval U_atan(Inf_U_atan,succ(Inf_U_atan)); // optimal inclusion of 00115 // ln(4); 00116 00117 00118 // 00119 //-- end SQRT_2 and INV_SQRT_2 ------------------------------------------------ 00120 00121 00122 /* ***************************************************************************/ 00123 /* ***************************************************************************/ 00124 /* *** Single-valued functions *** */ 00125 /* ***************************************************************************/ 00126 /* ***************************************************************************/ 00127 00128 00129 /* ***************************************************************************/ 00130 /* *** Power operator pow is not listed here, since it relies on the ****/ 00131 /* *** (multi-valued) logarithm ****/ 00132 /* ***************************************************************************/ 00133 00134 00135 /* ***************************************************************************/ 00136 /* *** The hyperbolic functions exp, sin, cos, sinh, cosh are separable: ****/ 00137 /* *** Their real and imaginary parts are products of real functions ****/ 00138 /* ***************************************************************************/ 00139 /* *** With Re(z)=x, Im(z)=y : ****/ 00140 /* *** ****/ 00141 /* *** exp : Re(exp(z)) = exp(x) * cos(y) ****/ 00142 /* *** Im(exp(z)) = exp(x) * sin(y) ****/ 00143 /* *** ****/ 00144 /* *** sin : Re(sin(z)) = sin(x) * cosh(y) ****/ 00145 /* *** Im(sin(x)) = cos(x) * sinh(y) ****/ 00146 /* *** ****/ 00147 /* *** cos : Re(cos(z)) = cos(x) * cosh(y) ****/ 00148 /* *** Im(sin(x)) = -sin(x) * sinh(y) ****/ 00149 /* *** ****/ 00150 /* *** sinh : Re(sinh(z)) = sinh(x) * cos(y) ****/ 00151 /* *** Im(sinh(z)) = cosh(x) * sin(y) ****/ 00152 /* *** ****/ 00153 /* *** cosh : Re(cosh(z)) = cosh(x) * cos(y) ****/ 00154 /* *** Im(cosh(z)) = sinh(x) * sin(y) ****/ 00155 /* *** ****/ 00156 /* ***************************************************************************/ 00157 00158 00159 cinterval exp(const cinterval& z) throw() 00160 { 00161 interval 00162 A( exp( Re(z) ) ), 00163 B( Im(z) ); 00164 return cinterval( A*cos( B ) , A*sin( B ) ); 00165 } 00166 00167 cinterval exp2(const cinterval& z) throw() 00168 { 00169 return exp(z*Ln2_interval); 00170 } 00171 00172 cinterval exp10(const cinterval& z) throw() 00173 { 00174 return exp(z*Ln10_interval); 00175 } 00176 00177 cinterval expm1(const cinterval& z) throw() 00178 // exp(z) - 1; 00179 // Calculates nearly optimal inclusions for not too wide intervals z. 00180 // Blomquist, 03.12.2008; 00181 { 00182 const interval cancl_test = interval(0.9,1.1); 00183 interval rez(Re(z)), imz(Im(z)); 00184 interval exp_x, sin_y, cos_y, h, Xt; 00185 cinterval res; 00186 00187 exp_x = exp(rez); 00188 sin_y = sin(imz); 00189 cos_y = cos(imz); 00190 00191 h = exp_x*cos_y; 00192 00193 if (h < cancl_test && cos_y < cancl_test) 00194 { 00195 h = lnp1(-sqr(sin_y)); 00196 times2pown(h,-1); 00197 // h = 0.5 * ln(1-sqr( sin(y) )); 00198 h = expm1(rez+h); // Cancellation also possible here! 00199 } 00200 else h = h - 1; // Cancellation possible here (real part)! 00201 // h: Real part; 00202 imz = exp_x * sin_y; 00203 res = cinterval(h,imz); 00204 return res; 00205 } 00206 00207 cinterval cos(const cinterval& z) throw() 00208 { 00209 interval 00210 A( Re(z) ), 00211 B( Im(z) ); 00212 return cinterval( cos( A )*cosh( B ) , -sin( A )*sinh( B ) ); 00213 } 00214 00215 cinterval sin(const cinterval& z) throw() 00216 { 00217 interval 00218 A( Re(z) ), 00219 B( Im(z) ); 00220 return cinterval( sin( A )*cosh( B ) , cos( A )*sinh( B ) ); 00221 } 00222 00223 cinterval cosh(const cinterval& z) throw() 00224 { 00225 interval 00226 A( Re(z) ), 00227 B( Im(z) ); 00228 return cinterval( cos( B )*cosh( A ) , sin( B )*sinh( A ) ); 00229 } 00230 00231 cinterval sinh(const cinterval& z) throw() 00232 { 00233 interval 00234 A( Re(z) ), 00235 B( Im(z) ); 00236 return cinterval( cos( B )*sinh( A ) , sin( B )*cosh( A ) ); 00237 } 00238 00239 00240 00241 //----------------------------------------------------------------------------- 00242 // 00243 // Section 2: tan, cot, tanh, coth 00244 // 00245 // The implementation of cot, tanh, and coth is based on tan: 00246 // 00247 // cot( z ) = tan( pi/2 - z ) 00248 // tanh( z ) = transp( i * tan( transp( i * z ) ) 00249 // coth( z ) = i * cot( i * z ) = i * tan( pi/2 - i * z ) 00250 // 00251 //----------------------------------------------------------------------------- 00252 00253 //-- tan ------------------------------------------------------------ 040827 -- 00254 // 00255 // Complex tangent function 00256 // 00257 void horizontal_check( //-------------------------------------------- 040726 -- 00258 const interval& hy, const interval& cosh_2y, real irez, real srez, 00259 const interval& hxl, const interval& hxu, real& resxl, real& resxu ) 00260 // 00261 // Subroutine of tangent function. 00262 // Check intersections with extremal curves of tan on a horizontal boundary. 00263 // This subroutine is only called if an intersection occurs. 00264 // In this case, sinh( 2 * hy ) <> 0.0 (poles are handled before). 00265 // 00266 // There may be 1 or 2 intersections. 00267 // If intersections lie next to a boundary of rez, then it is impossible to 00268 // decide if there are 1 or 2 intersections. 00269 // In this case, 2 intersections are assumed 00270 // (valid enclosure, at the expense of a potential slight overestimation). 00271 // 00272 { 00273 bool both = false, left = false, right = false; 00274 00275 if (srez - irez > Inf( PI() )) 00276 // 2 intersections 00277 both = true; 00278 else 00279 { 00280 interval 00281 res_l = cos( 2 * hxl ) - cosh_2y, 00282 res_u = cos( 2 * hxu ) - cosh_2y; 00283 00284 if( Inf( res_l * res_u ) > 0.0 ) 00285 // 2 intersections 00286 both = true; 00287 else 00288 { 00289 if( Sup( res_l * res_u ) < 0.0 ) 00290 { 00291 // 1 intersection (3 intersections are PI() apart) 00292 // neither of the intervals res_l and res_u contains zero 00293 if( Inf( res_l ) > 0.0 ) 00294 // "left" intersection 00295 left = true; 00296 else 00297 // "right" intersection 00298 right = true; 00299 } 00300 else 00301 // 00302 // 1 (or both) intersections lie next to a boundary point 00303 // here, the task is to decide if 2 intersections occurs 00304 // if only 1 intersection takes place, then which one? 00305 // 00306 { 00307 interval 00308 sin_2xl = sin( 2 * hxl ), 00309 sin_2xu = sin( 2 * hxu ); 00310 00311 if( !disjoint( ZERO_INTERVAL(), res_l ) ) 00312 // intersection on the left boundary 00313 { 00314 if( Inf( sin_2xl ) >= 0.0 ) 00315 // "left" intersection 00316 { 00317 left = true; 00318 // remove the intersection by changing res_l! 00319 res_l = - ONE_INTERVAL(); 00320 } 00321 else 00322 { 00323 if( Sup( sin_2xl ) <= 0.0 ) 00324 // "right" intersection 00325 { 00326 right = true; 00327 // remove the intersection by changing res_l! 00328 res_l = ONE_INTERVAL(); 00329 } 00330 else 00331 // zero is interior point of sin_2xl 00332 // if the real sine function has optimal precision, 00333 // this case should never happen 00334 both = true; 00335 } 00336 } 00337 00338 if( !disjoint( ZERO_INTERVAL(), res_u ) ) 00339 // intersection on the right boundary 00340 { 00341 if( Inf( sin_2xu ) >= 0.0 ) 00342 // "left" intersection 00343 { 00344 left = true; 00345 // remove the intersection by changing res_u! 00346 res_u = ONE_INTERVAL(); 00347 } 00348 else 00349 { 00350 if( Sup( sin_2xu ) <= 0.0 ) 00351 // "right" intersection 00352 { 00353 right = true; 00354 // remove the intersection by changing res_u! 00355 res_u = - ONE_INTERVAL(); 00356 } 00357 else 00358 // zero is interior point of sin_2xu 00359 // if the real sine function has optimal precision, 00360 // this case should never happen 00361 both = true; 00362 } 00363 } 00364 // 00365 // finally, check if there is a second intersection 00366 // 00367 if( Inf( res_l * res_u ) < 0.0 ) 00368 both = true; 00369 } 00370 } 00371 } 00372 // 00373 // Calculate extremal values 00374 // 00375 interval re_tan = 1 / sinh( 2 * abs( hy ) ); 00376 00377 // "left" intersection, sin( 2x ) > 0 00378 if( left || both ) 00379 { 00380 resxl = min( resxl, Inf( re_tan ) ); 00381 resxu = max( resxu, Sup( re_tan ) ); 00382 } 00383 00384 // "right" intersection, sin( 2x ) < 0 00385 if( right || both ) 00386 { 00387 resxl = min( resxl, - Sup( re_tan ) ); 00388 resxu = max( resxu, - Inf( re_tan ) ); 00389 } 00390 } // end horizontal_check 00391 00392 00393 cinterval tan( const cinterval& z ) throw() //----------------------- 040827 -- 00394 { 00395 interval 00396 rez = Re(z), // rez = z.re(), 00397 imz = Im(z); // imz = z.im(); 00398 00399 real 00400 irez = Inf(rez), 00401 srez = Sup(rez), 00402 iimz = Inf(imz), 00403 simz = Sup(imz); 00404 00405 interval 00406 hxl(irez), hxu(srez), hyl(iimz), hyu(simz); 00407 00408 real 00409 resxl, resxu, resyl, resyu; 00410 // 00411 // 1st: check for poles 00412 // 00413 if( ( !disjoint( ZERO_INTERVAL(), imz ) ) && ( !disjoint( ZERO_INTERVAL(), cos( rez ) ) ) ) 00414 cxscthrow (STD_FKT_OUT_OF_DEF("cinterval tan( const cinterval& Z); Pole(s) in Z")); 00415 // 00416 // 2nd: real part 00417 // 00418 // evaluate tan on vertical boundaries 00419 // 00420 interval 00421 cos_2rez = cos( 2 * rez ), 00422 sinh_imz_2 = sqr( sinh( imz ) ); 00423 00424 interval 00425 re_tan_l = sin( 2 * hxl ) / ( 2 * ( sqr( cos( hxl ) ) + sinh_imz_2 ) ), 00426 re_tan_u = sin( 2 * hxu ) / ( 2 * ( sqr( cos( hxu ) ) + sinh_imz_2 ) ); 00427 00428 resxl = min( Inf( re_tan_l ), Inf( re_tan_u ) ); 00429 resxu = max( Sup( re_tan_l ), Sup( re_tan_u ) ); 00430 // 00431 // look for extremal values on horizontal boundaries 00432 // if one of the horizontal boundaries is the x-axes, 00433 // then the complex tangent is the real tangent on this 00434 // boundary, and due to monotonicity, its range 00435 // is already included in the ranges of the vertical boundaries 00436 // 00437 if( irez < srez ) 00438 { 00439 interval 00440 cosh_2yl = - 1 / cosh( 2 * hyl ), 00441 cosh_2yu = - 1 / cosh( 2 * hyu ); 00442 00443 if( !disjoint( cos_2rez, cosh_2yl ) && iimz != 0.0 ) 00444 //extremal curve intersects lower boundary 00445 horizontal_check( hyl, cosh_2yl, irez, srez, hxl, hxu, resxl, resxu ); 00446 00447 if( !disjoint( cos_2rez, cosh_2yu ) && simz != 0.0 ) 00448 //extremal curve intersects upper boundary 00449 horizontal_check( hyu, cosh_2yu, irez, srez, hxl, hxu, resxl, resxu ); 00450 } 00451 // 00452 // 3rd: imaginary part 00453 // 00454 // evaluate tan on horizontal boundaries 00455 // 00456 interval 00457 cos_rez_2 = sqr( cos( rez ) ); 00458 00459 interval 00460 im_tan_l = sinh( 2 * hyl ) / ( 2 * ( cos_rez_2 + sqr( sinh( hyl ) ) ) ), 00461 im_tan_u = sinh( 2 * hyu ) / ( 2 * ( cos_rez_2 + sqr( sinh( hyu ) ) ) ); 00462 00463 resyl = min( Inf( im_tan_l ), Inf( im_tan_u ) ); 00464 resyu = max( Sup( im_tan_l ), Sup( im_tan_u ) ); 00465 00466 // 00467 // look for extremal values on vertical boundaries 00468 // here, the situation is simpler than for the real part 00469 // if 2 intersections with extremal curves appear , 00470 // one lies in the lower half plane, the other in the upper half plane 00471 // 00472 interval 00473 cos_2xl = cos( 2 * hxl ), 00474 cos_2xu = cos( 2 * hxu ); 00475 interval im_tan; 00476 00477 if( iimz < 0.0 ) 00478 // intersection in lower half plane? 00479 { 00480 interval 00481 imz_h = interval( iimz, min( simz, 0.0 ) ), 00482 cosh_2imz = - 1 / cosh( 2 * imz_h ); 00483 00484 if( ( !disjoint( cosh_2imz, cos_2xl ) ) ) 00485 //extremal curve intersects left boundary 00486 //in this case, sin( 2 * xl ) <> 0.0 (no poles here!) 00487 { 00488 im_tan = - 1 / abs( sin( 2 * hxl ) ); 00489 resyl = min( resyl, Inf( im_tan ) ); 00490 resyu = max( resyu, Sup( im_tan ) ); 00491 } 00492 if( ( !disjoint( cosh_2imz, cos_2xu ) ) ) 00493 //extremal curve intersects right boundary 00494 //in this case, sin( 2 * xu ) <> 0.0 (no poles here!) 00495 { 00496 im_tan = - 1 / abs( sin( 2 * hxu ) ); 00497 resyl = min( resyl, Inf( im_tan ) ); 00498 resyu = max( resyu, Sup( im_tan ) ); 00499 } 00500 } 00501 if( simz > 0.0 ) 00502 // intersection in upper half plane? 00503 { 00504 interval 00505 imz_h = interval( max( iimz, 0.0 ), simz ), 00506 cosh_2imz = - 1 / cosh( 2 * imz_h ); 00507 00508 if( ( !disjoint( cosh_2imz, cos_2xl ) ) ) 00509 //extremal curve intersects left boundary 00510 //in this case, sin( 2 * xl ) <> 0.0 (no poles here!) 00511 { 00512 im_tan = + 1 / abs( sin( 2 * hxl ) ); 00513 resyl = min( resyl, Inf( im_tan ) ); 00514 resyu = max( resyu, Sup( im_tan ) ); 00515 } 00516 if( ( !disjoint( cosh_2imz, cos_2xu ) ) ) 00517 //extremal curve intersects right boundary 00518 //in this case, sin( 2 * xu ) <> 0.0 (no poles here!) 00519 { 00520 im_tan = + 1 / abs( sin( 2 * hxu ) ); 00521 resyl = min( resyl, Inf( im_tan ) ); 00522 resyu = max( resyu, Sup( im_tan ) ); 00523 } 00524 } 00525 00526 return cinterval( interval( resxl, resxu ), interval( resyl, resyu ) ); 00527 // return cinterval( interval( resxu-resxl, resxu-resxl ), interval( resyu, resyu ) ); 00528 //return cinterval( im_tan_l, im_tan_u ); 00529 00530 } // end tan 00531 00532 00533 //-- cot ------------------------------------------------------------ 040730 -- 00534 // 00535 // cot( z ) = tan( pi/2 - z ) 00536 // 00537 00538 cinterval cot( const cinterval& z ) throw() 00539 { // Improved cot-function; Blomquist,05.07.2005; 00540 // Improvements near the zeros z_(s,k) = Pi*(k+0.5), k=-4,-3,-2,-1,0,1,2,3,4; 00541 // where X = Re(z) must be a point interval near the zeros z_(s,k); 00542 // Blomquist,08.07.2005; 00543 interval Rez(Re(z)),re; 00544 real irez = Inf(Rez); // irez = Inf( Re(z) ) 00545 irez = irez/Inf_Pi - 0.5; 00546 double dbr = _double(irez); 00547 int p,s(sign(irez)); 00548 p = s>=0 ? CUTINT(dbr+0.5) : CUTINT(dbr-0.5); 00549 if (-5<p && p<5) { 00550 re = (Inf_Pi)*interval(p+0.5) - Rez; 00551 re = diam(re)==0 ? re + (Pi2)*(p+0.5) : HALFPI() - Rez; 00552 } 00553 else re = HALFPI() - Rez; 00554 cinterval res(cinterval(re,-Im(z))); 00555 return tan(res); 00556 } 00557 00558 // 00559 //-- end cot ------------------------------------------------------------------ 00560 00561 //-- tanh ----------------------------------------------------------- 040904 -- 00562 // 00563 // tanh( z ) = transp( i * tan( transp( i * z ) ) 00564 // 00565 cinterval tanh( const cinterval& z ) throw() 00566 { 00567 cinterval res = tan( cinterval( Im(z), Re(z) ) ); 00568 return cinterval( Im(res), Re(res) ); 00569 } 00570 // 00571 //-- end tanh ----------------------------------------------------------------- 00572 00573 //-- coth ----------------------------------------------------------- 040904 -- 00574 // 00575 // coth( z ) = i * cot( i * z ); 00576 // 00577 00578 cinterval coth( const cinterval& z ) throw() 00579 { // coth( z ) = i * cot( i * z ); 00580 cinterval zh = cinterval( -Im(z), Re(z) ); // zh = i*z; 00581 cinterval res = cot(zh); 00582 return( cinterval( -Im(res),Re(res) ) ); 00583 } 00584 // 00585 //-- end coth ----------------------------------------------------------------- 00586 00587 00588 //----------------------------------------------------------------------------- 00589 // 00590 // Part II: Multi-valued functions 00591 // 00592 //----------------------------------------------------------------------------- 00593 // 00594 // 00595 interval Atan(const interval& y, const interval& x) throw() 00596 // Calculating an inclusion of atan(y/x) with x<>[0,0]; 00597 // This help function must only be used for POINT intervals y,x !! 00598 // This function avoids internal overflow by calculating y/x. 00599 { 00600 const int c = 54; 00601 real Infx(Inf(x)), 00602 Infy(Inf(y)); 00603 int ex_x(expo(Infx)), 00604 ex_y(expo(Infy)), 00605 signx(sign(Infx)), 00606 signy(sign(Infy)), 00607 signq; 00608 interval res(0); 00609 00610 if (signy!=0) { 00611 signq = signx * signy; 00612 if (ex_y-ex_x > c) res = signq>0 ? HALFPI() : -HALFPI(); 00613 else res = atan(y/x); 00614 } 00615 00616 return res; 00617 } 00618 00619 interval Atan(const interval& y, const real& x) throw() 00620 // Calculating an inclusion of atan(y/x) with x<>0.0; 00621 // This help function must only be used for POINT intervals y !! 00622 // This function avoids internal overflow by calculating y/x. 00623 { 00624 interval xi(x); 00625 return Atan(y,xi); 00626 } 00627 00628 // 00629 // For the Multi-valued functions, two different procedures are 00630 // implemented. 00631 // 00632 // First, there is a subroutine for computing the principal value 00633 // of the respective function. The principal value is usually 00634 // analytic in a subset of the complex plane and undefined otherwise. 00635 // 00636 // Second, there are procedures for computing interval supersets 00637 // of all function values of the respective function, where feasible. 00638 // 00639 //----------------------------------------------------------------------------- 00640 // 00641 // Section 1: Argument functions 00642 // 00643 //----------------------------------------------------------------------------- 00644 00645 //-- Arg: analytic argument function -------------------------------- 040916 -- 00646 // 00647 // (i) Arg(Z) subset (-pi,pi). 00648 // (ii) Arg([0,0]) = 0. 00649 // (iii) Arg(Z) is undefined if Z contains negative real numbers. 00650 // (iv) Otherwise, Arg(Z) is the interval hull of { Arg(z) | z in Z, z<>0 }. 00651 // 00652 // atan is the inverse function of tan(t), t in (-pi/2,pi/2). 00653 // 00654 interval Arg( const cinterval& z ) throw() 00655 { 00656 real 00657 srez = Sup( Re(z) ), 00658 irez = Inf( Re(z) ), 00659 simz = Sup( Im(z) ), 00660 iimz = Inf( Im(z) ); 00661 00662 interval 00663 hxl(irez), hxu(srez), hyl(iimz), hyu(simz); 00664 00665 real resl, resu; 00666 00667 if( iimz > 0.0 ) 00668 // case I: Im(z) > 0 00669 { 00670 resl = ( srez > 0.0 ? Inf( Atan( hyl,hxu ) ) : ( srez < 0.0 ? Inf( Atan( hyu,hxu ) + PI() ) : Inf( HALFPI() ) ) ); 00671 resu = ( irez > 0.0 ? Sup( Atan( hyu,hxl ) ) : ( irez < 0.0 ? Sup( Atan( hyl,hxl ) + PI() ) : Sup( HALFPI() ) ) ); 00672 return interval( resl, resu ); 00673 } 00674 else 00675 { 00676 if( simz < 0.0 ) 00677 // case II: Im(z) < 0 00678 { 00679 resl = ( irez < 0.0 ? Inf( Atan( hyu,hxl ) - PI() ) : ( irez > 0.0 ? Inf( Atan( hyl,hxl ) ) : - Sup( HALFPI() ) ) ); 00680 resu = ( srez < 0.0 ? Sup( Atan( hyl,hxu ) - PI() ) : ( srez > 0.0 ? Sup( Atan( hyu,hxu ) ) : - Inf( HALFPI() ) ) ); 00681 return interval( resl, resu ); 00682 } 00683 else 00684 // 0 in Im(z) 00685 { 00686 if( irez > 0.0 ) 00687 // case III: Re(z) > 0 00688 // z contains positive real values 00689 { 00690 resl = ( iimz < 0.0 ? Inf( Atan( hyl,hxl ) ) : 0.0 ); 00691 return interval( resl, Sup( Atan( hyu,hxl ) ) ); 00692 } 00693 else 00694 // z contains nonpositive real numbers 00695 { 00696 if( irez < 0.0 ) 00697 { 00698 // case IV: z contains negative real numbers 00699 cxscthrow (STD_FKT_OUT_OF_DEF("interval Arg( const cinterval& z ); z contains negative real numbers")); 00700 return interval(0.0); 00701 } 00702 else 00703 // case V: 0 in z, but z doesn't contain negative real numbers 00704 { 00705 if( srez > 0.0 ) 00706 // diam( Re(z) > 0.0 ) 00707 { 00708 resl = ( iimz < 0.0 ? - Sup( HALFPI() ) : 0.0 ); 00709 resu = ( simz > 0.0 ? Sup( HALFPI() ) : 0.0 ); 00710 return interval( resl, resu ); 00711 } 00712 else 00713 // Re(z) == 0.0 00714 { 00715 if( iimz == 0.0 && simz == 0.0 ) 00716 // Z == 0 00717 return ZERO_INTERVAL(); 00718 else 00719 { 00720 resl = ( iimz < 0.0 ? - Sup( HALFPI() ) : Inf( HALFPI() ) ); 00721 resu = ( simz > 0.0 ? Sup( HALFPI() ) : - Inf( HALFPI() ) ); 00722 return interval( resl, resu ); 00723 } 00724 } 00725 } 00726 } 00727 } 00728 } 00729 } 00730 // 00731 //-- end Arg ------------------------------------------------------------------ 00732 00733 //-- arg: non-analytic argument function ---------------------------- 040916 -- 00734 // 00735 // (i) arg(Z) is defined for all Z in IC. 00736 // (ii) arg(Z) subset [-pi,3*pi/2]. 00737 // (iii) arg(Z) == Arg(Z) if Arg(Z) is well-defined. 00738 // 00739 // atan is the inverse function of tan(t), t in (-pi/2,pi/2). 00740 // 00741 interval arg( const cinterval& z ) throw() 00742 { 00743 real 00744 srez = Sup( Re(z) ), 00745 irez = Inf( Re(z) ), 00746 simz = Sup( Im(z) ), 00747 iimz = Inf( Im(z) ); 00748 00749 real resl, resu; 00750 00751 if( irez < 0.0 && iimz <= 0.0 && simz >= 0.0 ) 00752 // z contains negative real values 00753 { 00754 if( srez > 0.0 ) 00755 // 0 in z and 0 interior point of Re(z) 00756 { 00757 resl = ( iimz < 0.0 ? - Sup( PI() ) : 0.0 ); 00758 resu = ( ( iimz < 0.0 && simz == 0.0 ) ? 0.0 : Sup( PI() ) ); 00759 return interval( resl, resu ); 00760 } 00761 else 00762 { // srez <= 0.0 00763 if( iimz == simz ) 00764 // z is real interval containing no positive values 00765 return PI(); 00766 else 00767 // sup( Re(z) ) <= 0, diam( Im(z) ) > 0 00768 { 00769 if( srez == 0.0 ) 00770 { 00771 resl = ( simz > 0.0 ? Inf( HALFPI() ) : - Sup( PI() ) ); 00772 resu = ( iimz < 0.0 ? ( simz > 0.0 ? Sup( 3 * HALFPI() ) : - Inf( HALFPI() ) ) : Sup( PI() ) ); 00773 return interval( resl, resu ); 00774 } 00775 else 00776 // sup( Re(z) ) < 0, diam( Im(z) ) > 0 00777 { 00778 interval hyl(iimz), hyu(simz); 00779 resl = ( simz > 0.0 ? Inf( Atan( hyu,srez ) + PI() ) : - Sup( PI() ) ); 00780 resu = ( iimz < 0.0 ? ( simz > 0.0 ? Sup( Atan( hyl,srez ) + PI() ) : 00781 Sup( Atan( hyl,srez ) - PI() ) ) : Sup( PI() ) ); 00782 return interval( resl, resu ); 00783 } 00784 } 00785 } 00786 } 00787 else 00788 // Arg(z) is well-defined 00789 return Arg( z ); 00790 } 00791 // 00792 //-- end arg ------------------------------------------------------------------ 00793 00794 00795 /* ***************************************************************************/ 00796 /* ***************************************************************************/ 00797 /* *** Multi-valued functions ****/ 00798 /* ***************************************************************************/ 00799 /* ***************************************************************************/ 00800 00801 00802 //-- arg_inclmon: non-analytic inclusion-monotone argument function - 040617 -- 00803 // 00804 // (i) arg_inclmon(Z) is defined for all Z in IC. 00805 // (ii) arg_inclmon(Z) = [-pi,pi] if Arg(Z) is not defined. 00806 // 00807 interval arg_inclmon( const cinterval& z ) throw() 00808 { 00809 if( Inf( Re(z) ) < 0.0 && Inf( Im(z) ) <= 0.0 && Sup( Im(z) ) >= 0.0 ) 00810 return interval( -Sup( PI() ),Sup( PI() ) ); 00811 else 00812 return Arg(z); 00813 } 00814 // 00815 //-- end arg_inclmon ---------------------------------------------------------- 00816 00817 00818 //----------------------------------------------------------------------------- 00819 // 00820 // Section 2: Logarithms 00821 // 00822 //----------------------------------------------------------------------------- 00823 00824 //-- Ln: analytic natural logarithm --------------------------------- 040625 -- 00825 // 00826 // Ln(z) is undefined if z contains zero; z must not touch the negative real 00827 // axis from below; 00828 // 00829 cinterval Ln( const cinterval& z ) throw() 00830 { // Blomquist; 00831 real 00832 srez = Sup( Re(z) ), 00833 simz = Sup( Im(z) ), 00834 iimz = Inf( Im(z) ); 00835 interval a1( abs(Re(z)) ), 00836 a2( abs(Im(z)) ); 00837 if ( Inf(a1) == 0.0 && Inf(a2) == 0.0 ) 00838 // z contains 0 00839 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval LN( const cinterval& z ); z contains 0")); 00840 if ( srez<0 && iimz<0 && simz>=0 ) 00841 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval LN( const cinterval& z ); z not allowed")); 00842 return cinterval( ln_sqrtx2y2(Re(z),Im(z)),arg(z) ); 00843 } 00844 // 00845 //-- end Ln ------------------------------------------------------------------- 00846 00847 //-- ln: non-analytic natural logarithm ----------------------------- 040923 -- 00848 // 00849 // ln(z) is undefined if z contains zero. 00850 // 00851 cinterval ln( const cinterval& z ) throw() 00852 { 00853 interval a1( abs(Re(z)) ), 00854 a2( abs(Im(z)) ); 00855 if ( Inf(a1) == 0.0 && Inf(a2) == 0.0 ) { 00856 // z contains 0 00857 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval ln( const cinterval& z ); z contains 0")); 00858 return z; 00859 } 00860 else 00861 // return cinterval( ln( abs_z_2 ) / 2.0 , arg( z ) ); 00862 return cinterval( ln_sqrtx2y2(Re(z),Im(z)), arg(z) ); 00863 } 00864 // 00865 //-- end ln ------------------------------------------------------------------- 00866 00867 cinterval lnp1(const cinterval& z) throw() 00868 { // ln(1+z); 00869 // Calculates nearly optimal inclusions for not too wide intervals z. 00870 // Blomquist, 03.12.2008; 00871 const real c1 = 1.0; 00872 cinterval y; 00873 interval abs_z(abs(z)); 00874 real 00875 srez = Sup( Re(z) ), 00876 simz = Sup( Im(z) ), 00877 iimz = Inf( Im(z) ); 00878 00879 if (-1 <= z) // z contains -1 00880 cxscthrow(STD_FKT_OUT_OF_DEF( 00881 "cinterval lnp1(const cinterval& z); z contains -1")); 00882 if ( srez<-1 && iimz<0 && simz>=0 ) 00883 cxscthrow(STD_FKT_OUT_OF_DEF( 00884 "cinterval lnp1(const cinterval& z); z not allowed")); 00885 00886 if (Sup(abs_z) < c1) 00887 { 00888 abs_z = Re(z); 00889 abs_z = lnp1( abs_z*(2+abs_z) + sqr(Im(z)) ); 00890 times2pown(abs_z,-1); 00891 y = cinterval( abs_z, arg(1+z) ); 00892 } 00893 else 00894 y = Ln(1+z); 00895 return y; 00896 } 00897 00898 cinterval log2( const cinterval& z ) throw() 00899 { 00900 return Ln(z) / Ln2_interval; 00901 } 00902 00903 cinterval log10( const cinterval& z ) throw() 00904 { 00905 return Ln(z) / Ln10_interval; 00906 } 00907 00908 //----------------------------------------------------------------------------- 00909 // 00910 // Section 3: Root functions 00911 // 00912 //----------------------------------------------------------------------------- 00913 00914 interval Sqrt_zpx( const interval& x, const interval& y ) 00915 // Calculating sqrt(|z|+|x|) without any internal overflow; 00916 // Notice: |z| = sqrt(x^2+y^2); sqrt(|z|+|x|) < Maxreal 00917 { 00918 const int c1 = 1021; 00919 real Infx(Inf(x)), Infy(Inf(y)); 00920 int ex_x(expo(Infx)), ex_y(expo(Infy)); 00921 interval xc(abs(x)),yc(y),res; 00922 bool yeq0(Infy==0); 00923 00924 if ((ex_x>=c1) || (ex_y>=c1)) 00925 { // To avoid overflow, scaling is necessary: 00926 times2pown(xc,-2); 00927 if (yeq0) { 00928 times2pown(xc,1); 00929 res = sqrt(xc); 00930 } else { 00931 times2pown(yc,-2); 00932 res = sqrt( sqrtx2y2(xc,yc)+xc); 00933 } 00934 times2pown(res,1); // Backscaling 00935 } else // Normal calculation without scaling: 00936 if (yeq0) { 00937 times2pown(xc,1); 00938 res = sqrt(xc); 00939 } else res = sqrt( sqrtx2y2(xc,yc)+xc); 00940 return res; 00941 } 00942 00943 //-- sqrt: analytic square root ------------------------------------- 040626 -- 00944 // 00945 interval Re_Sqrt_point( const interval& rez, const interval& imz ) // 040626 -- 00946 // 00947 // Real part of analytic square root of A POINT INTERVAL ONLY. 00948 // Do not use this as a general function 00949 // - it's only a subroutine for sqrt and sqrt_all. 00950 // The calculation is void if (rez+I*imz) is not a complex number. 00951 // 00952 { 00953 real 00954 irez = Inf( rez ), 00955 iimz = Inf( imz ); 00956 00957 if( iimz == 0.0 ) 00958 { 00959 if( irez >= 0.0 ) 00960 return sqrt( rez ); 00961 else 00962 return ZERO_INTERVAL(); 00963 } 00964 else 00965 { // iimz <> 0 00966 if (irez >= 0.0) 00967 return INV_SQRT_2() * Sqrt_zpx(rez,imz); 00968 else 00969 return INV_SQRT_2() * abs(iimz) / Sqrt_zpx(rez,imz); 00970 } 00971 } 00972 00973 interval Im_Sqrt_point( const interval& rez, const interval& imz ) // 040626 -- 00974 // 00975 // Imaginary part of analytic square root of A POINT INTERVAL ONLY 00976 // Do not use this as a general function 00977 // - it's only a subroutine for sqrt and sqrt_all 00978 // The calculation is void if (rez+I*imz) is not a complex number 00979 // 00980 { 00981 real 00982 irez = Inf( rez ), 00983 iimz = Inf( imz ); 00984 00985 if( iimz == 0.0 ) 00986 { 00987 if( irez >= 0.0 ) 00988 return ZERO_INTERVAL(); 00989 else 00990 return sqrt( -rez ); 00991 } 00992 else 00993 { 00994 if( Inf( rez ) >= 0.0 ) 00995 return ( iimz * INV_SQRT_2() ) / Sqrt_zpx(rez,imz); 00996 else 00997 { 00998 if( iimz > 0.0 ) 00999 return INV_SQRT_2() * Sqrt_zpx(rez,imz); 01000 else 01001 return -INV_SQRT_2() * Sqrt_zpx(rez,imz); 01002 } 01003 } 01004 } 01005 01006 01007 cinterval sqrt( const cinterval& z ) throw() // ------------------------------- 01008 // 01009 // Analytic square root function with z in the principal branch. 01010 // The branch cut is the negative real axis. On the branch cut 01011 // the function values are defined by comming from the II quadrant. 01012 // Blomquist, 23.06.2005; 01013 // 01014 { 01015 real 01016 irez = Inf( Re(z) ), 01017 srez = Sup( Re(z) ), 01018 iimz = Inf( Im(z) ), 01019 simz = Sup( Im(z) ); 01020 interval 01021 hxl( irez ), hxu( srez ), hyl( iimz ), hyu( simz ); 01022 real 01023 resxl, resxu, resyl, resyu; 01024 01025 if( irez < 0.0 && iimz < 0.0 && simz >= 0.0 ) 01026 // if z is not in the principal branch then the inclusion monotony is violated! 01027 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval sqrt(const cinterval& z); z not in the principal branch.")); 01028 01029 if (iimz>=0.0) 01030 { 01031 resxl = Inf( Re_Sqrt_point( hxl,hyl ) ); 01032 resxu = Sup( Re_Sqrt_point( hxu,hyu ) ); 01033 01034 resyl = Inf( Im_Sqrt_point( hxu,hyl ) ); 01035 resyu = Sup( Im_Sqrt_point( hxl,hyu ) ); 01036 } else 01037 if (simz<=0.0) { 01038 resxl = Inf( Re_Sqrt_point( hxl,hyu ) ); 01039 resxu = Sup( Re_Sqrt_point( hxu,hyl ) ); 01040 01041 resyl = Inf( Im_Sqrt_point( hxl,hyl ) ); 01042 resyu = Sup( Im_Sqrt_point( hxu,hyu ) ); 01043 } else { 01044 resxl = Inf( sqrt( hxl ) ); 01045 resxu = ( -iimz > simz ? Sup( Re_Sqrt_point( hxu, hyl ) ) 01046 : Sup( Re_Sqrt_point( hxu, hyu ) ) ); 01047 resyl = Inf( Im_Sqrt_point( hxl,hyl ) ); 01048 resyu = Sup( Im_Sqrt_point( hxl,hyu ) ); 01049 } 01050 01051 return cinterval( interval( resxl,resxu ), interval( resyl,resyu ) ); 01052 } 01053 01054 cinterval sqrtp1m1(const cinterval& z) throw() 01055 // sqrt(1+z)-1; 01056 // Calculates nearly optimal inclusions for not too wide intervals z. 01057 // Blomquist, 08.07.2008; 01058 { 01059 const real c = 1.5; 01060 cinterval res; 01061 interval absz(abs(z)); 01062 real Sup_absz(Sup(absz)); 01063 01064 if (Sup_absz < c) 01065 res = z / (sqrt(z+1) + 1); 01066 else 01067 res = sqrt(z+1) - 1; 01068 return res; 01069 } 01070 01071 cinterval sqrt1px2(const cinterval& z) throw() 01072 // sqrt(1+z^2); 01073 // Blomquist, 03.07.2008; 01074 { 01075 const real c = 5e8; 01076 cinterval res; 01077 interval absz(abs(z)); 01078 real Inf_absz(Inf(absz)); 01079 01080 if (Inf_absz > c) 01081 { 01082 absz = 1 / interval(Inf_absz); 01083 Inf_absz = Sup(absz); 01084 res = cinterval( interval(-Inf_absz,Inf_absz), 01085 interval(-Inf_absz,Inf_absz) ); 01086 // res is the correcture interval, i.e. 01087 // z + res or -z + res is the inclusionof sqrt{1+z^2} 01088 res = (Inf(Re(z))>=0)? z + res : -z + res; 01089 } 01090 else 01091 { 01092 res = cinterval( interval(0), interval(1) ); // res = i 01093 if ( Sup(abs(z-res))<0.5 || Sup(abs(z+res))<0.5 ) 01094 { 01095 res = cinterval(-Im(z),Re(z)); // Res = i*z; 01096 // (1 - i*z)*(1 + i*z) = 1+z^2; 01097 res = sqrt( (1-res)*(1+res) ); 01098 } 01099 else 01100 res = sqrt(1+sqr(z)); 01101 } 01102 if (Inf(Re(res))<0) 01103 res = cinterval( interval(0.0,Sup(Re(res))) , Im(res) ); 01104 01105 return res; 01106 } 01107 // -- end sqrt1px2 ------------------------------------------------------------ 01108 01109 cinterval sqrtx2m1(const cinterval& z) throw() 01110 // sqrt(z^2-1); 01111 // Calculates nearly optimal inclusions for not too wide intervals z. 01112 // Blomquist, 04.12.2008; 01113 { 01114 const real c = 5e8; 01115 cinterval res,u; 01116 interval absz(abs(z)); 01117 real Inf_absz(Inf(absz)); 01118 01119 if (Inf_absz > c) 01120 { 01121 absz = 1 / interval(Inf_absz); 01122 Inf_absz = Sup(absz); 01123 res = cinterval(interval(-Inf_absz,Inf_absz), 01124 interval(-Inf_absz,Inf_absz)); // res = Delta 01125 // res is the correcture interval, i.e. 01126 res = (Inf(Re(z))>=0)? z + res : -z + res; 01127 } 01128 else 01129 { 01130 res = z-1; u = z+1; 01131 res = (Sup(abs(res))<0.5 || Sup(abs(u))<0.5)? sqrt(res*u) : sqrt(sqr(z)-1); 01132 } 01133 01134 if (Inf(Re(res))<0) 01135 res = cinterval( interval(0.0,Sup(Re(res))) , Im(res) ); 01136 01137 return res; 01138 } 01139 01140 cinterval sqrt1mx2(const cinterval& z) throw() 01141 // sqrt(1-z^2); 01142 // Calculates nearly optimal inclusions for not too wide intervals z. 01143 // Blomquist, 04.12.2008; 01144 { 01145 const real c = 5e8; 01146 cinterval res,u; 01147 interval absz(abs(z)); 01148 real Inf_absz(Inf(absz)); 01149 01150 if (Inf_absz > c) 01151 { 01152 absz = 1 / interval(Inf_absz); 01153 Inf_absz = Sup(absz); 01154 res = cinterval(interval(-Inf_absz,Inf_absz), 01155 interval(-Inf_absz,Inf_absz)); // res = Delta 01156 u = cinterval(-Im(z),Re(z)); // u = i*z; 01157 // res is the correcture interval, i.e. 01158 // i*z + res or -i*z + res is the inclusion of sqrt{1-z^2} 01159 res = (Inf(Im(z))>=0)? -u + res : u + res; 01160 } 01161 else 01162 { 01163 res = 1-z; u = 1+z; 01164 res = (Sup(abs(res))<0.5 || Sup(abs(u))<0.5)? sqrt(res*u) : sqrt(1-sqr(z)); 01165 } 01166 if (Inf(Re(res))<0) 01167 res = cinterval( interval(0.0,Sup(Re(res))) , Im(res) ); 01168 01169 return res; 01170 } 01171 01172 //-- sqrt_all ------------------------------------------------------- 040621 -- 01173 // 01174 // sqrt_all(z) computes a list of 2 intervals containing all square roots of z 01175 // 01176 std::list<cinterval> sqrt_all( const cinterval& z ) 01177 { 01178 real 01179 irez = Inf( Re(z) ), 01180 srez = Sup( Re(z) ), 01181 iimz = Inf( Im(z) ), 01182 simz = Sup( Im(z) ); 01183 interval 01184 hxl( irez ), hxu( srez ), hyl( iimz ), hyu( simz ); 01185 real 01186 resxl, resxu, resyl, resyu; 01187 cinterval w; 01188 01189 if( irez < 0.0 && iimz <= 0.0 && simz >= 0.0 ) 01190 // z contains negative real values 01191 { 01192 if( iimz == 0.0 ) 01193 // z in upper half plane 01194 // principal values can be used 01195 { 01196 // min( Re ( sqrt( z ) ) ) in lower left corner 01197 // max( Re ( sqrt( z ) ) ) in upper right corner 01198 resxl = Inf( Re_Sqrt_point( hxl, hyl ) ); 01199 resxu = Sup( Re_Sqrt_point( hxu, hyu ) ); 01200 // min( Im ( sqrt( z ) ) ) in lower right corner 01201 // max( Im ( sqrt( z ) ) ) in upper left corner 01202 resyl = Inf( Im_Sqrt_point( hxu, hyl ) ); 01203 resyu = Sup( Im_Sqrt_point( hxl, hyu ) ); 01204 } 01205 else 01206 { 01207 if( simz == 0.0 ) 01208 // z in lower half plane 01209 // principal values can be used in lower corners 01210 { 01211 // z in lower half plane 01212 // min( Re ( sqrt( z ) ) ) in upper left corner 01213 // max( Re ( sqrt( z ) ) ) in lower right corner 01214 resxl = 0; ; 01215 resxu = Sup( Re_Sqrt_point( hxu, hyl ) ); 01216 // min( Im ( sqrt( z ) ) ) in lower left corner 01217 // max( Im ( sqrt( z ) ) ) in upper right corner 01218 resyl = Inf( Im_Sqrt_point( hxl, hyl ) ); 01219 resyu = ( srez > 0.0 ? 0.0 : -Inf( sqrt( -hxu ) ) ); 01220 } 01221 else 01222 // 0 is interior point of Im( z ) 01223 { 01224 if( srez <= 0.0 ) 01225 { 01226 // 0 is no interior point of Re (z ) 01227 // in quadrant III, Re( z ) = Im_Sqrt_point(|x|,y), 01228 // Im( z ) = Re_Sqrt_point(|x|,y) 01229 // min( Re ( sqrt( z ) ) ) in lower right corner = quadrant II/III 01230 // max( Re ( sqrt( z ) ) ) in upper right corner = quadrant II 01231 resxl = Inf( Im_Sqrt_point( -hxu, hyl ) ); 01232 resxu = Sup( Re_Sqrt_point( hxu, hyu ) ); 01233 // min( Im ( sqrt( z ) ) ) on real line 01234 // max( Im ( sqrt( z ) ) ) in lower or upper left corner 01235 resyl = Inf( sqrt( -hxu ) ); 01236 resyu = ( - iimz > simz ? Sup( Re_Sqrt_point( -hxl, hyl ) ) : Sup( Im_Sqrt_point( hxl, hyu ) ) ); 01237 } 01238 else 01239 // 0 is interior point of z 01240 // here, the principal values apply in all corner points 01241 { 01242 resxl = 0; 01243 // max( Re ( sqrt( z ) ) ) in lower or upper right corner 01244 resxu = ( - iimz > simz ? Sup( Re_Sqrt_point( hxu, hyl ) ) : Sup( Re_Sqrt_point( hxu, hyu ) ) ); 01245 // min( Im ( sqrt( z ) ) ) in lower left corner 01246 // max( Im ( sqrt( z ) ) ) in upper left corner 01247 resyl = Inf( Im_Sqrt_point( hxl, hyl ) ); 01248 resyu = Sup( Im_Sqrt_point( hxl, hyu ) ); 01249 } 01250 } 01251 } 01252 w = cinterval( interval( resxl, resxu ), interval( resyl, resyu ) ); 01253 } 01254 else 01255 // sqrt( z ) is well-defined 01256 w = sqrt( z ); 01257 01258 std::list<cinterval> res; 01259 res.push_back( w ); 01260 res.push_back( -w ); 01261 01262 return res; 01263 } 01264 // 01265 //-- end sqrt_all ------------------------------------------------------------- 01266 01267 01268 //-- sqrt(z,n): analytic n-th root ---------------------------------- 040624 -- 01269 // 01270 interval Re_Sqrt_point( const interval& rez, const interval& imz, 01271 int n ) // before: unsigned int n ---------- 040624 -- 01272 // 01273 // Real part of analytic n-th root. 01274 // Do not use this as a general function 01275 // - it's only a subroutine for sqrt(z,n) and sqrt_all(z,n). 01276 // The calculation is validated but largely overestimating 01277 // if (rez+I*imz) is not a complex number. 01278 // 01279 { 01280 interval abs_z_2 = sqr( rez ) + sqr( imz ); 01281 if( Sup( abs_z_2 ) == 0.0 ) 01282 // z == 0 01283 return ZERO_INTERVAL(); 01284 else 01285 return sqrt( abs_z_2, 2 * n ) * cos( Arg( cinterval( rez, imz ) ) / n ); 01286 } 01287 01288 interval Im_Sqrt_point( const interval& rez, const interval& imz, 01289 int n ) // before: unsigned int n --- 040624 -- 01290 // 01291 // Imaginary part of analytic n-th root. 01292 // Do not use this as a general function 01293 // - it's only a subroutine for sqrt(z,n) and sqrt_all(z,n). 01294 // The calculation is validated but largely overestimating 01295 // if (rez+I*imz) is not a complex number. 01296 // 01297 { 01298 interval abs_z_2 = sqr( rez ) + sqr( imz ); 01299 if( Sup( abs_z_2 ) == 0.0 ) 01300 // z == 0 01301 return ZERO_INTERVAL(); 01302 else 01303 return sqrt( abs_z_2, 2 * n ) * sin( Arg( cinterval( rez, imz ) ) / n ); 01304 } 01305 01306 cinterval sqrt( const cinterval& z, int n ) throw() // ----- 040915 -- 01307 // 01308 // Analytic n-th root function 01309 // sqrt(z,n) is undefined if z contains negative real numbers. 01310 // 01311 { 01312 if( n == 0 ) 01313 return cinterval( ONE_INTERVAL() ); 01314 if( n == 1 ) 01315 return z; 01316 if( n == 2 ) 01317 return sqrt( z ); 01318 else 01319 { 01320 real 01321 irez = Inf( Re(z) ), 01322 srez = Sup( Re(z) ), 01323 iimz = Inf( Im(z) ), 01324 simz = Sup( Im(z) ); 01325 interval 01326 hxl( irez ), hxu( srez ), hyl( iimz ), hyu( simz ); 01327 real 01328 resxl, resxu, resyl, resyu; 01329 01330 if( irez < 0.0 && iimz <= 0.0 && simz >= 0.0 ) 01331 { 01332 // z contains negative real values 01333 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval sqrt(const cinterval& z, int n ); z contains negative real values.")); 01334 return z; 01335 } 01336 else 01337 { 01338 if( simz < 0.0 ) 01339 { 01340 // z in lower half plane 01341 cinterval hres = sqrt( cinterval( Re(z), -Im(z) ), n ); 01342 return cinterval( Re(hres), -Im(hres) ); 01343 } 01344 else 01345 { 01346 if( iimz > 0.0 ) 01347 { 01348 // z in upper half plane 01349 interval tangle = tan( ( PI() * n ) / ( 2 * ( n-1 ) ) ); 01350 real tanglel = Inf( tangle ), 01351 tangleu = Sup( tangle ); 01352 // 01353 // min( Re( Root( z ) ) ) 01354 // 01355 if ( irez >= 0.0 || Sup( hyl / irez ) <= tanglel ) 01356 // lower boundary right of phi = n*Pi/(2n-2) 01357 // min( Re( Root( z ) ) ) in lower left corner 01358 resxl = Inf( Re_Sqrt_point( hxl, hyl, n ) ); 01359 else 01360 { 01361 if( srez < 0.0 && Inf( hyl / srez ) >= tangleu ) 01362 // lower boundary left of phi = n*Pi/(2n-2) 01363 // min( Re( Root( z ) ) ) in lower right corner 01364 resxl = Inf( Re_Sqrt_point( hxu, hyl, n ) ); 01365 else 01366 // lower boundary intersects phi = n*Pi/(2n-2) 01367 // min( Re( Root( z ) ) ) on intersection 01368 resxl = Inf( Re_Sqrt_point( iimz / tangle , hyl, n ) ); 01369 } 01370 // 01371 // max( Re( Root( z ) ) ) 01372 // 01373 if ( irez >= 0.0 || Sup( hyu / irez ) <= tanglel ) 01374 // upper boundary right of phi = n*Pi/(2n-2) 01375 // max( Re( Root( z ) ) ) in upper right corner 01376 resxu = Sup( Re_Sqrt_point( interval(srez), interval(simz), n ) ); 01377 else 01378 { 01379 if ( srez < 0.0 && Inf( hyu / srez ) >= tangleu ) 01380 // upper boundary left of phi = n*Pi/(2n-2) 01381 // max( Re( Root( z ) ) ) in upper left corner 01382 resxu = Sup( Re_Sqrt_point( hxl, hyu, n ) ); 01383 else 01384 // upper boundary intersects phi = n*Pi/(2n-2) 01385 // max( Re( Root( z ) ) ) on upper left or right corner 01386 resxu = max( Sup( Re_Sqrt_point( hxl, hyu, n ) ), Sup( Re_Sqrt_point( hxu, hyu, n ) ) ); 01387 } 01388 // 01389 // min( Im( Root( z ) ) ) 01390 // 01391 if ( srez >= 0.0 || Sup( hyl / srez ) <= tanglel ) 01392 // right boundary right of phi = n*Pi/(2n-2) 01393 // min( Im( Root( z ) ) ) in lower right corner 01394 resyl = Inf( Im_Sqrt_point( hxu, hyl, n ) ); 01395 else 01396 { 01397 if( Inf( hyu / srez ) >= tangleu ) 01398 // right boundary left of phi = n*Pi/(2n-2) 01399 // min( Im( Root( z ) ) ) in upper right corner 01400 resyl = Inf( Im_Sqrt_point( hxu, hyu, n ) ); 01401 else 01402 // right boundary intersects phi = n*Pi/(2n-2) 01403 // min( Im( Root( z ) ) ) on intersection 01404 resyl = Inf( Im_Sqrt_point( hxu, srez * tangle, n ) ); 01405 } 01406 // 01407 // max( Im( Root( z ) ) ) 01408 // 01409 if( irez >= 0.0 || Sup( hyl / irez ) <= tanglel ) 01410 // left boundary right of phi = n*Pi/(2n-2) 01411 // max( Im( Root( z ) ) ) in upper left corner 01412 resyu = Sup( Im_Sqrt_point( hxl, hyu, n ) ); 01413 else 01414 { 01415 if( Inf( hyu / irez ) >= tangleu ) 01416 // left boundary left of phi = n*Pi/(2n-2) 01417 // max( Im( Root( z ) ) ) in lower left corner 01418 resyu = Sup( Im_Sqrt_point( hxl, hyl, n ) ); 01419 else 01420 // left boundary intersects phi = n*Pi/(2n-2) 01421 // max( Im( Root( z ) ) ) on lower or upper left corner 01422 resyu = max( Sup( Im_Sqrt_point( hxl, hyl, n ) ), Sup( Im_Sqrt_point( hxl, hyu, n ) ) ); 01423 } 01424 } 01425 else 01426 { 01427 // z intersects positive real axis 01428 // min( Re( Root( z ) ) ) on real line 01429 // max( Re( Root( z ) ) ) in lower or upper right corner 01430 resxl = ( irez == 0.0 ? 0.0 : Inf( sqrt( hxl, n ) ) ); 01431 resxu = ( - iimz > simz ? Sup( Re_Sqrt_point( hxu, hyl, n ) ) : Sup( Re_Sqrt_point( hxu, hyu, n ) ) ); 01432 // min( Im ( sqrt( z ) ) ) in lower left corner 01433 // max( Im ( sqrt( z ) ) ) in upper left corner 01434 resyl = Inf( Im_Sqrt_point( hxl, hyl, n ) ); 01435 resyu = Sup( Im_Sqrt_point( hxl, hyu, n ) ); 01436 } 01437 return cinterval( interval( resxl, resxu ), interval( resyl, resyu ) ); 01438 } 01439 } 01440 } 01441 } 01442 // 01443 //-- end sqrt ----------------------------------------------------------------- 01444 01445 01446 //-- sqrt_all ------------------------------------------------------- 040628 -- 01447 // 01448 std::list<cinterval> sqrt_all( const cinterval& z, int n ) 01449 // 01450 // sqrt_all(z,n) computes a list of n intervals containing all n-th roots of z 01451 // 01452 // For n >=3, computing the optimal interval bounds is very expensive 01453 // and thus not considered cost-effective. 01454 // 01455 // Hence, the polar form is used to calculate sqrt_all(z,n) 01456 // (observed overestimation of Re() and Im() in test cases: 5-15%). 01457 // 01458 // z is enclosed into an interval in polar coordinates 01459 // (i.e. a sector of an annulus), from which the roots 01460 // (also polar intervals) are computed error-free 01461 // (save roundoff, which is enclosed). 01462 // 01463 // The the final inclusion of the roots into a rectangular complex interval 01464 // involves some additional overestimation. 01465 // 01466 { 01467 std::list<cinterval> res; 01468 01469 if( n == 0 ) 01470 { 01471 res.push_back( cinterval( ONE_INTERVAL(), ZERO_INTERVAL() ) ); 01472 return res; 01473 } 01474 else if( n == 1 ) 01475 { 01476 res.push_back(z); 01477 return res; 01478 } 01479 else if( n == 2 ) return sqrt_all( z ); 01480 else 01481 { 01482 interval 01483 arg_z = arg( z ), root_abs_z = sqrt( abs( z ), n ); 01484 01485 for(int k = 0; k < n; k++) 01486 { 01487 interval arg_k = ( arg_z + 2 * k * PI() ) / n; 01488 01489 res.push_back( cinterval( root_abs_z * cos( arg_k ), 01490 root_abs_z * sin( arg_k ) ) ); 01491 } 01492 return res; 01493 } 01494 } 01495 // 01496 //-- end sqrt_all ------------------------------------------------------------- 01497 01498 01499 01500 //----------------------------------------------------------------------------- 01501 // 01502 // Section 4: Power functions 01503 // 01504 //----------------------------------------------------------------------------- 01505 01506 //-- power_fast ----------------------------------------------------- 040714 -- 01507 // 01508 // Fast, validated power function for integer powers, based on exp and ln. 01509 // Medium amount of overestimation. 01510 // 01520 cinterval power_fast( const cinterval& z, int n ) throw() 01521 { 01522 if( n == 0 ) 01523 return cinterval( ONE_INTERVAL() ); 01524 else if( n == 1 ) 01525 return z; 01526 else if( n == -1 ) 01527 return 1 / z; 01528 else if( n == 2 ) 01529 return sqr(z); 01530 else 01531 // n >= 3 or n <= -2 01532 // If z is a large interval, z^n is a distorted set, for which the 01533 // inclusion into a complex rectangle contains large overestimation. 01534 // For example, if n * Arg( z ) intersects the cartesian axes 01535 // more than once then 0 is contained in the rectangular enclosure 01536 // of z^n. 01537 // For n <= -2, also inversion of z or z^n is required; 01538 // both inversions lead to large overestimation of the resulting interval. 01539 // 01540 // The computation of an optimal rectangular enclosure is implemented 01541 // in power(z,n). In power_fast(z,n), z is enclosed into a sector S of 01542 // an annulus. S^n is again some sector S' of a (different) annulus. 01543 // S' is calculated exactly (apart from roundoff), and then enclosed 01544 // into a rectangle. There is a certain amount of overestimation 01545 // compared with the optimal rectangular enclosure of z^n, but the 01546 // calculations are much cheaper here. 01547 { 01548 interval abs_z = abs( z ); 01549 01550 if( n < 0 && Inf( abs_z ) == 0.0 ) 01551 // z contains 0 01552 cxscthrow (STD_FKT_OUT_OF_DEF("cinterval power_fast(const cinterval& z, int n ); z contains 0.")); 01553 if( Sup( abs_z ) == 0.0 ) 01554 return cinterval( ZERO_INTERVAL(), ZERO_INTERVAL() ); 01555 else 01556 { 01557 interval arg_z = arg( z ); 01558 interval abs_z_n = exp( n * ln( abs_z ) ); 01559 01560 return cinterval( abs_z_n * cos( n * arg_z ), 01561 abs_z_n * sin( n * arg_z ) ); 01562 } 01563 } 01564 } 01565 // 01566 //-- end power_fast ----------------------------------------------------------- 01567 01568 01569 //-- power ---------------------------------------------------------- 040720 -- 01570 // 01571 // Power function for integer powers with optimal (save roundoff) accuracy. 01572 // 01573 // The extremal curves of Re(z^n) and Im(z^n) are straight lines defined 01574 // by the rays arg(z) = k pi/ ( 2n - 2 ), k = 0,...4n-5. 01575 // 01576 // Intersections of these rays with the boundary of z are called 01577 // "ray intersections" in the following. 01578 // 01579 cinterval power_point( const cinterval& z, int n ) //---------------- 040715 -- 01580 // 01581 // z^n for A POINT INTERVAL z ONLY. 01582 // Do not use this as a general function 01583 // - it's only a subroutine for power. 01584 // The calculation may break down otherwise. 01585 // The case 0 in z for negative n is handled in power(z,n). 01586 // 01587 { 01588 if( Inf( Re(z) ) == 0.0 && Inf( Im(z) ) == 0.0 ) 01589 // if z is a valid point interval, it must be 0 01590 return cinterval( ZERO_INTERVAL(), ZERO_INTERVAL() ); 01591 else 01592 { 01593 interval abs_z = abs( z ); 01594 interval arg_z = arg( z ); 01595 interval abs_z_n = exp( n * ln( abs_z ) ); 01596 01597 return cinterval( abs_z_n * cos( n * arg_z ), 01598 abs_z_n * sin( n * arg_z ) ); 01599 } 01600 } 01601 01602 void update_res( const cinterval& res, //---------------------------- 040716 -- 01603 real& resxl, real& resxu, real& resyl, real& resyu ) 01604 // Subroutine of power(z,n). 01605 // Update extremal values of power function. 01606 { 01607 resxl = min( resxl, Inf( Re(res) ) ); 01608 resxu = max( resxu, Sup( Re(res) ) ); 01609 resyl = min( resyl, Inf( Im(res) ) ); 01610 resyu = max( resyu, Sup( Im(res) ) ); 01611 } 01612 01613 void horizontal_check( //-------------------------------------------- 040720 -- 01614 const interval& hy, real hyy, const interval& arg_h, 01615 real irez, real srez, 01616 real& resxl, real& resxu, real& resyl, real& resyu, int n ) 01617 // Subroutine of power(z,n). 01618 // Check all relevant ray intersections on a horizontal boundary. 01619 { 01620 double r_int; 01621 int 01622 il1, il2, iu1, iu2; 01623 cinterval res; 01624 // 01625 // Here, the most difficult task is 01626 // to determine the relevant ray intersections 01627 // Both arg_hl and n can be negative, which makes it very complicated 01628 // to decide the correct indexes for the "rightmost" intersections, etc. 01629 // 01630 // To simplify the distinction of cases, we introduce the variable 01631 // nofrays (number of rays) = abs( n-1 ) 01632 // 01633 // Note that we still have to pass n to power_point 01634 // 01635 iu1 = n-1; if (iu1<0) iu1 = -iu1; 01636 int nofrays = iu1; 01637 real arg_hlR = Inf( 2 * nofrays * arg_h / PI() ); 01638 double arg_hl = _double(arg_hlR); 01639 if( arg_hl >= 0.0 ) 01640 modf( arg_hl, &r_int ); 01641 else 01642 modf( arg_hl-1, &r_int ); 01643 il1 = int( r_int + 1.0 ); 01644 real arg_huR = Sup( 2 * nofrays * arg_h / PI() ); 01645 double arg_hu = _double(arg_huR); 01646 if( arg_hu >= 0.0 ) 01647 modf( arg_hu, &r_int ); 01648 else 01649 modf( arg_hu-1, &r_int ); 01650 iu1 = int( r_int ); 01651 01652 if( iu1 >= il1 ) 01653 { 01654 // at least one ray intersection 01655 // maybe more? 01656 if( iu1 > il1 + 3 ) 01657 // 01658 // we're in trouble: 01659 // there are more than 4 ray intersections 01660 // now we must decide which of these are relevant 01661 // depending on il1, iu1, n and on the quadrants, 01662 // 4 to 7 intersections must be considered 01663 // 01664 { // Neu Blomquist 13.12.2010 01665 if( n > 0 ) 01666 // outmost intersections are relevant 01667 { 01668 if( irez >= 0.0 ) 01669 // z in quadrants I or IV: 01670 // only 4 rightmost intersections are relevant 01671 { 01672 if( hyy < 0.0 ) 01673 // quadrant IV 01674 il1 = iu1 - 3; 01675 else 01676 // quadrant I 01677 iu1 = il1 + 3; 01678 } 01679 else if( srez <= 0.0 ) 01680 // z in quadrants II or III: 01681 // only 4 leftmost intersections are relevant 01682 { 01683 if( hyy > 0.0 ) 01684 // quadrant II 01685 il1 = iu1 - 3; 01686 else 01687 // quadrant III 01688 iu1 = il1 + 3; 01689 } 01690 else 01691 // z intersects imaginary axes 01692 // we may have two lists of intersections! 01693 { 01694 iu2 = iu1; 01695 il2 = iu2 - 3; 01696 iu1 = il1 + 3; 01697 // remove intersection points that are contained in both lists 01698 if( il2 <= iu1 ) 01699 il2 = iu1 + 1; 01700 // 01701 // here, list 2 is processed 01702 // list 1 is processed below 01703 // 01704 for(int i = il2; i <= iu2; i++) 01705 { 01706 interval cotangle = cot( ( PI() * i ) / ( 2 * nofrays ) ); 01707 res = power_point( cinterval( hy * cotangle , hy ), n ); 01708 update_res( res, resxl, resxu, resyl, resyu ); 01709 } 01710 } 01711 } 01712 else 01713 // n < 0: 01714 // innermost intersections are relevant 01715 { 01716 if( irez >= 0.0 ) 01717 // z in quadrants I or IV: 01718 // only 4 leftmost intersections are relevant 01719 { 01720 if( hyy > 0.0 ) 01721 // quadrant I 01722 il1 = iu1 - 3; 01723 else 01724 // quadrant IV 01725 iu1 = il1 + 3; 01726 } 01727 else if( srez <= 0.0 ) 01728 // z in quadrants II or III: 01729 // only 4 rightmost intersections are relevant 01730 { 01731 if( hyy < 0.0 ) 01732 // quadrant III 01733 il1 = iu1 - 3; 01734 else 01735 // quadrant II 01736 iu1 = il1 + 3; 01737 } 01738 else 01739 // z intersects imaginary axes 01740 // we have one lists of 5 to 7 intersections 01741 { 01742 if( hyy > 0.0 ) 01743 { 01744 il2 = nofrays - 3; 01745 iu2 = nofrays + 3; 01746 } 01747 else 01748 { 01749 il2 = -nofrays - 3; 01750 iu2 = -nofrays + 3; 01751 } 01752 // list 1 contains all intersections 01753 // list 2 is a filter for all relevant intersections 01754 // store intersection of lists 1 and 2 in list 1 01755 il1 = ( il1 > il2 ? il1 : il2 ); 01756 iu1 = ( iu1 < iu2 ? iu1 : iu2 ); 01757 } 01758 } 01759 } // Neu Blomquist 13.12.2010 01760 // 01761 // list 1 has been left for processing 01762 // 01763 for(int i = il1; i <= iu1; i++) 01764 { 01765 interval cotangle = cot( ( PI() * i ) / ( 2 * nofrays ) ); 01766 res = power_point( cinterval( hy * cotangle , hy ), n ); 01767 update_res( res, resxl, resxu, resyl, resyu ); 01768 } 01769 } 01770 } 01771 01772 void vertical_check( //---------------------------------------------- 040720 -- 01773 const interval& hx, real hxx, const interval& arg_h, 01774 real iimz, real simz, 01775 real& resxl, real& resxu, real& resyl, real& resyu, int n ) 01776 // Subroutine of power(z,n). 01777 // Check all relevant ray intersections on a vertical boundary. 01778 { 01779 double r_int; 01780 int 01781 il1, il2, iu1, iu2; 01782 cinterval res; 01783 // 01784 // Here, the most difficult task is 01785 // to determine the relevant ray intersections 01786 // Both arg_hl and n can be negative, which makes it very complicated 01787 // to decide the correct indexes for the topmost intersections, etc. 01788 // 01789 // To simplify the distinction of cases, we introduce the variable 01790 // nofrays (number of rays) = abs( n-1 ) 01791 // 01792 // Note that we still have to pass n to power_point 01793 // 01794 iu1 = n-1; if (iu1<0) iu1 = -iu1; 01795 int nofrays = iu1; 01796 01797 real arg_hlR = Inf( 2 * nofrays * arg_h / PI() ); 01798 double arg_hl = _double(arg_hlR); 01799 if( arg_hl >= 0.0 ) 01800 modf( arg_hl, &r_int ); 01801 else 01802 modf( arg_hl-1, &r_int ); 01803 il1 = int( r_int + 1.0 ); 01804 real arg_huR = Sup( 2 * nofrays * arg_h / PI() ); 01805 double arg_hu = _double(arg_huR); 01806 if( arg_hu >= 0.0 ) 01807 modf( arg_hu, &r_int ); 01808 else 01809 modf( arg_hu-1, &r_int ); 01810 iu1 = int( r_int ); 01811 01812 if( iu1 >= il1 ) 01813 { 01814 // at least one ray intersection 01815 // maybe more? 01816 if( iu1 > il1 + 3 ) 01817 // 01818 // we're in trouble: 01819 // there are more than 4 ray intersections 01820 // now we must decide which of these are relevant 01821 // depending on il1, iu1, n and on the quadrants, 01822 // 4 to 7 intersections must be considered 01823 // 01824 { // Neu Blomquist 13.12.2010 01825 if( n > 0 ) 01826 // outmost intersections are relevant 01827 { 01828 if( iimz >= 0.0 ) 01829 // z in quadrants I or II: 01830 // only 4 topmost intersections are relevant 01831 { 01832 if( hxx > 0.0 ) 01833 // quadrant I 01834 il1 = iu1 - 3; 01835 else 01836 // quadrant II 01837 iu1 = il1 + 3; 01838 } 01839 else if( simz <= 0.0 ) 01840 // z in quadrants III or IV: 01841 // only 4 lowest intersections are relevant 01842 { 01843 if( hxx < 0.0 ) 01844 // quadrant III 01845 il1 = iu1 - 3; 01846 else 01847 // quadrant IV 01848 iu1 = il1 + 3; 01849 } 01850 else 01851 // z intersects real axes 01852 // we may have two lists of intersections! 01853 { 01854 iu2 = iu1; 01855 il2 = iu2 - 3; 01856 iu1 = il1 + 3; 01857 // remove intersection points that are contained in both lists 01858 if( il2 <= iu1 ) 01859 il2 = iu1 + 1; 01860 // 01861 // here, list 2 is processed 01862 // list 1 is processed below 01863 // 01864 for(int i = il2; i <= iu2; i++) 01865 { 01866 interval tangle = tan( ( PI() * i ) / ( 2 * nofrays ) ); 01867 res = power_point( cinterval( hx, hx * tangle ), n ); 01868 update_res( res, resxl, resxu, resyl, resyu ); 01869 } 01870 } 01871 } 01872 else 01873 // n < 0: 01874 // innermost intersections are relevant 01875 { 01876 if( iimz >= 0.0 ) 01877 // z in quadrants I or II: 01878 // only 4 lowest intersections are relevant 01879 { 01880 if( hxx < 0.0 ) 01881 // quadrant II 01882 il1 = iu1 - 3; 01883 else 01884 // quadrant I 01885 iu1 = il1 + 3; 01886 } 01887 else if( simz <= 0.0 ) 01888 // z in quadrants III or IV: 01889 // only 4 topmost intersections are relevant 01890 { 01891 if( hxx > 0.0 ) 01892 // quadrant IV 01893 il1 = iu1 - 3; 01894 else 01895 // quadrant III 01896 iu1 = il1 + 3; 01897 } 01898 else 01899 // z intersects real axes 01900 // we have one lists of 5 to 7 intersections 01901 { 01902 if( hxx > 0.0 ) 01903 { 01904 il2 = -3; 01905 iu2 = 3; 01906 } 01907 else 01908 { 01909 il2 = 2 * nofrays - 3; 01910 iu2 = 2 * nofrays + 3; 01911 } 01912 // list 1 contains all intersections 01913 // list 2 is a filter for all relevant intersections 01914 // store intersection of lists 1 and 2 in list 1 01915 il1 = ( il1 > il2 ? il1 : il2 ); 01916 iu1 = ( iu1 < iu2 ? iu1 : iu2 ); 01917 } 01918 } 01919 } // Neu Blomquist 13.12.2010 01920 // 01921 // list 1 has been left for processing 01922 // 01923 for(int i = il1; i <= iu1; i++) 01924 { 01925 interval tangle = tan( ( PI() * i ) / ( 2 * nofrays ) ); 01926 res = power_point( cinterval( hx, hx * tangle ), n ); 01927 update_res( res, resxl, resxu, resyl, resyu ); 01928 } 01929 } 01930 } 01931 01941 cinterval power( const cinterval& z, int n ) throw() //---- 040720 -- 01942 // 01943 // Power function for integer powers with optimal (save roundoff) accuracy. 01944 // 01945 { 01946 if( n == 0 ) 01947 return cinterval( ONE_INTERVAL() ); 01948 else if( n == 1 ) 01949 return z; 01950 else if( n == -1 ) 01951 return 1 / z; 01952 else if( n == 2 ) 01953 return sqr(z); 01954 else 01955 // n >= 3 or n <= -2 01956 // 01957 // n may have a large absolute value and z may be a large interval. 01958 // In this case, we calculate function values at specific points 01959 // and look for min and max. 01960 // 01961 // An implementation with fewer function evaluations would be possible, 01962 // at the expense of an unreadable source code. 01963 { 01964 interval abs_z = abs( z ); 01965 01966 if( n < 0 && Inf( abs_z ) == 0.0 ) 01967 // z contains 0 01968 cxscthrow (STD_FKT_OUT_OF_DEF("cinterval power(const cinterval& z, int n ); z contains 0.")); 01969 if( Sup( abs_z ) == 0.0 ) 01970 return cinterval( ZERO_INTERVAL(), ZERO_INTERVAL() ); 01971 else 01972 { 01973 real 01974 irez = Inf(Re(z)), 01975 srez = Sup(Re(z)), 01976 iimz = Inf(Im(z)), 01977 simz = Sup(Im(z)); 01978 interval 01979 hxl( irez ), hxu( srez ), hyl( iimz ), hyu( simz ); 01980 real 01981 resxl, resxu, resyl, resyu; 01982 cinterval res; 01983 // 01984 // extremal values lie in corner points or on intersections of the 01985 // boundary of z with any ray arg( w ) = k*Pi/(2*(n-1)) 01986 // 01987 // first check the corners of z 01988 // 01989 res = power_point( cinterval( hxl, hyl ), n ); 01990 resxl = Inf( Re(res) ); 01991 resxu = Sup( Re(res) ); 01992 resyl = Inf( Im(res) ); 01993 resyu = Sup( Im(res) ); 01994 res = power_point( cinterval( hxu, hyl ), n ); 01995 update_res( res, resxl, resxu, resyl, resyu ); 01996 res = power_point( cinterval( hxl, hyu ), n ); 01997 update_res( res, resxl, resxu, resyl, resyu ); 01998 res = power_point( cinterval( hxu, hyu ), n ); 01999 update_res( res, resxl, resxu, resyl, resyu ); 02000 // 02001 // consider the origin, if it is a boundary point 02002 // (negative n have been taken care of above) 02003 // 02004 // if( irez * srez <= 0.0 && iimz * simz <= 0.0 && 02005 // irez * srez * iimz * simz == 0.0 ) 02006 if ( 0<=Re(z) && 0<=Im(z) && 02007 (irez==0 || srez==0 || iimz==0 || simz==0 ) ) 02008 update_res( cinterval( ZERO_INTERVAL(), ZERO_INTERVAL()), 02009 resxl, resxu, resyl, resyu ); 02010 // 02011 // now check for ray intersections 02012 // for each quadrant and each boundary, we must consider 02013 // the function values at at most 4 consecutive intersections 02014 // 02015 // Ia: lower boundary 02016 // 02017 if( iimz != 0.0 ) 02018 { 02019 interval arg_h = arg( cinterval( Re(z), hyl ) ); 02020 02021 // check if there are ray intersections 02022 horizontal_check( hyl, iimz, arg_h, irez, srez, 02023 resxl, resxu, resyl, resyu, n ); 02024 } 02025 // Ib: upper boundary 02026 if( simz != 0.0 ) 02027 { 02028 interval arg_h = arg( cinterval( Re(z), hyu ) ); 02029 02030 // check if there are ray intersections 02031 horizontal_check( hyu, simz, arg_h, irez, srez, 02032 resxl, resxu, resyl, resyu, n ); 02033 } 02034 // IIa: left boundary 02035 if( irez != 0.0 ) 02036 { 02037 interval arg_h = arg( cinterval( hxl, Im(z) ) ); 02038 02039 // check if there are ray intersections 02040 vertical_check( hxl, irez, arg_h, iimz, simz, 02041 resxl, resxu, resyl, resyu, n ); 02042 } 02043 // IIb: right boundary 02044 if( srez != 0.0 ) 02045 { 02046 interval arg_h = arg( cinterval( hxu, Im(z) ) ); 02047 02048 // check if there are ray intersections 02049 vertical_check( hxu, srez, arg_h, iimz, simz, 02050 resxl, resxu, resyl, resyu, n ); 02051 } 02052 return cinterval( interval( resxl, resxu ), interval( resyl, resyu ) ); 02053 } 02054 } 02055 } 02056 // 02057 //-- end power ---------------------------------------------------------------- 02058 02059 void times2pown(cinterval& x, int n) throw() 02060 // Fast multiplication with 2^n 02061 { 02062 interval R(Re(x)),I(Im(x)); 02063 times2pown(R,n); 02064 times2pown(I,n); 02065 x = cinterval(R,I); 02066 } 02067 02068 02069 //-- pow ------------------------------------------------------------ 040627 -- 02070 // 02071 // Analytic power function for real interval exponent, based on Ln. 02072 // 02073 02074 cinterval pow( const cinterval& z, const interval& p ) throw() 02075 // Neue Version von pow(...) von 040627 02076 { 02077 return exp( p*Ln(z) ); 02078 } 02079 02080 // 02081 //-- end pow ------------------------------------------------------------------ 02082 02083 //-- pow ------------------------------------------------------------ 040627 -- 02084 // 02085 // Analytic power function for complex interval exponent, based on Ln. 02086 // 02087 02088 cinterval pow( const cinterval& z, const cinterval& p ) throw() 02089 { 02090 return exp( p*Ln(z) ); 02091 } 02092 02093 // 02094 //-- end pow ------------------------------------------------------------------ 02095 02096 02097 //-- pow_all -------------------------------------------------------- 041013 -- 02098 // 02099 // Non-analytic power function for real interval exponent. 02100 // 02101 // If 0 \not\in z, then compute four rectangular intervals that comprehend 02102 // an annulus which contains all values zeta^phi, zeta in z, phi in p. 02103 // 02104 // If 0 in z and negative reals in p, then abort execution 02105 // (potential modification: return the entire complex plane). 02106 // 02107 std::list<cinterval> pow_all( const cinterval& z, const interval& p ) throw() 02108 { 02109 interval abs_z = abs( z ); 02110 02111 if( 0.0 < Inf( abs_z ) ) 02112 { 02113 interval abs_z_p = exp( p * ln( abs_z ) ); 02114 02115 // Inner and outer radii of the annulus are inf/sup( abs_z_n ) 02116 // Inscribed square has side length sqrt( 2 ) * rad_1 02117 interval rad_1 = INV_SQRT_2() * Inf( abs_z_p ); 02118 interval rad_2 = interval(Sup( abs_z_p )); 02119 02120 std::list<cinterval> res; 02121 02122 // 4 intervals covering the annulus, counter-clockwise 02123 res.push_back( cinterval( interval( Inf( rad_1 ), Sup( rad_2 ) ), 02124 interval( -Sup( rad_1 ), Sup( rad_2 ) ) ) ); 02125 res.push_back( cinterval( interval( -Sup( rad_2 ), Sup( rad_1 ) ), 02126 interval( Inf( rad_1 ), Sup( rad_2 ) ) ) ); 02127 res.push_back( cinterval( interval( -Sup( rad_2 ), -Inf( rad_1 ) ), 02128 interval( -Sup( rad_2 ), Sup( rad_1 ) ) ) ); 02129 res.push_back( cinterval( interval( -Sup( rad_1 ), Sup( rad_2 ) ), 02130 interval( -Sup( rad_2 ), -Inf( rad_1 ) ) ) ); 02131 02132 return res; 02133 } 02134 else 02135 // 0 in z 02136 { 02137 if( Inf( p ) > 0.0 ) 02138 // 02139 // All values zeta^phi, zeta in z, phi in p lie in a disk 02140 // 02141 { 02142 interval abs_z_p = exp( p * ln( interval( Sup( abs_z ) ) ) ); 02143 real rad_p = Sup( abs_z_p ); 02144 02145 std::list<cinterval> res; 02146 02147 res.push_back( cinterval( interval( -rad_p, rad_p ), 02148 interval( -rad_p, rad_p ) ) ); 02149 02150 return res; 02151 } 02152 else 02153 { 02154 // 02155 // The set zeta^phi, zeta in z, phi in p is unbounded 02156 // if inf( p ) < 0. 0^p is undefined for p <= 0. 02157 // 02158 cxscthrow(STD_FKT_OUT_OF_DEF("pow_all(cinterval, interval); 0^p is undefined for p <= 0.")); 02159 std::list<cinterval> res; 02160 return res; 02161 } 02162 } 02163 } 02164 // 02165 //-- end pow_all -------------------------------------------------------------- 02166 02167 02168 02169 //----------------------------------------------------------------------------- 02170 // 02171 // Section 5: asin, acos, asinh, acosh 02172 // 02173 // The implementation of acos, asinh, and acosh is based on asin: 02174 // 02175 // acos( z ) = pi / 2 - asin( z ) 02176 // asinh( z ) = i * asin( - i * z ) 02177 // acosh( z ) = i * acos( z ) = +/- i * ( pi / 2 - asin( z ) ) 02178 // 02179 // Only principal values are computed. 02180 // 02181 //----------------------------------------------------------------------------- 02182 02183 //-- asin ----------------------------------------------------------- 040905 -- 02184 // 02185 // Analytic inverse sine function 02186 // 02187 interval f_aux_asin( const interval& x, const interval& y ) //------- 040905 -- 02188 // 02189 // auxiliary function for evaluating asin 02190 // f_aux_asin(z) = ( |z+1| + |z-1| ) / 2 02191 // 02192 { 02193 interval res; 02194 // interval sqr_y = sqr( y ); 02195 // interval res = ( sqrt( sqr( x + 1.0 ) + sqr_y ) + sqrt( sqr( x - 1.0 ) + sqr_y ) ) / 2.0; 02196 if (y == 0.0 && abs(x) == 1.0) res = 1.0; 02197 else res = (sqrtx2y2(x+1.0,y) + sqrtx2y2(x-1.0,y)) / 2.0; // Blomquist; 02198 02199 if ( Sup(res)==Infinity ) // Blomquist: program stop, if overflow occurs. 02200 cxscthrow (STD_FKT_OUT_OF_DEF("cinterval asin( const cinterval& z); z out of range")); 02201 02202 // correct overestimation of lower boundary 02203 // (x is a point interval) 02204 real hlb = max( 1.0, abs( Sup( x ) ) ); 02205 if( Inf( res ) < hlb ) 02206 // invalid overestimation! 02207 res = interval( hlb, Sup(res) ); 02208 return res; 02209 } 02210 02211 02212 interval f_aux_asin_Vn(const interval& x, const interval& y) 02213 { // normal calculation of V; 02214 interval V,f1,f2; 02215 f1 = x+1.0; f2 = x-1; 02216 V = abs(f1)*sqrtp1m1(sqr(y/f1)) + abs(f2)*sqrtp1m1(sqr(y/f2)); 02217 times2pown(V,-1); 02218 return V; 02219 } // f_aux_asin_Vn 02220 02221 interval ACOSH_p1(const interval& x, const interval& y) 02222 { // Calculating an inclusion for acosh(1+V/2) if |x|<1; 02223 const int p = -80; 02224 real r1(Inf(y)),t; 02225 int ex(expo(r1)); 02226 interval res(0.0),u,V; 02227 02228 if (ex>-2000 && ex <= -80) { 02229 u = abs(y)/sqrt1mx2(x); 02230 t = pred(pred(Inf(u))); 02231 res = interval(t,Sup(u)); 02232 } else 02233 if (ex>p) { 02234 V = f_aux_asin_Vn(x,y); // usual calculation 02235 res = acoshp1(V); 02236 } 02237 return res; 02238 } // ACOSH_p1 02239 02240 interval ACOSH_f_aux( const interval& x, const interval& y ) 02241 // Calculating acosh( f_aux_asin(x,y) ); x,y: point intervals !! 02242 // Blomquist, 22.04.2005; 02243 { 02244 interval res,delta; 02245 real rx(abs(Inf(x))), ry(abs(Inf(y))); 02246 02247 if (rx>2.0 || ry>2.0) res = acosh( f_aux_asin(x,y) ); // as before! 02248 else { // Now with improvements !! 02249 if (rx == 1.0) { 02250 delta = abs(y); 02251 if (expo(Inf(delta))<=-50) { 02252 res = sqrt(delta); 02253 rx = Sup(res); 02254 if (rx>0) res = interval(pred(Inf(res)),succ(rx)); 02255 } else { 02256 times2pown(delta,-1); // delta: |y|/2; 02257 delta = sqrtp1m1(sqr(delta)) + delta; 02258 res = acoshp1(delta); 02259 } 02260 } 02261 else 02262 if (rx<1.0) res = ACOSH_p1(x,y); 02263 else res = acoshp1( (abs(x)-1.0) + f_aux_asin_Vn(x,y) ); 02264 } 02265 return res; 02266 } // ACOSH_f_aux 02267 02268 02269 interval Asin_beta( const interval& x, const interval& y ) 02270 // Calculating the improved real part of asin(z); Blomquist 19.06.2005; 02271 // Re(asin(z)) = asin[ 2x/(sqrt[(x+1)^2+y^2] + sqrt[(x-1)^2+y^2]) ] = asin[beta] 02272 // Improvements for beta --> +1 and beta --> -1 are necessary because of nearly 02273 // vertical tangents of the real asin(t)-function for |t|-->+1; 02274 { 02275 const real c1 = 0.75; 02276 bool neg_b; 02277 real Infxa; 02278 interval res,beta,abs_beta,delta,tm,tp,u,v,xa; 02279 beta = x / ( (sqrtx2y2(1+x,y) + sqrtx2y2(1-x,y))/2 ); 02280 if (Inf(beta)<-1) Inf(beta)=-1; 02281 if (Sup(beta)> 1) Sup(beta)=1; 02282 abs_beta = abs(beta); 02283 if (Inf(abs_beta)<c1) res = asin(beta); // Normal calculation 02284 else { // Inf(abs_beta)>=c1; Calculation now with improvements: 02285 xa = x; 02286 neg_b = Inf(x)<0; 02287 if (neg_b) xa = -xa; // Inf(xa) >0 : 02288 Infxa = Inf(xa); 02289 if (Infxa > 1) { 02290 tm = y/(xa-1); 02291 tp = y/(xa+1); 02292 u = sqrtp1m1(sqr(tm)); 02293 v = sqrtp1m1(sqr(tp)); 02294 delta = (tm*tp - u*v) / (2+u+v); 02295 } else 02296 if (Infxa == 1) { 02297 u = abs(y); 02298 times2pown(u,-1); // u = |y|/2 02299 delta = u - sqrtp1m1(sqr(u)); 02300 } else { 02301 tp = 1+xa; tm = 1-xa; 02302 delta = tm*(sqrt(1+sqr(y/tm))+1) - tp*sqrtp1m1(sqr(y/tp)); 02303 times2pown(delta,-1); 02304 } 02305 res = HALFPI() - asin( sqrt(delta*(2-delta)) ); 02306 if (neg_b) res = -res; 02307 } 02308 return res; 02309 } 02310 02311 cinterval asin( const cinterval& z ) throw() //---------------------- 040730 -- 02312 { 02313 const real gr = 6.355804e307; // upper bound for abs(rez),abs(imz) 02314 interval 02315 rez = Re(z), 02316 imz = Im(z); 02317 02318 real irez = Inf(rez), 02319 srez = Sup(rez), 02320 iimz = Inf(imz), 02321 simz = Sup(imz); 02322 02323 interval hxl(irez), hxu(srez), hyl(iimz), hyu(simz); 02324 02325 real resxl, resxu, resyl, resyu; 02326 02327 bool bl = (iimz< 0.0) && (simz>0.0), 02328 raxis = (iimz==0.0) && (simz==0); 02329 02330 // 02331 // 1st: check for singularities 02332 // 02333 if( (irez<-1 && (bl || (iimz<0 && simz==0))) || 02334 (srez >1 && (bl || (iimz==0 && simz>0))) ) 02335 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval asin( const cinterval& z ); z contains singularities.")); 02336 // 02337 // check for too large bounds of abs(rez) and abs(imz) to prevent 02338 // overflow by calculating f_aux_asin(...) 02339 // 02340 resxl = max(abs(irez),abs(srez)); 02341 resxu = max(abs(iimz),abs(simz)); 02342 if (resxl>gr || resxu>gr) 02343 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval asin( const cinterval& z ); z with too large bounds.")); 02344 // 02345 // 2nd: real part 02346 // 02347 if( iimz < 0.0 && simz > 0.0 ) 02348 // z intersects [-1,1] 02349 { 02350 if( irez <= 0.0 ) 02351 resxl = Inf( asin( hxl ) ); 02352 else 02353 // resxl = Inf( asin( hxl / f_aux_asin( hxl, interval( max( - iimz, simz ) ) ) ) ); 02354 resxl = Inf( Asin_beta(hxl,interval( max(-iimz,simz) )) ); // Blomquist, 19.06.2005; 02355 if( srez < 0.0 ) 02356 // resxu = Sup( asin( hxu / f_aux_asin( hxu, interval( max( - iimz, simz ) ) ) ) ); 02357 resxu = Sup( Asin_beta(hxu,interval( max(-iimz,simz) )) ); // Blomquist, 19.06.2005; 02358 else 02359 resxu = Sup( asin( hxu ) ); 02360 } 02361 else 02362 { 02363 if( ( iimz >= 0.0 && irez >= 0.0 ) || ( simz <= 0.0 && irez <= 0.0 ) ) 02364 // left boundary in quadrants I or III 02365 // min( Re( z ) ) in upper left corner 02366 // resxl = Inf( asin( hxl / f_aux_asin( hxl, hyu ) ) ); 02367 resxl = Inf( Asin_beta(hxl,hyu) ); // Blomquist, 19.06.2005; 02368 else 02369 // left boundary in quadrants II or IV 02370 // min( Re( z ) ) in lower left corner 02371 // resxl = Inf( asin( hxl / f_aux_asin( hxl, hyl ) ) ); 02372 resxl = Inf( Asin_beta(hxl,hyl) ); // Blomquist, 19.06.2005; 02373 if( ( iimz >= 0.0 && srez >= 0.0 ) || ( simz <= 0.0 && srez <= 0.0 ) ) 02374 // right boundary in quadrants I or III 02375 // max( Re( z ) ) in lower right corner 02376 // resxu = Sup( asin( hxu / f_aux_asin( hxu, hyl ) ) ); 02377 resxu = Sup( Asin_beta(hxu,hyl) ); // Blomquist, 19.06.2005; 02378 else 02379 // right boundary in quadrants II or IV 02380 // max( Re( z ) ) in upper right corner 02381 // resxu = Sup( asin( hxu / f_aux_asin( hxu, hyu ) ) ); 02382 resxu = Sup( Asin_beta(hxu,hyu) ); // Blomquist, 19.06.2005; 02383 } 02384 // 02385 // 3rd: imaginary part 02386 // 02387 if (raxis) { // Interval argument is now a subset of the real axis. 02388 // Blomquist, 16.06.2005; 02389 if (srez<0.0) resyl = Inf( ACOSH_f_aux( hxu, hyu )); 02390 else resyl = -Sup( ACOSH_f_aux( hxu, hyu )); 02391 if (irez>0.0) resyu = -Inf( ACOSH_f_aux( hxl, hyu )); 02392 else resyu = Sup( ACOSH_f_aux( hxl, hyu )); 02393 } else 02394 if( simz <= 0.0 ) 02395 // z in lower half plane 02396 // min( Im( z ) ) in point with max |z| 02397 // max( Im( z ) ) in point with min |z| 02398 { 02399 if( irez < -srez ) 02400 // most of z in quadrant III 02401 { 02402 resyl = - Sup( ACOSH_f_aux( hxl, hyl ) ); 02403 if( srez < 0.0 ) 02404 resyu = - Inf( ACOSH_f_aux( hxu, hyu ) ); 02405 else 02406 resyu = - Inf( ACOSH_f_aux( ZERO_INTERVAL(), hyu ) ); 02407 } 02408 else 02409 // most of z in quadrant IV 02410 { 02411 resyl = - Sup( ACOSH_f_aux( hxu, hyl ) ); 02412 if( irez > 0.0 ) 02413 resyu = - Inf( ACOSH_f_aux( hxl, hyu ) ); 02414 else 02415 resyu = - Inf( ACOSH_f_aux( ZERO_INTERVAL(), hyu ) ); 02416 } 02417 } 02418 else if( iimz >= 0.0 ) 02419 // z in upper half plane 02420 // min( Im( z ) ) in point with min |z| 02421 // max( Im( z ) ) in point with max |z| 02422 { 02423 if( irez < -srez ) // if( irez + srez < 0.0 ) 02424 // most of z in quadrant II 02425 { 02426 resyu = Sup( ACOSH_f_aux( hxl, hyu ) ); 02427 if( srez < 0.0 ) 02428 resyl = Inf( ACOSH_f_aux( hxu, hyl ) ); 02429 else 02430 resyl = Inf( ACOSH_f_aux( ZERO_INTERVAL(), hyl ) ); 02431 } 02432 else 02433 // most of z in quadrant I 02434 { 02435 resyu = Sup( ACOSH_f_aux( hxu, hyu ) ); 02436 if( irez > 0.0 ) 02437 resyl = Inf( ACOSH_f_aux( hxl, hyl ) ); 02438 else 02439 resyl = Inf( ACOSH_f_aux( ZERO_INTERVAL(), hyl ) ); 02440 } 02441 } 02442 else 02443 // z intersects imaginary axes 02444 // min( Im( z ) ) in point in lower half plane with max |z| 02445 // max( Im( z ) ) in point in upper half plane with max |z| 02446 { 02447 if( irez < -srez ) // if( irez + srez < 0.0 ) 02448 // most of z in quadrants II and IV 02449 { 02450 resyl = - Sup( ACOSH_f_aux( hxl, hyl ) ); 02451 resyu = Sup( ACOSH_f_aux( hxl, hyu ) ); 02452 } 02453 else 02454 { 02455 resyl = - Sup( ACOSH_f_aux( hxu, hyl ) ); 02456 resyu = Sup( ACOSH_f_aux( hxu, hyu ) ); 02457 } 02458 } 02459 02460 return cinterval( interval( resxl, resxu ), interval( resyl, resyu ) ); 02461 02462 } 02463 // 02464 //-- end asin ----------------------------------------------------------------- 02465 02466 02467 02468 interval Acos_beta( const interval& x, const interval& y ) 02469 // Calculating the improved real part of acos(z); Blomquist 05.06.2005; 02470 // Re(acos(z)) = acos[ 2x/(sqrt[(x+1)^2+y^2] + sqrt[(x-1)^2+y^2]) ] 02471 { 02472 const real c1 = 0.75; 02473 interval res(0),beta,delta,tm,tp,u,v,xa; 02474 real Infy(Inf(y)),Infx(Inf(x)); 02475 beta = x / ( (sqrtx2y2(1+x,y) + sqrtx2y2(1-x,y))/2 ); 02476 if (Inf(beta)<-1) Inf(beta)=-1; 02477 if (Sup(beta)> 1) Sup(beta)= 1; 02478 02479 if (Sup(beta)<c1) 02480 if (Sup(beta)<-c1) { // Improvement for beta --> -1 02481 xa = -x; // Inf(xa)>0: 02482 Infx = -Infx; // Infx > 0: 02483 if (Infx > 1) { 02484 tm = y/(xa-1); tp = y/(xa+1); 02485 u = sqrtp1m1(sqr(tm)); 02486 v = sqrtp1m1(sqr(tp)); 02487 delta = (tm*tp - u*v) / (2+u+v); 02488 } else 02489 if (Infx == 1) { 02490 u = abs(y); 02491 times2pown(u,-1); // u = |y|/2 02492 delta = u - sqrtp1m1(sqr(u)); 02493 } else { 02494 tp = 1+xa; tm = 1-xa; 02495 delta = tm*(sqrt(1+sqr(y/tm))+1) - tp*sqrtp1m1(sqr(y/tp)); 02496 times2pown(delta,-1); 02497 } 02498 res = PI() - asin( sqrt(delta*(2-delta)) ); 02499 } else res = acos(beta); // Normal calculation 02500 else // Sup(beta)>=c1 02501 if (Infx>1) 02502 { 02503 tm = y/(x-1); 02504 if (expo(Sup(tm))<=-27) { 02505 if (Infy!=0) { 02506 u = abs(Infy) / sqrtx2m1(x); 02507 res = interval( pred(Inf(u)),succ(succ(Sup(u))) ); 02508 } 02509 } else { 02510 tp = y/(x+1); 02511 u = sqrtp1m1(sqr(tm)); 02512 v = sqrtp1m1(sqr(tp)); 02513 delta = (tm*tp - u*v) / (2+u+v); 02514 res = asin(sqrt(delta*(2-delta))); 02515 } 02516 } else 02517 if (Infx==1) { 02518 if (expo(Inf(y))<=-52) { 02519 u = sqrt(abs(y)); 02520 if (Sup(u)==0) res = 0; 02521 else res = interval(pred(Inf(u)),succ(succ(Sup(u)))); 02522 } else { 02523 u = abs(y); 02524 times2pown(u,-1); // u = |y|/2 02525 delta = u - sqrtp1m1(sqr(u)); 02526 res = asin( sqrt(delta*(2-delta)) ); 02527 } 02528 } else { 02529 tp = 1+x; tm = 1-x; 02530 delta = tm*(sqrt(1+sqr(y/tm))+1) - tp*sqrtp1m1(sqr(y/tp)); 02531 times2pown(delta,-1); 02532 res = asin( sqrt(delta*(2-delta)) ); 02533 } 02534 02535 return res; 02536 } 02537 02538 02539 //-- acos ----------------------------------------------------------- 040730 -- 02540 // 02541 // cinterval acos( const cinterval& z ) 02542 // { 02543 // w := acos(z); 02544 // Re(w) in a new Version, 02545 // Im(w) = -Im(asin(z)); Blomquist, 14.06.2005; 02546 // } 02547 // 02548 //-- acos ----------------------------------------------------------------- 02549 02550 02551 //-- acos ----------------------------------------------------------- 040730 -- 02552 // 02553 cinterval acos( const cinterval& z ) throw() //--------------------- 040730 -- 02554 { 02555 const real gr = 6.355804e307; // upper bound for abs(rez),abs(imz) 02556 interval 02557 rez = Re(z), 02558 imz = Im(z); 02559 02560 real 02561 irez = Inf(rez), 02562 srez = Sup(rez), 02563 iimz = Inf(imz), 02564 simz = Sup(imz); 02565 02566 interval 02567 hxl(irez), hxu(srez), hyl(iimz), hyu(simz); 02568 02569 bool bl = (iimz< 0.0) && (simz>0.0), 02570 raxis = (iimz==0.0) && (simz==0); 02571 real 02572 resxl, resxu, resyl, resyu; 02573 // 02574 // 1st: check for singularities 02575 // 02576 if( (irez<-1 && (bl || (iimz<0 && simz==0))) || 02577 (srez >1 && (bl || (iimz==0 && simz>0))) ) 02578 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval acos( const cinterval& z ); z contains singularities.")); 02579 // 02580 // check for too large bounds of abs(rez) and abs(imz) to prevent 02581 // overflow by calculating f_aux_asin(...) 02582 // 02583 resxl = max(abs(irez),abs(srez)); 02584 resxu = max(abs(iimz),abs(simz)); 02585 if (resxl>gr || resxu>gr) 02586 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval acos( const cinterval& z ); z with too large bounds.")); 02587 // 02588 // 2nd: real part 02589 // 02590 // Blomquist, 06.06.2005; 02591 if( iimz < 0.0 && simz > 0.0 ) 02592 // z intersects [-1,1] on the x-axis 02593 { 02594 if( irez <= 0.0 ) resxu = Sup( acos( hxl ) ); 02595 else resxu = Sup( Acos_beta(hxl,interval( max(-iimz,simz) )) ); 02596 02597 if( srez < 0.0 ) 02598 resxl = Inf( Acos_beta(hxu,interval(max(-iimz,simz))) ); 02599 else resxl = Inf( acos( hxu ) ); 02600 } 02601 else 02602 { 02603 if (irez<0 && srez>0) 02604 // z intersects the posizive or negative y-axis 02605 if (iimz >= 0) { 02606 resxl = Inf( Acos_beta(hxu,hyl) ); 02607 resxu = Sup( Acos_beta(hxl,hyl) ); 02608 } else { 02609 resxl = Inf( Acos_beta(hxu,hyu) ); 02610 resxu = Sup( Acos_beta(hxl,hyu) ); 02611 } 02612 else 02613 { 02614 if( ( iimz >= 0.0 && irez >= 0.0 ) || ( simz <= 0.0 && irez < 0.0 ) ) 02615 // left boundary in quadrants I or III 02616 // min( Re( z ) ) in lower right corner 02617 resxl = Inf( Acos_beta(hxu,hyl) ); 02618 else 02619 // left boundary in quadrants II or IV 02620 // min( Re( z ) ) in upper right corner 02621 resxl = Inf( Acos_beta(hxu,hyu) ); 02622 02623 if( ( iimz >= 0.0 && srez > 0.0 ) || ( simz <= 0.0 && srez <= 0.0 ) ) 02624 // right boundary in quadrants I or III 02625 // max( Re( z ) ) in upper left corner 02626 resxu = Sup( Acos_beta(hxl,hyu) ); 02627 else 02628 // right boundary in quadrants II or IV 02629 // max( Re( z ) ) in lower left corner 02630 resxu = Sup( Acos_beta(hxl,hyl) ); 02631 } 02632 } 02633 // 02634 // 3rd: imaginary part 02635 // 02636 if (raxis) { // Interval argument is now a subset of the real axis. 02637 // Blomquist, 16.06.2005; 02638 if (srez<0.0) resyl = Inf( ACOSH_f_aux( hxu, hyu )); 02639 else resyl = -Sup( ACOSH_f_aux( hxu, hyu )); 02640 if (irez>0.0) resyu = -Inf( ACOSH_f_aux( hxl, hyu )); 02641 else resyu = Sup( ACOSH_f_aux( hxl, hyu )); 02642 } else 02643 if( simz <= 0.0 ) 02644 // z in lower half plane 02645 // min( Im( z ) ) in point with max |z| 02646 // max( Im( z ) ) in point with min |z| 02647 { 02648 if( irez + srez < 0.0 ) 02649 // most of z in quadrant III 02650 { 02651 resyl = - Sup( ACOSH_f_aux( hxl, hyl ) ); 02652 if( srez < 0.0 ) 02653 resyu = - Inf( ACOSH_f_aux( hxu, hyu ) ); 02654 else 02655 resyu = - Inf( ACOSH_f_aux( ZERO_INTERVAL(), hyu ) ); 02656 } 02657 else 02658 // most of z in quadrant IV 02659 { 02660 resyl = - Sup( ACOSH_f_aux( hxu, hyl ) ); 02661 if( irez > 0.0 ) 02662 resyu = - Inf( ACOSH_f_aux( hxl, hyu ) ); 02663 else 02664 resyu = - Inf( ACOSH_f_aux( ZERO_INTERVAL(), hyu ) ); 02665 } 02666 } 02667 else if( iimz >= 0.0 ) 02668 // z in upper half plane 02669 // min( Im( z ) ) in point with min |z| 02670 // max( Im( z ) ) in point with max |z| 02671 { 02672 if( irez < -srez ) // if( irez + srez < 0.0 ) 02673 // most of z in quadrant II 02674 { 02675 resyu = Sup( ACOSH_f_aux( hxl, hyu ) ); 02676 if( srez < 0.0 ) 02677 resyl = Inf( ACOSH_f_aux( hxu, hyl ) ); 02678 else 02679 resyl = Inf( ACOSH_f_aux( ZERO_INTERVAL(), hyl ) ); 02680 } 02681 else 02682 // most of z in quadrant I 02683 { 02684 resyu = Sup( ACOSH_f_aux( hxu, hyu ) ); 02685 if( irez > 0.0 ) 02686 resyl = Inf( ACOSH_f_aux( hxl, hyl ) ); 02687 else 02688 resyl = Inf( ACOSH_f_aux( ZERO_INTERVAL(), hyl ) ); 02689 } 02690 } 02691 else 02692 // z intersects imaginary axes 02693 // min( Im( z ) ) in point in lower half plane with max |z| 02694 // max( Im( z ) ) in point in upper half plane with max |z| 02695 { 02696 if( irez < -srez ) // if( irez + srez < 0.0 ) 02697 // most of z in quadrants II and IV 02698 { 02699 resyl = - Sup( ACOSH_f_aux( hxl, hyl ) ); 02700 resyu = Sup( ACOSH_f_aux( hxl, hyu ) ); 02701 } 02702 else 02703 { 02704 resyl = - Sup( ACOSH_f_aux( hxu, hyl ) ); 02705 resyu = Sup( ACOSH_f_aux( hxu, hyu ) ); 02706 } 02707 } 02708 02709 return cinterval( interval( resxl, resxu ), -interval( resyl, resyu ) ); 02710 02711 } 02712 // 02713 //-- end acos ----------------------------------------------------------------- 02714 02715 02716 //-- asinh ---------------------------------------------------------- 040730 -- 02717 // 02718 cinterval asinh( const cinterval& z ) throw() 02719 // 02720 // asinh( Z ) = i * asin( -i * z ) 02721 // 02722 { 02723 cinterval res = asin( cinterval( Im(z), -Re(z) ) ); 02724 return cinterval( -Im(res), Re(res) ); 02725 } 02726 // 02727 //-- end asinh ---------------------------------------------------------------- 02728 02729 02730 //-- acosh ---------------------------------------------------------- 040908 -- 02731 // 02732 cinterval acosh( const cinterval& z ) throw() 02733 // 02734 // acosh( z ) = i * acos( z ) = +/- i * ( pi / 2 - asin( z ) ) 02735 // 02736 { 02737 interval 02738 rez = Re(z), 02739 imz = Im(z); 02740 02741 real 02742 irez = Inf(rez), 02743 srez = Sup(rez), 02744 iimz = Inf(imz), 02745 simz = Sup(imz); 02746 02747 interval 02748 hxl(irez), hxu(srez), hyl(iimz), hyu(simz); 02749 02750 real 02751 resxl, resxu, resyl, resyu; 02752 02753 // cinterval res; 02754 02755 // 02756 // 1st: check for singularities 02757 // 02758 if( ( iimz <= 0.0 && simz >= 0.0 ) && ( irez < 1.0 ) ) 02759 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval acosh( const cinterval& z ); z contains singularities.")); 02760 // With this restriction the complex interval argument and the real axis must not have any common 02761 // point, if irez < +1; 02762 // So for example the negative real axis must not be touched from above if irez<1, although this 02763 // should be possible if the principal branch is considered! So the above restriction is too widely in 02764 // some cases; Blomquist, 21.06.2005; 02765 // 02766 // 2nd: z in upper half plane (or on the real axis) 02767 // acosh( z ) = + i * ( pi / 2 - asin( z ) ) 02768 // 02769 if( iimz > 0.0 ) 02770 { 02771 cinterval res = acos(z); 02772 return cinterval( -Im(res),Re(res) ); 02773 } 02774 // 02775 // 3rd: z in lower half plane 02776 // acosh( z ) = - i * ( pi / 2 - asin( z ) ) 02777 // 02778 if( simz < 0.0 ) 02779 { 02780 // cinterval res = HALFPI() - asin( z ); 02781 cinterval res = acos(z); // Blomquist, 14.06.2005 02782 return cinterval( Im(res), -Re(res) ); 02783 } 02784 // 02785 // z intersects [1,infinity) 02786 // 02787 // real part 02788 // minimum on the left on real axes, maximum in lower or upper right corner 02789 // 02790 resxl = Inf( acosh( hxl ) ); 02791 interval ytilde( max( -iimz, simz ) ); 02792 // resxu = Sup( acosh( f_aux_asin( hxu, ytilde ) ) ); 02793 resxu = Sup( ACOSH_f_aux(hxu,ytilde) ); // Blomquist, 14.06.2005; 02794 // 02795 // imaginary part 02796 // minimum in lower left corner, maximum in upper left corner 02797 // 02798 // resyl = -Sup( acos( hxl / f_aux_asin( hxl, hyl ) ) ); 02799 resyl = -Sup( Acos_beta(hxl,hyl) ); // Blomquist, 14.06.2005; 02800 // resyu = Sup( acos( hxl / f_aux_asin( hxl, hyu ) ) ); 02801 resyu = Sup( Acos_beta(hxl,hyu) ); 02802 02803 return cinterval( interval( resxl, resxu ), interval( resyl, resyu ) ); 02804 02805 } 02806 // 02807 //-- end acosh ---------------------------------------------------------------- 02808 02809 02810 //----------------------------------------------------------------------------- 02811 // 02812 // Section 6: atan, acot, atanh, acoth 02813 // 02814 // The implementation of acot, atanh, and acoth is based on atan: 02815 // 02816 // acot( z ) = atan( 1 / z ) 02817 // atanh( z ) = - i * atan( i * z ) 02818 // acoth( z ) = i * acot( i * z ) 02819 // 02820 // Only principal values are computed. 02821 // 02822 //----------------------------------------------------------------------------- 02823 02824 //-- atan ----------------------------------------------------------- 040912 -- 02825 // 02826 // Analytic inverse tangent function 02827 // 02828 02829 void re_vert( const real& x, const interval& hx, 02830 const real& rew_inf, const real& rew_sup, 02831 real& resxl, real& resxu ) //---------------------- 040729 -- 02832 // 02833 // Subroutine of analytic inverse tangent function. 02834 // Evaluate real part on a vertical boundary. 02835 // 02836 { 02837 if( x == 0.0 ) 02838 // singularities have been handled before, hence Re( w ) > 0 02839 { 02840 resxl = 0.0; 02841 resxu = 0.0; 02842 } 02843 else 02844 { 02845 if( x > 0.0 ) 02846 // w in quadrants I and/or II 02847 // atan is the inverse function of tan(t), t in (-pi/2,pi/2). 02848 { 02849 resxl = rew_sup > 0.0 ? Inf( Atan( 2 * hx,rew_sup )/2.0 ) 02850 : ( rew_sup < 0.0 ? Inf( (Atan( 2*hx,rew_sup ) + PI() )/2.0 ) 02851 : Inf( HALFPI()/2.0 ) ); 02852 02853 resxu = rew_inf > 0.0 ? Sup( Atan( 2*hx,rew_inf )/2.0 ) 02854 : ( rew_inf < 0.0 ? Sup( (Atan( 2*hx,rew_inf ) + PI())/2.0 ) 02855 : Sup( HALFPI()/2.0 ) ); 02856 } 02857 else 02858 // w in quadrants III and/or IV 02859 { 02860 resxl = rew_inf < 0.0 ? Inf( (Atan( 2*hx,rew_inf ) - PI())/2.0 ) 02861 : ( rew_inf > 0.0 ? Inf( Atan( 2*hx,rew_inf )/2.0 ) 02862 : -Sup( HALFPI()/2.0 ) ); 02863 resxu = rew_sup < 0.0 ? Sup( (Atan( 2*hx,rew_sup ) - PI())/2.0 ) 02864 : ( rew_sup > 0.0 ? Sup( Atan( 2*hx,rew_sup )/2.0 ) 02865 : -Inf( HALFPI()/2.0 ) ); 02866 } 02867 } 02868 } // re_vert 02869 02870 interval Aux_1_atan(const real& x) 02871 // x>=0; 02872 // Calculating: ln[ 1+2/(sqrt(1+x^2)-1) ], [x] = x, 02873 // [x] is a point interval ! 02874 // Blomquist; 19.02.05; 02875 { 02876 const int exOv = +54; 02877 const int exUn = -26; 02878 02879 interval res, 02880 ix(x), // ix is point interval with x>=0; 02881 r,t; 02882 int ex(expo(x)); 02883 02884 if (ex>=exOv) { // preventing overflow 02885 r = 2/ix; 02886 t = r*pred(1.0); 02887 r = r*succ(1.0); 02888 res = interval(Inf(t),Sup(r)); 02889 } else 02890 if (ex<=exUn) { // x < 2^(-27) 02891 res = U_atan - 2*ln(ix); 02892 } else { // normal calculation 02893 t = sqrtp1m1( sqr(ix) ); // t = sqrt(1+x^2)-1 02894 res = lnp1(2/t); // res = ln[1 + 2/(sqrt(1+x^2)-1) ] 02895 } 02896 return res; 02897 } // Aux_1_atan 02898 02899 interval Q_atan_UPSIGN(const interval& x, const interval& y) 02900 { 02901 // x: abs(Re(z)); x is real interval 02902 // y: Inf(Im(z)); y is point interval 02903 // Q_atan_UPSIGN: ln[ 1 + 4y/(x^2+(1-y)^2) ] 02904 02905 const int n = 511; 02906 interval res,t,t1,t2; 02907 int ex_x,ex,s; 02908 if (y==1.0) { 02909 if (Inf(x)>1.0) { 02910 t = 2/x; 02911 res = lnp1(sqr(t)); 02912 } else 02913 if(Sup(x)<1) res = ln(4+sqr(x)) - 2*ln(x); 02914 else { // Punkt 3.: 02915 t = interval(Sup(x)); t = 2/t; 02916 t1 = lnp1(sqr(t)); 02917 t = interval(Inf(x)); 02918 t2 = ln(4.0+sqr(t)) - 2*ln(t); 02919 res = interval(Inf(t1),Sup(t2)); 02920 } 02921 } else { // y <> [1,1] 02922 ex_x = expo( Sup(abs(x)) ); 02923 ex = expo( Sup(abs(y)) ); 02924 if (ex_x>ex) ex = ex_x; // Maximum 02925 if (ex>n) { // scaling: 02926 s = n-ex-1; 02927 t = x; times2pown(t,s); // fast scaling with 2^(s) 02928 t1 = y; times2pown(t1,s); // fast scaling with 2^(s) 02929 t2 = sqr(t) + sqr(comp(0.5,s+1)-t1); // t2: denominator 02930 t = y / t2; // scaled quotient 02931 times2pown(t,2*s+2); // back-scaling with 2^(s+2); '+2': factor 4 !! 02932 res = lnp1(t); 02933 } else res = lnp1(4*y/(sqr(x)+sqr(1-y))); // normal calculation 02934 } 02935 return res; 02936 } // Q_atan_UPSIGN 02937 02938 cinterval atan( const cinterval& z ) throw() //----- 040912 -- 02939 { 02940 interval 02941 rez = Re(z), 02942 imz = Im(z); 02943 02944 real 02945 irez = Inf(rez), 02946 srez = Sup(rez), 02947 iimz = Inf(imz), 02948 simz = Sup(imz); 02949 02950 const int n = 511; // For possible scaling 02951 02952 interval 02953 hxl(irez), hxu(srez), hyl(iimz), hyu(simz); 02954 02955 real 02956 resxl, resxu, resyl, resyu; 02957 // 02958 // 1st: check for singularities 02959 // 02960 if( ( irez <= 0.0 && srez >= 0.0 ) && ( iimz <= -1.0 || simz >= 1.0 ) ) 02961 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval atan( const cinterval& z ); z contains singularities.")); 02962 // 02963 // 2nd: real part 02964 // Re( atan( z ) ) = Arg( w ) / 2, where w = 1 - x^2 - y^2 + i * 2x ) 02965 // 02966 // evaluate atan on vertical boundaries 02967 // 02968 interval 02969 // y_sqr = sqr( imz ), 02970 // rew_l = (1 - y_sqr) - sqr( hxl ), // Blomquist; before: rew_l = 1 - sqr(hxl) - y_sqr, 02971 // rew_u = (1 - y_sqr) - sqr( hxu ); // Blomquist; before: rew_u = 1 - sqr(hxu) - y_sqr; 02972 rew_l, rew_u; 02973 02974 /* ------------------------------ Blomquist --------------------------------------------------- */ 02975 /* ---------- Improvements for Im(z) = [1,1] or Im(z) = [-1,-1] ------------------*/ 02976 bool sqrImz_1 = (iimz==simz) && (iimz==1.0 || iimz==-1.0); // Test for Im(z) = [1,1] or [-1,-1] 02977 02978 if (sqrImz_1) { 02979 rew_l = -abs(hxl); hxl = interval(sign(irez)); 02980 rew_u = -abs(hxu); hxu = interval(sign(srez)); 02981 } 02982 else { 02983 int ex,s; 02984 interval imz_, scf; 02985 int ex1 = expo(iimz); int ex2 = expo(simz); 02986 if (ex2>ex1) ex1 = ex2; 02987 02988 ex = expo(irez); 02989 if(ex1>ex) ex = ex1; // Maximum 02990 if (ex>n) { // Scaling necessary 02991 s = n - ex - 1; 02992 scf = interval(comp(0.5,s+1)); // scf: scaling factor 2^s 02993 times2pown(scf,s); // scf = 2^(2*s); 02994 times2pown(hxl,s); // hxl = hxl * 2^s 02995 imz_ = imz; 02996 times2pown(imz_,s); // imz_ = imz_ * 2^s 02997 rew_l = (scf - sqr(imz_)) - sqr(hxl); // here now without overflow!! 02998 times2pown(hxl,s); // hxl = hxl * 2^s 02999 } else rew_l = (1 - sqr( imz )) - sqr( hxl ); 03000 03001 ex = expo(srez); 03002 if(ex1>ex) ex = ex1; // Maximum 03003 if (ex>n) { // Scaling necessary 03004 s = n - ex - 1; 03005 scf = interval(comp(0.5,s+1)); // scf: scaling factor 2^s 03006 times2pown(scf,s); // scf = 2^(2*s); 03007 times2pown(hxu,s); // hxu = hxu * 2^s 03008 imz_ = imz; 03009 times2pown(imz_,s); // imz_ = imz_ * 2^s 03010 rew_u = (scf - sqr(imz_)) - sqr(hxu); // here now without overflow!! 03011 times2pown(hxu,s); // hxu = hxu * 2^s 03012 } else rew_u = (1 - sqr( imz )) - sqr( hxu ); 03013 } 03014 /* ------------------------------ Blomquist; 22.02.05; ---------------------------------------- */ 03015 03016 // 03017 // left boundary 03018 // 03019 real rew_inf = Inf( rew_l ); 03020 real rew_sup = Sup( rew_l ); 03021 re_vert( irez, hxl, rew_inf, rew_sup, resxl, resxu ); 03022 03023 // 03024 // right boundary 03025 // 03026 rew_inf = Inf( rew_u ); 03027 rew_sup = Sup( rew_u ); 03028 real res_l, res_u; 03029 re_vert( srez, hxu, rew_inf, rew_sup, res_l, res_u ); 03030 03031 resxl = min( resxl, res_l ); 03032 resxu = max( resxu, res_u ); 03033 // 03034 // look for extremal values on horizontal boundaries 03035 // since atan( x+iy ) = atan( x-iy ), 03036 // intersections can be considered in the upper half plane 03037 // 03038 real abs_y_min = Inf( abs( imz ) ); 03039 03040 if( abs_y_min > 1.0 ) 03041 { 03042 interval 03043 abs_hyl = interval( abs_y_min ), 03044 // abs_hxl = sqrt( sqr( abs_hyl ) - 1.0 ); 03045 abs_hxl = sqrtx2m1(abs_hyl); // Blomquist; 03046 03047 if( Sup( abs_hxl ) > irez && Inf( abs_hxl ) < srez ) 03048 // extremal curve intersects lower boundary of x+i|y| in quadrant I 03049 // intersection in Q I or Q IV: update minimum 03050 // resxl = inf( atan( abs_y_min / abs_hxl ) ) / 2.0; 03051 resxl = Inf( (PI() - atan( 1.0 / abs_hxl ))/2.0 ); 03052 else if( -Inf( abs_hxl ) > irez && -Sup( abs_hxl ) < srez ) 03053 // extremal curve intersects lower boundary of x+i|y| in quadrant II 03054 // intersection in Q II or Q III: update maximum 03055 resxu = Sup( (atan( 1.0 / abs_hxl ) - PI())/2.0 ); 03056 } 03057 // 3rd: imaginary part 03058 // Im( atan( z ) ) = +/- Ln( 1 +/- 4y/( x^2 + (1 -/+ y)^2 ) ) / 4 03059 // 03060 // evaluate atan on horizontal boundaries 03061 interval 03062 abs_rez = abs(rez), 03063 im_atan_l, im_atan_u; 03064 03065 if( iimz < 0.0 ) 03066 // im_atan_l = -ln( 1 - 4 * hyl / ( x_sqr + sqr( 1 + hyl ) ) ) / 4.0; 03067 // im_atan_l = -lnp1(-4 * hyl / ( x_sqr + sqr( 1 + hyl ) )) / 4.0; // Blomquist 03068 im_atan_l = -Q_atan_UPSIGN(abs_rez,-hyl); // Blomquist (Versuch) 03069 else 03070 // im_atan_l = ln( 1 + 4 * hyl / ( x_sqr + sqr( 1 - hyl ) ) ) / 4.0; 03071 im_atan_l = Q_atan_UPSIGN(abs_rez,hyl); // Blomquist 03072 times2pown(im_atan_l,-2); 03073 03074 if( simz < 0.0 ) 03075 // im_atan_u = -ln( 1 - 4 * hyu / ( x_sqr + sqr( 1 + hyu ) ) ) / 4.0; 03076 // im_atan_u = -lnp1(-4 * hyu / ( x_sqr + sqr( 1 + hyu ) ) ) / 4.0; // Blomquist 03077 im_atan_u = -Q_atan_UPSIGN(abs_rez,-hyu); // Blomquist 03078 else 03079 // im_atan_u = ln( 1 + 4 * hyu / ( x_sqr + sqr( 1 - hyu ) ) ) / 4.0; 03080 im_atan_u = Q_atan_UPSIGN(abs_rez,hyu); // Blomquist 03081 times2pown(im_atan_u,-2); 03082 03083 resyl = min( Inf( im_atan_l ), Inf( im_atan_u ) ); 03084 resyu = max( Sup( im_atan_l ), Sup( im_atan_u ) ); 03085 // 03086 // look for extremal values on vertical boundaries, 03087 // if vertical boundaries intersect extremal curves 03088 // 03089 real abs_x_min = Inf( abs( rez ) ); 03090 interval 03091 x_extr = interval( abs_x_min ), 03092 // y_extr = sqrt( 1.0 + sqr( x_extr ) ); 03093 y_extr = sqrt1px2(x_extr); // Blomquist; 03094 03095 if( Inf( y_extr ) < simz && Sup( y_extr ) > iimz ) 03096 // extremal curve intersects left boundary of |x|+iy in quadrant I 03097 // update maximum 03098 // resyu = Sup( ln( 1 + 4 * y_extr / ( sqr( x_extr ) + sqr( 1 - y_extr ) ) ) ) / 4.0; 03099 // resyu = Sup( Aux_1_atan(abs_x_min)/4.0 ); // Blomquist 03100 { 03101 rez = Aux_1_atan(abs_x_min); 03102 times2pown(rez,-2); 03103 resyu = Sup(rez); 03104 } 03105 03106 if( -Sup( y_extr ) < simz && -Inf( y_extr ) > iimz ) 03107 // extremal curve intersects left boundary of |x|+iy in quadrant IV 03108 // update minimum 03109 // resyl = -Sup( ln( 1 + 4 * y_extr / ( sqr( x_extr ) + sqr( 1 - y_extr ) ) ) ) / 4.0; 03110 // resyl = -Sup( Aux_1_atan(abs_x_min)/4.0 ); // Blomquist 03111 { 03112 rez = Aux_1_atan(abs_x_min); 03113 times2pown(rez,-2); 03114 resyl = -Sup(rez); 03115 } 03116 03117 return cinterval( interval( resxl, resxu ), interval( resyl, resyu ) ); 03118 03119 } 03120 // 03121 //-- end atan ----------------------------------------------------------------- 03122 03123 03124 //-- acot ----------------------------------------------------------- 040912 -- 03125 // 03126 // Analytic inverse cotangent function 03127 // acot( z ) = atan( 1/z ) 03128 // The code of acot( z ) is almost identical to the code of atan( z ) 03129 // 03130 cinterval acot( const cinterval& z ) throw() 03131 { 03132 interval 03133 rez = Re(z), 03134 imz = Im(z); 03135 03136 real 03137 irez = Inf(rez), 03138 srez = Sup(rez), 03139 iimz = Inf(imz), 03140 simz = Sup(imz); 03141 03142 const int n = 511; // For possible scaling 03143 03144 interval 03145 hxl(irez), hxu(srez), hyl(iimz), hyu(simz); 03146 03147 real 03148 resxl, resxu, resyl, resyu; 03149 // 03150 // 1st: check for singularities 03151 // 03152 if( ( (irez <= 0.0) && (srez >= 0.0) ) && ( (iimz <= 1.0) && (simz >= -1.0) ) ) 03153 cxscthrow(STD_FKT_OUT_OF_DEF("cinterval acot( const cinterval& z ); z contains singularities.")); 03154 // 03155 // 2nd: real part 03156 // Re( atan( z ) ) = Arg( w ) / 2, where w = 1 - x^2 - y^2 + i * 2x ) 03157 // Re( atan( 1 / z ) ) = Arg( w ) / 2, where w = x^2 + y^2 - 1 + i * 2x ) 03158 // 03159 // evaluate acot on vertical boundaries 03160 // 03161 interval 03162 // y_sqr = sqr( imz ), 03163 // rew_l = (y_sqr - 1) + sqr(hxl), 03164 // rew_u = (y_sqr - 1) + sqr(hxu); 03165 // rew_l = (sqr( hxl )-1) + y_sqr, 03166 // rew_u = (sqr( hxu )-1) + y_sqr; 03167 rew_l, rew_u; 03168 /* ------------------------------ Blomquist --------------------------------------------------- */ 03169 /* ---------- Improvements for Im(z) = [1,1] or Im(z) = [-1,-1] ------------------*/ 03170 bool sqrImz_1 = (iimz==simz) && (iimz==1.0 || iimz==-1.0); // Test for Im(z) = [1,1] or [-1,-1] 03171 03172 if (sqrImz_1) { 03173 rew_l = abs(hxl); hxl = interval(sign(irez)); 03174 rew_u = abs(hxu); hxu = interval(sign(srez)); 03175 } 03176 else { 03177 int ex,s; 03178 interval imz_, scf; 03179 int ex1 = expo(iimz); int ex2 = expo(simz); 03180 if (ex2>ex1) ex1 = ex2; 03181 03182 ex = expo(irez); 03183 if(ex1>ex) ex = ex1; // Maximum 03184 if (ex>n) { // Scaling necessary 03185 s = n - ex - 1; 03186 scf = interval(comp(0.5,s+1)); // scf: scaling factor 2^s 03187 times2pown(scf,s); // scf = 2^(2*s); 03188 times2pown(hxl,s); // hxl = hxl * 2^s 03189 imz_ = imz; 03190 times2pown(imz_,s); // imz_ = imz_ * 2^s 03191 rew_l = (sqr(imz_) - scf) + sqr(hxl); // here now without overflow!! 03192 times2pown(hxl,s); // hxl = hxl * 2^s 03193 } else rew_l = (sqr( imz ) - 1.0) + sqr( hxl ); 03194 03195 ex = expo(srez); 03196 if(ex1>ex) ex = ex1; // Maximum 03197 if (ex>n) { // Scaling necessary 03198 s = n - ex - 1; 03199 scf = interval(comp(0.5,s+1)); // scf: scaling factor 2^s 03200 times2pown(scf,s); // scf = 2^(2*s); 03201 times2pown(hxu,s); // hxu = hxu * 2^s 03202 imz_ = imz; 03203 times2pown(imz_,s); // imz_ = imz_ * 2^s 03204 rew_u = (sqr(imz_) - scf) + sqr(hxu); // here now without overflow!! 03205 times2pown(hxu,s); // hxu = hxu * 2^s 03206 } else rew_u = (sqr( imz )-1.0) + sqr( hxu ); 03207 } 03208 /* ------------------------------ Blomquist; 22.02.05; ---------------------------------------- */ 03209 03210 // 03211 // left boundary 03212 // 03213 real rew_inf = Inf( rew_l ); 03214 real rew_sup = Sup( rew_l ); 03215 re_vert( irez, hxl, rew_inf, rew_sup, resxl, resxu ); 03216 // 03217 // right boundary 03218 // 03219 rew_inf = Inf( rew_u ); 03220 rew_sup = Sup( rew_u ); 03221 real res_l, res_u; 03222 re_vert( srez, hxu, rew_inf, rew_sup, res_l, res_u ); 03223 03224 resxl = min( resxl, res_l ); 03225 resxu = max( resxu, res_u ); 03226 // 03227 // look for extremal values on horizontal boundaries 03228 // since acot( x+iy ) = acot( x-iy ), 03229 // intersections can be considered in the upper half plane 03230 // 03231 real abs_y_min = Inf( abs( imz ) ); 03232 03233 if( abs_y_min > 1.0 ) 03234 { 03235 interval 03236 abs_hyl = interval( abs_y_min ), 03237 // abs_hxl = sqrt( sqr( abs_hyl ) - 1.0 ); 03238 abs_hxl = sqrtx2m1(abs_hyl); // Blomquist; 03239 if( Sup( abs_hxl ) > irez && Inf( abs_hxl ) < srez ) 03240 // extremal curve intersects lower boundary of x+i|y| in quadrant I 03241 // intersection in Q I or Q IV: update maximum 03242 resxu = Sup( atan( 1.0 / abs_hxl ) / 2.0 ); 03243 if( -Inf( abs_hxl ) > irez && -Sup( abs_hxl ) < srez ) 03244 // extremal curve intersects lower boundary of x+i|y| in quadrant II 03245 // intersection in Q II or Q III: update minimum 03246 resxl = -Sup( atan( 1.0 / abs_hxl ) / 2.0 ); 03247 } 03248 // 03249 // 3rd: imaginary part 03250 // Im( atan( z ) ) = +/- Ln( 1 +/- 4y/( x^2 + (1 -/+ y)^2 ) ) / 4 03251 // Im( acot ) = - Im ( atan ): We calculate Im( atan ) and return "-" 03252 // 03253 // evaluate atan on horizontal boundaries 03254 // 03255 interval 03256 // x_sqr = sqr( rez ), // overflow is avoided by calling Q_atan_UPSIGN(...) 03257 im_atan_l, im_atan_u, 03258 abs_rez = abs(rez); // Blomquist; 03259 if( iimz < 0.0 ) 03260 // im_atan_l = -ln( 1 - 4 * hyl / ( x_sqr + sqr( 1 + hyl ) ) ) / 4.0; 03261 im_atan_l = -Q_atan_UPSIGN(abs_rez,-hyl); // Blomquist 03262 else 03263 // im_atan_l = ln( 1 + 4 * hyl / ( x_sqr + sqr( 1 - hyl ) ) ) / 4.0; 03264 im_atan_l = Q_atan_UPSIGN(abs_rez,hyl); // Blomquist 03265 times2pown(im_atan_l,-2); 03266 03267 if( simz < 0.0 ) 03268 // im_atan_u = -ln( 1 - 4 * hyu / ( x_sqr + sqr( 1 + hyu ) ) ) / 4.0; 03269 im_atan_u = -Q_atan_UPSIGN(abs_rez,-hyu); // Blomquist 03270 else 03271 // im_atan_u = ln( 1 + 4 * hyu / ( x_sqr + sqr( 1 - hyu ) ) ) / 4.0; 03272 im_atan_u = Q_atan_UPSIGN(abs_rez,hyu); // Blomquist 03273 times2pown(im_atan_u,-2); 03274 03275 resyl = min( Inf( im_atan_l ), Inf( im_atan_u ) ); 03276 resyu = max( Sup( im_atan_l ), Sup( im_atan_u ) ); 03277 // 03278 // look for extremal values on vertical boundaries, 03279 // if vertical boundaries intersect extremal curves 03280 // 03281 real abs_x_min = Inf( abs( rez ) ); 03282 interval 03283 x_extr = interval( abs_x_min ), 03284 // y_extr = sqrt( 1.0 + sqr( x_extr ) ); 03285 y_extr = sqrt1px2(x_extr); // Blomquist 03286 if( Inf( y_extr ) < simz && Sup( y_extr ) > iimz ) 03287 // extremal curve intersects left boundary of |x|+iy in quadrant I 03288 // update maximum 03289 // resyu = Sup( ln( 1 + 4 * y_extr / ( sqr( x_extr ) + sqr( 1 - y_extr ) ) ) ) / 4.0; 03290 // resyu = Sup( Aux_1_atan(abs_x_min)/4.0 ); // Blomquist 03291 { 03292 rez = Aux_1_atan(abs_x_min); 03293 times2pown(rez,-2); 03294 resyu = Sup(rez); 03295 } 03296 03297 if( -Sup( y_extr ) < simz && -Inf( y_extr ) > iimz ) 03298 // extremal curve intersects left boundary of |x|+iy in quadrant IV 03299 // update minimum 03300 // resyl = -Sup( ln( 1 + 4 * y_extr / ( sqr( x_extr ) + sqr( 1 - y_extr ) ) ) ) / 4.0; 03301 // resyl = -Sup( Aux_1_atan(abs_x_min)/4.0 ); // Blomquist 03302 { 03303 rez = Aux_1_atan(abs_x_min); 03304 times2pown(rez,-2); 03305 resyl = -Sup(rez); 03306 } 03307 03308 return cinterval( interval( resxl, resxu ), interval( -resyu, -resyl ) ); 03309 03310 } 03311 // 03312 //-- end acot ----------------------------------------------------------------- 03313 03314 03315 //-- atanh ---------------------------------------------------------- 040912 -- 03316 // 03317 cinterval atanh( const cinterval& z ) throw() 03318 // 03319 // atanh( z ) = - i * atan( i * z ) 03320 // 03321 { 03322 cinterval res = atan( cinterval( -Im(z), Re(z) ) ); 03323 return cinterval( Im(res), -Re(res) ); 03324 } 03325 // 03326 //-- end atanh ---------------------------------------------------------------- 03327 03328 //-- acoth ---------------------------------------------------------- 040912 -- 03329 // 03330 cinterval acoth( const cinterval& z ) throw() 03331 // 03332 // acoth( z ) = i * acot( i * z ) 03333 // 03334 { 03335 cinterval res = acot( cinterval( -Im(z), Re(z) ) ); 03336 return cinterval( -Im(res), Re(res) ); 03337 } 03338 // 03339 //-- end acoth ---------------------------------------------------------------- 03340 03341 03342 cinterval sqr(const cinterval& z) throw() 03343 // Improvement of the sqr(z)-function; Blomquist, 24.06.2005; 03344 { 03345 interval rez(Re(z)), reza(abs(rez)), 03346 imz(Im(z)), imza(abs(imz)); 03347 real 03348 irez = Inf(reza), 03349 srez = Sup(reza), 03350 iimz = Inf(imza), 03351 simz = Sup(imza); 03352 interval 03353 hxl(irez), hxu(srez), hyl(iimz), hyu(simz); 03354 real 03355 resxl, resxu; 03356 03357 resxl = Inf( (hxl-hyu)*(hxl+hyu) ); 03358 resxu = Sup( (hxu-hyl)*(hxu+hyl)); 03359 03360 hxl = rez * imz; 03361 times2pown(hxl,1); // fast multiplikation with 2; 03362 03363 return cinterval( interval(resxl,resxu), hxl ); 03364 } 03365 03366 } // namespace cxsc 03367 03368 /* 03369 03370 End of File: cimath.cpp 03371 03372 */