/* * dawson.i * Dawson's integral and error functions after SLATEC */ func dawson (x) /* DOCUMENT dawson(x) * return Dawson's integral, exp(-x^2)*integral[0 to x](exp(t^2)*dt) * maximum is dawson(0.9241388730) = 0.5410442246 * inflection point is dawson(1.5019752682) = 0.4276866160 * SEE ALSO: erf, erfc */ { { local mask1,mask2,mask3,xx,yy; } y = abs(x); if (any_in(,y,1., mask1, yy, x,xx)) d1 = xx * (0.75 + _cheby_eval(_dawson_1, 2.*yy*yy-1.)); if (any_in(1.,y,4., mask2, yy, x,xx)) d2 = xx * (0.25 + _cheby_eval(_dawson_2, 0.125*yy*yy-1.)); if (any_in(4.,y,, mask3, yy, x,xx)) d3 = (0.50 + _cheby_eval(_dawson_3, 32./(yy*yy)-1.)) / xx; return merge_n(d1,mask1, d2,mask2, d3,mask3); } _dawson_1 = [-.006351734375145949, -.229407147967738690, .022130500939084764, -.001549265453892985, .000084973277156849, -.000003828266270972, .000000146285480625, -.000000004851982381, .000000000142146357, -.000000000003728836, .000000000000088549, -.000000000000001920, .000000000000000038]; _dawson_2 = [-.056886544105215527, -.318113469961681310, .208738454136422370, -.124754099137791310, .067869305186676777, -.033659144895270940, .015260781271987972, -.006348370962596214, .002432674092074852, -.000862195414910650, .000283765733363216, -.000087057549874170, .000024986849985481, -.000006731928676416, .000001707857878557, -.000000409175512264, .000000092828292216, -.000000019991403610, .000000004096349064, -.000000000800324095, .000000000149385031, -.000000000026687999, .000000000004571221, -.000000000000751873, .000000000000118931, -.000000000000018116, .000000000000002661, -.000000000000000377, .000000000000000051]; _dawson_3 = [ .01690485637765704, .00868325227840695, .00024248640424177, .00001261182399572, .00000106645331463, .00000013581597947, .00000002171042356, .00000000286701050, -.00000000019013363, -.00000000030977804, -.00000000010294148, -.00000000000626035, .00000000000856313, .00000000000303304, -.00000000000025236, -.00000000000042106, -.00000000000004431, .00000000000004911, .00000000000001235, -.00000000000000578, -.00000000000000228, .00000000000000076, .00000000000000038, -.00000000000000011, -.00000000000000006, .00000000000000002]; func erf (x) /* DOCUMENT erf(x) * return erf(x), 2./sqrt(pi) * integral[0 to x](exp(-t^2)*dt) * SEE ALSO: erfc, dawson */ { { local mask1,mask2,mask3,mask4,xx,yy,zz; } y = abs(x); if (any_in(,y,1., mask1, yy, x,xx)) e1 = xx * (1.0 + _cheby_eval(_erf_1, 2.*yy*yy-1.)); if (any_in(1.,y,, mask2, yy, x,xx)) { z = yy*yy; yy = exp(-z)/yy; if (any_in(,z,4., mask3, zz, yy,y)) e3 = y * (0.5 + _cheby_eval(_erfc_1, (8./zz-5.)/3.)); if (any_in(4.,z,, mask4, zz, yy,y)) e4 = y * (0.5 + _cheby_eval(_erfc_2, 8./zz-1.)); e2 = sign(xx) * (1.0 - merge_n(e3,mask3, e4,mask4)); } return merge_n(e1,mask1, e2,mask2); } func erfc (x) /* DOCUMENT erfc(x) * return erfc(x), 2./sqrt(pi) * integral[x to infinity](exp(-t^2)*dt) * SEE ALSO: erf, dawson */ { { local mask1,mask2,mask3,mask4,xx,yy,zz; } y = abs(x); if (any_in(,y,1., mask1, yy, x,xx)) e1 = 1.0 - xx * (1.0 + _cheby_eval(_erf_1, 2.*yy*yy-1.)); if (any_in(1.,y,, mask2, yy, x,xx)) { z = yy*yy; yy = exp(-z)/yy; if (any_in(,z,4., mask3, zz, yy,y)) e3 = y * (0.5 + _cheby_eval(_erfc_1, (8./zz-5.)/3.)); if (any_in(4.,z,, mask4, zz, yy,y)) e4 = y * (0.5 + _cheby_eval(_erfc_2, 8./zz-1.)); e2 = 2.*(xx<0.) + sign(xx)*merge_n(e3,mask3, e4,mask4); } return merge_n(e1,mask1, e2,mask2); } _erf_1 = [-.049046121234691808, -.142261205103713640, .010035582187599796, -.000576876469976748, .000027419931252196, -.000001104317550734, .000000038488755420, -.000000001180858253, .000000000032334215, -.000000000000799101, .000000000000017990, -.000000000000000371, .000000000000000007]; _erfc_1 = [-.069601346602309501, -.041101339362620893, .003914495866689626, -.000490639565054897, .000071574790013770, -.000011530716341312, .000001994670590201, -.000000364266647159, .000000069443726100, -.000000013712209021, .000000002788389661, -.000000000581416472, .000000000123892049, -.000000000026906391, .000000000005942614, -.000000000001332386, .000000000000302804, -.000000000000069666, .000000000000016208, -.000000000000003809, .000000000000000904, -.000000000000000216, .000000000000000052]; _erfc_2 = [ .071517931020292500, -.026532434337606719, .001711153977920853, -.000163751663458512, .000019871293500549, -.000002843712412769, .000000460616130901, -.000000082277530261, .000000015921418724, -.000000003295071356, .000000000722343973, -.000000000166485584, .000000000040103931, -.000000000010048164, .000000000002608272, -.000000000000699105, .000000000000192946, -.000000000000054704, .000000000000015901, -.000000000000004729, .000000000000001432, -.000000000000000439, .000000000000000138, -.000000000000000048]; func _cheby_eval(cs, x) { n = numberof(cs); b0 = b1 = 0.; x *= 2.; for (i=0 ; i<n ; ++i) { b2 = b1; b1 = b0; b0 = x*b1 - b2 + cs(n-i); } return 0.5*(b0-b2); } func any_in (left,x,right, &mask, &xx, a,&aa, b,&bb, c,&cc) /* DOCUMENT any_in(left,x,right, mask, xx, a,aa, b,bb, c,cc * return the number of elements of the array X which are in the * interval LEFT < X <= RIGHT. Also return MASK, which has the * shape of X and is 1 where X is in the interval and 0 otherwise, * and XX = X(where(MASK)). Up to three optional arrays A, B, and C * of the same shape as X may be supplied; the arrays AA, BB, and CC * analogous to XX are returned. LEFT or RIGHT may be [] for the * interval to extend to infinity on the corresponding side. * LEFT and/or RIGHT may be arrays as long as they are conformable * with X. * SEE ALSO: merge_n, merge */ { if (is_void(left)) mask = array(1n, dimsof(x)); else mask = (x>left); if (!is_void(right)) mask &= (x<=right); list = where(mask); n = numberof(list); if (n) { xx = x(list); if (!is_void(a)) { aa = a(list); if (!is_void(b)) { bb = b(list); if (!is_void(c)) cc = c(list); } } } return n; } func merge_n (val,mask, ..) /* DOCUMENT merge_n(val1,mask1, val2,mask2, ...) * return array with shape of MASKi (which must all have same shape) * and values VALi where MASKi is true. Unspecified values will be * zero; the data type of the result is the data type of the first * non-nil VALi. Each VALi must be a 1D array of length sum(MASKi!=0). * SEE ALSO: any_in, merge */ { rslt = dimsof(mask); while (is_void(val)) { val = next_arg(); mask = next_arg(); if (is_void(mask)) return array(0., rslt); } rslt = array(structof(val), rslt); for (;;) { rslt(where(mask)) = val; do { val = next_arg(); mask = next_arg(); if (is_void(mask)) return rslt; } while (is_void(val)); } }