Skip to content

Commit 8be6bc9

Browse files
authored
add unexported critical points (#458)
* add unexported critical points * consolidate * clean up * add precompiles
1 parent cb23e64 commit 8be6bc9

6 files changed

+78
-1
lines changed

Project.toml

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

77
[deps]
88
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

src/Polynomials.jl

+2
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,6 @@ include("rational-functions/plot-recipes.jl")
3535
# compat; opt-in with `using Polynomials.PolyCompat`
3636
include("polynomials/Poly.jl")
3737

38+
include("precompiles.jl")
39+
3840
end # module

src/common.jl

+49
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,55 @@ Calculate the pseudo-Vandermonde matrix of the given polynomial type with the gi
205205
"""
206206
vander(::Type{<:AbstractPolynomial}, x::AbstractVector, deg::Integer)
207207

208+
209+
"""
210+
critical_points(p::AbstractPolynomial{<:Real}, I=domain(p); endpoints::Bool=true)
211+
212+
Return the critical points of `p` (real zeros of the derivative) within `I` in sorted order.
213+
214+
* `p`: a polynomial
215+
216+
* `I`: a specification of a closed or infinite domain, defaulting to `Polynomials.domain(p)`. When specified, the values of `extrema(I)` are used with closed endpoints when finite.
217+
218+
* `endpoints::Bool`: if `true`, return the endpoints of `I` along with the critical points
219+
220+
221+
Can be used in conjuction with `findmax`, `findmin`, `argmax`, `argmin`, `extrema`, etc.
222+
223+
## Example
224+
```
225+
x = variable()
226+
p = x^2 - 2
227+
cps = Polynomials.critical_points(p)
228+
findmin(p, cps) # (-2.0, 2.0)
229+
argmin(p, cps) # 0.0
230+
extrema(p, cps) # (-2.0, Inf)
231+
cps = Polynomials.critical_points(p, (0, 2))
232+
extrema(p, cps) # (-2.0, 2.0)
233+
```
234+
"""
235+
function critical_points(p::AbstractPolynomial{T}, I = domain(p);
236+
endpoints::Bool=true) where {T <: Real}
237+
238+
I′ = Interval(I)
239+
l, r = extrema(I′)
240+
241+
q = Polynomials.ngcd(derivative(p), derivative(p,2)).v
242+
pts = sort(real.(filter(isreal, roots(q))))
243+
pts = filter(in(I′), pts)
244+
245+
!endpoints && return pts
246+
247+
l !== first(pts) && pushfirst!(pts, l)
248+
r != last(pts) && push!(pts, r)
249+
pts
250+
end
251+
252+
253+
254+
255+
256+
208257
"""
209258
integrate(p::AbstractPolynomial)
210259

src/contrib.jl

+2
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ struct Interval{T, L <: Bound, R <: Bound}
174174
end
175175
Interval(f, l) = Interval{Closed, Closed}(f, l)
176176
end
177+
Interval(I::Interval) = I
178+
Interval(I) = Interval(extrema(I)...)
177179

178180
bounds_types(x::Interval{T,L,R}) where {T,L,R} = (L, R)
179181

src/precompiles.jl

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# precompiles
2+
3+
p = fromroots(Polynomial, [1,1,2])
4+
Multroot.multroot(p)
5+
gcd(p, derivative(p); method=:numerical)
6+
uvw(p, derivative(p); method=:numerical)

test/StandardBasis.jl

+18
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,24 @@ end
900900
end
901901
end
902902

903+
@testset "critical points" begin
904+
for P in (Polynomial, ImmutablePolynomial)
905+
p = fromroots(P, [-1,-1, 2]) |> integrate
906+
cps = Polynomials.critical_points(p, (-5,5); endpoints=false)
907+
@test all(cps .≈ [-1, 2])
908+
cps = Polynomials.critical_points(p, (0,5); endpoints=false)
909+
@test all(cps .≈ [2])
910+
911+
cps = Polynomials.critical_points(p)
912+
m, i = findmin(p, cps)
913+
@test m -6.0
914+
x = argmin(p, cps)
915+
@test x 2.0
916+
mn, mx = extrema(p, cps)
917+
@test mn -6.0 && isinf(mx)
918+
end
919+
end
920+
903921
@testset "Integrals and Derivatives" begin
904922
# Integrals derivatives
905923
@testset for P in Ps

0 commit comments

Comments
 (0)