Skip to content

Commit 27d548f

Browse files
authored
decouple basis from storage type (#517)
* adding in explicit basis code * add polynomial_composition code path * fix bug in scalar_add * WIP: coeffs * WIP: doc adjustments * WIP: fiddle with promotion * WIP: identify DescriptorSystems issue * WIP: More promotions to match old behaviours * WIP: run doctests, adjust Chebyshev printing * WIP: convert * WIP: change Polynomial type; migrate standard-basis.jl * WIP: work to shift to new base type for most polys * doc fix=true * WIP: fixes for downstream * relax error type for nightly * add skip, not broken for a test * aqua test * WIP, update docs, reduce redundancies * WIP: more cleanup * don't test Aqua on 1.6 * clean up * test that copy is not alias * clean up identified invalidations * remove tests of deprecated (now removed) functions * reorg docs * fix sparse * * reorg docs * fix sparse * * SP test * WIP: more cleanup * version bump; signal breaking changes
1 parent 0b78913 commit 27d548f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3676
-2471
lines changed

.github/workflows/downstream.yml

+8-3
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@ jobs:
1414
strategy:
1515
fail-fast: false
1616
matrix:
17-
julia-version: [1,1.6]
17+
julia-version: [1]
1818
os: [ubuntu-latest]
1919
package:
20-
- {user: jverzani, repo: SpecialPolynomials.jl, group: All}
2120
- {user: JuliaControl, repo: ControlSystems.jl, group: All}
22-
21+
- {user: andreasvarga, repo: DescriptorSystems.jl, group: All}
22+
- {user: andreasvarga, repo: MatrixPencils.jl, group: All}
23+
- {user: JuliaDSP, repo: DSP.jl, group: All}
24+
- {user: tkluck, repo: GaloisFields.jl, group: All}
25+
- {user: jverzani, repo: SpecialPolynomials.jl, group: All}
26+
- {user: JuliaGNI, repo: QuadratureRules.jl, group: All}
27+
- {user: JuliaGNI, repo: RungeKutta.jl, group: All}
2328
steps:
2429
- uses: actions/checkout@v3
2530
- uses: julia-actions/setup-julia@v1

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ docs/site/
55
*.jl.mem
66

77
Manifest.toml
8+
archive/

Project.toml

+7-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ name = "Polynomials"
22
uuid = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
33
license = "MIT"
44
author = "JuliaMath"
5-
version = "3.2.15"
5+
version = "4.0.0"
66

77
[deps]
88
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
99
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1010
MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
1111
MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
1212
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
13+
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"
1314

1415
[weakdeps]
1516
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
@@ -26,19 +27,21 @@ ChainRulesCore = "1"
2627
MakieCore = "0.6"
2728
MutableArithmetics = "1"
2829
RecipesBase = "0.7, 0.8, 1"
30+
Setfield = "1"
2931
julia = "1.6"
3032

3133
[extras]
34+
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
3235
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
33-
MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
3436
ChainRulesTestUtils = "cdddcdb0-9152-4a09-a978-84456f9df70a"
3537
DualNumbers = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
3638
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
37-
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
39+
MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
3840
MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
41+
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
3942
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
4043
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
4144
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
4245

4346
[targets]
44-
test = ["ChainRulesCore", "DualNumbers", "LinearAlgebra", "SparseArrays", "OffsetArrays", "SpecialFunctions", "Test"]
47+
test = ["Aqua", "ChainRulesCore", "DualNumbers", "LinearAlgebra", "SparseArrays", "OffsetArrays", "SpecialFunctions", "Test"]

README.md

+2-320
Original file line numberDiff line numberDiff line change
@@ -1,326 +1,8 @@
11
# Polynomials.jl
22

3-
Basic arithmetic, integration, differentiation, evaluation, and root finding over dense univariate [polynomials](https://en.wikipedia.org/wiki/Polynomial).
3+
Basic arithmetic, integration, differentiation, evaluation, root finding, and fitting for
4+
univariate [polynomials](https://en.wikipedia.org/wiki/Polynomial) in [Julia](https://julialang.org/).
45

56
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaMath.github.io/Polynomials.jl/stable)
67
[![CI](https://github.com/JuliaMath/Polynomials.jl/actions/workflows/ci.yml/badge.svg)](https://github.com/JuliaMath/Polynomials.jl/actions/workflows/ci.yml)
78
[![codecov](https://codecov.io/gh/JuliaMath/Polynomials.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaMath/Polynomials.jl)
8-
9-
10-
## Installation
11-
12-
```julia
13-
(v1.6) pkg> add Polynomials
14-
```
15-
16-
This package supports Julia v1.6 and later.
17-
18-
## Available Types of Polynomials
19-
20-
* `Polynomial` –⁠ standard basis polynomials, $a(x) = a_0 + a_1 x + a_2 x^2 + … + a_n x^n$ for $n ≥ 0$.
21-
* `ImmutablePolynomial` –⁠ standard basis polynomials backed by a [Tuple type](https://docs.julialang.org/en/v1/manual/functions/#Tuples-1) for faster evaluation of values
22-
* `SparsePolynomial` –⁠ standard basis polynomial backed by a [dictionary](https://docs.julialang.org/en/v1/base/collections/#Dictionaries-1) to hold sparse high-degree polynomials
23-
* `LaurentPolynomial` –⁠ [Laurent polynomials](https://docs.julialang.org/en/v1/base/collections/#Dictionaries-1), $a(x) = a_m x^m + … + a_n x^n$ for $m ≤ n$ and $m,n ∈ ℤ$. This is backed by an [offset array](https://github.com/JuliaArrays/OffsetArrays.jl); for example, if $m<0$ and $n>0$, we obtain $a(x) = a_m x^m + … + a_{-1} x^{-1} + a_0 + a_1 x + … + a_n x^n$
24-
* `FactoredPolynomial` –⁠ standard basis polynomials, storing the roots, with multiplicity, and leading coefficient of a polynomial
25-
* `ChebyshevT` –⁠ [Chebyshev polynomials](https://en.wikipedia.org/wiki/Chebyshev_polynomials) of the first kind
26-
* `RationalFunction` - a type for ratios of polynomials.
27-
28-
## Usage
29-
30-
```julia
31-
julia> using Polynomials
32-
```
33-
34-
### Construction and Evaluation
35-
36-
Construct a polynomial from an array (a vector) of its coefficients, lowest order first.
37-
38-
```julia
39-
julia> Polynomial([1,0,3,4])
40-
Polynomial(1 + 3*x^2 + 4*x^3)
41-
```
42-
43-
Optionally, the variable of the polynomial can be specified.
44-
45-
```julia
46-
julia> Polynomial([1,2,3], :s)
47-
Polynomial(1 + 2*s + 3*s^2)
48-
```
49-
50-
Construct a polynomial from its roots.
51-
52-
```julia
53-
julia> fromroots([1,2,3]) # (x-1)*(x-2)*(x-3)
54-
Polynomial(-6 + 11*x - 6*x^2 + x^3)
55-
```
56-
57-
Evaluate the polynomial `p` at `x`.
58-
59-
```julia
60-
julia> p = Polynomial([1, 0, -1]);
61-
julia> p(0.1)
62-
0.99
63-
```
64-
65-
### Arithmetic
66-
67-
Methods are added to the usual arithmetic operators so that they work on polynomials, and combinations of polynomials and scalars.
68-
69-
```julia
70-
julia> p = Polynomial([1,2])
71-
Polynomial(1 + 2*x)
72-
73-
julia> q = Polynomial([1, 0, -1])
74-
Polynomial(1 - x^2)
75-
76-
julia> p - q
77-
Polynomial(2*x + x^2)
78-
79-
julia> p = Polynomial([1,2])
80-
Polynomial(1 + 2*x)
81-
82-
julia> q = Polynomial([1, 0, -1])
83-
Polynomial(1 - x^2)
84-
85-
julia> 2p
86-
Polynomial(2 + 4*x)
87-
88-
julia> 2+p
89-
Polynomial(3 + 2*x)
90-
91-
julia> p - q
92-
Polynomial(2*x + x^2)
93-
94-
julia> p * q
95-
Polynomial(1 + 2*x - x^2 - 2*x^3)
96-
97-
julia> q / 2
98-
Polynomial(0.5 - 0.5*x^2)
99-
100-
julia> q ÷ p # `div`, also `rem` and `divrem`
101-
Polynomial(0.25 - 0.5*x)
102-
```
103-
104-
Most operations involving polynomials with different variables will error.
105-
106-
```julia
107-
julia> p = Polynomial([1, 2, 3], :x);
108-
julia> q = Polynomial([1, 2, 3], :s);
109-
julia> p + q
110-
ERROR: ArgumentError: Polynomials have different indeterminates
111-
```
112-
113-
#### Construction and Evaluation
114-
115-
While polynomials of type `Polynomial` are mutable objects, operations such as
116-
`+`, `-`, `*`, always create new polynomials without modifying its arguments.
117-
The time needed for these allocations and copies of the polynomial coefficients
118-
may be noticeable in some use cases. This is amplified when the coefficients
119-
are for instance `BigInt` or `BigFloat` which are mutable themselves.
120-
This can be avoided by modifying existing polynomials to contain the result
121-
of the operation using the [MutableArithmetics (MA) API](https://github.com/jump-dev/MutableArithmetics.jl).
122-
123-
Consider for instance the following arrays of polynomials
124-
```julia
125-
using Polynomials
126-
d, m, n = 30, 20, 20
127-
p(d) = Polynomial(big.(1:d))
128-
A = [p(d) for i in 1:m, j in 1:n]
129-
b = [p(d) for i in 1:n]
130-
```
131-
132-
In this case, the arrays are mutable objects for which the elements are mutable
133-
polynomials which have mutable coefficients (`BigInt`s).
134-
These three nested levels of mutable objects communicate with the MA
135-
API in order to reduce allocation.
136-
Calling `A * b` requires approximately 40 MiB due to 2 M allocations
137-
as it does not exploit any mutability.
138-
139-
Using
140-
141-
```julia
142-
using PolynomialsMutableArithmetics
143-
```
144-
145-
to register `Polynomials` with `MutableArithmetics`, then multiplying with:
146-
147-
```julia
148-
using MutableArithmetics
149-
const MA = MutableArithmetics
150-
MA.operate(*, A, b)
151-
```
152-
153-
exploits the mutability and hence only allocates approximately 70 KiB due to 4 k
154-
allocations.
155-
156-
If the resulting vector is already allocated, e.g.,
157-
158-
```julia
159-
z(d) = Polynomial([zero(BigInt) for i in 1:d])
160-
c = [z(2d - 1) for i in 1:m]
161-
```
162-
163-
then we can exploit its mutability with
164-
165-
```julia
166-
MA.operate!(MA.add_mul, c, A, b)
167-
```
168-
169-
to reduce the allocation down to 48 bytes due to 3 allocations.
170-
171-
These remaining allocations are due to the `BigInt` buffer used to
172-
store the result of intermediate multiplications. This buffer can be
173-
preallocated with:
174-
175-
```julia
176-
buffer = MA.buffer_for(MA.add_mul, typeof(c), typeof(A), typeof(b))
177-
MA.buffered_operate!(buffer, MA.add_mul, c, A, b)
178-
```
179-
180-
then the second line is allocation-free.
181-
182-
The `MA.@rewrite` macro rewrite an expression into an equivalent code that
183-
exploit the mutability of the intermediate results.
184-
For instance
185-
```julia
186-
MA.@rewrite(A1 * b1 + A2 * b2)
187-
```
188-
is rewritten into
189-
```julia
190-
c = MA.operate!(MA.add_mul, MA.Zero(), A1, b1)
191-
MA.operate!(MA.add_mul, c, A2, b2)
192-
```
193-
which is equivalent to
194-
```julia
195-
c = MA.operate(*, A1, b1)
196-
MA.mutable_operate!(MA.add_mul, c, A2, b2)
197-
```
198-
199-
*Note that currently, only the `Polynomial` type implements the API and it only
200-
implements part of it.*
201-
202-
### Integrals and Derivatives
203-
204-
Integrate the polynomial `p` term by term, optionally adding a constant
205-
term `k`. The degree of the resulting polynomial is one higher than the
206-
degree of `p` (for a nonzero polynomial).
207-
208-
```julia
209-
julia> integrate(Polynomial([1, 0, -1]))
210-
Polynomial(1.0*x - 0.3333333333333333*x^3)
211-
212-
julia> integrate(Polynomial([1, 0, -1]), 2)
213-
Polynomial(2.0 + 1.0*x - 0.3333333333333333*x^3)
214-
```
215-
216-
Differentiate the polynomial `p` term by term. For non-zero
217-
polynomials the degree of the resulting polynomial is one lower than
218-
the degree of `p`.
219-
220-
```julia
221-
julia> derivative(Polynomial([1, 3, -1]))
222-
Polynomial(3 - 2*x)
223-
```
224-
225-
### Root-finding
226-
227-
228-
Return the roots (zeros) of `p`, with multiplicity. The number of
229-
roots returned is equal to the degree of `p`. By design, this is not type-stable, the returned roots may be real or complex.
230-
231-
```julia
232-
julia> roots(Polynomial([1, 0, -1]))
233-
2-element Vector{Float64}:
234-
-1.0
235-
1.0
236-
237-
julia> roots(Polynomial([1, 0, 1]))
238-
2-element Vector{ComplexF64}:
239-
0.0 - 1.0im
240-
0.0 + 1.0im
241-
242-
julia> roots(Polynomial([0, 0, 1]))
243-
2-element Vector{Float64}:
244-
0.0
245-
0.0
246-
```
247-
248-
### Fitting arbitrary data
249-
250-
Fit a polynomial (of degree `deg` or less) to `x` and `y` using a least-squares approximation.
251-
252-
```julia
253-
julia> xs = 0:4; ys = @. exp(-xs) + sin(xs);
254-
255-
julia> fit(xs, ys) |> p -> round.(coeffs(p), digits=4) |> Polynomial
256-
Polynomial(1.0 + 0.0593*x + 0.3959*x^2 - 0.2846*x^3 + 0.0387*x^4)
257-
258-
julia> fit(ChebyshevT, xs, ys, 2) |> p -> round.(coeffs(p), digits=4) |> ChebyshevT
259-
ChebyshevT(0.5413T_0(x) - 0.8991T_1(x) - 0.4238T_2(x))
260-
```
261-
262-
Visual example:
263-
264-
![fit example](https://user-images.githubusercontent.com/14099459/70382587-9e055500-1902-11ea-8952-3f03ae08b7dc.png)
265-
266-
### Other methods
267-
268-
Polynomial objects also have other methods:
269-
270-
* For standard basis polynomials, 0-based indexing is used to extract
271-
the coefficients of `[a0, a1, a2, ...]`; for mutable polynomials,
272-
coefficients may be changed using indexing notation.
273-
274-
* `coeffs`: returns the coefficients
275-
276-
* `degree`: returns the polynomial degree, `length` is number of stored coefficients
277-
278-
* `variable`: returns the polynomial symbol as a polynomial in the underlying type
279-
280-
* `LinearAlgebra.norm`: find the `p`-norm of a polynomial
281-
282-
* `conj`: finds the conjugate of a polynomial over a complex field
283-
284-
* `truncate`: set to 0 all small terms in a polynomial;
285-
286-
* `chop` chops off any small leading values that may arise due to floating point operations.
287-
288-
* `gcd`: greatest common divisor of two polynomials.
289-
290-
* `Pade`: Return the
291-
[Padé approximant](https://en.wikipedia.org/wiki/Pad%C3%A9_approximant) of order `m/n` for a polynomial as a `Pade` object.
292-
293-
294-
## Related Packages
295-
296-
* [StaticUnivariatePolynomials.jl](https://github.com/tkoolen/StaticUnivariatePolynomials.jl) Fixed-size univariate polynomials backed by a Tuple
297-
298-
* [MultiPoly.jl](https://github.com/daviddelaat/MultiPoly.jl) for sparse multivariate polynomials
299-
300-
* [DynamicPolynomials.jl](https://github.com/JuliaAlgebra/DynamicPolynomials.jl) Multivariate polynomials implementation of commutative and non-commutative variables
301-
302-
* [MultivariatePolynomials.jl](https://github.com/JuliaAlgebra/MultivariatePolynomials.jl) for multivariate polynomials and moments of commutative or non-commutative variables
303-
304-
* [PolynomialRings.jl](https://github.com/tkluck/PolynomialRings.jl) A library for arithmetic and algebra with multi-variable polynomials.
305-
306-
* [AbstractAlgebra.jl](https://github.com/wbhart/AbstractAlgebra.jl), [Nemo.jl](https://github.com/wbhart/Nemo.jl) for generic polynomial rings, matrix spaces, fraction fields, residue rings, power series, [Hecke.jl](https://github.com/thofma/Hecke.jl) for algebraic number theory.
307-
308-
* [LaurentPolynomials.jl](https://github.com/jmichel7/LaurentPolynomials.jl) A package for Laurent polynomials.
309-
310-
* [CommutativeAlgebra.jl](https://github.com/KlausC/CommutativeRings.jl) the start of a computer algebra system specialized to discrete calculations with support for polynomials.
311-
312-
* [PolynomialRoots.jl](https://github.com/giordano/PolynomialRoots.jl) for a fast complex polynomial root finder. For larger degree problems, also [FastPolynomialRoots](https://github.com/andreasnoack/FastPolynomialRoots.jl) and [AMRVW](https://github.com/jverzani/AMRVW.jl). For real roots only [RealPolynomialRoots](https://github.com/jverzani/RealPolynomialRoots.jl).
313-
314-
315-
* [SpecialPolynomials.jl](https://github.com/jverzani/SpecialPolynomials.jl) A package providing various polynomial types beyond the standard basis polynomials in `Polynomials.jl`. Includes interpolating polynomials, Bernstein polynomials, and classical orthogonal polynomials.
316-
317-
* [ClassicalOrthogonalPolynomials.jl](https://github.com/JuliaApproximation/ClassicalOrthogonalPolynomials.jl) A Julia package for classical orthogonal polynomials and expansions. Includes `chebyshevt`, `chebyshevu`, `legendrep`, `jacobip`, `ultrasphericalc`, `hermiteh`, and `laguerrel`. The same repository includes `FastGaussQuadrature.jl`, `FastTransforms.jl`, and the `ApproxFun` packages.
318-
319-
320-
## Legacy code
321-
322-
As of v0.7, the internals of this package were greatly generalized and new types and method names were introduced. For compatibility purposes, legacy code can be run after issuing `using Polynomials.PolyCompat`.
323-
324-
## Contributing
325-
326-
If you are interested in contributing, feel free to open an issue or pull request to get started.

0 commit comments

Comments
 (0)