| 
									
										
										
										
											2015-12-02 16:00:19 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <limits.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Original code copied from 
 | 
					
						
							|  |  |  |    http://rosettacode.org/wiki/Evaluate_binomial_coefficients
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  | /* We go to some effort to handle overflow situations */ | 
					
						
							|  |  |  |   | 
					
						
							| 
									
										
										
										
											2015-12-02 16:13:44 +00:00
										 |  |  | static unsigned long long gcd_ui(unsigned long long x, unsigned long long y) { | 
					
						
							|  |  |  |   unsigned long long t; | 
					
						
							| 
									
										
										
										
											2015-12-02 16:00:19 +00:00
										 |  |  |   if (y < x) { t = x; x = y; y = t; } | 
					
						
							|  |  |  |   while (y > 0) { | 
					
						
							|  |  |  |     t = y;  y = x % y;  x = t;  /* y1 <- x0 % y0 ; x1 <- y0 */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  |   | 
					
						
							| 
									
										
										
										
											2015-12-02 16:13:44 +00:00
										 |  |  | unsigned long long binomial(unsigned long long n, unsigned long long k) { | 
					
						
							|  |  |  |   unsigned long long d, g, r = 1; | 
					
						
							| 
									
										
										
										
											2015-12-02 16:00:19 +00:00
										 |  |  |   if (k == 0) return 1; | 
					
						
							|  |  |  |   if (k == 1) return n; | 
					
						
							|  |  |  |   if (k >= n) return (k == n); | 
					
						
							|  |  |  |   if (k > n/2) k = n-k; | 
					
						
							|  |  |  |   for (d = 1; d <= k; d++) { | 
					
						
							| 
									
										
										
										
											2015-12-02 16:43:03 +00:00
										 |  |  |     if (r >= ULLONG_MAX/n) {  /* Possible overflow */ | 
					
						
							| 
									
										
										
										
											2015-12-02 16:13:44 +00:00
										 |  |  |       unsigned long long nr, dr;  /* reduced numerator / denominator */ | 
					
						
							| 
									
										
										
										
											2015-12-02 16:00:19 +00:00
										 |  |  |       g = gcd_ui(n, d);  nr = n/g;  dr = d/g; | 
					
						
							|  |  |  |       g = gcd_ui(r, dr);  r = r/g;  dr = dr/g; | 
					
						
							| 
									
										
										
										
											2015-12-02 16:43:03 +00:00
										 |  |  |       if (r >= ULLONG_MAX/nr) return 0;  /* Unavoidable overflow */ | 
					
						
							| 
									
										
										
										
											2015-12-02 16:00:19 +00:00
										 |  |  |       r *= nr; | 
					
						
							|  |  |  |       r /= dr; | 
					
						
							|  |  |  |       n--; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       r *= n--; | 
					
						
							|  |  |  |       r /= d; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-02 16:13:44 +00:00
										 |  |  | unsigned long long binomial_(int *n, int *k) | 
					
						
							| 
									
										
										
										
											2015-12-02 16:00:19 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   //  printf("n=%d  k=%d  %lu\n",*n,*k,binomial(*n,*k));
 | 
					
						
							|  |  |  |   return binomial(*n,*k); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | double hypergeo_(int *x, int *NN, int *XX, int *s) | 
					
						
							|  |  |  | {     | 
					
						
							|  |  |  |   double a,b,c; | 
					
						
							|  |  |  |   a=(double)binomial(*XX, *x); | 
					
						
							|  |  |  |   b=(double)binomial(*NN-*XX, *s-*x); | 
					
						
							|  |  |  |   c=(double)binomial(*NN, *s); | 
					
						
							|  |  |  |   return a*b/c; | 
					
						
							|  |  |  | } |