double fd_y0(double x) /* wrapper fd_y0 */ { double z, s,c,ss,cc,u,v; int hx,ix,lx; hx = FD_HI(x); ix = 0x7fffffff&hx; lx = FD_LO(x); /* Y0(NaN) is NaN, fd_y0(-inf) is Nan, fd_y0(inf) is 0 */ if(ix>=0x7ff00000) return gD( one, gA(x, gM(x,x))); if((ix|lx)==0) return gD(-one, zero); if(hx<0) return gD(zero,zero); if(ix >= 0x40000000) { /* |x| >= 2.0 */ /* fd_y0(x) = fd_sqrt(2/(pi*x))*(p0(x)*fd_sin(x0)+q0(x)*fd_cos(x0)) * where x0 = x-pi/4 * Better formula: * fd_cos(x0) = fd_cos(x)fd_cos(pi/4)+fd_sin(x)fd_sin(pi/4) * = 1/fd_sqrt(2) * (fd_sin(x) + fd_cos(x)) * fd_sin(x0) = fd_sin(x)fd_cos(3pi/4)-fd_cos(x)fd_sin(3pi/4) * = 1/fd_sqrt(2) * (fd_sin(x) - fd_cos(x)) * To avoid cancellation, use * fd_sin(x) +- fd_cos(x) = -fd_cos(2x)/(fd_sin(x) -+ fd_cos(x)) * to compute the worse one. */ s = fd_sin(x); c = fd_cos(x); ss = gS(s,c); cc = gA(s,c); /* * fd_j0(x) = 1/fd_sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / fd_sqrt(x) * fd_y0(x) = 1/fd_sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / fd_sqrt(x) */ if(ix<0x7fe00000) { /* make sure x+x not overflow */ z = -fd_cos(gA(x,x)); if (gM(s,c) < zero) cc = gD(z,ss); else ss = gD(z,cc); } if(ix>0x48000000) z = gD(gM(invsqrtpi,ss), gSqrt(x)); else { u = pzero(x); v = qzero(x); z = gD(gM(invsqrtpi, gA(gM(u,ss), gM(v,cc))), gSqrt(x)); } return z; } if(ix<=0x3e400000) { /* x < 2**-27 */ return gA(u00, gM(tpi, fd_log(x))); } z = gM(x,x); u = gA(u00, gM(z,gA(u01, gM(z,gA(u02, gM(z,gA(u03, gM(z,gA(u04, gM(z,gA(u05, gM(z,u06)))))))))))); v = gA(one, gM(z,gA(v01, gM(z,gA(v02, gM(z,gA(v03, gM(z,v04)))))))); return(gD(u,v) + gM(tpi,gM(fd_j0(x), fd_log(x)))); }
static JSBool math_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { jsdouble x, z; if (!js_ValueToNumber(cx, argv[0], &x)) return JS_FALSE; z = fd_log(x); return js_NewNumberValue(cx, z, rval); }