require'more_math'moduleMoreMathmoduleFunctionsmodule_functionincludeMathextendMath# Returns the natural logarithm of Euler gamma function value for +x+ using# the Lanczos approximation.ifMath.respond_to?(:lgamma)deflog_gamma(x)lgamma(x).firstendelsedeflog_gamma(x)ifx.nan?||x<=00/0.0elsesum=0.0lc=Constants::FunctionsConstants::LANCZOS_COEFFICIENTShalf_log_2_pi=Constants::FunctionsConstants::HALF_LOG_2_PI(lc.size-1).downto(1)do|i|sum+=lc[i]/(x+i)endsum+=lc[0]tmp=x+607.0/128+0.5(x+0.5)*log(tmp)-tmp+half_log_2_pi+log(sum/x)endrescueErrno::ERANGE,Errno::EDOM0/0.0endend# Returns the natural logarithm of the beta function value for +(a, b)+.deflog_beta(a,b)log_gamma(a)+log_gamma(b)-log_gamma(a+b)rescueErrno::ERANGE,Errno::EDOM0/0.0end# Return an approximation value of Euler's regularized beta function for# +x+, +a+, and +b+ with an error <= +epsilon+, but only iterate# +max_iterations+-times.defbeta_regularized(x,a,b,epsilon=1E-16,max_iterations=1<<16)x,a,b=x.to_f,a.to_f,b.to_fcasewhena.nan?||b.nan?||x.nan?||a<=0||b<=0||x<0||x>10/0.0whenx>(a+1)/(a+b+2)1-beta_regularized(1-x,b,a,epsilon,max_iterations)elsefraction=ContinuedFraction.for_bdo|n,x|ifn%2==0m=n/2.0(m*(b-m)*x)/((a+(2*m)-1)*(a+(2*m)))elsem=(n-1)/2.0-((a+m)*(a+b+m)*x)/((a+2*m)*(a+2*m+1))endendexp(a*log(x)+b*log(1.0-x)-log(a)-log_beta(a,b))/fraction[x,epsilon,max_iterations]endrescueErrno::ERANGE,Errno::EDOM0/0.0end# Return an approximation of the regularized gammaP function for +x+ and# +a+ with an error of <= +epsilon+, but only iterate# +max_iterations+-times.defgammaP_regularized(x,a,epsilon=1E-16,max_iterations=1<<16)x,a=x.to_f,a.to_fcasewhena.nan?||x.nan?||a<=0||x<00/0.0whenx==00.0when1<=a&&a<x1-gammaQ_regularized(x,a,epsilon,max_iterations)elsen=0an=1/asum=anwhilean.abs>epsilon&&n<max_iterationsn+=1an*=x/(a+n)sum+=anendifn>=max_iterationsraiseErrno::ERANGEelseexp(-x+a*log(x)-log_gamma(a))*sumendendrescueErrno::ERANGE,Errno::EDOM0/0.0end# Return an approximation of the regularized gammaQ function for +x+ and# +a+ with an error of <= +epsilon+, but only iterate# +max_iterations+-times.defgammaQ_regularized(x,a,epsilon=1E-16,max_iterations=1<<16)x,a=x.to_f,a.to_fcasewhena.nan?||x.nan?||a<=0||x<00/0.0whenx==01.0whena>x||a<11-gammaP_regularized(x,a,epsilon,max_iterations)elsefraction=ContinuedFraction.for_ado|n,x|(2*n+1)-a+xend.for_bdo|n,x|n*(a-n)endexp(-x+a*log(x)-log_gamma(a))*fraction[x,epsilon,max_iterations]**-1endrescueErrno::ERANGE,Errno::EDOM0/0.0endunlessMath.respond_to?(:erf)# Returns an approximate value for the error function's value for +x+.deferf(x)erf_a=MoreMath::Constants::FunctionsConstants::ERF_Ar=sqrt(1-exp(-x**2*(4/Math::PI+erf_a*x**2)/(1+erf_a*x**2)))x<0?-r:rendelsedeferf(x)Math.erf(x)endend# Returns Cantor's tuple function for the tuple +*xs+ (the size must be at# least 2).defcantor_pairing(*xs)CantorPairingFunction.cantor_pairing(*xs)end# Returns the inverse of Cantor's tuple function for the value +c+. +n+ is# the length of the tuple (defaults to 2, a pair).defcantor_pairing_inv(c,n=2)CantorPairingFunction.cantor_pairing_inv(c,n)endendend