| 86 | // `perm(n)` is `n!`; optional `k` gives the falling factorial `n*(n-1)*...*(n-k+1)`. |
| 87 | #[plugin_fn] |
| 88 | fn perm(n: i128, rest: Args) -> Result<i128> { |
| 89 | if n < 0 { return Err(Error::Value(String::from("perm() arguments must be non-negative"))); } |
| 90 | let k = match rest.len() { |
| 91 | 0 => n, |
| 92 | 1 => rest.get::<i128>(0).unwrap()?, |
| 93 | _ => return Err(Error::Type(String::from("perm expected at most 2 arguments"))), |
| 94 | }; |
| 95 | if k < 0 { return Err(Error::Value(String::from("perm() arguments must be non-negative"))); } |
| 96 | if k > n { return Ok(0); } |
| 97 | let mut acc: i128 = 1; |
| 98 | let mut i: i128 = 0; |
| 99 | while i < k { |
| 100 | acc = acc.checked_mul(n - i).ok_or_else(|| too_large("perm"))?; |
| 101 | i += 1; |
| 102 | } |
| 103 | Ok(acc) |
| 104 | } |