summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/combin.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/combin.c')
-rwxr-xr-xreference/C/CONTRIB/SNIP/combin.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/combin.c b/reference/C/CONTRIB/SNIP/combin.c
new file mode 100755
index 0000000..e9b5687
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/combin.c
@@ -0,0 +1,66 @@
+/*
+** Compute C(n,m) = the number of combinations of n items,
+** taken m at a time.
+**
+** Written by Thad Smith III, Boulder County, CO.
+** Released to the Public Domain 10/14/91.
+**
+** The def of this function is
+** C(n,m) = n! / (m! * (n-m)!).
+** Computing this formula can cause overflow for large values of n,
+** even when C(n,m) would be defined.
+**
+** The first version will not overflow if C(n,m) * (n-m+1) < ULONG_MAX.
+** The second version will not overflow if C(n,m) < ULONG_MAX, but
+** is slightly more complex.
+** Function domain: n >= 0, 0 <= m <= n.
+**
+** Both versions work by reducing the product as it is computed. It
+** relies on the property that the product on n consecutive integers
+** must be evenly divisible by n.
+**
+** The first version can be changed to make cnm and the return value
+** double to extend the range of the function.
+*/
+
+unsigned long ncomb1 (int n, int m)
+{
+ unsigned long cnm = 1UL;
+ int i;
+
+ if (m*2 >n) m = n-m;
+ for (i=1 ; i <= m; n--, i++)
+ cnm = cnm * n / i;
+ return cnm;
+}
+
+unsigned long ncomb2 (int n, int m)
+{
+ unsigned long cnm = 1UL;
+ int i, f;
+
+ if (m*2 >n) m = n-m;
+ for (i=1 ; i <= m; n--, i++)
+ {
+ if ((f=n) % i == 0)
+ f /= i;
+ else cnm /= i;
+ cnm *= f;
+ }
+ return cnm;
+}
+
+#ifdef TEST
+
+#include <stdio.h>
+#include <stdlib.h>
+
+main (int argc, char *argv[]) {
+ int n,m;
+ n = atoi (argv[1]);
+ m = atoi (argv[2]);
+ printf ("ncomb1 = %lu, ncomb2 = %lu\n", ncomb1(n,m), ncomb2(n,m));
+ return 0;
+}
+
+#endif