1: 
    2:     3:     4:     5:     6:     7:     8:     9:    10:    11: 
   12: 
   13:    14:    15:    16:    17:    18:    19:    20:    21:    22:    23:    24:    25:    26:    27:    28:    29:    30:    31:    32:    33:    34:    35:    36:    37:    38:    39:    40:    41:    42:    43:    44:    45:    46:    47:    48:    49:    50:    51:    52:    53:    54:    55:    56: 
   57: 
   58: #include "math.h"
   59: #include "math_private.h"
   60: 
   61: static double pone(double), qone(double);
   62: 
   63: static const double 
   64: huge    = 1e300,
   65: one     = 1.0,
   66: invsqrtpi=  5.64189583547756279280e-01, 
   67: tpi      =  6.36619772367581382433e-01, 
   68:         
   69: r00  = -6.25000000000000000000e-02, 
   70: r01  =  1.40705666955189706048e-03, 
   71: r02  = -1.59955631084035597520e-05, 
   72: r03  =  4.96727999609584448412e-08, 
   73: s01  =  1.91537599538363460805e-02, 
   74: s02  =  1.85946785588630915560e-04, 
   75: s03  =  1.17718464042623683263e-06, 
   76: s04  =  5.04636257076217042715e-09, 
   77: s05  =  1.23542274426137913908e-11; 
   78: 
   79: static const double zero    = 0.0;
   80: 
   81: double
   82: j1(double x) 
   83: {
   84:         double z, s,c,ss,cc,r,u,v,y;
   85:         int32_t hx,ix;
   86: 
   87:         GET_HIGH_WORD(hx,x);
   88:         ix = hx&0x7fffffff;
   89:         if(ix>=0x7ff00000) return one/x;
   90:         y = fabs(x);
   91:         if(ix >= 0x40000000) { 
   92:                 s = sin(y);
   93:                 c = cos(y);
   94:                 ss = -s-c;
   95:                 cc = s-c;
   96:                 if(ix<0x7fe00000) {  
   97:                     z = cos(y+y);
   98:                     if ((s*c)>zero) cc = z/ss;
   99:                     else          ss = z/cc;
  100:                 }
  101:           102:   103:   104: 
  105:                 if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(y);
  106:                 else {
  107:                     u = pone(y); v = qone(y);
  108:                     z = invsqrtpi*(u*cc-v*ss)/sqrt(y);
  109:                 }
  110:                 if(hx<0) return -z;
  111:                 else           return  z;
  112:         }
  113:         if(ix<0x3e400000) {    
  114:             if(huge+x>one) return 0.5*x;
  115:         }
  116:         z = x*x;
  117:         r =  z*(r00+z*(r01+z*(r02+z*r03)));
  118:         s =  one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
  119:         r *= x;
  120:         return(x*0.5+r/s);
  121: }
  122: 
  123: static const double U0[5] = {
  124:  -1.96057090646238940668e-01, 
  125:   5.04438716639811282616e-02, 
  126:  -1.91256895875763547298e-03, 
  127:   2.35252600561610495928e-05, 
  128:  -9.19099158039878874504e-08, 
  129: };
  130: static const double V0[5] = {
  131:   1.99167318236649903973e-02, 
  132:   2.02552581025135171496e-04, 
  133:   1.35608801097516229404e-06, 
  134:   6.22741452364621501295e-09, 
  135:   1.66559246207992079114e-11, 
  136: };
  137: 
  138: double
  139: y1(double x) 
  140: {
  141:         double z, s,c,ss,cc,u,v;
  142:         int32_t hx,ix,lx;
  143: 
  144:         EXTRACT_WORDS(hx,lx,x);
  145:         ix = 0x7fffffff&hx;
  146:     
  147:         if(ix>=0x7ff00000) return  one/(x+x*x); 
  148:         if((ix|lx)==0) return -one/zero;
  149:         if(hx<0) return zero/zero;
  150:         if(ix >= 0x40000000) {  
  151:                 s = sin(x);
  152:                 c = cos(x);
  153:                 ss = -s-c;
  154:                 cc = s-c;
  155:                 if(ix<0x7fe00000) {  
  156:                     z = cos(x+x);
  157:                     if ((s*c)>zero) cc = z/ss;
  158:                     else            ss = z/cc;
  159:                 }
  160:           161:   162:   163:   164:   165:   166:   167:   168:   169:   170: 
  171:                 if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x);
  172:                 else {
  173:                     u = pone(x); v = qone(x);
  174:                     z = invsqrtpi*(u*ss+v*cc)/sqrt(x);
  175:                 }
  176:                 return z;
  177:         } 
  178:         if(ix<=0x3c900000) {    
  179:             return(-tpi/x);
  180:         } 
  181:         z = x*x;
  182:         u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
  183:         v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
  184:         return(x*(u/v) + tpi*(j1(x)*log(x)-one/x));
  185: }
  186: 
  187:   188:   189:   190:   191:   192:   193:   194:   195: 
  196: 
  197: static const double pr8[6] = { 
  198:   0.00000000000000000000e+00, 
  199:   1.17187499999988647970e-01, 
  200:   1.32394806593073575129e+01, 
  201:   4.12051854307378562225e+02, 
  202:   3.87474538913960532227e+03, 
  203:   7.91447954031891731574e+03, 
  204: };
  205: static const double ps8[5] = {
  206:   1.14207370375678408436e+02, 
  207:   3.65093083420853463394e+03, 
  208:   3.69562060269033463555e+04, 
  209:   9.76027935934950801311e+04, 
  210:   3.08042720627888811578e+04, 
  211: };
  212: 
  213: static const double pr5[6] = { 
  214:   1.31990519556243522749e-11, 
  215:   1.17187493190614097638e-01, 
  216:   6.80275127868432871736e+00, 
  217:   1.08308182990189109773e+02, 
  218:   5.17636139533199752805e+02, 
  219:   5.28715201363337541807e+02, 
  220: };
  221: static const double ps5[5] = {
  222:   5.92805987221131331921e+01, 
  223:   9.91401418733614377743e+02, 
  224:   5.35326695291487976647e+03, 
  225:   7.84469031749551231769e+03, 
  226:   1.50404688810361062679e+03, 
  227: };
  228: 
  229: static const double pr3[6] = {
  230:   3.02503916137373618024e-09, 
  231:   1.17186865567253592491e-01, 
  232:   3.93297750033315640650e+00, 
  233:   3.51194035591636932736e+01, 
  234:   9.10550110750781271918e+01, 
  235:   4.85590685197364919645e+01, 
  236: };
  237: static const double ps3[5] = {
  238:   3.47913095001251519989e+01, 
  239:   3.36762458747825746741e+02, 
  240:   1.04687139975775130551e+03, 
  241:   8.90811346398256432622e+02, 
  242:   1.03787932439639277504e+02, 
  243: };
  244: 
  245: static const double pr2[6] = {
  246:   1.07710830106873743082e-07, 
  247:   1.17176219462683348094e-01, 
  248:   2.36851496667608785174e+00, 
  249:   1.22426109148261232917e+01, 
  250:   1.76939711271687727390e+01, 
  251:   5.07352312588818499250e+00, 
  252: };
  253: static const double ps2[5] = {
  254:   2.14364859363821409488e+01, 
  255:   1.25290227168402751090e+02, 
  256:   2.32276469057162813669e+02, 
  257:   1.17679373287147100768e+02, 
  258:   8.36463893371618283368e+00, 
  259: };
  260: 
  261: static double
  262: pone(double x)
  263: {
  264:         const double *p,*q;
  265:         double z,r,s;
  266:         int32_t ix;
  267:         GET_HIGH_WORD(ix,x);
  268:         ix &= 0x7fffffff;
  269:         if(ix>=0x40200000)     {p = pr8; q= ps8;}
  270:         else if(ix>=0x40122E8B){p = pr5; q= ps5;}
  271:         else if(ix>=0x4006DB6D){p = pr3; q= ps3;}
  272:         else if(ix>=0x40000000){p = pr2; q= ps2;}
  273:         z = one/(x*x);
  274:         r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
  275:         s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
  276:         return one+ r/s;
  277: }
  278:                 
  279: 
  280:   281:   282:   283:   284:   285:   286:   287:   288: 
  289: 
  290: static const double qr8[6] = { 
  291:   0.00000000000000000000e+00, 
  292:  -1.02539062499992714161e-01, 
  293:  -1.62717534544589987888e+01, 
  294:  -7.59601722513950107896e+02, 
  295:  -1.18498066702429587167e+04, 
  296:  -4.84385124285750353010e+04, 
  297: };
  298: static const double qs8[6] = {
  299:   1.61395369700722909556e+02, 
  300:   7.82538599923348465381e+03, 
  301:   1.33875336287249578163e+05, 
  302:   7.19657723683240939863e+05, 
  303:   6.66601232617776375264e+05, 
  304:  -2.94490264303834643215e+05, 
  305: };
  306: 
  307: static const double qr5[6] = { 
  308:  -2.08979931141764104297e-11, 
  309:  -1.02539050241375426231e-01, 
  310:  -8.05644828123936029840e+00, 
  311:  -1.83669607474888380239e+02, 
  312:  -1.37319376065508163265e+03, 
  313:  -2.61244440453215656817e+03, 
  314: };
  315: static const double qs5[6] = {
  316:   8.12765501384335777857e+01, 
  317:   1.99179873460485964642e+03, 
  318:   1.74684851924908907677e+04, 
  319:   4.98514270910352279316e+04, 
  320:   2.79480751638918118260e+04, 
  321:  -4.71918354795128470869e+03, 
  322: };
  323: 
  324: static const double qr3[6] = {
  325:  -5.07831226461766561369e-09, 
  326:  -1.02537829820837089745e-01, 
  327:  -4.61011581139473403113e+00, 
  328:  -5.78472216562783643212e+01, 
  329:  -2.28244540737631695038e+02, 
  330:  -2.19210128478909325622e+02, 
  331: };
  332: static const double qs3[6] = {
  333:   4.76651550323729509273e+01, 
  334:   6.73865112676699709482e+02, 
  335:   3.38015286679526343505e+03, 
  336:   5.54772909720722782367e+03, 
  337:   1.90311919338810798763e+03, 
  338:  -1.35201191444307340817e+02, 
  339: };
  340: 
  341: static const double qr2[6] = {
  342:  -1.78381727510958865572e-07, 
  343:  -1.02517042607985553460e-01, 
  344:  -2.75220568278187460720e+00, 
  345:  -1.96636162643703720221e+01, 
  346:  -4.23253133372830490089e+01, 
  347:  -2.13719211703704061733e+01, 
  348: };
  349: static const double qs2[6] = {
  350:   2.95333629060523854548e+01, 
  351:   2.52981549982190529136e+02, 
  352:   7.57502834868645436472e+02, 
  353:   7.39393205320467245656e+02, 
  354:   1.55949003336666123687e+02, 
  355:  -4.95949898822628210127e+00, 
  356: };
  357: 
  358: static double
  359: qone(double x)
  360: {
  361:         const double *p,*q;
  362:         double  s,r,z;
  363:         int32_t ix;
  364:         GET_HIGH_WORD(ix,x);
  365:         ix &= 0x7fffffff;
  366:         if(ix>=0x40200000)     {p = qr8; q= qs8;}
  367:         else if(ix>=0x40122E8B){p = qr5; q= qs5;}
  368:         else if(ix>=0x4006DB6D){p = qr3; q= qs3;}
  369:         else if(ix>=0x40000000){p = qr2; q= qs2;}
  370:         z = one/(x*x);
  371:         r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
  372:         s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
  373:         return (.375 + r/s)/x;
  374: }