0
# Polynomial Functions
1
2
Comprehensive polynomial operations including fitting, evaluation, arithmetic, root finding, and advanced polynomial manipulation. CuPy provides both traditional polynomial functions and object-oriented polynomial classes for mathematical analysis, curve fitting, and signal processing applications.
3
4
## Capabilities
5
6
### Basic Polynomial Operations
7
8
Fundamental polynomial operations for construction, evaluation, and manipulation of polynomial expressions.
9
10
```python { .api }
11
def poly(seq_of_zeros):
12
"""
13
Find polynomial coefficients with given roots.
14
15
Parameters:
16
- seq_of_zeros: array_like, sequence of polynomial roots
17
18
Returns:
19
- ndarray: Polynomial coefficients from highest to lowest degree
20
21
Notes:
22
- Returns coefficients of monic polynomial
23
- Opposite of roots() function
24
"""
25
26
def roots(p):
27
"""
28
Return roots of polynomial with given coefficients.
29
30
Parameters:
31
- p: array_like, polynomial coefficients from highest to lowest degree
32
33
Returns:
34
- ndarray: Roots of polynomial
35
36
Notes:
37
- Uses eigenvalue method for numerical stability
38
- Complex roots returned for higher-degree polynomials
39
"""
40
41
def polyval(p, x):
42
"""
43
Evaluate polynomial at specific values.
44
45
Parameters:
46
- p: array_like, polynomial coefficients from highest to lowest degree
47
- x: array_like, values at which to evaluate polynomial
48
49
Returns:
50
- ndarray: Polynomial values at x
51
52
Notes:
53
- Uses Horner's method for numerical stability
54
- Broadcasts over x values
55
"""
56
57
def polyder(p, m=1):
58
"""
59
Return derivative of polynomial.
60
61
Parameters:
62
- p: array_like, polynomial coefficients
63
- m: int, order of derivative (default: 1)
64
65
Returns:
66
- ndarray: Coefficients of derivative polynomial
67
"""
68
69
def polyint(p, m=1, k=None):
70
"""
71
Return antiderivative (integral) of polynomial.
72
73
Parameters:
74
- p: array_like, polynomial coefficients
75
- m: int, order of integration (default: 1)
76
- k: array_like, integration constants
77
78
Returns:
79
- ndarray: Coefficients of integrated polynomial
80
"""
81
```
82
83
### Polynomial Arithmetic
84
85
Mathematical operations between polynomials including addition, subtraction, multiplication, and division.
86
87
```python { .api }
88
def polyadd(a1, a2):
89
"""
90
Find sum of two polynomials.
91
92
Parameters:
93
- a1: array_like, coefficients of first polynomial
94
- a2: array_like, coefficients of second polynomial
95
96
Returns:
97
- ndarray: Coefficients of sum polynomial
98
99
Notes:
100
- Handles polynomials of different degrees
101
- Removes leading zeros from result
102
"""
103
104
def polysub(a1, a2):
105
"""
106
Difference (subtraction) of two polynomials.
107
108
Parameters:
109
- a1: array_like, coefficients of first polynomial
110
- a2: array_like, coefficients of second polynomial
111
112
Returns:
113
- ndarray: Coefficients of difference polynomial
114
"""
115
116
def polymul(a1, a2):
117
"""
118
Find product of two polynomials.
119
120
Parameters:
121
- a1: array_like, coefficients of first polynomial
122
- a2: array_like, coefficients of second polynomial
123
124
Returns:
125
- ndarray: Coefficients of product polynomial
126
127
Notes:
128
- Degree of product is sum of input degrees
129
- Uses convolution for efficient computation
130
"""
131
132
def polydiv(u, v):
133
"""
134
Return polynomial division quotient and remainder.
135
136
Parameters:
137
- u: array_like, dividend polynomial coefficients
138
- v: array_like, divisor polynomial coefficients
139
140
Returns:
141
- tuple: (quotient, remainder) polynomial coefficients
142
143
Notes:
144
- Performs polynomial long division
145
- Remainder degree is less than divisor degree
146
"""
147
```
148
149
### Curve Fitting
150
151
Polynomial fitting functions for data analysis, trend analysis, and function approximation from experimental data.
152
153
```python { .api }
154
def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False):
155
"""
156
Least squares polynomial fit.
157
158
Parameters:
159
- x: array_like, x-coordinates of data points
160
- y: array_like, y-coordinates of data points
161
- deg: int, degree of fitting polynomial
162
- rcond: float, relative condition number cutoff
163
- full: bool, return additional fit information
164
- w: array_like, weights for data points
165
- cov: bool or str, return covariance matrix
166
167
Returns:
168
- ndarray or tuple: Polynomial coefficients, optionally with fit info
169
170
Notes:
171
- Uses least squares method for optimal fit
172
- Higher degrees may lead to overfitting
173
- Returns coefficients from highest to lowest degree
174
"""
175
176
def polyvander(x, deg):
177
"""
178
Generate Vandermonde matrix.
179
180
Parameters:
181
- x: array_like, points at which to evaluate polynomials
182
- deg: int, degree of polynomial basis
183
184
Returns:
185
- ndarray: Vandermonde matrix of shape (..., deg + 1)
186
187
Notes:
188
- Each column is x**i for i from 0 to deg
189
- Used internally by polyfit
190
- Useful for custom fitting algorithms
191
"""
192
```
193
194
### Object-Oriented Polynomial Interface
195
196
Advanced polynomial class providing convenient methods for polynomial manipulation and analysis.
197
198
```python { .api }
199
class poly1d:
200
"""
201
One-dimensional polynomial class.
202
203
Parameters:
204
- c_or_r: array_like, polynomial coefficients or roots
205
- r: bool, if True, c_or_r contains roots instead of coefficients
206
- variable: str, variable name for string representation
207
"""
208
209
def __init__(self, c_or_r, r=False, variable=None): ...
210
211
@property
212
def coeffs(self):
213
"""Polynomial coefficients from highest to lowest degree"""
214
215
@property
216
def order(self):
217
"""Order (degree) of polynomial"""
218
219
@property
220
def roots(self):
221
"""Roots of polynomial"""
222
223
def __call__(self, val):
224
"""Evaluate polynomial at given values"""
225
226
def __add__(self, other):
227
"""Add polynomials or polynomial and scalar"""
228
229
def __sub__(self, other):
230
"""Subtract polynomials or polynomial and scalar"""
231
232
def __mul__(self, other):
233
"""Multiply polynomials or polynomial and scalar"""
234
235
def __truediv__(self, other):
236
"""Divide polynomial by scalar"""
237
238
def __pow__(self, val):
239
"""Raise polynomial to integer power"""
240
241
def deriv(self, m=1):
242
"""
243
Return mth derivative of polynomial.
244
245
Parameters:
246
- m: int, order of derivative
247
248
Returns:
249
- poly1d: Derivative polynomial
250
"""
251
252
def integ(self, m=1, k=0):
253
"""
254
Return antiderivative of polynomial.
255
256
Parameters:
257
- m: int, order of integration
258
- k: scalar or array, integration constant(s)
259
260
Returns:
261
- poly1d: Integrated polynomial
262
"""
263
```
264
265
### Advanced Polynomial Types
266
267
Specialized polynomial classes for different mathematical domains and applications.
268
269
```python { .api }
270
# Chebyshev Polynomials (cupy.polynomial.chebyshev)
271
class Chebyshev:
272
"""Chebyshev polynomial series"""
273
def __init__(self, coef, domain=None, window=None): ...
274
def __call__(self, arg): ...
275
def degree(self): ...
276
def roots(self): ...
277
def convert(self, domain=None, kind=None, window=None): ...
278
279
def chebval(x, c):
280
"""Evaluate Chebyshev series at points x"""
281
282
def chebfit(x, y, deg, rcond=None, full=False, w=None):
283
"""Least squares fit of Chebyshev polynomial to data"""
284
285
def chebroots(c):
286
"""Compute roots of Chebyshev polynomial"""
287
288
def chebder(c, m=1, scl=1, axis=0):
289
"""Differentiate Chebyshev polynomial"""
290
291
def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
292
"""Integrate Chebyshev polynomial"""
293
294
# Legendre Polynomials (cupy.polynomial.legendre)
295
class Legendre:
296
"""Legendre polynomial series"""
297
def __init__(self, coef, domain=None, window=None): ...
298
299
def legval(x, c):
300
"""Evaluate Legendre series at points x"""
301
302
def legfit(x, y, deg, rcond=None, full=False, w=None):
303
"""Least squares fit of Legendre polynomial to data"""
304
305
def legroots(c):
306
"""Compute roots of Legendre polynomial"""
307
308
# Hermite Polynomials (cupy.polynomial.hermite)
309
class Hermite:
310
"""Hermite polynomial series"""
311
def __init__(self, coef, domain=None, window=None): ...
312
313
def hermval(x, c):
314
"""Evaluate Hermite series at points x"""
315
316
def hermfit(x, y, deg, rcond=None, full=False, w=None):
317
"""Least squares fit of Hermite polynomial to data"""
318
319
# Laguerre Polynomials (cupy.polynomial.laguerre)
320
class Laguerre:
321
"""Laguerre polynomial series"""
322
def __init__(self, coef, domain=None, window=None): ...
323
324
def lagval(x, c):
325
"""Evaluate Laguerre series at points x"""
326
327
def lagfit(x, y, deg, rcond=None, full=False, w=None):
328
"""Least squares fit of Laguerre polynomial to data"""
329
```
330
331
### Usage Examples
332
333
#### Basic Polynomial Operations
334
335
```python
336
import cupy as cp
337
338
# Create polynomial from roots
339
roots = cp.array([1, -2, 3]) # Roots at x = 1, -2, 3
340
coeffs = cp.poly(roots)
341
print(f"Polynomial coefficients: {coeffs}")
342
343
# Find roots from coefficients
344
original_roots = cp.roots(coeffs)
345
print(f"Recovered roots: {original_roots}")
346
347
# Evaluate polynomial at specific points
348
x_vals = cp.linspace(-5, 5, 100)
349
y_vals = cp.polyval(coeffs, x_vals)
350
351
# Polynomial derivatives and integrals
352
first_deriv = cp.polyder(coeffs, 1)
353
second_deriv = cp.polyder(coeffs, 2)
354
integral = cp.polyint(coeffs)
355
356
print(f"First derivative coefficients: {first_deriv}")
357
print(f"Integral coefficients: {integral}")
358
```
359
360
#### Polynomial Arithmetic
361
362
```python
363
import cupy as cp
364
365
# Define two polynomials: p1(x) = x^2 + 2x + 1, p2(x) = x - 1
366
p1 = cp.array([1, 2, 1]) # x^2 + 2x + 1
367
p2 = cp.array([1, -1]) # x - 1
368
369
# Polynomial arithmetic
370
sum_poly = cp.polyadd(p1, p2) # Addition
371
diff_poly = cp.polysub(p1, p2) # Subtraction
372
prod_poly = cp.polymul(p1, p2) # Multiplication
373
quot_poly, rem_poly = cp.polydiv(p1, p2) # Division
374
375
print(f"Sum: {sum_poly}")
376
print(f"Product: {prod_poly}")
377
print(f"Quotient: {quot_poly}, Remainder: {rem_poly}")
378
379
# Verify division: p1 = p2 * quotient + remainder
380
verification = cp.polyadd(cp.polymul(p2, quot_poly), rem_poly)
381
print(f"Division verification: {cp.allclose(p1, verification)}")
382
```
383
384
#### Curve Fitting
385
386
```python
387
import cupy as cp
388
389
# Generate noisy data from known polynomial
390
true_coeffs = cp.array([0.5, -2, 1, 3]) # 0.5x^3 - 2x^2 + x + 3
391
x_data = cp.linspace(-2, 2, 50)
392
y_true = cp.polyval(true_coeffs, x_data)
393
noise = 0.1 * cp.random.randn(len(x_data))
394
y_data = y_true + noise
395
396
# Fit polynomial of various degrees
397
degrees = [2, 3, 4, 5]
398
fits = {}
399
400
for deg in degrees:
401
coeffs = cp.polyfit(x_data, y_data, deg)
402
y_fit = cp.polyval(coeffs, x_data)
403
mse = cp.mean((y_data - y_fit)**2)
404
fits[deg] = {'coeffs': coeffs, 'mse': mse}
405
406
# Find best fit
407
best_deg = min(fits.keys(), key=lambda k: fits[k]['mse'])
408
print(f"Best degree: {best_deg}, MSE: {fits[best_deg]['mse']:.6f}")
409
print(f"True coefficients: {true_coeffs}")
410
print(f"Fitted coefficients: {fits[best_deg]['coeffs']}")
411
412
# Get fit statistics
413
coeffs, residuals, rank, s = cp.polyfit(x_data, y_data, 3, full=True)
414
print(f"Residuals: {residuals}, Rank: {rank}")
415
```
416
417
#### Object-Oriented Interface
418
419
```python
420
import cupy as cp
421
422
# Create polynomial objects
423
p1 = cp.poly1d([1, -2, 1]) # x^2 - 2x + 1 = (x-1)^2
424
p2 = cp.poly1d([1, -1]) # x - 1
425
426
print(f"p1: {p1}")
427
print(f"p1 order: {p1.order}")
428
print(f"p1 roots: {p1.roots}")
429
430
# Polynomial evaluation
431
x_vals = cp.array([0, 1, 2, 3])
432
print(f"p1({x_vals}) = {p1(x_vals)}")
433
434
# Polynomial arithmetic with objects
435
p_sum = p1 + p2
436
p_prod = p1 * p2
437
p_deriv = p1.deriv()
438
p_integ = p1.integ()
439
440
print(f"Sum: {p_sum}")
441
print(f"Product: {p_prod}")
442
print(f"Derivative: {p_deriv}")
443
print(f"Integral: {p_integ}")
444
445
# Create polynomial from roots
446
roots = cp.array([1, 2, -1])
447
p_from_roots = cp.poly1d(roots, True) # r=True indicates roots
448
print(f"Polynomial from roots {roots}: {p_from_roots}")
449
```
450
451
#### Specialized Polynomial Types
452
453
```python
454
import cupy as cp
455
from cupy.polynomial import Chebyshev, Legendre
456
457
# Chebyshev polynomial approximation
458
x_data = cp.linspace(-1, 1, 100)
459
y_data = cp.sin(cp.pi * x_data) # Approximate sine function
460
461
# Fit with Chebyshev polynomials
462
cheb_coeffs = cp.polynomial.chebyshev.chebfit(x_data, y_data, 10)
463
cheb_approx = cp.polynomial.chebyshev.chebval(x_data, cheb_coeffs)
464
465
# Create Chebyshev polynomial object
466
cheb_poly = Chebyshev(cheb_coeffs)
467
print(f"Chebyshev approximation error: {cp.max(cp.abs(y_data - cheb_approx)):.6f}")
468
469
# Legendre polynomial approximation
470
leg_coeffs = cp.polynomial.legendre.legfit(x_data, y_data, 10)
471
leg_approx = cp.polynomial.legendre.legval(x_data, leg_coeffs)
472
473
leg_poly = Legendre(leg_coeffs)
474
print(f"Legendre approximation error: {cp.max(cp.abs(y_data - leg_approx)):.6f}")
475
476
# Compare approximation quality
477
cheb_error = cp.mean((y_data - cheb_approx)**2)
478
leg_error = cp.mean((y_data - leg_approx)**2)
479
print(f"Chebyshev MSE: {cheb_error:.8f}")
480
print(f"Legendre MSE: {leg_error:.8f}")
481
```
482
483
#### Signal Processing Applications
484
485
```python
486
import cupy as cp
487
488
# Polynomial detrending of signal
489
t = cp.linspace(0, 10, 1000)
490
signal = cp.sin(2 * cp.pi * t) + 0.1 * t**2 + 0.02 * t**3 # Signal with polynomial trend
491
noise = 0.1 * cp.random.randn(len(t))
492
noisy_signal = signal + noise
493
494
# Fit and remove polynomial trend
495
trend_degree = 3
496
trend_coeffs = cp.polyfit(t, noisy_signal, trend_degree)
497
trend = cp.polyval(trend_coeffs, t)
498
detrended = noisy_signal - trend
499
500
print(f"Original signal std: {cp.std(noisy_signal):.4f}")
501
print(f"Detrended signal std: {cp.std(detrended):.4f}")
502
503
# Polynomial interpolation
504
sparse_indices = cp.arange(0, len(t), 50) # Every 50th point
505
sparse_t = t[sparse_indices]
506
sparse_signal = noisy_signal[sparse_indices]
507
508
# Fit high-degree polynomial for interpolation
509
interp_coeffs = cp.polyfit(sparse_t, sparse_signal, 15)
510
interpolated = cp.polyval(interp_coeffs, t)
511
512
interp_error = cp.mean((noisy_signal - interpolated)**2)
513
print(f"Interpolation MSE: {interp_error:.6f}")
514
```
515
516
## Notes
517
518
- All polynomial operations are performed on GPU for improved performance
519
- High-degree polynomial fitting may be numerically unstable; consider regularization
520
- Specialized polynomial types (Chebyshev, Legendre, etc.) often provide better numerical properties
521
- For large datasets, consider chunked processing to manage GPU memory
522
- Polynomial evaluation uses Horner's method for numerical stability and efficiency
523
- The `poly1d` class provides convenient operator overloading for polynomial arithmetic
524
- Root finding uses eigenvalue methods which may return complex roots for real polynomials
525
- Fitting functions support weighted least squares through the `w` parameter
526
- For very high-degree polynomials, consider using orthogonal polynomial bases (Chebyshev, Legendre) for better conditioning