aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/integers.c33
-rw-r--r--stdlib/integers.h2
2 files changed, 35 insertions, 0 deletions
diff --git a/stdlib/integers.c b/stdlib/integers.c
index 33e967cb..e5344370 100644
--- a/stdlib/integers.c
+++ b/stdlib/integers.c
@@ -382,6 +382,39 @@ public Int_t Int$prev_prime(Int_t x)
return Int$from_mpz(p);
}
+public Int_t Int$choose(Int_t n, Int_t k)
+{
+ if unlikely (Int$compare_value(n, I_small(0)) < 0)
+ fail("Negative inputs are not supported for choose()");
+
+ mpz_t ret;
+ mpz_init(ret);
+
+ int64_t k_i64 = Int_to_Int64(k, false);
+ if unlikely (k_i64 < 0)
+ fail("Negative inputs are not supported for choose()");
+
+ if likely (n.small & 1) {
+ mpz_bin_uiui(ret, (unsigned long)(n.small >> 2), (unsigned long)k_i64);
+ } else {
+ mpz_t n_mpz;
+ mpz_init_set_int(n_mpz, n);
+ mpz_bin_ui(ret, n_mpz, (unsigned long)k_i64);
+ }
+ return Int$from_mpz(ret);
+}
+
+public Int_t Int$factorial(Int_t n)
+{
+ mpz_t ret;
+ mpz_init(ret);
+ int64_t n_i64 = Int_to_Int64(n, false);
+ if unlikely (n_i64 < 0)
+ fail("Factorials are not defined for negative numbers");
+ mpz_fac_ui(ret, (unsigned long)n_i64);
+ return Int$from_mpz(ret);
+}
+
static bool Int$is_none(const void *i, const TypeInfo_t*)
{
return ((Int_t*)i)->small == 0;
diff --git a/stdlib/integers.h b/stdlib/integers.h
index 2f6b5125..033a6873 100644
--- a/stdlib/integers.h
+++ b/stdlib/integers.h
@@ -144,6 +144,8 @@ Int_t Int$slow_negated(Int_t x);
bool Int$is_prime(Int_t x, Int_t reps);
Int_t Int$next_prime(Int_t x);
Int_t Int$prev_prime(Int_t x);
+Int_t Int$choose(Int_t n, Int_t k);
+Int_t Int$factorial(Int_t n);
extern const TypeInfo_t Int$info;