From 7558f1fa2744b5c4095a508b613bdbfd18ba0588 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sun, 16 Aug 2020 22:05:37 +0200 Subject: [PATCH 1/3] Add ForwardDiff as a dependency to work around limitations in generated functions that causes world age errors in exp_pade_p if the function has been called before ForwardDiff was loaded. --- Project.toml | 2 ++ src/ExponentialUtilities.jl | 2 +- test/runtests.jl | 12 ++++++++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 1325eb8..0cadfc6 100644 --- a/Project.toml +++ b/Project.toml @@ -4,12 +4,14 @@ authors = ["Chris Rackauckas "] version = "1.7.0" [deps] +ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Requires = "ae029012-a4dd-5104-9daa-d747884805df" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [compat] +ForwardDiff = "0.10" Requires = "1.0" julia = "1" diff --git a/src/ExponentialUtilities.jl b/src/ExponentialUtilities.jl index 7a584b1..f19974e 100644 --- a/src/ExponentialUtilities.jl +++ b/src/ExponentialUtilities.jl @@ -1,5 +1,5 @@ module ExponentialUtilities -using LinearAlgebra, SparseArrays, Printf, Requires +using LinearAlgebra, SparseArrays, Printf, Requires, ForwardDiff """ @diagview(A,d) -> view of the `d`th diagonal of `A`. diff --git a/test/runtests.jl b/test/runtests.jl index a833ac6..e845250 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,14 +14,14 @@ using ExponentialUtilities: getH, getV, _exp! @test A2 ≈ expA2 end -@testset "exp_generic" begin +@testset "exp_generic" begin for n in [5, 10, 30, 50, 100, 500] M = rand(n, n) @test exp(M) ≈ exp_generic(M) M′ = M / 10opnorm(M, 1) @test exp(M′) ≈ exp_generic(M′) - + N = randn(n, n) @test exp(N) ≈ exp_generic(N) @@ -29,6 +29,14 @@ end end end +# The issue was only triggered if exp_generic had been called before loading +# ForwardDiff so it's importnat that the loading happens after the "exp_generic" +# testset +using ForwardDiff +@testset "Issue 41" begin + @test ForwardDiff.derivative(exp_generic, 0.1) == exp_generic(0.1) +end + @testset "Phi" begin # Scalar phi K = 4 From 452ca612ed6d45b15e88252100e3ccd7d94141cf Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sun, 16 Aug 2020 22:07:19 +0200 Subject: [PATCH 2/3] Remove white space --- src/exp.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/exp.jl b/src/exp.jl index c930c53..fa1b862 100644 --- a/src/exp.jl +++ b/src/exp.jl @@ -105,16 +105,16 @@ function _exp!(A::StridedMatrix{T}; caches=nothing) where T <: LinearAlgebra.Bla end """ - exp(x, vk=Val{13}()) -Generic exponential function, working on any `x` for which the functions -`LinearAlgebra.opnorm`, `+`, `*`, `^`, and `/` (including addition with -UniformScaling objects) are defined. Use the argument `vk` to adjust the + exp(x, vk=Val{13}()) +Generic exponential function, working on any `x` for which the functions +`LinearAlgebra.opnorm`, `+`, `*`, `^`, and `/` (including addition with +UniformScaling objects) are defined. Use the argument `vk` to adjust the number of terms used in the Pade approximants at compile time. See "The Scaling and Squaring Method for the Matrix Exponential Revisited" by Higham, Nicholas J. in 2005 for algorithm details. """ -function exp_generic(x, vk=Val{13}()) +function exp_generic(x, vk=Val{13}()) nx = opnorm(x, 1) s = ceil(Int, log2(nx)) if s >= 1 From 172920fc88a67bb96dfa51cfa8eaa143a41945e4 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sun, 16 Aug 2020 22:29:29 +0200 Subject: [PATCH 3/3] Handle exp_generic(0.0) --- src/exp.jl | 6 +++++- test/runtests.jl | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/exp.jl b/src/exp.jl index fa1b862..794c1c4 100644 --- a/src/exp.jl +++ b/src/exp.jl @@ -116,7 +116,11 @@ by Higham, Nicholas J. in 2005 for algorithm details. """ function exp_generic(x, vk=Val{13}()) nx = opnorm(x, 1) - s = ceil(Int, log2(nx)) + nxl2 = log2(nx) + if iszero(nx) + return x + oneunit(x) + end + s = ceil(Int, nxl2) if s >= 1 exp_generic(x/(2^s), vk)^(2^s) else diff --git a/test/runtests.jl b/test/runtests.jl index e845250..f18ab47 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -37,6 +37,11 @@ using ForwardDiff @test ForwardDiff.derivative(exp_generic, 0.1) == exp_generic(0.1) end +@testset "Issue 42" begin + @test exp_generic(0.0) == 1 + @test ForwardDiff.derivative(exp_generic, 0.0) == 1 +end + @testset "Phi" begin # Scalar phi K = 4