// $Id: choose.c,v 1.3 2000/10/20 01:21:48 trow Exp $

#include "mconf.h"

double
factorial (int n)
{
  static double lookup[24] = {
    1.,
    1.,
    2.,
    6.,
    24.,
    120.,
    720.,
    5040.,
    40320.,
    362880.,
    3628800.,
    39916800.,
    479001600.,
    6227020800.,
    87178291200.,
    1307674368000.,
    20922789888000.,
    355687428096000.,
    6402373705728000.,
    121645100408832000.,
    2432902008176640000.,
    51090942171709440000.,
    1124000727777607680000.,
    25852016738884976640000.
  };
  if (n < 0) {
    return mtherr ("factorial", 1);
  } else if (n < 24)
    return lookup[n];
  else
    return floor (exp (log_factorial (n)) + 0.5);
}

double
log_factorial (int n)
{
  if (n < 0) {
    return mtherr ("log_factorial", 1);
  }
  return lgam (1.0 + n);
}

double
choose (int n, int k)
{
  if (n < 1 || k < 0 || k > n)
    return 0;
  else if (k == 0 || k == n)
    return 1;
  else if (k == 1 || k == n - 1)
    return n;
  else if (n < 13)
    return factorial (n) / (factorial (k) * factorial (n - k));
  else
    return floor (exp (log_choose (n, k)) + 0.5);
}

double
log_choose (int n, int k)
{
  return log_factorial (n) - log_factorial (k) - log_factorial (n - k);
}








// $Id: choose.c,v 1.3 2000/10/20 01:21:48 trow Exp $


syntax highlighted by Code2HTML, v. 0.9.1