cas_compute/funcs/
combinatoric.rs

1//! Counting functions.
2
3use cas_attrs::builtin;
4use crate::{funcs::miscellaneous::partial_factorial, primitive::int};
5use rug::Integer;
6
7/// Combinations function.
8///
9/// The returned value can be interepeted in a number of ways:
10///
11/// - Returns the number of ways to choose `k` (`r`) items from `n` items, where the order of the
12///   items does not matter.
13/// - Returns the coefficient of the `x^k` term in the polynomial expansion of `(x + 1)^n`, or the
14///   coefficient of the `x^k * y^(n - k)` term in the polynomial expansion of `(x + y)^n`.
15/// - Returns the number in row `n` and column `k` of Pascal's triangle.
16#[derive(Debug)]
17pub struct Ncr;
18
19#[cfg_attr(feature = "numerical", builtin)]
20impl Ncr {
21    pub fn eval_static(n: Integer, k: Integer) -> Integer {
22        if k > n {
23            // TODO: what if k > n, return an error
24            return Integer::from(0);
25        }
26
27        let sub = int(&n - &k);
28        if k > sub {
29            partial_factorial(n, k) / partial_factorial(sub, int(1))
30        } else {
31            partial_factorial(n, sub) / partial_factorial(k, int(1))
32        }
33    }
34}
35
36/// Permutations function. Returns the number of ways to choose `k` (`r`) items from `n` items,
37/// where the order of the items does matter.
38#[derive(Debug)]
39pub struct Npr;
40
41#[cfg_attr(feature = "numerical", builtin)]
42impl Npr {
43    pub fn eval_static(n: Integer, k: Integer) -> Integer {
44        // TODO: report error
45
46        let sub = &n - k;
47        partial_factorial(n, sub)
48    }
49}