Merge pull request #19 from chendotjs/comb

add ncr and npr
This commit is contained in:
Lewis Van Winkle
2017-03-27 12:49:36 -05:00
committed by GitHub
2 changed files with 53 additions and 9 deletions

41
test.c
View File

@@ -214,6 +214,12 @@ void test_nans() {
"1%(1%0)", "1%(1%0)",
"(1%0)%1", "(1%0)%1",
"fac(-1)", "fac(-1)",
"ncr(2, 4)",
"ncr(-2, 4)",
"ncr(2, -4)",
"npr(2, 4)",
"npr(-2, 4)",
"npr(2, -4)",
}; };
int i; int i;
@@ -242,6 +248,12 @@ void test_infs() {
"log(0)", "log(0)",
"pow(2,10000000)", "pow(2,10000000)",
"fac(300)", "fac(300)",
"ncr(300,100)",
"ncr(300000,100)",
"ncr(300000,100)*8",
"npr(3,2)*ncr(300000,100)",
"npr(100,90)",
"npr(30,25)",
}; };
int i; int i;
@@ -618,13 +630,28 @@ void test_pow() {
void test_combinatorics() { void test_combinatorics() {
test_case cases[] = { test_case cases[] = {
{"fac(0) ", 1}, {"fac(0)", 1},
{"fac(0.2) ", 1}, {"fac(0.2)", 1},
{"fac(1) ", 1}, {"fac(1)", 1},
{"fac(2) ", 2}, {"fac(2)", 2},
{"fac(3) ", 6}, {"fac(3)", 6},
{"fac(4.8) ", 24}, {"fac(4.8)", 24},
{"fac(10) ", 3628800}, {"fac(10)", 3628800},
{"ncr(0,0)", 1},
{"ncr(10,1)", 10},
{"ncr(10,0)", 1},
{"ncr(10,10)", 1},
{"ncr(16,7)", 11440},
{"ncr(16,9)", 11440},
{"ncr(100,95)", 75287520},
{"npr(0,0)", 1},
{"npr(10,1)", 10},
{"npr(10,0)", 1},
{"npr(10,10)", 3628800},
{"npr(20,5)", 1860480},
{"npr(100,4)", 94109400},
}; };

View File

@@ -125,14 +125,29 @@ static double fac(double a) {/* simplest version of fac */
if (a > UINT_MAX) if (a > UINT_MAX)
return INFINITY; return INFINITY;
unsigned int ua = (unsigned int)(a); unsigned int ua = (unsigned int)(a);
unsigned long int result = 1, i = 1; unsigned long int result = 1, i;
for (i = 1; i <= ua; i++) { for (i = 1; i <= ua; i++) {
if (ua > ULONG_MAX / result) if (i > ULONG_MAX / result)
return INFINITY; return INFINITY;
result *= i; result *= i;
} }
return (double)result; return (double)result;
} }
static double ncr(double n, double r) {
if (n < 0.0 || r < 0.0 || n < r) return NAN;
if (n > UINT_MAX || r > UINT_MAX) return INFINITY;
unsigned long int un = (unsigned int)(n), ur = (unsigned int)(r), i;
unsigned long int result = 1;
if (ur > un / 2) ur = un - ur;
for (i = 1; i <= ur; i++) {
if (result > ULONG_MAX / (un - ur + i))
return INFINITY;
result *= un - ur + i;
result /= i;
}
return result;
}
static double npr(double n, double r) {return ncr(n, r) * fac(r);}
static const te_variable functions[] = { static const te_variable functions[] = {
/* must be in alphabetical order */ /* must be in alphabetical order */
@@ -155,6 +170,8 @@ static const te_variable functions[] = {
{"log", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {"log", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0},
#endif #endif
{"log10", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {"log10", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0},
{"ncr", ncr, TE_FUNCTION2 | TE_FLAG_PURE, 0},
{"npr", npr, TE_FUNCTION2 | TE_FLAG_PURE, 0},
{"pi", pi, TE_FUNCTION0 | TE_FLAG_PURE, 0}, {"pi", pi, TE_FUNCTION0 | TE_FLAG_PURE, 0},
{"pow", pow, TE_FUNCTION2 | TE_FLAG_PURE, 0}, {"pow", pow, TE_FUNCTION2 | TE_FLAG_PURE, 0},
{"sin", sin, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {"sin", sin, TE_FUNCTION1 | TE_FLAG_PURE, 0},