|
11 | 11 | from matplotlib import _api |
12 | 12 |
|
13 | 13 |
|
14 | | -# same algorithm as 3.8's math.comb |
15 | | -@np.vectorize |
16 | | -@lru_cache(maxsize=128) |
17 | | -def _comb(n, k): |
18 | | - if k > n: |
19 | | - return 0 |
20 | | - k = min(k, n - k) |
21 | | - i = np.arange(1, k + 1) |
22 | | - return np.prod((n + 1 - i)/i).astype(int) |
| 14 | +@lru_cache(maxsize=16) |
| 15 | +def _get_coeff_matrix(n): |
| 16 | + """ |
| 17 | + Compute the matrix for converting Bezier control points to polynomial |
| 18 | + coefficients for a curve of degree n. |
| 19 | +
|
| 20 | + The matrix M is such that M @ control_points gives polynomial coefficients. |
| 21 | + Entry M[j, i] = C(n, j) * (-1)^(i+j) * C(j, i) where C is the binomial |
| 22 | + coefficient. |
| 23 | + """ |
| 24 | + def _comb(n, k): |
| 25 | + return np.vectorize(math.comb)(n, k) |
| 26 | + |
| 27 | + j = np.arange(n + 1)[:, None] |
| 28 | + i = np.arange(n + 1)[None, :] # _comb is non-zero for i <= j |
| 29 | + prefactor = (-1) ** (i + j) * _comb(j, i) # j on axis 0, i on axis 1 |
| 30 | + return (_comb(n, j) * prefactor).astype(float) |
23 | 31 |
|
24 | 32 |
|
25 | 33 | class NonIntersectingPathException(ValueError): |
@@ -279,11 +287,7 @@ def polynomial_coefficients(self): |
279 | 287 | if n > 10: |
280 | 288 | warnings.warn("Polynomial coefficients formula unstable for high " |
281 | 289 | "order Bezier curves!", RuntimeWarning) |
282 | | - P = self.control_points |
283 | | - j = np.arange(n+1)[:, None] |
284 | | - i = np.arange(n+1)[None, :] # _comb is non-zero for i <= j |
285 | | - prefactor = (-1)**(i + j) * _comb(j, i) # j on axis 0, i on axis 1 |
286 | | - return _comb(n, j) * prefactor @ P # j on axis 0, self.dimension on 1 |
| 290 | + return _get_coeff_matrix(n) @ self.control_points |
287 | 291 |
|
288 | 292 | def axis_aligned_extrema(self): |
289 | 293 | """ |
|
0 commit comments