diff --git a/Project.toml b/Project.toml index beddaa9c..82dfb77c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "TaylorSeries" uuid = "6aa5eb33-94cf-58f4-a9d0-e4b2c4fc25ea" repo = "https://github.com/JuliaDiff/TaylorSeries.jl.git" -version = "0.10.3" +version = "0.11.0" [deps] InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" diff --git a/benchmark/REQUIRE b/benchmark/REQUIRE new file mode 100644 index 00000000..6ce08119 --- /dev/null +++ b/benchmark/REQUIRE @@ -0,0 +1,2 @@ +BenchmarkTools 0.3.1 +PkgBenchmark 0.1.1 diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl new file mode 100644 index 00000000..6cdc76ce --- /dev/null +++ b/benchmark/benchmarks.jl @@ -0,0 +1,57 @@ +using BenchmarkTools, TaylorSeries + +const SUITE = BenchmarkGroup() + +S = SUITE["Constructors"] = BenchmarkGroup() +for i in (05,10,20,50) + x = rand(i) + t = tuple(x...) + S["STaylor1(x::Array[len = $i])"] = @benchmarkable STaylor1($x) + S["STaylor1(x::Float64, Val($i))"] = @benchmarkable STaylor1($t) +end + +function f(g, x, y, n) + t = x + for i=1:n + t = g(x,y) + end + t +end +function f(g, x, n) + t = x + for i=1:n + t = g(t) + end + t +end +n = 100 +dims = (5,20) + +S = SUITE["arithmetic"] = BenchmarkGroup() +for i in dims + r = rand(i) + x = Taylor1(r) + x2 = Taylor1(r) + q = STaylor1(r) + q2 = STaylor1(r) + y = rand() + for g in (+, -, /, *) + S["Taylor1{$i,Float64} $(Symbol(g)) Float64"] = @benchmarkable f($g, $x, $y, $n) + S["STaylor1{$i,Float64} $(Symbol(g)) Float64"] = @benchmarkable f($g, $q, $y, $n) + S["Taylor1{$i,Float64} $(Symbol(g)) Taylor1{$i,Float64}"] = @benchmarkable f($g, $x, $x2, $n) + S["STaylor1{$i,Float64} $(Symbol(g)) STaylor1{$i,Float64}"] = @benchmarkable f($g, $q, $q2, $n) + end +end + +S = SUITE["functions"] = BenchmarkGroup() +for i in dims + r = rand(i) + x = Taylor1(r) + q = STaylor1(r) + y = rand() + for g in (exp, abs, zero, one, real, imag, conj, adjoint, iszero, isnan, + isinf, deg2rad, rad2deg) + S["$(Symbol(g))(Taylor1{Float64}), len = $i"] = @benchmarkable f($g, $x, $n) + S["$(Symbol(g))(STaylor1{$i,Float64}),"] = @benchmarkable f($g, $q, $n) + end +end diff --git a/benchmark/run_benchmark.jl b/benchmark/run_benchmark.jl new file mode 100644 index 00000000..c074a539 --- /dev/null +++ b/benchmark/run_benchmark.jl @@ -0,0 +1,12 @@ +using PkgBenchmark +results = benchmarkpkg("TaylorSeries") +show(results) + +#= +# specify tag and uncommit to benchmark versus prior tagged version +tag = +results = judge("TaylorSeries", tag) +show(results) +=# + +export_markdown("results.md", results) diff --git a/benchmark/tune.json b/benchmark/tune.json new file mode 100644 index 00000000..229325de --- /dev/null +++ b/benchmark/tune.json @@ -0,0 +1 @@ +[{"Julia":"1.3.1","BenchmarkTools":"0.4.3"},[["BenchmarkGroup",{"data":{"Constructors":["BenchmarkGroup",{"data":{"STaylor1(x::Float64, Val(5))":["BenchmarkTools.Parameters",{"gctrial":true,"time_tolerance":0.05,"samples":10000,"evals":12,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"STaylor1(x::Array[length = 10])":["BenchmarkTools.Parameters",{"gctrial":true,"time_tolerance":0.05,"samples":10000,"evals":15,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"STaylor1(x::Float64, Val(10))":["BenchmarkTools.Parameters",{"gctrial":true,"time_tolerance":0.05,"samples":10000,"evals":24,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"STaylor1(x::Float64, Val(50))":["BenchmarkTools.Parameters",{"gctrial":true,"time_tolerance":0.05,"samples":10000,"evals":22,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"STaylor1(x::Array[length = 5])":["BenchmarkTools.Parameters",{"gctrial":true,"time_tolerance":0.05,"samples":10000,"evals":10,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}],"STaylor1(x::Array[length = 50])":["BenchmarkTools.Parameters",{"gctrial":true,"time_tolerance":0.05,"samples":10000,"evals":10,"gcsample":false,"seconds":5.0,"overhead":0.0,"memory_tolerance":0.01}]},"tags":[]}]},"tags":[]}]]] \ No newline at end of file diff --git a/src/arithmetic.jl b/src/arithmetic.jl index 7a3ec714..9680a9de 100644 --- a/src/arithmetic.jl +++ b/src/arithmetic.jl @@ -205,7 +205,6 @@ end -(a::Taylor1{T}, b::TaylorN{S}) where {T<:NumberNotSeries,S<:NumberNotSeries} = -(promote(a,b)...) - ## Multiplication ## for T in (:Taylor1, :HomogeneousPolynomial, :TaylorN) diff --git a/src/auxiliary.jl b/src/auxiliary.jl index 98741c3b..541598e5 100644 --- a/src/auxiliary.jl +++ b/src/auxiliary.jl @@ -103,7 +103,6 @@ function setindex!(a::Taylor1{T}, x::Array{T,1}, u::StepRange{Int,Int}) where {T end end - """ getcoeff(a, v) @@ -237,7 +236,6 @@ for T in (:Taylor1, :HomogeneousPolynomial, :TaylorN) end end - ## fixorder ## for T in (:Taylor1, :TaylorN) @eval begin @@ -271,7 +269,6 @@ function Base.findlast(a::Taylor1{T}) where {T<:Number} return last-1 end - ## copyto! ## # Inspired from base/abstractarray.jl, line 665 for T in (:Taylor1, :HomogeneousPolynomial, :TaylorN) @@ -317,3 +314,46 @@ linear_polynomial(a::TaylorN) = TaylorN([a[1]]) linear_polynomial(a::Vector{T}) where {T<:Number} = linear_polynomial.(a) linear_polynomial(a::Number) = a + + +#= +Tuple operations taken from ForwardDiff.jl + +Copyright (c) 2015: Jarrett Revels, Theodore Papamarkou, Miles Lubin, and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +=# +function tupexpr(f, N) + ex = Expr(:tuple, [f(i) for i=1:N]...) + return quote + $(Expr(:meta, :inline)) + @inbounds return $ex + end +end + +@generated function scale_tuple(tup::NTuple{N}, x) where N + return tupexpr(i -> :(tup[$i] * x), N) +end + +@generated function div_tuple_by_scalar(tup::NTuple{N}, x) where N + return tupexpr(i -> :(tup[$i] / x), N) +end + +@generated function add_tuples(a::NTuple{N}, b::NTuple{N}) where N + return tupexpr(i -> :(a[$i] + b[$i]), N) +end + +@generated function sub_tuples(a::NTuple{N}, b::NTuple{N}) where N + return tupexpr(i -> :(a[$i] - b[$i]), N) +end + +@generated function minus_tuple(tup::NTuple{N}) where N + return tupexpr(i -> :(-tup[$i]), N) +end + +@generated function mul_tuples(a::NTuple{N}, b::NTuple{N}, afactor, bfactor) where N + return tupexpr(i -> :((afactor * a[$i]) + (bfactor * b[$i])), N) +end diff --git a/src/broadcasting.jl b/src/broadcasting.jl index 4c7790ea..2679010e 100644 --- a/src/broadcasting.jl +++ b/src/broadcasting.jl @@ -12,7 +12,7 @@ import .Broadcast: BroadcastStyle, Broadcasted, broadcasted # BroadcastStyle definitions and basic precedence rules struct Taylor1Style{T} <: Base.Broadcast.AbstractArrayStyle{0} end -Taylor1Style{T}(::Val{N}) where {T, N}= Base.Broadcast.DefaultArrayStyle{N}() +Taylor1Style{T}(::Val{N}) where {T, N} = Base.Broadcast.DefaultArrayStyle{N}() BroadcastStyle(::Type{<:Taylor1{T}}) where {T} = Taylor1Style{T}() BroadcastStyle(::Taylor1Style{T}, ::Base.Broadcast.DefaultArrayStyle{0}) where {T} = Taylor1Style{T}() BroadcastStyle(::Taylor1Style{T}, ::Base.Broadcast.DefaultArrayStyle{1}) where {T} = Base.Broadcast.DefaultArrayStyle{1}() diff --git a/src/constructors.jl b/src/constructors.jl index cbac7c17..e4166f99 100644 --- a/src/constructors.jl +++ b/src/constructors.jl @@ -71,7 +71,6 @@ julia> Taylor1(Rational{Int}, 4) Taylor1(::Type{T}, order::Int) where {T<:Number} = Taylor1( [zero(T), one(T)], order) Taylor1(order::Int) = Taylor1(Float64, order) - ######################### HomogeneousPolynomial """ HomogeneousPolynomial{T<:Number} <: AbstractSeries{T} diff --git a/src/conversion.jl b/src/conversion.jl index 9b82e5d6..01ffc4b9 100644 --- a/src/conversion.jl +++ b/src/conversion.jl @@ -28,7 +28,6 @@ convert(::Type{Taylor1{T}}, b::T) where {T<:Number} = Taylor1([b], 0) convert(::Type{Taylor1}, a::T) where {T<:Number} = Taylor1(a, 0) - convert(::Type{HomogeneousPolynomial{T}}, a::HomogeneousPolynomial) where {T<:Number} = HomogeneousPolynomial(convert(Array{T,1}, a.coeffs), a.order) @@ -171,7 +170,6 @@ promote_rule(::Type{Taylor1{T}}, ::Type{S}) where {T<:Number, S<:Number} = promote_rule(::Type{Taylor1{Taylor1{T}}}, ::Type{Taylor1{T}}) where {T<:Number} = Taylor1{Taylor1{T}} - promote_rule(::Type{HomogeneousPolynomial{T}}, ::Type{HomogeneousPolynomial{S}}) where {T<:Number, S<:Number} = HomogeneousPolynomial{promote_type(T,S)} diff --git a/src/evaluate.jl b/src/evaluate.jl index e521be6f..8b12d17b 100644 --- a/src/evaluate.jl +++ b/src/evaluate.jl @@ -10,9 +10,10 @@ """ evaluate(a, [dx]) -Evaluate a `Taylor1` polynomial using Horner's rule (hand coded). If `dx` is -ommitted, its value is considered as zero. Note that the syntax `a(dx)` is -equivalent to `evaluate(a,dx)`, and `a()` is equivalent to `evaluate(a)`. +Evaluate a `Taylor1` (or `STaylor1{N,T}`) polynomial using Horner's rule (hand +coded). If `dx` is ommitted, its value is considered as zero. Note that the +syntax `a(dx)` is equivalent to `evaluate(a,dx)`, and `a()` is equivalent +to `evaluate(a)`. """ function evaluate(a::Taylor1{T}, dx::T) where {T<:Number} @inbounds suma = a[end] @@ -33,10 +34,10 @@ evaluate(a::Taylor1{T}) where {T<:Number} = a[0] """ evaluate(x, δt) -Evaluates each element of `x::Union{ Vector{Taylor1{T}}, Matrix{Taylor1{T}} }`, -representing the dependent variables of an ODE, at *time* δt. Note that the -syntax `x(δt)` is equivalent to `evaluate(x, δt)`, and `x()` -is equivalent to `evaluate(x)`. +Evaluates each element of `x::Union{Vector{Taylor1{T}}, Matrix{Taylor1{T}}, +Vector{STaylor1{N,T}}, Matrix{STaylor1{N,T}}}`, representing the dependent +variables of an ODE, at *time* δt. Note that the syntax `x(δt)` is equivalent +to `evaluate(x, δt)`, and `x()` is equivalent to `evaluate(x)`. """ evaluate(x::Union{Array{Taylor1{T}}, SubArray{Taylor1{T}}}, δt::S) where {T<:Number, S<:Number} = evaluate.(x, δt) @@ -110,7 +111,6 @@ evaluate(p::Taylor1{T}, x::Array{S}) where {T<:Number, S<:Number} = #function-like behavior for Taylor1 (p::Taylor1)(x) = evaluate(p, x) - (p::Taylor1)() = evaluate(p) #function-like behavior for Vector{Taylor1} diff --git a/src/functions.jl b/src/functions.jl index f642e374..2bffb9de 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -147,7 +147,6 @@ for T in (:Taylor1, :TaylorN) end end - # Recursive functions (homogeneous coefficients) for T in (:Taylor1, :TaylorN) @eval begin @@ -422,7 +421,6 @@ for T in (:Taylor1, :TaylorN) end end - @doc doc""" inverse(f) diff --git a/src/intervals.jl b/src/intervals.jl index ef280624..85d65a4b 100644 --- a/src/intervals.jl +++ b/src/intervals.jl @@ -146,3 +146,5 @@ function _normalize(a::TaylorN, I::IntervalBox{N,T}, ::Val{false}) where {N,T} end return a(x) end + +square(x::Interval{T}) where {T <: Real} = pow(x,2) diff --git a/src/other_functions.jl b/src/other_functions.jl index e34acbb9..d1f8ef3b 100644 --- a/src/other_functions.jl +++ b/src/other_functions.jl @@ -21,7 +21,6 @@ for T in (:Taylor1, :HomogeneousPolynomial, :TaylorN) @eval isnan(a::$T) = any( isnan.(a.coeffs) ) end - ## Division functions: rem and mod ## for op in (:mod, :rem) for T in (:Taylor1, :TaylorN) diff --git a/src/power.jl b/src/power.jl index 52a6636b..a5cc05c9 100644 --- a/src/power.jl +++ b/src/power.jl @@ -150,7 +150,6 @@ function ^(a::TaylorN, r::S) where {S<:Real} return c end - # Homogeneous coefficients for real power @doc doc""" pow!(c, a, r::Real, k::Int) @@ -283,6 +282,8 @@ function square(a::HomogeneousPolynomial) return res end +#two(x::T) = convert(T, x) +square(x::T) where {T <: Real} = x^2 # Homogeneous coefficients for square @doc doc""" diff --git a/src/static.jl b/src/static.jl new file mode 100644 index 00000000..76800b71 --- /dev/null +++ b/src/static.jl @@ -0,0 +1,63 @@ +==(a::STaylor1, b::STaylor1) = (a.coeffs == b.coeffs) + +iszero(a::STaylor1) = all(iszero, a.coeffs) + +zero(::STaylor1{N,T}) where {N, T<:Number} = STaylor1(zero(T), Val(N-1)) +one(::STaylor1{N,T}) where {N, T<:Number} = STaylor1(one(T), Val(N-1)) + +@inline +(a::STaylor1{N,T}, b::STaylor1{N,T}) where {N, T<:Number} = STaylor1(a.coeffs .+ b.coeffs) +@inline -(a::STaylor1{N,T}, b::STaylor1{N,T}) where {N, T<:Number} = STaylor1(a.coeffs .- b.coeffs) +@inline +(a::STaylor1) = a +@inline -(a::STaylor1) = STaylor1(minus_tuple(a.coeffs)) + +function +(a::STaylor1{N,T}, b::T) where {N, T<:Number} + STaylor1{N,T}(ntuple(i -> i == 1 ? a.coeffs[1] + b : a.coeffs[i], Val(N))) +end +function +(b::T, a::STaylor1{N,T}) where {N, T<:Number} + STaylor1{N,T}(ntuple(i -> i == 1 ? a.coeffs[1] + b : a.coeffs[i], Val(N))) +end +function -(a::STaylor1{N,T}, b::T) where {N, T<:Number} + STaylor1{N,T}(ntuple(i -> i == 1 ? a.coeffs[1] - b : a.coeffs[i], Val(N))) +end +-(b::T, a::STaylor1{N,T}) where {N, T<:Number} = b + (-a) + +#+(a::STaylor1{N,T}, b::S) where {N, T<:NumberNotSeries, S<:NumberNotSeries} = +(promote(a,b)...) +#+(a::STaylor1{N,T}, b::STaylor1{N,S}) where {N, T<:NumberNotSeries, S<:NumberNotSeries} = +(promote(a,b)...) +#+(a::STaylor1{N,T}, b::S) where {N, T<:NumberNotSeries, S<:NumberNotSeries} = +(promote(a,b)...) +#+(b::S, a::STaylor1{N,T}) where {N, T<:NumberNotSeries, S<:NumberNotSeries} = +(promote(b,a)...) + +#-(a::STaylor1{N,T}, b::STaylor1{N,S}) where {N, T<:NumberNotSeries, S<:NumberNotSeries} = -(promote(a,b)...) +#-(a::STaylor1{N,T}, b::S) where {N, T<:NumberNotSeries, S<:NumberNotSeries} = -(promote(a,b)...) +#-(b::S, a::STaylor1{N,T}) where {N, T<:NumberNotSeries, S<:NumberNotSeries} = -(promote(b,a)...) + +@generated function *(x::STaylor1{N,T}, y::STaylor1{N,T}) where {T<:Number,N} + ex_calc = quote end + append!(ex_calc.args, Any[nothing for i in 1:N]) + syms = Symbol[Symbol("c$i") for i in 1:N] + for j = 1:N + ex_line = :(x.coeffs[1]*y.coeffs[$j]) + for k = 2:j + ex_line = :($ex_line + x.coeffs[$k]*y.coeffs[$(j-k+1)]) + end + sym = syms[j] + ex_line = :($sym = $ex_line) + ex_calc.args[j] = ex_line + end + exout = :(($(syms[1]),)) + for i = 2:N + push!(exout.args, syms[i]) + end + return quote + Base.@_inline_meta + $ex_calc + return STaylor1{N,T}($exout) + end +end + + +function *(a::STaylor1{N,T}, b::T) where {N, T<:Number} + STaylor1{N,T}(b .* a.coeffs) +end +function *(b::T, a::STaylor1{N,T}) where {N, T<:Number} + STaylor1{N,T}(b .* a.coeffs) +end diff --git a/test/onevariable.jl b/test/onevariable.jl index 0a1687f3..c3e52c20 100644 --- a/test/onevariable.jl +++ b/test/onevariable.jl @@ -523,6 +523,17 @@ eeuler = Base.MathConstants.e @test Taylor1{Int}(false) == Taylor1([0]) end +function test_vs_Taylor1(x,y) + flag = true + for i in 0:2 + if x[i] !== y[i] + flag = false + break + end + end + flag +end + @testset "Test `inv` for `Matrix{Taylor1{Float64}}``" begin t = Taylor1(5) a = Diagonal(rand(0:10,3)) + rand(3, 3)