| 69 | |
| 70 | #[plugin_fn] |
| 71 | fn comb(n: i128, k: i128) -> Result<i128> { |
| 72 | if n < 0 || k < 0 { return Err(Error::Value(String::from("comb() arguments must be non-negative"))); } |
| 73 | if k > n { return Ok(0); } |
| 74 | let k = k.min(n - k); |
| 75 | let mut acc: i128 = 1; |
| 76 | let mut i: i128 = 1; |
| 77 | // acc holds C(n, i) at each step, staying integral, so the divide is exact. |
| 78 | while i <= k { |
| 79 | acc = acc.checked_mul(n - k + i).ok_or_else(|| too_large("comb"))?; |
| 80 | acc /= i; |
| 81 | i += 1; |
| 82 | } |
| 83 | Ok(acc) |
| 84 | } |
| 85 | |
| 86 | // `perm(n)` is `n!`; optional `k` gives the falling factorial `n*(n-1)*...*(n-k+1)`. |
| 87 | #[plugin_fn] |