mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 13:30:52 -05:00 
			
		
		
		
	
		
			
	
	
		
			70 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			70 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#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 */
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								static unsigned long gcd_ui(unsigned long x, unsigned long y) {
							 | 
						||
| 
								 | 
							
								  unsigned long t;
							 | 
						||
| 
								 | 
							
								  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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								unsigned long binomial(unsigned long n, unsigned long k) {
							 | 
						||
| 
								 | 
							
								  unsigned long d, g, r = 1;
							 | 
						||
| 
								 | 
							
								  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++) {
							 | 
						||
| 
								 | 
							
								    if (r >= ULONG_MAX/n) {  /* Possible overflow */
							 | 
						||
| 
								 | 
							
								      unsigned long nr, dr;  /* reduced numerator / denominator */
							 | 
						||
| 
								 | 
							
								      g = gcd_ui(n, d);  nr = n/g;  dr = d/g;
							 | 
						||
| 
								 | 
							
								      g = gcd_ui(r, dr);  r = r/g;  dr = dr/g;
							 | 
						||
| 
								 | 
							
								      if (r >= ULONG_MAX/nr) return 0;  /* Unavoidable overflow */
							 | 
						||
| 
								 | 
							
								      r *= nr;
							 | 
						||
| 
								 | 
							
								      r /= dr;
							 | 
						||
| 
								 | 
							
								      n--;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      r *= n--;
							 | 
						||
| 
								 | 
							
								      r /= d;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return r;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								int main() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //Get test results
							 | 
						||
| 
								 | 
							
								  printf("%lu\n", binomial(5, 3));     // 10
							 | 
						||
| 
								 | 
							
								  printf("%lu\n", binomial(40, 19));   // 131282408400
							 | 
						||
| 
								 | 
							
								  printf("%lu\n", binomial(67, 31));   // 11923179284862717872
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Compute special cases for paper on TF soft-decision RS decoder:
							 | 
						||
| 
								 | 
							
								  double a,b,c,p;
							 | 
						||
| 
								 | 
							
								  a=(double)binomial(40, 35);
							 | 
						||
| 
								 | 
							
								  b=(double)binomial(23, 5);
							 | 
						||
| 
								 | 
							
								  c=(double)binomial(63, 40);
							 | 
						||
| 
								 | 
							
								  p=a*b/c;
							 | 
						||
| 
								 | 
							
								  printf("%e   %e   %e   %e\n",a,b,c,p);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  a=(double)binomial(40, 36);
							 | 
						||
| 
								 | 
							
								  b=(double)binomial(23, 4);
							 | 
						||
| 
								 | 
							
								  c=(double)binomial(63, 40);
							 | 
						||
| 
								 | 
							
								  p=a*b/c;
							 | 
						||
| 
								 | 
							
								  printf("%e   %e   %e   %e\n",a,b,c,p);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  a=(double)binomial(40, 37);
							 | 
						||
| 
								 | 
							
								  b=(double)binomial(23, 8);
							 | 
						||
| 
								 | 
							
								  c=(double)binomial(63, 45);
							 | 
						||
| 
								 | 
							
								  p=a*b/c;
							 | 
						||
| 
								 | 
							
								  printf("%e   %e   %e   %e\n",a,b,c,p);
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 |