Main Page | Alphabetical List | Class List | File List | Class Members | File Members

math_next.h

Go to the documentation of this file.
00001 #ifndef _MATH_NEXT_H_
00002 #define _MATH_NEXT_H_
00003 
00004 #include <nlibc.h>
00005 
00006 /*==================================================================
00007 !! Syntax extensions for mathematical functions on apeNEXT
00008 !!
00009 !! All constants changed to records which are defined
00010 !! and initialized in mathvar.hzt
00011 !!
00012 !! $Id: math_next.h,v 2.7 2005/06/08 14:06:53 pleiter Exp $
00013 !! from : math_next.hzt,v 1.3 2001/11/02 09:28:41 simma Exp
00014 !!
00015 !! ZZ version : Roberto De Pietri: v. 0.4 26/08/2001
00016 !! C conversion : N. Paschedag : 15/02/2002
00017 !!
00018 !! Implemented functions:
00019 !!
00020 !!   ->  sqrt(x)     <- 
00021 !!   ->  isqrt(x)    <- 1/sqrt(x)
00022 !!   ->  exp(x)      <- e^x
00023 !!   ->  exp1m(x)    <- e^x-1
00024 !!   ->  sinh(x)     <- 
00025 !!   ->  cosh(x)     <- 
00026 !!   ->  tanh(x)     <- 
00027 !!   ->  log(x)      <- log(x)   \__ / Using a degree 33 approximations
00028 !!   ->  log1p(x)    <- log(1+x) /   \ of log(1+y) for -0.5<y<0.5
00029 !!   ->  sin_1oct(x) <- sin(x), -pi/4<x<pi/4  
00030 !!   ->  sin_1oct(x) <- cos(x), -pi/4<x<pi/4  
00031 !!   ->  sin(x)      <- 
00032 !!   ->  cos(x)      <- 
00033 !!   ->  tan(x)      <- 
00034 !!   ->  asin_k(x)   <- asin(x), -1/2<x<1/2 
00035 !!   ->  asin(x)     <- 
00036 !!   ->  acos(x)     <- 
00037 !!   ->  atan_k(x)   <- atan(x), -1<x<1 
00038 !!   ->  atan(x)     <- 
00039 !!
00040 !!==================================================================*/
00041 
00042 
00043 #ifdef _INLINE_MATH_
00044 #  define math_inline inline
00045 #else
00046 #  define math_inline 
00047 #endif
00048 
00049 /*======================================================
00050 !! macro to set a double from its hex representation
00051 !!====================================================*/
00052 
00053 #define _math_setdouble(U,D) { \
00054   register union { double d; unsigned i; } u; \
00055   u.i=U; D=u.d; \
00056 }
00057 
00058 /*======================================================
00059 !!  Function inverted square root (Newton iterations)
00060 !!====================================================*/
00061 
00062 math_inline double isqrt( double a ) {
00063     register double ris, tmp_a2;
00064     register double three_half, one_half;
00065     register double aR;
00066 
00067     _math_setdouble(0x3FE0000000000000ULL,one_half);    // 0.5
00068     _math_setdouble(0x3FF8000000000000ULL,three_half);  // 1.5
00069 
00070     aR = a;
00071     asm("\tlutinvsqrt.L %0 %1" : "=r" (ris) : "r" (aR));
00072     asm("\tlutcross.H %0 $ZERO" : "=r" (ris));
00073 
00074     tmp_a2 = aR * one_half;
00075     ris = ris*( three_half - tmp_a2 * ris * ris);
00076     ris = ris*( three_half - tmp_a2 * ris * ris);
00077     ris = ris*( three_half - tmp_a2 * ris * ris);
00078     ris = ris*( three_half - tmp_a2 * ris * ris);
00079     return ris;
00080 }
00081 
00082 /*======================================================
00083 !!  Function square root (Newton iterations)
00084 !!====================================================*/
00085 
00086 inline double sqrt( double a ) {
00087     register double ris, tmp_a2;
00088     register double three_half, one_half;
00089     register double aR;
00090 
00091     _math_setdouble(0x3FE0000000000000ULL,one_half);   // 0.5
00092     _math_setdouble(0x3FF8000000000000ULL,three_half); // 1.5
00093 
00094     aR = a;
00095     ris = 0.0;
00096     where ( aR ) {
00097         asm("\tlutisqrt.L %0 %1" : "=r" (ris) : "r" (aR));
00098         asm("\tlutcross.H %0 $ZERO" : "=r" (ris));
00099     }
00100     tmp_a2 = aR * one_half;
00101     ris = ris*( three_half - tmp_a2 * ris * ris);
00102     ris = ris*( three_half - tmp_a2 * ris * ris);
00103     ris = ris*( three_half - tmp_a2 * ris * ris);
00104     ris = ris*( three_half - tmp_a2 * ris * ris);
00105     ris *= aR;
00106     return ris;
00107 }
00108 
00109 
00110 /*-----------------------------------------------------------------
00111 !!
00112 !! The invsqrt function compute 1/Sqrt(x) using a table based guess  
00113 !! y0 = lutisqrt(x) such that r = 1 - x y0^2 is |r|<2^(-6.72)
00114 !!
00115 !! 1/Sqrt[x] = y0 ( 1 + r Q(r) )
00116 !!  
00117 !!        (    1          )    1
00118 !! Q(r) = ( --------- - 1 ) x ---
00119 !!        ( Sqrt[1-r]     )    r
00120 !!
00121 !! Q(r) has been approximated by a Remez minimax polynomial:
00122 !!
00123 !! degree = 5
00124 !! [a,b]  = [-0.01104854345604,0.01104854345604]
00125 !! w(x)   = r Sqrt(1-r)
00126 !! N Iter = 10000 
00127 !! Max Error = 6.6*10^-17
00128 !!
00129 !!---------------------------------------------------------------*/
00130 
00131 
00132 math_inline double isqrt2( double x ) {
00133     register double xx,y0,q0,q1;
00134     register double r,r2,Q;
00135     register double t1,t2,t3;
00136     register double p0,p1,p2,p3,p4,p5;
00137 
00138     // -- Remez coefficients for 1/sqrt(x) -------------------------------
00139     _math_setdouble( 0x3fe0000000000176ULL, p0 );
00140     _math_setdouble( 0x3fd8000000000640ULL, p1 );
00141     _math_setdouble( 0x3fd3fffffd11f1d0ULL, p2 );
00142     _math_setdouble( 0x3fd17ffffbfd0ec7ULL, p3 );
00143     _math_setdouble( 0x3fcf81774c2db32fULL, p4 );
00144     _math_setdouble( 0x3fcce1962db980e2ULL, p5 );
00145     
00146     xx = x;
00147     
00148     asm("\tlutisqrt.L %0 %1" : "=r" (y0) : "r" (xx));
00149     asm("\tlutcross.H %0 $ZERO" : "=r" (y0));
00150     
00151     q0 = y0 * y0;
00152     r  = (1.0) - xx * q0;
00153     r2 = r * r;
00154     
00155     t1 = p5 * r + p4;
00156     t2 = p3 * r + p2;
00157     t3 = p1 * r + p0;
00158     
00159     t1 = t1 * r2 + t2;
00160     Q  = t1 * r2 + t3;
00161     q1 = r  * y0;
00162     Q  = q1 * Q + y0;
00163 
00164     return Q;
00165 }
00166 
00167 math_inline double sqrt2( double x ) { 
00168     register double xx,y0,q0,q1;
00169     register double r,r2,Q;
00170     register double t1,t2,t3;
00171     register double p0,p1,p2,p3,p4,p5;
00172 
00173     // -- Remez coefficients for 1/sqrt(x) -------------------------------
00174     _math_setdouble( 0x3fe0000000000176ULL, p0 );
00175     _math_setdouble( 0x3fd8000000000640ULL, p1 );
00176     _math_setdouble( 0x3fd3fffffd11f1d0ULL, p2 );
00177     _math_setdouble( 0x3fd17ffffbfd0ec7ULL, p3 );
00178     _math_setdouble( 0x3fcf81774c2db32fULL, p4 );
00179     _math_setdouble( 0x3fcce1962db980e2ULL, p5 );
00180     
00181     xx = x;
00182     y0 = xx;
00183 
00184     where ( xx ) {
00185         asm("\tlutisqrt.L %0 %1" : "=r" (y0) : "r" (xx));
00186         asm("\tlutcross.H %0 $ZERO" : "=r" (y0));
00187     }
00188 
00189     q0 = y0 * y0;
00190     r  = 1.0 - xx * q0;
00191     r2 = r * r;
00192     
00193     y0 = y0 * xx;
00194     q1 = r  * y0;
00195     
00196     t1 = p5 * r + p4;
00197     t2 = p3 * r + p2;
00198     t3 = p1 * r + p0;
00199     
00200     t1 = t1 * r2 + t2;
00201     Q  = t1 * r2 + t3;
00202     
00203     Q  = q1 * Q + y0;
00204 
00205     return Q;
00206 }
00207 
00208 
00209 /*==================================================================
00210 !!==================================================================
00211 !! Exponential and Hyperbolic functions
00212 !!
00213 !! Exp(x) = 2^(1/log[2) b) 
00214 !!        = 2^f 2^(1/Log(2) x -f ) 
00215 !!        = P 2^q'                   where  q' = 1/Log[2] x - f
00216 !!        = P Exp(q)                    and    q  = x - Log[2] f
00217 !!
00218 !! Since 0 < |q'| < 0.5  we will have  0 < |q| < Log[2]/2 ~ 0.347 
00219 !!
00220 !!                   1
00221 !! Exp[q] = 1 + q + --- q^2 + q^3 P(q) )
00222 !!                   2
00223 !!
00224 !! ---------------------------------------------------------------
00225 !!
00226 !!        Exp[q] - 1 - q - q^2/2
00227 !! P(q) = -----------------------
00228 !!                q^3
00229 !! P(q) has been approximated by a Remez minimax polynomial:
00230 !!
00231 !! degree = 8 
00232 !! [a,b]  = [-0.34657359027997,0.34657359027997]
00233 !! w(q)   = q^3/(Exp[q]). 
00234 !! N Iter = 20000 
00235 !! Max Error = 5.3*10^-18  
00236 !!
00237 !!---------------------------------------------------------------*/
00238 
00239 
00240 
00241 /*======================================================
00242 !! Function exponential (CORE) 
00243 !!====================================================*/
00244 math_inline double exp( double x ) { 
00245 
00246     register double PP,QQ,Qh,res;
00247     register double b,z,f;
00248     register double q,qlead,qtrail;
00249     register double q2,q4,q5;
00250     register double t1,t2,t3;
00251     register double t1h,t2h,t3h;
00252     register double log2e,ln2lead,ln2trail,nummag;
00253     register double p0,p1,p2,p3,p4,p5,p6,p7,p8;
00254     register double half;
00255 
00256     _math_setdouble(  0x3fe0000000000000 , half );
00257 
00258     _math_setdouble(  0x3ff71547652b82fe, log2e    );
00259     _math_setdouble(  0x3fe62e42fefa4000, ln2lead  ); 
00260     _math_setdouble(  0xbd48432a1b0e2634, ln2trail ); 
00261     _math_setdouble(  0x43300000000003ff, nummag   ); 
00262 
00263     // -- Remez coefficients for exp -------------------------------
00264     _math_setdouble(  0x3fc5555555555502 , p0 );
00265     _math_setdouble(  0x3fa555555555320b , p1 );
00266     _math_setdouble(  0x3f81111111128589 , p2 );
00267     _math_setdouble(  0x3f56c16c17cc1b0b , p3 );
00268     _math_setdouble(  0x3f2a01a011cdf3cb , p4 );     
00269     _math_setdouble(  0x3efa019ab32afe96 , p5 );     
00270     _math_setdouble(  0x3ec71df5419f16f5 , p6 );     
00271     _math_setdouble(  0x3e9289f84ba3248e , p7 );     
00272     _math_setdouble(  0x3e5ad2147cc869b8 , p8 );
00273 
00274     b = log2e * x;
00275     z = nummag + b;
00276     f = z - nummag;
00277 
00278     asm("\tlutexp.L %0 %1" : "=r" (PP) : "r" (z));
00279     asm("\tlutcross.H %0 $ZERO" : "=r" (PP));
00280 
00281     qlead  = x - f * ln2lead;
00282     qtrail =    - f * ln2trail;
00283     q  = qlead + qtrail;
00284     q2 = q  * q;
00285     q4 = q2 * q2;
00286     q5 = q  * q4;
00287 
00288     t1h = p7 + q  * p8;
00289     t2h = p4 + q  * p5;
00290     t3h = p6 + q  * t1h;
00291     Qh  = t2h + q2 * t3h;
00292 
00293     t1 = p2   + q  * p3;
00294     t2 = half + q  * p0;
00295     t3 = p1   + q  * t1;
00296     QQ = t2    + q2 * t3;
00297 
00298     QQ = QQ + q5 * Qh;
00299     QQ = qtrail + q2 * QQ;
00300     QQ = qlead  + QQ;
00301 
00302     res = PP + PP * QQ;
00303 
00304     return res;
00305 }
00306 
00307 /*======================================================
00308 !! Function exponential minus 1 (CORE) 
00309 !!====================================================*/
00310 math_inline double exp1m( double x ) {
00311 
00312     register double PP, Pm1, QQ, Qh, res;
00313     register double b, z, f;
00314     register double q, qlead, qtrail;
00315     register double q2, q4, q5;
00316     register double t1, t2, t3;
00317     register double t1h, t2h, t3h;
00318     register double log2e, ln2lead, ln2trail, nummag;
00319     register double p0, p1, p2, p3, p4, p5, p6, p7, p8;
00320     register double half;
00321 
00322     _math_setdouble(  0x3fe0000000000000 , half    );
00323  
00324     _math_setdouble(  0x3ff71547652b82fe, log2e    );
00325     _math_setdouble(  0x3fe62e42fefa4000, ln2lead  ); 
00326     _math_setdouble(  0xbd48432a1b0e2634, ln2trail ); 
00327     _math_setdouble(  0x43300000000003ff, nummag   ); 
00328 
00329     // -- Remez coefficients for exp -------------------------------
00330     _math_setdouble(  0x3fc5555555555502 , p0 );
00331     _math_setdouble(  0x3fa555555555320b , p1 );
00332     _math_setdouble(  0x3f81111111128589 , p2 );
00333     _math_setdouble(  0x3f56c16c17cc1b0b , p3 );
00334     _math_setdouble(  0x3f2a01a011cdf3cb , p4 );     
00335     _math_setdouble(  0x3efa019ab32afe96 , p5 );     
00336     _math_setdouble(  0x3ec71df5419f16f5 , p6 );     
00337     _math_setdouble(  0x3e9289f84ba3248e , p7 );     
00338     _math_setdouble(  0x3e5ad2147cc869b8 , p8 );
00339 
00340     b = log2e * x;
00341     z = nummag + b;
00342     f = z - nummag;
00343 
00344     asm("\tlutexp.L %0 %1" : "=r" (PP) : "r" (z));
00345     asm("\tlutcross.H %0 $ZERO" : "=r" (PP));
00346 
00347     Pm1 = PP - 1.0;
00348 
00349     qlead  = x - f * ln2lead;
00350     qtrail =    - f * ln2trail;
00351     q  = qlead + qtrail;
00352     q2 = q  * q;
00353     q4 = q2 * q2;
00354     q5 = q  * q4;
00355 
00356     t1h = p7 + q  * p8;
00357     t2h = p4 + q  * p5;
00358     t3h = p6 + q  * t1h;
00359     Qh  = t2h + q2 * t3h;
00360 
00361     t1 = p2   + q  * p3;
00362     t2 = half + q  * p0;
00363     t3 = p1   + q  * t1;
00364     QQ = t2   + q2 * t3;
00365 
00366     QQ = QQ + q5 * Qh;
00367     QQ = qtrail + q2 * QQ;
00368     QQ = qlead  + QQ;
00369 
00370     res = Pm1 + PP * QQ;
00371 
00372     return res;
00373 }
00374 
00375 
00376 /*======================================================
00377 !! Function sinh(x) 
00378 !!====================================================*/
00379 math_inline double sinh( double x ) {
00380 
00381     register double xm, expx, expxm, half, res;
00382 
00383     half = 0.5;
00384     xm = - x;
00385 
00386     expx  = exp1m(x);
00387     expxm = exp1m(xm);
00388 
00389     res = half * expx - half * expxm;
00390 
00391     return res;
00392 }
00393 
00394 /*======================================================
00395 !! Function cosh(x) 
00396 !!====================================================*/
00397 math_inline double cosh( double x ) {
00398 
00399     register double xm, expx, expxm, half, res;
00400 
00401     half = 0.5;
00402     xm = - x;
00403 
00404     expx  = exp1m( x );
00405     expxm = exp1m( xm );
00406 
00407     res = half * expx + half * expxm + 1.0;
00408 
00409     return res;
00410 
00411 }
00412 
00413 /*======================================================
00414 !! Function tanh(x) 
00415 !!====================================================*/
00416 math_inline double tanh( double xxx ) {
00417 
00418     register double x, x2, exp2x, two, temp;
00419     register double res;
00420     two = 1.0 + 1.0;
00421 
00422     x  = xxx;
00423     x2 = x;
00424     where ( x < 0.0 ) {
00425       x2 = -x;
00426     }
00427 
00428     x2  = two * x2;
00429     exp2x  = exp1m(x2);
00430 
00431     temp = exp2x + 2.0;
00432     temp = 1.0 / temp;
00433 
00434     res = exp2x * temp;
00435     where ( x2 > two ) {
00436       res = 1.0 - two * temp;
00437     }
00438 
00439     where ( x < 0.0 ) {
00440       res = - res;
00441     }
00442 
00443     return res;
00444 }
00445 
00446 
00447 /*-------------------------------------------------------
00448 !!
00449 !! Log(x) = e log(2) + log(x0)
00450 !!        = e log(2) + log(1+r) 
00451 !!        = e log(2) + r + r^2 Q(r)
00452 !! 
00453 !! where:  e   = lutloge(x)     x = 2^e x0
00454 !!         x0  = lutlogm(x),    0.5 < x0 < 1.5
00455 !!         r   = x0 - 1  
00456 !!
00457 !! --------------------------------------
00458 !!        Log(1+r) - r
00459 !! Q(r) = ------------- 
00460 !!            r^2
00461 !! has been approximated by a Remez minimax polynomial:
00462 !! ==> p0 + p1 r + p2 r^2 + ..... + p36 r^36
00463 !!
00464 !! degree = 36
00465 !! [a,b]  = [-0.5,0.5]
00466 !! w(r)   = r^2/(Log[1+r]). 
00467 !! N Iter = 20000 
00468 !! Max Error = 1.6*10^-18  
00469 !!-----------------------------------------------------*/
00470 
00471 
00472 
00473 //-----------------------------------------------------------------
00474 
00475 math_inline double log( double x ) {
00476     register double xx, x0, e, e1, r, r2, r4;
00477     register double P, Pa, Pb, Pc, Pd;
00478     register double trail;
00479     register double log2e, ln2lead, ln2trail, nummag;
00480 
00481     register double p0, p1, p2, p3, p4, p5, p6, p7, p8, p9;
00482     register double p10, p11, p12, p13, p14, p15, p16, p17, p18, p19;
00483     register double p20, p21, p22, p23, p24, p25, p26, p27, p28, p29;
00484     register double p30, p31, p32, p33, p34, p35, p36;
00485 
00486     _math_setdouble(  0x3ff71547652b82fe, log2e    );
00487     _math_setdouble(  0x3fe62e42fefa4000, ln2lead  ); 
00488     _math_setdouble(  0xbd48432a1b0e2634, ln2trail ); 
00489     _math_setdouble(  0x43300000000003ff, nummag   ); 
00490 
00491     // -- Remez coefficients for log -------------------------------
00492     _math_setdouble(  0xbfe0000000000000 , p0  );
00493     _math_setdouble(  0x3fd5555555555555 , p1  );
00494     _math_setdouble(  0xbfcfffffffffffd2 , p2  );
00495     _math_setdouble(  0x3fc9999999999944 , p3  );
00496     _math_setdouble(  0xbfc555555555839f , p4  );
00497     _math_setdouble(  0x3fc24924924994cb , p5  );
00498     _math_setdouble(  0xbfbfffffffd3792a , p6  );
00499     _math_setdouble(  0x3fbc71c71bfbb905 , p7  );
00500     _math_setdouble(  0xbfb99999a6067f7a , p8  );
00501     _math_setdouble(  0x3fb745d1960bf8dd , p9  );
00502     _math_setdouble(  0xbfb555531a405781 , p10 );
00503     _math_setdouble(  0x3fb3b1351bb667d8 , p11 );
00504     _math_setdouble(  0xbfb2496af8fbbbe4 , p12 );
00505     _math_setdouble(  0x3fb111c6afc8c6e1 , p13 );
00506     _math_setdouble(  0xbfaff38dd41057ce , p14 );
00507     _math_setdouble(  0x3fadffb7d7a94696 , p15 );
00508     _math_setdouble(  0xbfad41ba8a134738 , p16 );
00509     _math_setdouble(  0x3faccbc9726ece12 , p17 );
00510     _math_setdouble(  0xbf9ec38f119d3d06 , p18 );
00511     _math_setdouble(  0x3f785f81962a50fb , p19 );
00512     _math_setdouble(  0xbfce4be7a8a5d72b , p20 );
00513     _math_setdouble(  0x3fd9d8d252726e6c , p21 );
00514     _math_setdouble(  0x3ff5c8aa212fd722 , p22 );
00515     _math_setdouble(  0xc0026bd5ff44cd4e , p23 );
00516     _math_setdouble(  0xc01fa5187761a8ad , p24 );
00517     _math_setdouble(  0x4026d78e0bf83a6c , p25 );
00518     _math_setdouble(  0x4040ba1a1b262a4f , p26 );
00519     _math_setdouble(  0xc044570c25ae2da0 , p27 );
00520     _math_setdouble(  0xc05a8787b4194713 , p28 );
00521     _math_setdouble(  0x405a009c5d877e88 , p29 );
00522     _math_setdouble(  0x406e49c81a0007b0 , p30 );
00523     _math_setdouble(  0xc0666aa1bfe5d0fe , p31 );
00524     _math_setdouble(  0xc077926b8e4542e3 , p32 );
00525     _math_setdouble(  0x406767610205d729 , p33 );
00526     _math_setdouble(  0x40765b8a9462a4c6 , p34 );
00527     _math_setdouble(  0xc0564d5567c48d46 , p35 );
00528     _math_setdouble(  0xc06383c8abcc91fa , p36 );
00529     
00530     xx = x;
00531 
00532     asm("\tlutlogm.L %0 %1" : "=r" (x0) : "r" (xx));
00533     asm("\tlutloget.L %0 %1" : "=r" (e1) : "r" (xx));
00534     asm("\tlutcross.H %0 $ZERO" : "=r" (x0));
00535     asm("\tlutcross.H %0 $ZERO" : "=r" (e1));
00536 
00537     e = e1 - nummag;
00538     r = x0 - 1.0;
00539     r2 = r  * r;
00540     r4 = r2 * r2;
00541     
00542     Pa = p36;
00543     Pa = r4 * Pa + p32;
00544     Pa = r4 * Pa + p28;
00545     Pa = r4 * Pa + p24;
00546     Pa = r4 * Pa + p20;
00547     Pa = r4 * Pa + p16;
00548     Pa = r4 * Pa + p12;
00549     Pa = r4 * Pa + p8;
00550     Pa = r4 * Pa + p4;
00551     Pa = r4 * Pa + p0;
00552     
00553     Pb = p33;
00554     Pb = r4 * Pb + p29;
00555     Pb = r4 * Pb + p25;
00556     Pb = r4 * Pb + p21;
00557     Pb = r4 * Pb + p17;
00558     Pb = r4 * Pb + p13;
00559     Pb = r4 * Pb + p9;
00560     Pb = r4 * Pb + p5;
00561     Pb = r4 * Pb + p1;
00562     
00563     Pc = p34;
00564     Pc = r4 * Pc + p30;
00565     Pc = r4 * Pc + p26;
00566     Pc = r4 * Pc + p22;
00567     Pc = r4 * Pc + p18;
00568     Pc = r4 * Pc + p14;
00569     Pc = r4 * Pc + p10;
00570     Pc = r4 * Pc + p6;
00571     Pc = r4 * Pc + p2;
00572     
00573     Pd = p35;
00574     Pd = r4 * Pd + p31;
00575     Pd = r4 * Pd + p27;
00576     Pd = r4 * Pd + p23;
00577     Pd = r4 * Pd + p19;
00578     Pd = r4 * Pd + p15;
00579     Pd = r4 * Pd + p11;
00580     Pd = r4 * Pd + p7;
00581     Pd = r4 * Pd + p3;
00582     
00583     P = Pa + r * Pb + r2 * (Pc + r * Pd);
00584     
00585     trail = e * ln2trail;
00586     trail = r2 * P + trail;
00587     trail = trail + r;
00588     P     = trail + e * ln2lead;
00589 
00590     return P;
00591 }
00592 
00593 
00594 //-----------------------------------------------------------------
00595 
00596 math_inline double log1p( double xxx ) {
00597     register double x,xx,x0,e,e1,r,r2,r4;
00598     register double P,Pa,Pb,Pc,Pd;
00599     register double trail;
00600     register double log2e,ln2lead,ln2trail,nummag  ;
00601 
00602     register double p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
00603     register double p10,p11,p12,p13,p14,p15,p16,p17,p18,p19;
00604     register double p20,p21,p22,p23,p24,p25,p26,p27,p28,p29;
00605     register double p30,p31,p32,p33,p34,p35,p36;
00606 
00607     _math_setdouble(  0x3ff71547652b82fe, log2e    );
00608     _math_setdouble(  0x3fe62e42fefa4000, ln2lead  ); 
00609     _math_setdouble(  0xbd48432a1b0e2634, ln2trail ); 
00610     _math_setdouble(  0x43300000000003ff, nummag   ); 
00611 
00612     // -- Remez coefficients for log -------------------------------
00613     _math_setdouble(  0xbfe0000000000000 , p0  );
00614     _math_setdouble(  0x3fd5555555555555 , p1  );
00615     _math_setdouble(  0xbfcfffffffffffd2 , p2  );
00616     _math_setdouble(  0x3fc9999999999944 , p3  );
00617     _math_setdouble(  0xbfc555555555839f , p4  );
00618     _math_setdouble(  0x3fc24924924994cb , p5  );
00619     _math_setdouble(  0xbfbfffffffd3792a , p6  );
00620     _math_setdouble(  0x3fbc71c71bfbb905 , p7  );
00621     _math_setdouble(  0xbfb99999a6067f7a , p8  );
00622     _math_setdouble(  0x3fb745d1960bf8dd , p9  );
00623     _math_setdouble(  0xbfb555531a405781 , p10 );
00624     _math_setdouble(  0x3fb3b1351bb667d8 , p11 );
00625     _math_setdouble(  0xbfb2496af8fbbbe4 , p12 );
00626     _math_setdouble(  0x3fb111c6afc8c6e1 , p13 );
00627     _math_setdouble(  0xbfaff38dd41057ce , p14 );
00628     _math_setdouble(  0x3fadffb7d7a94696 , p15 );
00629     _math_setdouble(  0xbfad41ba8a134738 , p16 );
00630     _math_setdouble(  0x3faccbc9726ece12 , p17 );
00631     _math_setdouble(  0xbf9ec38f119d3d06 , p18 );
00632     _math_setdouble(  0x3f785f81962a50fb , p19 );
00633     _math_setdouble(  0xbfce4be7a8a5d72b , p20 );
00634     _math_setdouble(  0x3fd9d8d252726e6c , p21 );
00635     _math_setdouble(  0x3ff5c8aa212fd722 , p22 );
00636     _math_setdouble(  0xc0026bd5ff44cd4e , p23 );
00637     _math_setdouble(  0xc01fa5187761a8ad , p24 );
00638     _math_setdouble(  0x4026d78e0bf83a6c , p25 );
00639     _math_setdouble(  0x4040ba1a1b262a4f , p26 );
00640     _math_setdouble(  0xc044570c25ae2da0 , p27 );
00641     _math_setdouble(  0xc05a8787b4194713 , p28 );
00642     _math_setdouble(  0x405a009c5d877e88 , p29 );
00643     _math_setdouble(  0x406e49c81a0007b0 , p30 );
00644     _math_setdouble(  0xc0666aa1bfe5d0fe , p31 );
00645     _math_setdouble(  0xc077926b8e4542e3 , p32 );
00646     _math_setdouble(  0x406767610205d729 , p33 );
00647     _math_setdouble(  0x40765b8a9462a4c6 , p34 );
00648     _math_setdouble(  0xc0564d5567c48d46 , p35 );
00649     _math_setdouble(  0xc06383c8abcc91fa , p36 );
00650 
00651     x  = xxx;
00652     xx = x + 1.0;
00653 
00654     asm("\tlutlogm.L %0 %1" : "=r" (x0) : "r" (xx));
00655     asm("\tlutloget.L %0 %1" : "=r" (e1) : "r" (xx));
00656     asm("\tlutcross.H %0 $ZERO" : "=r" (x0));
00657     asm("\tlutcross.H %0 $ZERO" : "=r" (e1));
00658 
00659     e = e1 - nummag;
00660     r = x0 - 1.0;
00661     
00662     where ( e == 0.0 ) {
00663         r = x;
00664     }
00665     
00666     r2 = r  * r;
00667     r4 = r2 * r2;
00668 
00669     Pa = p36;
00670     Pa = r4 * Pa + p32;
00671     Pa = r4 * Pa + p28;
00672     Pa = r4 * Pa + p24;
00673     Pa = r4 * Pa + p20;
00674     Pa = r4 * Pa + p16;
00675     Pa = r4 * Pa + p12;
00676     Pa = r4 * Pa + p8;
00677     Pa = r4 * Pa + p4;
00678     Pa = r4 * Pa + p0;
00679 
00680     Pb = p33;
00681     Pb = r4 * Pb + p29;
00682     Pb = r4 * Pb + p25;
00683     Pb = r4 * Pb + p21;
00684     Pb = r4 * Pb + p17;
00685     Pb = r4 * Pb + p13;
00686     Pb = r4 * Pb + p9;
00687     Pb = r4 * Pb + p5;
00688     Pb = r4 * Pb + p1;
00689 
00690     Pc = p34;
00691     Pc = r4 * Pc + p30;
00692     Pc = r4 * Pc + p26;
00693     Pc = r4 * Pc + p22;
00694     Pc = r4 * Pc + p18;
00695     Pc = r4 * Pc + p14;
00696     Pc = r4 * Pc + p10;
00697     Pc = r4 * Pc + p6;
00698     Pc = r4 * Pc + p2;
00699 
00700     Pd = p35;
00701     Pd = r4 * Pd + p31;
00702     Pd = r4 * Pd + p27;
00703     Pd = r4 * Pd + p23;
00704     Pd = r4 * Pd + p19;
00705     Pd = r4 * Pd + p15;
00706     Pd = r4 * Pd + p11;
00707     Pd = r4 * Pd + p7;
00708     Pd = r4 * Pd + p3;
00709 
00710     P = Pa + r * Pb + r2 * (Pc + r * Pd);
00711 
00712     trail = e * ln2trail;
00713     trail = r2 * P + trail;
00714     trail = trail + r;
00715     P = trail + e * ln2lead;
00716 
00717     return P;
00718 }
00719 
00720 
00721 /*-----------------------------------------------------------------
00722 !!
00723 !! Kernel function for the computation of Sin[x]
00724 !!
00725 !! Sin[x] = x ( 1 + x^2 Q[x^2] )    ;   -pi/4 < x < pi/4
00726 !!
00727 !!---------------------------------------------------------------*/
00728 
00729 math_inline double sin_1oct( double xx ) {
00730     register double x, x2s, x4s, Qs;
00731     register double t1s, t2s, t3s;
00732     register double Sp0, Sp1, Sp2, Sp3, Sp4, Sp5, Sp6;
00733 
00734     // -- Remez coefficients for kernel sin -------------------------------
00735     _math_setdouble(  0x0 , Sp0 );
00736     _math_setdouble(  0xbfc5555555555555 , Sp1 );
00737     _math_setdouble(  0x3f81111111110eb8 , Sp2 );
00738     _math_setdouble(  0xbf2a01a019f1c947 , Sp3 );
00739     _math_setdouble(  0x3ec71de384036e7d , Sp4 );
00740     _math_setdouble(  0xbe5ae60a561eeab5 , Sp5 );
00741     _math_setdouble(  0x3de5e3c6b7eeb28d , Sp6 );
00742 
00743     x = xx;
00744     x2s  = x * x;
00745     x4s = x2s * x2s;
00746     
00747     t1s = Sp5 + x2s * Sp6;
00748     t2s = Sp3 + x2s * Sp4;
00749     t3s = Sp1 + x2s * Sp2;
00750     
00751     t1s = t2s + x4s * t1s;
00752     Qs  = t3s + x4s * t1s;
00753     
00754     Qs  = x2s * Qs;
00755     Qs  = x + Qs * x;
00756     
00757     return Qs;
00758     
00759 }
00760 
00761 /*-----------------------------------------------------------------
00762 !!
00763 !!
00764 !! Kernel function for the computation of Cos[x]
00765 !!
00766 !! Cos[x] = ( 1 + x^2 (1/2 + x^2 Q[x^2] ) )  ;   -pi/4 < x < pi/4
00767 !!
00768 !!---------------------------------------------------------------*/
00769 
00770 math_inline double cos_1oct( double x ) { 
00771 
00772     register double x2c, x4c, Qc;
00773     register double t1c, t2c, t3c;
00774     register double Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6;
00775 
00776     // -- Remez coefficients for kernel cos -------------------------------
00777     _math_setdouble(  0xbfe0000000000000 , Cp0 );
00778     _math_setdouble(  0x3fa5555555555555 , Cp1 );
00779     _math_setdouble(  0xbf56c16c16c16910 , Cp2 );
00780     _math_setdouble(  0x3efa01a019f556d1 , Cp3 );
00781     _math_setdouble(  0xbe927e4fa28f90c6 , Cp4 );
00782     _math_setdouble(  0x3e21eeb7c6903ba2 , Cp5 );
00783     _math_setdouble(  0xbda908b4ef9a7e2e , Cp6 );
00784 
00785     x2c  = x * x;
00786     x4c = x2c * x2c;
00787 
00788     t1c = Cp5 + x2c * Cp6;
00789     t2c = Cp3 + x2c * Cp4;
00790     t3c = Cp1 + x2c * Cp2;
00791 
00792     t1c = t2c + x4c * t1c;
00793     Qc  = t3c + x4c * t1c;
00794 
00795     Qc  = x2c * Qc + Cp0;
00796     Qc  = (1.0) + x2c * Qc;
00797 
00798     return Qc;
00799 
00800 }
00801 
00802 
00803 /*-----------------------------------------------------------------
00804 !! sin(x)
00805 !!---------------------------------------------------------------*/
00806 
00807 math_inline double sin( double x ) { 
00808 
00809     register double y, siny, cosy;
00810     register double res;
00811 
00812     register union { 
00813       double z;
00814       int    zint;
00815     } zu;
00816 
00817     register double f;
00818     register int k;
00819     register double twooverpi, pihalflead, pihalftrail1, pihalftrail2, magic2;
00820        
00821     _math_setdouble(  0x3fe45f306dc9c883 , twooverpi   );
00822     _math_setdouble(  0x4337ffffffffffff , magic2      );
00823     _math_setdouble(  0x3ff921fb50000000 , pihalflead  );
00824     _math_setdouble(  0x3e5110b460000000 , pihalftrail1 );
00825     _math_setdouble(  0x3c91a62633145c07 , pihalftrail2 );
00826 
00827     zu.z = magic2 + twooverpi * x;
00828     f = zu.z - magic2;
00829     y = x - f * pihalflead;
00830     y = y - f * pihalftrail1;
00831     y = y - f * pihalftrail2;
00832 
00833     // -----------------------------------------
00834     // Comute the sin and the cos of y for (-pi/4<y<pi/4) 
00835     // -----------------------------------------
00836     
00837     siny = sin_1oct(y);
00838     cosy = cos_1oct(y);
00839     
00840     /* -----------------------------------------
00841     !! get the module 4 of _f  The modul is get 
00842     !! over z that has mantissa _f+0x7fff...f
00843     !! That means _k = (f%4 + 3)%4
00844     !! f = 0 -> k= 3 
00845     !! f = 1 -> k= 0 
00846     !! f = 2 -> k= 1 
00847     !! f = 3 -> k= 2 
00848     !! ---------------------------------------*/
00849     k = 0x3;
00850     k = zu.zint & k;
00851 
00852     where ( k == 3 ) {
00853       res = siny;
00854     }
00855     where ( k == 0 ) {
00856       res = cosy;
00857     }
00858     where ( k == 1 ) {
00859       res = - siny;
00860     }
00861     where ( k == 2 ) {
00862       res = - cosy;
00863     }
00864     
00865     return res;
00866     
00867 }
00868 
00869 /*-----------------------------------------------------------------
00870 !! cos(x)
00871 !!---------------------------------------------------------------*/
00872 
00873 math_inline double cos( double x ) {
00874     register double y, siny, cosy;
00875     register double res;
00876 
00877     register double f;
00878 
00879     register union { 
00880       double z;
00881       int zint;
00882     } zu;
00883 
00884     register int k;
00885     register double twooverpi, pihalflead, pihalftrail1, pihalftrail2, magic2;
00886        
00887     _math_setdouble(  0x3fe45f306dc9c883 , twooverpi   );
00888     _math_setdouble(  0x4337ffffffffffff , magic2      );
00889     _math_setdouble(  0x3ff921fb50000000 , pihalflead  );
00890     _math_setdouble(  0x3e5110b460000000 , pihalftrail1 );
00891     _math_setdouble(  0x3c91a62633145c07 , pihalftrail2 );
00892 
00893     zu.z = magic2 + twooverpi * x;
00894     f = zu.z - magic2;
00895     y = x - f * pihalflead;
00896     y = y - f * pihalftrail1;
00897     y = y - f * pihalftrail2;
00898     
00899     // Comute the sin and the cos of (y)
00900     
00901     siny = sin_1oct(y);
00902     cosy = cos_1oct(y);
00903     
00904     /* -----------------------------------------
00905     !! get the module 4 of _f  The modul is get 
00906     !! over z that has mantissa _f+0x7fff...f
00907     !! That means _k = (_f%4 + 3)%4
00908     !! _f = 0 -> _k= 3 
00909     !! _f = 1 -> _k= 0 
00910     !! _f = 2 -> _k= 1 
00911     !! _f = 3 -> _k= 2 
00912     !! ---------------------------------------*/    
00913     k = 0x3;
00914     k = zu.zint & k ;
00915     
00916     where ( k == 3 ) {
00917       res = cosy;
00918     }
00919     where ( k == 0 ) {
00920       res = - siny;
00921     }
00922     where ( k == 1 ) {
00923       res = - cosy;
00924     }
00925     where ( k == 2 ) {
00926       res = siny;
00927     }
00928     
00929     return res;
00930     
00931 }
00932 
00933 /*==================================================================
00934 !!
00935 !! The argument of the function Tan(x) is first reduce to y such that
00936 !!
00937 !! x = k pi/2 + y,   k integer and -pi/4 < y < pi/4  
00938 !!
00939 !! and then:
00940 !!
00941 !! -pi/4 + k pi < x < pi/4 + k pi :   Tan(x) = Tan(y)     
00942 !! -pi/4 + k pi < x < pi/4 + k pi :   Tan(x) = - Cotan(y)
00943 !!
00944 !! Tan(y) and CoTan(y) are computed according to:
00945 !! 
00946 !! -----------------------------------------------------------------
00947 !!
00948 !! P = Tan(y) = y + y^3 P13(y^2) 
00949 !!
00950 !! Where P22(r) is a degree 13 minimax polinomial approximating
00951 !! 
00952 !!        Tan(Sqrt(r))-Sqrt(r)
00953 !! P(r) = ---------------------
00954 !!            Sqrt(r) r 
00955 !!
00956 !! degree = 13
00957 !! [a,b]  = [0,0.61685027506808]
00958 !! w(r)   = r^3/(Tan[r]). 
00959 !! N Iter = 20000 
00960 !! Max Error = 5.3*10^-18  
00961 !!
00962 !! -----------------------------------------------------------------
00963 !!      1
00964 !! Q = --- - CoTan(y) = y + y^3 Q10(y^2) 
00965 !!      y
00966 !!
00967 !! Where Q22(t) is a degree 10 minimax polinomial approximating
00968 !! 
00969 !!        1/Sqrt[r] - CoTan(Sqrt[r]) - Sqrt[r]
00970 !! Q[r] = ------------------------------------
00971 !!                 Sqrt[r] r
00972 !!
00973 !! degree = 10
00974 !! [a,b]  = [0,0.61685027506808]
00975 !! w(r)   = r^3/( 1/Sqrt(r) - CoTan(sqrt(r)) ). 
00976 !! N Iter = 2000 
00977 !! Max Error = 2.36*10^-20  
00978 !!===============================================================*/
00979 
00980 math_inline double tan( double x ) {
00981 
00982     register double y, y2, y3, y4, invy;
00983     register double res, Q, P, Qn, Qp, Pn, Pp;
00984     
00985     register double p0, p1, p2, p3, p4, p5, p6, p7, p8, p9;
00986     register double p10, p11, p12, p13;
00987     register double q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10;
00988 
00989     register double f;
00990 
00991     register union { 
00992      double z;
00993      int    zint;
00994     } zu;
00995 
00996     register int k;
00997     register double twooverpi,pihalflead,pihalftrail1,pihalftrail2,magic2;
00998        
00999     _math_setdouble(  0x3fe45f306dc9c883 , twooverpi   );
01000     _math_setdouble(  0x4337ffffffffffff , magic2      );
01001     _math_setdouble(  0x3ff921fb50000000 , pihalflead  );
01002     _math_setdouble(  0x3e5110b460000000 , pihalftrail1 );
01003     _math_setdouble(  0x3c91a62633145c07 , pihalftrail2 );
01004   
01005     // -- Remez coefficients for tan -------------------------------
01006     _math_setdouble(  0x3fd55555555554f2 , p0  );
01007     _math_setdouble(  0x3fc111111111823f , p1  );
01008     _math_setdouble(  0x3faba1ba1b472c71 , p2  );
01009     _math_setdouble(  0x3f9664f49a7087a7 , p3  );
01010     _math_setdouble(  0x3f8226e1281741ed , p4  );
01011     _math_setdouble(  0x3f6d6d92e4dc1ec9 , p5  );
01012     _math_setdouble(  0x3f57d5b9d094e180 , p6  );
01013     _math_setdouble(  0x3f437f87931093e9 , p7  );
01014     _math_setdouble(  0x3f2d28899e55dabc , p8  );
01015     _math_setdouble(  0x3f21df93999dc111 , p9  );
01016     _math_setdouble(  0xbefb6ea2534187cb , p10 );
01017     _math_setdouble(  0x3f17656fc1431ef6 , p11 );
01018     _math_setdouble(  0xbf0778cb8106dd3d , p12 );
01019     _math_setdouble(  0x3ef5d99c5b37b8fb , p13 );
01020     // -- Remez coefficients for cotan -------------------------------    
01021     _math_setdouble(  0x3fd5555555555555 , q0  );
01022     _math_setdouble(  0x3f96c16c16c16c16 , q1  );
01023     _math_setdouble(  0x3f61566abc011734 , q2  );
01024     _math_setdouble(  0x3f2bbd7793321936 , q3  );
01025     _math_setdouble(  0x3ef66a8f2d1bc68f , q4  );
01026     _math_setdouble(  0x3ec228059183e28c , q5  );
01027     _math_setdouble(  0x3e8d6dc6da8b4b97 , q6  );
01028     _math_setdouble(  0x3e57d86d9f6cba62 , q7  );
01029     _math_setdouble(  0x3e23722fc10fb082 , q8  );
01030     _math_setdouble(  0x3ded3f62bcb56407 , q9  );
01031     _math_setdouble(  0x3dc2113add876256 , q10 );
01032 
01033     zu.z = magic2 + twooverpi * x;
01034     f = zu.z - magic2;
01035     y = x - f * pihalflead;
01036     y = y - f * pihalftrail1;
01037     y = y - f * pihalftrail2;
01038     
01039     y2 = y * y;
01040     y3 = y * y2;
01041     y4 = y2 * y2;
01042     
01043     invy = y;
01044     where ( invy == 0.0) {
01045        invy = 1.0;
01046     }
01047     invy = 1.0 / invy;
01048     
01049     Pp = p13;
01050     Pn = p12;
01051     Pp = y4*Pp + p11;
01052     Pn = y4*Pn + p10;
01053     Pp = y4*Pp + p9;
01054     Pn = y4*Pn + p8;
01055     Pp = y4*Pp + p7;
01056     Pn = y4*Pn + p6;
01057     Pp = y4*Pp + p5;
01058     Pn = y4*Pn + p4;
01059     Pp = y4*Pp + p3;
01060     Pn = y4*Pn + p2;
01061     Pp = y4*Pp + p1;
01062     Pn = y4*Pn + p0;
01063     P = y + y3 *(Pn+y2*Pp);
01064     
01065     Qn =  q10;
01066     Qp =  q9;
01067     Qn = y4*Qn + q8;
01068     Qp = y4*Qp + q7;
01069     Qn = y4*Qn + q6;
01070     Qp = y4*Qp + q5;
01071     Qn = y4*Qn + q4;
01072     Qp = y4*Qp + q3;
01073     Qn = y4*Qn + q2;
01074     Qp = y4*Qp + q1;
01075     Qn = y4*Qn + q0;
01076     Q = Qn + y2 * Qp;
01077 
01078     /* -----------------------------------------
01079     !! get the module 2 of f  The modul is get 
01080     !! over z that has mantissa f+0x7fff...f
01081     !! That means k = (f%2 + 1)%2
01082     !! f = 0 -> k= 1 
01083     !! f = 1 -> k= 0 
01084     !! ---------------------------------------*/    
01085     k = 0x1;
01086     k = zu.zint & k;
01087     
01088     where ( k  ==  0 ) {
01089         P = Q * y  - invy;
01090     }
01091 
01092     return P;
01093 
01094 }
01095 
01096 
01097 /*===================================================================
01098 !! Kernel function for the computation Atan(x) for |x|<1
01099 !!
01100 !! Res = Atan(x) = x + x^3 P22(x^2) 
01101 !!
01102 !! Where P22(y) is a degree 22 minimax polinomial approximating
01103 !! 
01104 !!        Atan(Sqrt[y])-Sqrt[y]
01105 !! P[y] = ---------------------
01106 !!            Sqrt[y] y
01107 !!
01108 !! degree = 22 
01109 !! [a,b]  = [0,1.0]
01110 !! w(y)   = y^3 / (Atan[Sqrt[y]]). 
01111 !! N Iter = 20000 
01112 !! Max Error = 2.38*10^-20  
01113 !!
01114 !!=================================================================*/
01115 
01116 math_inline double atan_k( double xx ) {
01117     register double x, x2, x3, P;
01118     register double r2, r4, Pa, Pb, Pc, Pd;
01119     register double p0, p1, p2, p3, p4, p5, p6, p7, p8, p9;
01120     register double p10, p11, p12, p13, p14, p15, p16, p17, p18, p19;
01121     register double p20, p21, p22;
01122 
01123     // -- Remez coefficients for atan -------------------------------
01124     _math_setdouble(  0xbfd5555555555555 , p0  );
01125     _math_setdouble(  0x3fc9999999999971 , p1  );
01126     _math_setdouble(  0xbfc2492492490f58 , p2  );
01127     _math_setdouble(  0x3fbc71c71c68e470 , p3  );
01128     _math_setdouble(  0xbfb745d173541a68 , p4  );
01129     _math_setdouble(  0x3fb3b13affee80cf , p5  );
01130     _math_setdouble(  0xbfb111100b7ee084 , p6  );
01131     _math_setdouble(  0x3fae1e0a5cf4626e , p7  );
01132     _math_setdouble(  0xbfaaf1f6218828be , p8  );
01133     _math_setdouble(  0x3fa85e4efb1caacf , p9  );
01134     _math_setdouble(  0xbfa634430a602ac3 , p10 );
01135     _math_setdouble(  0x3fa446067f9429b9 , p11 );
01136     _math_setdouble(  0xbfa25977aa870234 , p12 );
01137     _math_setdouble(  0x3fa0269900f0cc1e , p13 );
01138     _math_setdouble(  0xbf9ae16c1b259e80 , p14 );
01139     _math_setdouble(  0x3f946df0d7c219b5 , p15 );
01140     _math_setdouble(  0xbf8b503895880e16 , p16 );
01141     _math_setdouble(  0x3f7ee47c1bf074f6 , p17 );
01142     _math_setdouble(  0xbf6c59076eef60d7 , p18 );
01143     _math_setdouble(  0x3f54123312f3c886 , p19 );
01144     _math_setdouble(  0xbf346fc2146a8776 , p20 );
01145     _math_setdouble(  0x3f0a81635a5fa23b , p21 );
01146     _math_setdouble(  0xbed063c89c3fdaca , p22 );
01147     
01148     x  = xx;
01149     x2 = x * x;
01150     x3 = x * x2;
01151     r2 = x2 * x2;
01152     r4 = r2 * r2;
01153     
01154     Pa = p20;
01155     Pa = r4 * Pa + p16;
01156     Pa = r4 * Pa + p12;
01157     Pa = r4 * Pa + p8;
01158     Pa = r4 * Pa + p4;
01159     Pa = r4 * Pa + p0;
01160     
01161     Pb = p21;
01162     Pb = r4 * Pb + p17;
01163     Pb = r4 * Pb + p13;
01164     Pb = r4 * Pb + p9;
01165     Pb = r4 * Pb + p5;
01166     Pb = r4 * Pb + p1;
01167     
01168     Pc =  p22;
01169     Pc = r4 * Pc + p18;
01170     Pc = r4 * Pc + p14;
01171     Pc = r4 * Pc + p10;
01172     Pc = r4 * Pc + p6;
01173     Pc = r4 * Pc + p2;
01174     
01175     Pd = p19;
01176     Pd = r4 * Pd + p15;
01177     Pd = r4 * Pd + p11;
01178     Pd = r4 * Pd + p7;
01179     Pd = r4 * Pd + p3;
01180     
01181     P = Pa + x2 * Pb + r2 * (Pc + x2 * Pd);
01182     P = x + x3 *P;
01183 
01184     return P;
01185 }
01186 
01187 /* ===================================================================
01188 !! 
01189 !! The computation of Atan(x) is compute according to
01190 !!
01191 !!  1 < x      : Atan(x) =  pi/2 - Atan_k(1/x)
01192 !! -1 < x <  1 : Atan(x) = Atan_k(x)
01193 !!      x < -1 : Atan(x) = -pi/2 - Atan_k(1/x)
01194 !! 
01195 !! Where P22(y) is a degree 22 minimax polinomial approximating
01196 !! (Atan(x)-x)/x^3 in [-1 1]
01197 !!
01198 !! =================================================================*/
01199 
01200 math_inline double atan( double x ) { 
01201     register double xx, absx, y, res;
01202     register double pihalflead, pihalftrail;
01203 
01204     _math_setdouble(  0x3ff9220000000000 , pihalflead  );
01205     _math_setdouble(  0xbed2aeef4b9ee59e , pihalftrail );
01206 
01207     xx   = x;
01208     absx = xx;
01209     where ( xx < 0.0 ) {
01210       absx = - absx;
01211     }
01212 
01213     y = absx;
01214     where ( absx > 1.0 ) {
01215       y = 1.0 / absx;
01216     }
01217     
01218     res = atan_k( y );
01219     
01220     where ( absx > 1.0 ) {
01221       res = pihalftrail - res;
01222       res = pihalflead  + res;
01223     }
01224     where ( xx < 0.0 ) {
01225       res = - res;
01226     }
01227  
01228     return res;
01229 }
01230 
01231 
01232 /* -----------------------------------------------------------------
01233 !!
01234 !! Main part: Computation of Asin(x) where -0.5 < x < 0.5
01235 !! 
01236 !! Res = Asin(x) = x + x^3 P19(x^2) 
01237 !!
01238 !! Where P19(y) is a degree 19 minimax polinomial approximating
01239 !! 
01240 !!        Asin(Sqrt[y])-Sqrt[y]
01241 !! P[y] = ---------------------
01242 !!            Sqrt[y] y
01243 !!
01244 !! degree = 19
01245 !! [a,b]  = [0,0.5]
01246 !! w(y)   = 1/(Asin[y]). 
01247 !! N Iter = 20000 
01248 !! Max Error = 4.41*10^-19  
01249 !!
01250 !! ---------------------------------------------------------------*/
01251 
01252 math_inline double asin_k( double xx ) { 
01253     register double x, x2, x3, P;
01254     register double r2, r4, Pa, Pb, Pc, Pd;
01255     register double p0, p1, p2, p3, p4, p5, p6, p7, p8, p9;
01256     register double p10, p11, p12, p13, p14, p15, p16, p17, p18, p19;
01257 
01258     // -- Remez coefficients for asin -------------------------------
01259     _math_setdouble(  0x3fc5555555555555 , p0  );
01260     _math_setdouble(  0x3fb3333333333ff8 , p1  );
01261     _math_setdouble(  0x3fa6db6db6c8299f , p2  );
01262     _math_setdouble(  0x3f9f1c71d2cb0419 , p3  );
01263     _math_setdouble(  0x3f96e8b839a6eb1f , p4  );
01264     _math_setdouble(  0x3f91c5217cd11e53 , p5  );
01265     _math_setdouble(  0x3f8c91ddc9cccb8b , p6  );
01266     _math_setdouble(  0x3f880fff7f9aa201 , p7  );
01267     _math_setdouble(  0x3f7ff0699c7911d9 , p8  );
01268     _math_setdouble(  0x3f97c8c548d85470 , p9  );
01269     _math_setdouble(  0xbfb43c911218c604 , p10 );
01270     _math_setdouble(  0x3fd968af9c41272b , p11 );
01271     _math_setdouble(  0xbff5ecfed8eb21be , p12 );
01272     _math_setdouble(  0x400e2c596eac2542 , p13 );
01273     _math_setdouble(  0xc01fb74a405ddd3f , p14 );
01274     _math_setdouble(  0x4029446d2f84e0c3 , p15 );
01275     _math_setdouble(  0xc02d7056e867daf6 , p16 );
01276     _math_setdouble(  0x4027cbd4a391e704 , p17 );
01277     _math_setdouble(  0xc017e8e8f8f0fb8c , p18 );
01278     _math_setdouble(  0x3ff6d9ee9188998b , p19 );
01279     
01280     x  = xx;
01281     x2 = x * x;
01282     x3 = x * x2;
01283     
01284     r2 = x2 * x2;
01285     r4 = r2 * r2;
01286     
01287     Pa = p16;
01288     Pa = r4 * Pa + p12;
01289     Pa = r4 * Pa + p8;
01290     Pa = r4 * Pa + p4;
01291     Pa = r4 * Pa + p0;
01292     
01293     Pb = p17;
01294     Pb = r4 * Pb + p13;
01295     Pb = r4 * Pb + p9;
01296     Pb = r4 * Pb + p5;
01297     Pb = r4 * Pb + p1;
01298     
01299     Pc = p18;
01300     Pc = r4 * Pc + p14;
01301     Pc = r4 * Pc + p10;
01302     Pc = r4 * Pc + p6;
01303     Pc = r4 * Pc + p2;
01304     
01305     Pd = p19;
01306     Pd = r4 * Pd + p15;
01307     Pd = r4 * Pd + p11;
01308     Pd = r4 * Pd + p7;
01309     Pd = r4 * Pd + p3;
01310     
01311     P = Pa + x2 * Pb + r2 * (Pc + x2 * Pd);
01312     
01313     P = x + x3 * P;
01314 
01315     return P;
01316 }
01317 
01318 /*-----------------------------------------------------------------
01319 !!
01320 !! The ArcSin[x] function is computed in terms of the ArcSin[y]
01321 !! function (with |y|<0.5) according to the following reduction 
01322 !! formula:
01323 !!
01324 !!
01325 !! ( 0.5 < x )     ==>  Asin[x] =  pi/2  - 2 Asin[sqrt[(1-x)/2]]
01326 !! ( -0.5 < x <.5) ==>  Asin[x] = Asin[x]
01327 !! ( x < -0.5 )    ==>  Asin[x] = - pi/2 + 2 Asin[sqrt[(1+x)/2]] )
01328 !! 
01329 !!---------------------------------------------------------------*/
01330 
01331 math_inline double asin( double x ) { 
01332     register double xx, y, absx, res;
01333     register double half, two;
01334     register double pihalflead, pihalftrail;
01335 
01336     _math_setdouble(  0x3ff9220000000000 , pihalflead  );
01337     _math_setdouble(  0xbed2aeef4b9ee59e , pihalftrail );
01338 
01339     half = 0.5;
01340     two  = 1.0 + 1.0;
01341     
01342     xx  = x;
01343     absx = xx;
01344     where ( xx < 0.0 ) {
01345       absx = - absx;
01346     }
01347     y = absx ;
01348     where ( absx > half ) {
01349       y = half - half * y;
01350       y = sqrt(y);
01351     }
01352     
01353     res = asin_k(y);
01354     
01355     where ( absx > half ) {
01356       res = pihalftrail - two * res;
01357       res = pihalflead  + res;
01358     }
01359     where ( xx < 0.0 ) {
01360       res = - res;
01361     }
01362  
01363     return res;
01364 }
01365 
01366 /*-----------------------------------------------------------------
01367 !! The ArcCos[x] function is computed in terms of the ArcSin[y]
01368 !! function (with |y|<0.5) according to the following reduction 
01369 !! formula
01370 !!
01371 !! ( 0.5 < x )     ==>  Acos[x] = 2 Asin[sqrt[(1-x)/2]]
01372 !! ( -0.5 < x <.5) ==>  Acos[x] = pi/2 - Asin[x]
01373 !! ( x < -0.5 )    ==>  Acos[x] = 2 (pi/2 - Asin[sqrt[(1+x)/2]] )
01374 !!---------------------------------------------------------------*/
01375 math_inline double acos( double x ) {
01376     register double xx, y, absx, res;
01377     register double half, two;
01378     register double pihalflead, pihalftrail;
01379 
01380     _math_setdouble(  0x3ff9220000000000 , pihalflead  );
01381     _math_setdouble(  0xbed2aeef4b9ee59e , pihalftrail );
01382 
01383     half = 0.5;
01384     two  = 1.0 + 1.0;
01385     
01386     xx   =x;
01387     absx = xx;
01388     where ( xx < 0.0 ) {
01389       absx = - absx;
01390     }
01391     y = absx;
01392     where ( absx > half ) {
01393       y = half - half * absx;
01394       y = sqrt(y);
01395     }
01396     
01397     res = asin_k(y);
01398     
01399     where ( xx < 0.0 ) {
01400       res = - res;
01401     }
01402     
01403     where ( absx > half ) {
01404       res = two * res;
01405     }
01406     where ( absx <= half ) {
01407       res = pihalftrail - res;
01408       res = pihalflead  + res;
01409     }
01410     where ( xx + half < 0.0) {
01411       res = two * pihalftrail + res;
01412       res = two * pihalflead  + res;
01413     }
01414 
01415     return res;
01416 }
01417 
01418 
01419 #undef _math_setdouble
01420 
01421 #endif

Generated on Fri Jul 14 10:51:31 2006 for nlibc by doxygen 1.3.5