mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-13 15:41:50 -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;
|
||
|
}
|