| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  | ! Copyright (C) 2008 Doug Coleman, Slava Pestov, Aaron Schaefer. | 
					
						
							| 
									
										
										
										
											2008-10-03 03:19:03 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  | USING: combinators.short-circuit kernel math math.constants math.functions | 
					
						
							|  |  |  |     math.vectors sequences ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | IN: math.analysis | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! http://www.rskey.org/gamma.htm  "Lanczos Approximation" | 
					
						
							|  |  |  | ! n=6: error ~ 3 x 10^-11 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-22 20:08:45 -05:00
										 |  |  | CONSTANT: gamma-g6 5.15
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-23 22:40:17 -05:00
										 |  |  | CONSTANT: gamma-p6 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     { | 
					
						
							|  |  |  |         2.50662827563479526904 225.525584619175212544 -268.295973841304927459
 | 
					
						
							| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  |         80.9030806934622512966 -5.00757863970517583837 0.0114684895434781459556
 | 
					
						
							| 
									
										
										
										
											2009-02-23 22:40:17 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : gamma-z ( x n -- seq )
 | 
					
						
							| 
									
										
										
										
											2008-01-09 17:36:30 -05:00
										 |  |  |     [ + recip ] with map 1.0 0 pick set-nth ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : (gamma-lanczos6) ( x -- log[gamma[x+1]] )
 | 
					
						
							|  |  |  |     #! log(gamma(x+1) | 
					
						
							| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  |     [ 0.5 + dup gamma-g6 + [ log * ] keep - ] | 
					
						
							| 
									
										
										
										
											2008-10-03 03:19:03 -04:00
										 |  |  |     [ 6 gamma-z gamma-p6 v. log ] bi + ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : gamma-lanczos6 ( x -- gamma[x] )
 | 
					
						
							|  |  |  |     #! gamma(x) = gamma(x+1) / x | 
					
						
							| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  |     [ (gamma-lanczos6) exp ] keep / ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : gammaln-lanczos6 ( x -- gammaln[x] )
 | 
					
						
							|  |  |  |     #! log(gamma(x)) = log(gamma(x+1)) - log(x) | 
					
						
							| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  |     [ (gamma-lanczos6) ] keep log - ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : gamma-neg ( gamma[abs[x]] x -- gamma[x] )
 | 
					
						
							|  |  |  |     dup pi * sin * * pi neg swap / ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : gamma ( x -- y )
 | 
					
						
							|  |  |  |     #! gamma(x) = integral 0..inf [ t^(x-1) exp(-t) ] dt | 
					
						
							|  |  |  |     #! gamma(n+1) = n! for n > 0 | 
					
						
							| 
									
										
										
										
											2008-10-03 03:19:03 -04:00
										 |  |  |     dup { [ 0.0 <= ] [ 1.0 mod zero? ] } 1&& [ | 
					
						
							| 
									
										
										
										
											2009-04-14 18:09:16 -04:00
										 |  |  |         drop 1/0. | 
					
						
							| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  |     ] [ | 
					
						
							|  |  |  |         [ abs gamma-lanczos6 ] keep dup 0 > [ drop ] [ gamma-neg ] if
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : gammaln ( x -- gamma[x] )
 | 
					
						
							|  |  |  |     #! gammaln(x) is an alternative when gamma(x)'s range | 
					
						
							|  |  |  |     #! varies too widely | 
					
						
							|  |  |  |     dup 0 < [ | 
					
						
							| 
									
										
										
										
											2009-04-14 18:09:16 -04:00
										 |  |  |         drop 1/0. | 
					
						
							| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  |     ] [ | 
					
						
							|  |  |  |         [ abs gammaln-lanczos6 ] keep dup 0 > [ drop ] [ gamma-neg ] if
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : nth-root ( n x -- y )
 | 
					
						
							| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  |     swap recip ^ ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! Forth Scientific Library Algorithm #1 | 
					
						
							|  |  |  | !
 | 
					
						
							|  |  |  | ! Evaluates the Real Exponential Integral, | 
					
						
							|  |  |  | !     E1(x) = - Ei(-x) =   int_x^\infty exp^{-u}/u du      for x > 0 | 
					
						
							|  |  |  | ! using a rational approximation | 
					
						
							|  |  |  | !
 | 
					
						
							|  |  |  | ! Collected Algorithms from ACM, Volume 1 Algorithms 1-220, | 
					
						
							|  |  |  | ! 1980; Association for Computing Machinery Inc., New York, | 
					
						
							|  |  |  | ! ISBN 0-89791-017-6 | 
					
						
							|  |  |  | !
 | 
					
						
							|  |  |  | ! (c) Copyright 1994 Everett F. Carter.  Permission is granted by the | 
					
						
							|  |  |  | ! author to use this software for any application provided the | 
					
						
							|  |  |  | ! copyright notice is preserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : exp-int ( x -- y )
 | 
					
						
							|  |  |  |     #! For real values of x only. Accurate to 7 decimals. | 
					
						
							|  |  |  |     dup 1.0 < [ | 
					
						
							|  |  |  |         dup 0.00107857 * 0.00976004 -
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         0.05519968 +
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         0.24991055 -
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         0.99999193 +
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         0.57721566 -
 | 
					
						
							|  |  |  |         swap log -
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         dup 8.5733287401 +
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         18.059016973 +
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         8.6347608925 +
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         0.2677737343 +
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         over
 | 
					
						
							|  |  |  |         dup 9.5733223454 +
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         25.6329561486 +
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         21.0996530827 +
 | 
					
						
							|  |  |  |         over *
 | 
					
						
							|  |  |  |         3.9584969228 +
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         nip
 | 
					
						
							|  |  |  |         /
 | 
					
						
							|  |  |  |         over /
 | 
					
						
							|  |  |  |         swap -1.0 * exp | 
					
						
							|  |  |  |         *
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							| 
									
										
										
										
											2008-02-12 17:24:32 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! James Stirling's approximation for N!: | 
					
						
							|  |  |  | ! http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Numerical/Stirling/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : stirling-fact ( n -- fact )
 | 
					
						
							| 
									
										
										
										
											2008-02-12 18:32:26 -05:00
										 |  |  |     [ pi 2 * * sqrt ] | 
					
						
							| 
									
										
										
										
											2008-11-06 01:20:08 -05:00
										 |  |  |     [ [ e / ] keep ^ ] | 
					
						
							|  |  |  |     [ 12 * recip 1+ ] tri * * ;
 | 
					
						
							|  |  |  | 
 |