Skip to content

Commit 905e749

Browse files
authored
Merge pull request #250 from robin-oval/feature/binomial_coefficient
binomial coefficient function
2 parents 573abef + 18f429c commit 905e749

File tree

4 files changed

+50
-30
lines changed

4 files changed

+50
-30
lines changed

src/compas/geometry/_primitives/curve.py

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from __future__ import absolute_import
33
from __future__ import division
44

5-
from math import factorial
6-
75
from compas.geometry.basic import scale_vector
86
from compas.geometry.basic import normalize_vector
97
from compas.geometry.basic import add_vectors
@@ -12,36 +10,11 @@
1210
from compas.geometry._primitives import Point
1311
from compas.geometry._primitives import Vector
1412

13+
from compas.utilities import binomial_coefficient
1514

1615
__all__ = ['Bezier']
1716

1817

19-
def binomial(n, k):
20-
"""Returns the binomial coefficient of the :math:`x^k` term in the
21-
polynomial expansion of the binmoial power :math:`(1 + x)^n` [wikipedia2017j]_.
22-
23-
Notes
24-
-----
25-
Arranging binomial coefficients into rows for successive values of `n`,
26-
and in which `k` ranges from 0 to `n`, gives a triangular array known as
27-
Pascal's triangle.
28-
29-
Parameters
30-
----------
31-
n : int
32-
The number of terms.
33-
k : int
34-
The index of the coefficient.
35-
36-
Returns
37-
-------
38-
int
39-
The coefficient.
40-
41-
"""
42-
return factorial(n) / float(factorial(k) * factorial(n - k))
43-
44-
4518
def bernstein(n, k, t):
4619
"""k:sup:`th` of `n` + 1 Bernstein basis polynomials of degree `n`. A
4720
weighted linear combination of these basis polynomials is called a Bernstein
@@ -71,7 +44,7 @@ def bernstein(n, k, t):
7144
return 0
7245
if k > n:
7346
return 0
74-
return binomial(n, k) * t ** k * (1 - t) ** (n - k)
47+
return binomial_coefficient(n, k) * t ** k * (1 - t) ** (n - k)
7548

7649

7750
class BezierException(Exception):

src/compas/utilities/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
:nosignatures:
7373
7474
fibonacci
75+
binomial_coefficient
7576
7677
itertools
7778
=========

src/compas/utilities/functions.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
from __future__ import absolute_import
33
from __future__ import division
44

5+
from math import factorial
56

67
__all__ = [
7-
'fibonacci'
8+
'fibonacci',
9+
'binomial_coefficient'
810
]
911

1012

@@ -19,10 +21,37 @@ def fibonacci(n, memo={}):
1921
memo[n] = fibonacci(n - 2, memo) + fibonacci(n - 1, memo)
2022
return memo[n]
2123

24+
def binomial_coefficient(n, k):
25+
"""Returns the binomial coefficient of the :math:`x^k` term in the
26+
polynomial expansion of the binomial power :math:`(1 + x)^n` [wikipedia2017j]_.
27+
28+
Notes
29+
-----
30+
Arranging binomial coefficients into rows for successive values of `n`,
31+
and in which `k` ranges from 0 to `n`, gives a triangular array known as
32+
Pascal's triangle.
33+
34+
Parameters
35+
----------
36+
n : int
37+
The number of terms.
38+
k : int
39+
The index of the coefficient.
40+
41+
Returns
42+
-------
43+
int
44+
The coefficient.
45+
46+
"""
47+
return int(factorial(n) / float(factorial(k) * factorial(n - k)))
48+
2249
# ==============================================================================
2350
# Main
2451
# ==============================================================================
2552

2653
if __name__ == "__main__":
2754

2855
print(fibonacci(100))
56+
57+
print(binomial_coefficient(10, 4))

tests/utilities/test_functions.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import pytest
2+
3+
from compas.utilities import binomial_coefficient
4+
5+
6+
@pytest.mark.parametrize(("n", "k", "result"),
7+
[
8+
pytest.param(3, 1, 3),
9+
pytest.param(21, 10, 352716),
10+
pytest.param(10, 0, 1),
11+
pytest.param(0, 0, 1),
12+
pytest.param(1, 2, 0, marks=pytest.mark.xfail(raises=ValueError)),
13+
pytest.param(2, -1, 0, marks=pytest.mark.xfail(raises=ValueError)),
14+
]
15+
)
16+
def test_binomial(n, k, result):
17+
assert binomial_coefficient(n, k) == pytest.approx(result)

0 commit comments

Comments
 (0)