11using DiffRules
2+ using FiniteDifferences
23using Test
34
45import SpecialFunctions, NaNMath, LogExpFunctions
56import Random
67Random. seed! (1 )
78
8- function finitediff (f, x)
9- ϵ = cbrt (eps (typeof (x))) * max (one (typeof (x)), abs (x))
10- return (f (x + ϵ) - f (x - ϵ)) / (ϵ + ϵ)
11- end
9+ const finitediff = central_fdm (5 , 1 )
1210
1311@testset " DiffRules" begin
1412@testset " check rules" begin
@@ -20,22 +18,25 @@ for (M, f, arity) in DiffRules.diffrules(; filter_modules=nothing)
2018 if arity == 1
2119 @test DiffRules. hasdiffrule (M, f, 1 )
2220 deriv = DiffRules. diffrule (M, f, :goo )
23- modifier = if f in (:asec , :acsc , :asecd , :acscd , :acosh , :acoth )
24- 1.0
25- elseif f === :log1mexp
26- - 1.0
27- elseif f === :log2mexp
28- - 0.5
29- else
30- 0.0
31- end
3221 @eval begin
3322 let
34- goo = rand () + $ modifier
35- @test isapprox ($ deriv, finitediff ($ M.$ f, goo), rtol= 0.05 )
23+ goo = if $ (f in (:asec , :acsc , :asecd , :acscd , :acosh , :acoth ))
24+ # avoid singularities with finite differencing
25+ rand () + 1.5
26+ elseif $ (f === :log )
27+ # avoid singularities with finite differencing
28+ rand () + 0.5
29+ elseif $ (f === :log1mexp )
30+ rand () - 1.0
31+ elseif $ (f in (:log2mexp , :asin , :acos , :erfinv ))
32+ rand () - 0.5
33+ else
34+ rand ()
35+ end
36+ @test $ deriv ≈ finitediff ($ M.$ f, goo) rtol= 1e-9 atol= 1e-9
3637 # test for 2pi functions
37- if " mod2pi " == string ( $ M. $ f )
38- goo = 4pi + $ modifier
38+ if $ (f === :mod2pi )
39+ goo = 4 * pi
3940 @test NaN === $ deriv
4041 end
4142 end
@@ -45,17 +46,28 @@ for (M, f, arity) in DiffRules.diffrules(; filter_modules=nothing)
4546 derivs = DiffRules. diffrule (M, f, :foo , :bar )
4647 @eval begin
4748 let
48- if " mod" == string ($ M.$ f)
49- foo, bar = rand () + 13 , rand () + 5 # make sure x/y is not integer
49+ foo, bar = if $ (f === :mod )
50+ rand () + 13 , rand () + 5 # make sure x/y is not integer
51+ elseif $ (f === :polygamma )
52+ rand (1 : 10 ), rand () # only supports integers as first arguments
53+ elseif $ (f === :bessely )
54+ # avoid singularities with finite differencing
55+ rand (), rand () + 0.5
56+ elseif $ (f === :log )
57+ # avoid singularities with finite differencing
58+ rand () + 1.5 , rand ()
59+ elseif $ (f === :^ )
60+ # avoid singularities with finite differencing
61+ rand () + 0.5 , rand ()
5062 else
51- foo, bar = rand (1 : 10 ), rand ()
63+ rand (), rand ()
5264 end
5365 dx, dy = $ (derivs[1 ]), $ (derivs[2 ])
54- if ! ( isnan (dx) )
55- @test isapprox (dx, finitediff (z -> $ M.$ f (z, bar), float (foo)), rtol= 0.05 )
66+ if ! isnan (dx)
67+ @test dx ≈ finitediff (z -> $ M.$ f (z, bar), float (foo)) rtol= 1e-9 atol = 1e-9
5668 end
57- if ! ( isnan (dy) )
58- @test isapprox (dy, finitediff (z -> $ M.$ f (foo, z), bar), rtol= 0.05 )
69+ if ! isnan (dy)
70+ @test dy ≈ finitediff (z -> $ M.$ f (foo, z), bar) rtol= 1e-9 atol = 1e-9
5971 end
6072 end
6173 end
@@ -89,7 +101,7 @@ for xtype in [:Float64, :BigFloat, :Int64]
89101 x = $ xtype (rand (1 : 10 ))
90102 y = $ mode
91103 dx, dy = $ (derivs[1 ]), $ (derivs[2 ])
92- @test isapprox (dx, finitediff (z -> rem2pi (z, y), float (x)), rtol= 0.05 )
104+ @test dx ≈ finitediff (z -> rem2pi (z, y), float (x)) rtol= 1e-9 atol = 1e-9
93105 @test isnan (dy)
94106 end
95107 end
@@ -105,7 +117,7 @@ for xtype in [:Float64, :BigFloat]
105117 x = rand ($ xtype)
106118 y = $ ytype (rand (1 : 10 ))
107119 dx, dy = $ (derivs[1 ]), $ (derivs[2 ])
108- @test isapprox (dx, finitediff (z -> ldexp (z, y), x), rtol= 0.05 )
120+ @test dx ≈ finitediff (z -> ldexp (z, y), x) rtol= 1e-9 atol = 1e-9
109121 @test isnan (dy)
110122 end
111123 end
0 commit comments