C-XSC - A C++ Class Library for Extended Scientific Computing  2.5.4
cimath.cpp
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 */