Add Int:factorial() and n:choose(k)
This commit is contained in:
parent
f4b105456a
commit
9e0017e86e
@ -122,6 +122,60 @@ Each integer type has its own version of the following functions. Functions
|
|||||||
can be called either on the type itself: `Int.sqrt(x)` or as a method call:
|
can be called either on the type itself: `Int.sqrt(x)` or as a method call:
|
||||||
`x:sqrt()`. Method call syntax is preferred.
|
`x:sqrt()`. Method call syntax is preferred.
|
||||||
|
|
||||||
|
### `choose`
|
||||||
|
|
||||||
|
**Description:**
|
||||||
|
Computes the binomial coefficient of the given numbers (the equivalent of `n`
|
||||||
|
choose `k` in combinatorics). This is equal to `n:factorial()/(k:factorial() *
|
||||||
|
(n-k):factorial())`.
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```tomo
|
||||||
|
func choose(n: Int, k: Int -> Int)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
- `n`: The number of things to choose from.
|
||||||
|
- `k`: The number of things to be chosen.
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
The binomial coefficient, equivalent to the number of ways to uniquely choose
|
||||||
|
`k` objects from among `n` objects, ignoring order.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> 4:choose(2)
|
||||||
|
= 6
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `factorial`
|
||||||
|
|
||||||
|
**Description:**
|
||||||
|
Computes the factorial of an integer.
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```tomo
|
||||||
|
func factorial(n: Int -> Text)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
- `n`: The integer to compute the factorial of.
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
The factorial of the given integer.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```tomo
|
||||||
|
>> 10:factorial()
|
||||||
|
= 3628800
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `format`
|
### `format`
|
||||||
|
|
||||||
**Description:**
|
**Description:**
|
||||||
|
@ -119,8 +119,10 @@ env_t *new_compilation_unit(CORD libname)
|
|||||||
{"bit_and", "Int$bit_and", "func(x,y:Int -> Int)"},
|
{"bit_and", "Int$bit_and", "func(x,y:Int -> Int)"},
|
||||||
{"bit_or", "Int$bit_or", "func(x,y:Int -> Int)"},
|
{"bit_or", "Int$bit_or", "func(x,y:Int -> Int)"},
|
||||||
{"bit_xor", "Int$bit_xor", "func(x,y:Int -> Int)"},
|
{"bit_xor", "Int$bit_xor", "func(x,y:Int -> Int)"},
|
||||||
|
{"choose", "Int$choose", "func(x,y:Int -> Int)"},
|
||||||
{"clamped", "Int$clamped", "func(x,low,high:Int -> Int)"},
|
{"clamped", "Int$clamped", "func(x,low,high:Int -> Int)"},
|
||||||
{"divided_by", "Int$divided_by", "func(x,y:Int -> Int)"},
|
{"divided_by", "Int$divided_by", "func(x,y:Int -> Int)"},
|
||||||
|
{"factorial", "Int$factorial", "func(x:Int -> Int)"},
|
||||||
{"format", "Int$format", "func(i:Int, digits=0 -> Text)"},
|
{"format", "Int$format", "func(i:Int, digits=0 -> Text)"},
|
||||||
{"gcd", "Int$gcd", "func(x,y:Int -> Int)"},
|
{"gcd", "Int$gcd", "func(x,y:Int -> Int)"},
|
||||||
{"parse", "Int$parse", "func(text:Text -> Int?)"},
|
{"parse", "Int$parse", "func(text:Text -> Int?)"},
|
||||||
|
@ -382,6 +382,39 @@ public Int_t Int$prev_prime(Int_t x)
|
|||||||
return Int$from_mpz(p);
|
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*)
|
static bool Int$is_none(const void *i, const TypeInfo_t*)
|
||||||
{
|
{
|
||||||
return ((Int_t*)i)->small == 0;
|
return ((Int_t*)i)->small == 0;
|
||||||
|
@ -144,6 +144,8 @@ Int_t Int$slow_negated(Int_t x);
|
|||||||
bool Int$is_prime(Int_t x, Int_t reps);
|
bool Int$is_prime(Int_t x, Int_t reps);
|
||||||
Int_t Int$next_prime(Int_t x);
|
Int_t Int$next_prime(Int_t x);
|
||||||
Int_t Int$prev_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;
|
extern const TypeInfo_t Int$info;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user