2 * special_functions - special functions (e.g.: gamma, zeta, psi)
4 * Copyright (C) 2013 Christoph Zurnieden
6 * special_functions is open software; you can redistribute it and/or modify
7 * it under the terms of the version 2.1 of the GNU Lesser General Public
8 * License as published by the Free Software Foundation.
10 * special_functions is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
13 * General Public License for more details.
15 * A copy of version 2.1 of the GNU Lesser General Public License is
16 * distributed with calc under the filename COPYING-LGPL. You should have
17 * received a copy with calc; if not, write to Free Software Foundation, Inc.
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * @(#) $Revision: 30.4 $
21 * @(#) $Id: specialfunctions.cal,v 30.4 2013/08/11 08:41:38 chongo Exp $
22 * @(#) $Source: /usr/local/src/bin/calc/cal/RCS/specialfunctions.cal,v $
24 * Under source code control: 2013/08/11 01:31:28
25 * File existed as early as: 2013
30 * hide internal function from resource debugging
32 static resource_debug_level;
33 resource_debug_level = config("resource_debug", 0);
43 zeta2(x,s) is in the extra file "zeta2.cal" because of a different license:
48 /* Not the best way, I'm afraid, but a way. */
49 return hurwitzzeta(s,1);
53 local i k m x y eps_digits eps ret;
56 One can use the Stirling series, too, which might be faster for some
57 values. The series used here converges very fast but needs a lot of
58 bernoulli numbers which are quite expensive to compute.
63 if(isint(z) && z<=0)return newerror("psi(z); z is a negative integer or 0");
65 return ( pi() * cot(pi() * (0-z) ) ) + psi0(1-z);
67 eps_digits = digits(1/epsilon());
69 R.W. Gosper has r = .41 as the relation, empirical tests showed that
70 for d<100 r = .375 is sufficient and r = .396 for d<200.
71 It does not save much time but for a long series even a little
75 k = 2 * ceil(.375 * eps_digits);
76 else if(eps_digits < 200)
77 k = 2 * ceil(.395 * eps_digits);
79 k = 2 * ceil(11/27 * eps_digits);
84 There is a chance to speed up the first partial sum with binary splitting.
85 The second partial sum is dominated by the calculation of the Bernoulli
86 numbers but can profit from binary splitting when the Bernoulli numbers are
89 for(i = 1; i <= (k/2); i++){
90 m = 1 / ( z + 2*i - 1) + 1 / ( z + 2*i -2 ) + m;
91 x = ( x + bernoulli(k-2*i+2) / (k-2*i+2) ) / y ;
93 ret = ln(z+k) - 1 / ( 2 * (z+k) ) - x - m ;
103 define polygamma(m,z)
107 http://functions.wolfram.com/GammaBetaErf/PolyGamma2/16/01/01/0002/
109 if(!isint(m))return newerror("polygamma(m,z); m not an integer");
110 if( m<0 )return newerror("polygamma(m,z); m is < 0");
112 Reflection formula not implemented yet, needs cot-differentiation
113 http://functions.wolfram.com/ElementaryFunctions/Cot/20/02/0003/
114 which is not implemented yet.
120 use factorial for m a (small) integer?
121 use lngamma for m large?
124 return (-1)* gamma(m+1) * hurwitzzeta(m+1,z)
126 return gamma(m+1) * hurwitzzeta(m+1,z);
130 Cache for the variable independent coefficients in the sum for the
135 Log-Gamma function for Re(z) > 0.
137 define __CZ__lngammarp(z)
139 local epsilon accuracy a factrl sum n ret holds_enough term;
142 accuracy = digits(int(1/epsilon)) + 3;
145 a = ceil(1.252850440912568095810522965 * accuracy);
147 epsilon(epsilon*10^(-(digits(1/epsilon)//2)));
151 if(size( __CZ__Ck) != a) {
158 __CZ__Ck[0] = sqrt(2*pi()); /* c_0*/
159 for(n = 1; n < a; n++){
160 if(holds_enough == 1){
161 __CZ__Ck[n] = (a - n)^(n - 0.5) * exp(a - n) /factrl;
166 for (n = 1; n < a; n++){
167 sum += __CZ__Ck[n]/(z+n);
170 ret = ln(sum)+(-(z+a)) + ln(z+a)*( z+0.5);
174 Will take some time for large im(z) but almost all time is spend above
178 ret = re(ret) + ln( exp( im(ret) *1i ) );
184 /* Simple lngamma with low precision*/
185 define __CZ__lngamma_lanczos(z){
186 local a k g zghalf lanczos;
188 9.9999999999999709182e-1,
189 5.7156235665862923516e1,
190 -5.9597960355475491248e1,
191 1.4136097974741747173e1,
192 -4.9191381609762019978e-1,
193 3.3994649984811888638e-5,
194 4.6523628927048576010e-5,
195 -9.8374475304879566105e-5,
196 1.5808870322491249322e-4,
197 -2.1026444172410489480e-4,
198 2.1743961811521265523e-4,
199 -1.6431810653676390482e-4,
200 8.4418223983852751308e-5,
201 -2.6190838401581411237e-5,
202 3.6899182659531626821e-6
207 for(k = 12; k >= 1; k--){
208 a += lanczos[k]/(z+k);
212 return ( ln(sqrt(2*pi())) + ln(a) -zghalf ) + (z+.5)*ln( zghalf );
215 /* Prints the Spouge coefficients actually in use. */
216 define __CZ__print__CZ__Ck(){
218 if(size(__CZ__Ck) <=1){
219 __CZ__lngammarp(2.2-2.2i);
221 for(k=0;k<size(__CZ__Ck);k++){
226 /*Kronecker delta function */
227 define kroneckerdelta(i,j){
236 /* (Pre-)Computed terms of the Stirling series */
237 static __CZ__precomp_stirling;
238 /* Number of terms in mat[0,0], precision in mat[0,1] with |z| >= mat[0,2]*/
239 static __CZ__stirling_params;
241 define __CZ__lngstirling(z,n){
242 local k head sum z2 bernterm zz;
243 head = (z-1/2)*ln(z)-z+(ln(2*pi())/2);
249 if(size(__CZ__precomp_stirling)<n){
250 __CZ__precomp_stirling = mat[n];
252 bernterm = bernoulli(2*k)/( 2*k*(2*k-1 ) );
253 __CZ__precomp_stirling[k-1] = bernterm;
260 bernterm = __CZ__precomp_stirling[k-1];
268 /* Compute error for Stirling series for "z" with "k" terms*/
270 local a b ab stirlingterm;
271 stirlingterm = bernoulli(2*k)/( 2*k*(2*k-1)*z^(2*k));
272 a = abs( stirlingterm );
273 b = (cos(.5*arg(z)^(2*k)));
275 /* a/b might round to zero */
276 if( abs(ab) < epsilon()){
277 return digits(1/epsilon());
279 return digits(1/(a/b));
283 /*Low precision lngamma(z) for testing the branch correction */
284 define lngammasmall(z){
285 local ret eps flag corr;
289 return newerror("gamma(z): z is a negative integer");
291 /* may hold up accuracy a bit longer, but YMMV */
295 return __CZ__lngamma_lanczos(z);
300 if(im(z) && im(z)<0){
305 ret = ln( pi() / sin(pi() *z ) ) -__CZ__lngamma_lanczos(1-z);
309 ret = re(ret) - pi()*1i;
310 else if( isodd(floor(abs(re(z)))) ){
311 ret = re(ret) + ( ceil(abs(z)) * pi() * 1i);
313 else if( iseven(floor(abs(re(z)))) ){
315 if(iseven(floor(abs(z)))){
316 ret = re(ret) + ( ceil(abs(z)-1/2 -1 ) * pi() * 1i);
319 ret = re(ret) + ( ceil(abs(z) -1/2 ) * pi() * 1i);
324 corr = ceil( re(z)/2 -3/4 - kroneckerdelta(im(z))/4);
325 ret = ret +2*(corr *pi() )*1i;
331 ret = (__CZ__lngamma_lanczos(z));
338 The logarithmic gamma function lngamma(z)
339 It has a different principal branch than log(gamma(z))
343 local ret eps flag increasedby Z k tmp tmp2 decdigits;
344 local corr d37 d52 termcount;
345 /* z \in \mathbf{Z}*/
347 /*The gamma-function has poles at zero and the negative integers*/
349 return newerror("lngamma(z): z is a negative integer");
351 /* may hold up accuracy a bit longer, but YMMV */
355 return __CZ__lngammarp(z);
358 else{/*if(isint(z))*/
364 /* Compute values on the real line with Spouge's algorithm*/
366 ret = __CZ__lngammarp(z);
370 /* Do the rest with the Stirling series.*/
371 /* This code repeats down under. Booh! */
372 /* Make it a positive im(z) */
377 /* Evaluate the number of terms needed */
378 decdigits = floor( digits(1/eps) );
379 /* 20 dec. digits is the default in calc(?)*/
381 /* set 20 as the minimum */
391 ret = __CZ__lngstirling(z,11);
394 for(k=0;k<increasedby;k++){
395 ret = ret - ln(Z+(k));
398 ## ret = ret + 2*pi()*1i*ceil(re(x+1)/2-3/4 );
399 /* Undo conjugate if one has been applied */
404 }/* if(decdigits <= 20) */
407 Compute the number of terms for the Stirling-sum first.
408 The error is bound by
410 |R(k,z)| <= ----------------------------------------
412 2 k (2 k - 1) z cos(0.5 arg(z) )
416 T(k) = ----------------------
418 the terms of the Stirling-sum and B(n) the n-th Bernoulli number.
420 We do know the current precision and the result of the helper
421 function __CZ__R(z,k) returns the same number as "decdigits" if
422 fed with the correct "z" and "n".
423 The largest error is near the real line, so we try Z = re(1-z).
424 If Z is small, say < 20 we increment it until it is.
425 Computing Bernoulli numbers is expensive but they are small on
426 average, get cached and because of the method used, computing
427 any Bernoulli number > 0 produces the rest as a by-product.
428 Nevertheless we could use a faster asymptotic approximation.
430 We increment the number of terms "k" in R(z,k) until the result
431 quits incrementing (it may even get smaller!). If the result is
432 still smaller than the current precision we increment "z" with
433 fixed "k" untill the result quits incrementing.
434 The results, the current precision, abs(re(z)) and "k" are kept.
436 BTW: incrementing the number of terms might be more costly than
437 incrementing "z" -- computing large Bernoulli numbers vs.
438 computing a large number of complex logarithms is a fight with
439 a hard to know result -- and that the series isn't convergent
440 is of not much help either. E.g:
450 Bernoulli(222) has a denominator of 9388 with a 254 digit
451 numerator. Computing up to 100 complex logarithms on the
454 D.E.G. Hare has found the bounds
455 |im(z)| > .37d or re(z) >= 0 and |z| > .52d
456 to be usefull to compute "z" to d digits accuracy. The numbers
457 correspond to the table above.
459 To avoid repeated expensive computation, the result is cached
460 together with the current precision. It might be a good idea
461 to keep it more permanently in a config-file?
463 d37 = decdigits * .37;
464 d52 = decdigits * .52;
465 termcount = ceil(d52);
467 if(abs(im(z))>= d37 )
468 termcount = ceil(d37);
470 termcount = ceil(d52);
476 if( abs(im(z))>= d37){
477 while(abs(z) < d52+1){
483 tmp = R(z,termcount);
485 while(tmp2 < decdigits){
488 tmp2 = R(z,termcount);
490 return newerror("lngamma(1): something happend that "
491 "should not have happend");
495 corr = ceil( re(z)/2 -3/4 - kroneckerdelta(im(z))/4);
497 ret = __CZ__lngstirling(z,termcount);
501 for(k=0;k<increasedby;k++){
502 ret = ret - ln(Z+(k));
505 /* Undo conjugate if one has been applied */
510 }/* if(decdigits <= 20){...} else */
516 /* Use Spouge's approximation on the real line */
519 ret = ln( pi() / sin(pi() *z ) ) - __CZ__lngammarp(1-z);
520 /* it is log(gamma) and im(log(even(-x))) = k\pi, therefore: */
522 ret = re(ret) - pi()*1i;
523 else if( isodd(floor(abs(re(z)))) ){
524 ret = re(ret) + ( ceil(abs(z)) * pi() * 1i);
526 else if( iseven(floor(abs(re(z)))) ){
528 if(iseven(floor(abs(z)))){
529 ret = re(ret) + ( ceil(abs(z)-1/2 -1 ) * pi() * 1i);
532 ret = re(ret) + ( ceil(abs(z) -1/2 ) * pi() * 1i);
538 /* Use Stirlinsg approximation for the rest of the complex plane */
540 /* Make it a positive im(z) */
545 /* Evaluate the number of terms needed */
546 decdigits = floor( digits(1/eps) );
548 Evaluate the correction term for the imaginary part needed because
551 D. E. G. Hare, "Computing the Principal Branch of log-Gamma",
552 Journal of Algorithms 25(2):221-236 (1997)
553 http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.84.2063
556 /* 20 dec. digits is the default in calc(?)*/
558 /* set 20 as the minimum */
564 if( im(z)>= digits(1/epsilon()) * .37){
565 while(abs(1-z) < 10){
566 /* making z more negative makes 1-z more positive. */
572 tmp = R(1-z,termcount);
577 tmp2 = R(1-z,termcount);
579 return newerror("lngamma(1): something happend "
580 "that should not have happend");
584 corr = ceil( re(z)/2 -3/4 - kroneckerdelta(im(z))/4);
587 ret = ln( pi() / sin(pi() * z ) ) - __CZ__lngstirling(1-z,termcount);
591 for(k=0;k<increasedby;k++){
592 ret = ret + ln(z+(k));
595 /* Apply correction term */
596 ret = ret +2*(corr *pi() )*1i;
597 /* Undo conjugate if one has been applied */
603 }/* if(decdigits <= 20) */
605 d37 = decdigits * .37;
606 d52 = decdigits * .52;
607 termcount = ceil(d52);
609 if(abs(im(z))>= d37 )
610 termcount = ceil(d37);
612 termcount = ceil(d52);
618 if( abs(im(z))>= d37){
619 while(abs(1-z) < d52+1){
620 /* making z more negative makes 1-z more positive. */
626 tmp = R(1-z,termcount);
628 while(tmp2 < decdigits){
631 tmp2 = R(1-z,termcount);
633 return newerror("lngamma(1): something happend that "
634 "should not have happend");
637 corr = ceil( re(z)/2 -3/4 - kroneckerdelta(im(z))/4);
639 ret = ln( pi() / sin(pi() *(z) ) ) -
640 __CZ__lngstirling(1-z,termcount);
643 for(k=0;k<increasedby;k++){
644 ret = ret + ln(z+(k));
647 /* Apply correction term */
648 ret = ret +2*((corr) *pi() )*1i;
649 /* Undo conjugate if one has been applied */
654 }/* if(decdigits <= 20){...} else */
655 }/*if(!im(z)){...} else*/
656 }/* if(re(z) > 0){...} else */
657 }/*if(isint(z)){...} else*/
660 /* Warning about large values? */
664 /* exp(log(gamma(z))) = exp(lngamma(z)), so use Spouge here?*/
668 return newerror("gamma(z): z is a negative integer");
670 /* may hold up accuracy a bit longer, but YMMV */
674 eps = epsilon(epsilon()*1e-2);
675 ret = exp(lngamma(z));
682 eps = epsilon(epsilon()*1e-2);
683 ret = exp(lngamma(z));
689 define __CZ__harmonicF( a, b ,s)
692 if( b == a) return s ;
695 return( __CZ__harmonicF(a, c,1/a) + __CZ__harmonicF(c+1, b,1/b));
700 define harmonic(limit)
703 return newerror("harmonic(limit): limit is not an integer");
705 return newerror("harmonic(limit): limit is <=0");
706 /* The binary splitting algorithm returns 0 for f(1,1,0) */
707 if( limit == 1 ) return 1;
708 return __CZ__harmonicF( 1, limit ,0);
711 /* lower incomplete gamma function */
716 define __CZ__gammainc_series_lower(a,z){
717 local k ret tmp eps fact;
723 while(abs(tmp-ret) > eps){
725 ret += (z^(k+a))/( (a+k)*fact );
735 define __CZ__gammainc_cf(a,z,n){
736 local ret k num1 denom1 num2 denom2 ;
739 ret = ((1-k)*(k-1-a))/(2*k-1+z-a+ret);
741 return ((z^a*exp(-z))/(1+z-a+ret));
745 define __CZ__gammainc_integer_a(a,z){
750 return (a-1)!*exp(-z)*sum;
754 P = precision in dec digits
758 define __CZ__endcf(n,a,z,P){
761 ret = P*ln(10)+ln(4*pi()*sqrt(n)) + re(z+(3/2-a)*ln(z)-lngamma(1-a));
762 ret = ret /( sqrt( 8*(abs(z)+re(z)) ) );
767 /* lower incomplete gamma function */ define gammainc(a,z){
768 local ret nterms eps epsilon tmp_before tmp_after n A B C sum k;
773 if(a==1) return exp(-z); return __CZ__gammainc_integer_a(a,z);
776 return -expoint(-z)+1/2*( ln(-z) - ln(-1/z) ) -ln(z);
778 return expoint(-z)+1/2*(ln(-1/z)-ln(-z))+ln(z)+(exp(-z)/z);
780 A = (-1)^((-a)-1)/((-a)!); B =
781 expoint(-z)-1/2*(ln(-z)-ln(1/-z))+ln(z); C = exp(-z); sum =0;
783 sum += (z^(k-a-1))/( fallingfactorial(-a,k) );
784 } return A * B - C *sum;
787 } if(re(z)<=1.1|| re(z) < a+1){##print "series";
788 eps = epsilon(epsilon()*1e-10); ret =
789 __CZ__gammainc_series_lower(a,z); epsilon(eps); return ret;
791 eps = epsilon(epsilon()*1e-10); if(abs(exp(-z)) <= eps) return 0;
792 tmp_before = 0; tmp_after = 1; n = 1; while(ceil(tmp_before) !=
794 tmp_before = tmp_after; tmp_after =
795 __CZ__endcf(n++,a,z,digits(1/eps)); /* a still quite arbitrary
797 return newerror("gammainc: evaluating limit for continued "
798 "fraction does not converge");
800 } ret = __CZ__gammainc_cf(a,z,ceil(tmp_after)); epsilon(eps);
805 define heavisidestep(x){
806 return (1+sign(x))/2;
809 define NUMBER_POSITIVE_INFINITY(){ return 1/epsilon();}
811 define NUMBER_NEGATIVE_INFINITY(){ return -(1/epsilon());}
827 define __CZ__series_converged(new,old,max){
833 if( abs(re(new - old)) <= eps * abs(re(new))
834 && abs(im(new - old)) <= eps * abs(im(new)))
839 define __CZ__ei_power(z){
841 ei = g() + ln(abs(z)) + sgn(im(z)) * 1i * abs(arg(z));
842 ##ei = g() + ln(z) -1i*pi()*floor( (arg(z)+pi()) / (2*pi()) );
849 if (__CZ__series_converged(ei,old)) break;
855 define __CZ__ei_asymp(z){
857 ei = sgn(im(z)) * 1i * pi();
859 for(k=1; k<=floor(abs(z))+1; k++){
862 if (__CZ__series_converged(ei, old)) return ei;
865 return newerror("expoint: asymptotic series does not converge");
868 define __CZ__ei_cf(z){
870 ei = sgn(im(z)) * 1i * pi();
874 c = 1 / (1 - z - exp(z) * c);
875 d = 1 / (1 - z - exp(z) * d);
879 c = NUMBER_POSITIVE_INFINITY();
882 d = 1 / (1 - z - exp(z) * d);
887 c = 1 / (2 * k + 1 - z - k * k * c);
888 d = 1 / (2 * k + 1 - z - k * k * d);
891 if (__CZ__series_converged(ei, old)) break;
899 eps=epsilon(epsilon()*1e-5);
900 if(abs(z) >= NUMBER_POSITIVE_INFINITY()){
901 if (config("user_debug") > 0) {
902 print "expoint: abs(z) > +inf";
904 ret = sgn(im(z)) * 1i * pi() + exp(z) / z;
908 if(abs(z) > 2 - 1.035 * log(epsilon())){
909 if (config("user_debug") > 0) {
910 print "expoint: using asymptotic series";
912 ei = __CZ__ei_asymp(z);
919 if(abs(z) > 1 && (re(z) < 0 || abs(im(z)) > 1)){
920 if (config("user_debug") > 0) {
921 print "expoint: using continued fraction";
923 ret = __CZ__ei_cf(z);
928 if (config("user_debug") > 0) {
929 print "expoint: using power series";
931 ret = __CZ__ei_power(z);
936 if (config("user_debug") > 0) {
937 print "expoint: abs(z) = zero ";
940 return NUMBER_NEGATIVE_INFINITY();
945 return sqrt(z^2)/z * ( 1-1/sqrt(pi()) *gammainc(1/2,z^2) );
953 return -1i*erf(1i*z);
957 return exp(-z^2)*erfc(-1i*z);
961 return gammainc(a,z)/gamma(a);
965 return 1-gammap(a,z);
970 eps=epsilon(epsilon()*1e-3);
971 ret = (lngamma(a)+lngamma(b))-lngamma(a+b);
977 return exp(lnbeta(a,b));
980 define __CZ__ibetacf_a(a,b,z,n){
984 places = highbit(1 + int(1/epsilon())) + 1;
985 A = bround((a+m-1) * (a+b+m-1) * m * (b-m) * z^2,places++);
986 B = bround((a+2*(m)-1)^2,places++);
990 define __CZ__ibetacf_b(a,b,z,n){
992 places = highbit(1 + int(1/epsilon())) + 1;
994 A = bround((m*(b-m)*z)/(a+2*m-1),places++);
995 B = bround(( (a+m) * (a-(a+b)*z+1+m*(2-z)) )/(a+2*m+1),places++);
999 /* Didonato-Morris */
1000 define __CZ__ibeta_cf_var_dm(a,b,z,max){
1001 local m f c d check del h qab qam qap eps places;
1005 if(isnull(max)) max = 100;
1006 places = highbit(1 + int(1/epsilon())) + 1;
1010 for(m=1;m<=max;m++){
1011 d =bround( __CZ__ibetacf_b(a,b,z,m)+__CZ__ibetacf_a(a,b,z,m)*d,places++);
1012 if(abs(d)<eps ) d=eps;
1013 c =bround( __CZ__ibetacf_b(a,b,z,m)+__CZ__ibetacf_a(a,b,z,m)/c,places++);
1014 if(abs(c)<eps ) c=eps;
1018 if(abs(check-1)<eps)break;
1020 if(m > max) return newerror("ibeta: continous fraction does not converge");
1024 define betainc_complex(z,a,b){
1025 local factor ret eps cf sum k N places tmp tmp2;
1028 if(re(a) > 0) return 0;
1029 if(re(a) < 0) return newerror("betainc_complex: z == 0 and re(a) < 0");
1032 if(re(b)>0) return 1;
1033 else return newerror("betainc_complex: z == 1 and re(b) < 0");
1036 if(isint(b)) return 0;
1037 else return newerror("betainc_complex: b <= 0");
1039 if(z==1/2 && (a==b)){return 1/2;
1042 if(isint(a) && isint(b)){
1043 eps=epsilon(epsilon()*1e-10);
1047 tmp = ln(z)*k+ln(1-z)*(N-k);
1048 tmp2 = exp(ln(comb(N,k))+tmp);
1054 else if(re(z) <= re((a+1)/(a+b+2))){
1055 eps=epsilon(epsilon()*1e-10);
1056 places = highbit(1 + int(1/epsilon())) + 1;
1057 factor = bround(( ln(z^a*(1-z)^b ) - lnbeta(a,b) ),places);
1058 cf =bround( __CZ__ibeta_cf_var_dm(a,b,z),places);
1059 ret = factor + ln(cf);
1060 if(abs(ret//ln(2)) >= places)
1063 ret = bround(exp(factor + ln(cf)),places);
1067 else if( re(z) > re( (a+1)/(a+b+2) ) || re(1-z) < re( (b+1)/(a+b+2) ) ){
1068 ret = 1 - betainc_complex(1-z,b,a);
1074 /******************************************************************************/
1078 __CZ__ibetaas63 computes the incomplete Beta function ratio.
1082 This code is distributed under the GNU LGPL license.
1086 2013-08-03 20:52:05 +0000
1090 Original FORTRAN77 version by KL Majumder, GP Bhattacharjee.
1091 C version by John Burkardt
1092 Calc version by Christoph Zurnieden
1096 KL Majumder, GP Bhattacharjee,
1098 The incomplete Beta Integral,
1100 Volume 22, Number 3, 1973, pages 409-411.
1104 Input, x, the argument, between 0 and 1.
1106 Input, a, b, the parameters, which
1110 Output, the value of the incomplete
1111 Beta function ratio.
1113 define __CZ__ibetaas63(x, a, b,beta){
1114 local ai betain cx indx ns aa asb bb rx temp term value xx acu places;
1118 /* inverse incbeta calculates it already */
1122 if ( a <= 0.0 || b <= 0.0 ){
1123 return newerror("betainc: domain error: a < 0 and/or b < 0");
1125 if ( x < 0.0 || 1.0 < x ){
1126 return newerror("betainc: domain error: x<0 or x>1");
1128 if ( x == 0.0 || x == 1.0 ){
1151 ns = floor( bb + cx * asb );
1158 places = highbit(1 + int(1/acu)) + 1;
1160 term = bround(term * temp * rx / ( aa + ai ),places++);
1161 value = value + term;;
1162 temp = abs ( term );
1164 if ( temp <= acu && temp <= abs(acu * value) ){
1165 value = value * exp ( aa * ln ( xx )
1166 + ( bb - 1.0 ) * ln ( cx ) - beta ) / aa;
1169 value = 1.0 - value;
1196 1/beta(a,b) * I (1 - t) t dt
1203 define betainc(z,a,b){
1204 local factor ret eps cf sum k N places tmp tmp2;
1206 if(im(z) || im(a) || im(b))
1207 return betainc_complex(z,a,b);
1210 if(re(a) > 0) return 0;
1211 if(re(a) < 0) return newerror("betainc: z == 0 and re(a) < 0");
1214 if(re(b)>0) return 1;
1215 else return newerror("betainc: z == 1 and re(b) < 0");
1218 if(isint(b)) return 0;
1219 else return newerror("betainc: b <= 0");
1224 return __CZ__ibetaas63(z,a,b);
1228 define __CZ__erfinvapprox(x){
1231 return sgn(x)*sqrt(sqrt((2/(pi()*a)+(ln(1-x^2))/2)^2-(ln(1-x^2))/a)-
1232 (2/(pi()*a)+(ln(1-x^2))/2));
1235 /* complementary inverse errror function, faster at about x < 1-.91
1236 Henry E. Fettis. "A stable algorithm for computing the inverse error function
1237 in the 'tail-end' region" Math. Comp., 28:585-587, 1974.
1239 define __CZ__inverffettis(x,n){
1240 local y sqrtpi oldy k places;
1243 y = erfinvapprox(1-x);
1244 places = highbit(1 + int(1/epsilon())) + 1;
1245 sqrtpi = sqrt(pi());
1249 y = bround((ln( __CZ__fettiscf(y,n) / (sqrtpi * x)))^(1/2),places);
1250 } while( abs(y - oldy)/y > epsilon());
1255 define __CZ__fettiscf(y,n){
1256 local k t tt r a b ;
1267 /* inverse errror function, faster at about x<=.91*/
1268 define __CZ__inverfbin(x){
1269 local places approx flow fhigh eps high low mid fmid epsilon;
1270 approx = erfinvapprox(x);
1271 epsilon = epsilon();
1272 high = approx + 1e-4;
1274 places = highbit(1 + int(1/epsilon)) + 1;
1275 fhigh = x-erf(high);
1278 mid = bround(high - fhigh * (high - low) / (fhigh - flow), places);
1279 if ((mid == low) || (mid == high))
1282 if (abs(fmid) < epsilon)
1284 if (sgn(fmid) == sgn(flow)) {
1296 local ret approx a eps y old places errfunc sqrtpihalf flag k;
1297 if(x<-1 || x > 1) return newerror("erfinv: input out of domain (-1<=x<=1)");
1298 if(x == 0) return 0;
1299 if(x == -1) return NUMBER_NEGATIVE_INFINITY();
1300 if(x == +1) return NUMBER_POSITIVE_INFINITY();
1306 /* No need for full pecision */
1309 /* Winitzki, Sergei (6 February 2008). "A handy approximation for the error
1310 function and its inverse"*/
1312 y = sgn(x)*sqrt(sqrt((2/(pi()*a)
1315 -(2/(pi()*a)+(ln(1-x^2))/2));
1319 /* 20 digits instead of 5 */
1321 y = __CZ__inverfbin(x);
1323 y = __CZ__inverffettis(1-x);
1331 /* binary digits in number (here: number = epsilon()) */
1332 places = highbit(1 + int(1/eps)) + 1;
1333 sqrtpihalf = 2/sqrt(pi());
1336 Do some Newton-Raphson steps to reach final accuracy.
1337 Only a couple of steps are necessary but calculating the error function at
1338 higher precision is quite costly;
1342 errfunc = bround( erf(y),places);
1343 if( abs(errfunc-x) <= eps ) break;
1344 y = bround(y-( errfunc -x) / ( sqrtpihalf * exp(-y^2)),places);
1348 This is not really necessary but e.g:
1350 0.00000000000000000000000000000000000000000000000001
1351 ; erfinv(.9999999999999999999999999999999)
1352 8.28769266865549025938
1353 ; erfinv(.999999999999999999999999999999)
1354 8.14861622316986460738453487549552168842204512959346
1355 ; erf(8.28769266865549025938)
1356 0.99999999999999999999999999999990000000000000000000
1357 ; erf(8.14861622316986460738453487549552168842204512959346)
1358 0.99999999999999999999999999999900000000000000000000
1359 The precision "looks too short".
1362 y = bround(y-( errfunc -x) / ( sqrtpihalf * exp(-y^2)),places);
1370 * restore internal function from resource debugging
1372 config("resource_debug", resource_debug_level),;
1373 if (config("resource_debug") & 3) {
1376 print "polygamma(m,z)";
1379 print "harmonic(limit)";
1380 print "gammainc(a,z)";
1381 print "heavisidestep(x)";
1388 print "faddeeva(z)";
1389 print "gammap(a,z)";
1390 print "gammaq(a,z)";
1392 print "lnbeta(a,b)";
1393 print "betainc(z,a,b)";