11using DiffRules
22using Test
3+ using FiniteDifferences
34
45using IrrationalConstants: fourπ
56
67import SpecialFunctions, NaNMath, LogExpFunctions
78import Random
89Random. seed! (1 )
910
10- function finitediff (f, x)
11- ϵ = cbrt (eps (typeof (x))) * max (one (typeof (x)), abs (x))
12- return (f (x + ϵ) - f (x - ϵ)) / (ϵ + ϵ)
13- end
11+ # Set `max_range` to avoid domain errors.
12+ const finitediff = central_fdm (5 , 1 , max_range= 1e-3 )
1413
1514@testset " DiffRules" begin
1615@testset " check rules" begin
@@ -23,24 +22,27 @@ for (M, f, arity) in DiffRules.diffrules(; filter_modules=nothing)
2322 if arity == 1
2423 @test DiffRules. hasdiffrule (M, f, 1 )
2524 deriv = DiffRules. diffrule (M, f, :goo )
26- modifier = if f in (:asec , :acsc , :asecd , :acscd , :acosh , :acoth )
27- one (T)
28- elseif f === :log1mexp
29- - one (T)
30- elseif f === :log2mexp
31- - (one (T) / 2 )
32- else
33- zero (T)
34- end
3525 @eval begin
3626 let
37- goo = rand ($ T) + $ modifier
27+ goo = if $ (f in (:asec , :acsc , :asecd , :acscd , :acosh , :acoth ))
28+ # avoid singularities with finite differencing
29+ rand ($ T) + $ T (1.5 )
30+ elseif $ (f in (:log , :airyaix , :airyaiprimex ))
31+ # avoid singularities with finite differencing
32+ rand ($ T) + $ T (0.5 )
33+ elseif $ (f === :log1mexp )
34+ rand ($ T) - one ($ T)
35+ elseif $ (f in (:log2mexp , :erfinv ))
36+ rand ($ T) - $ T (0.5 )
37+ else
38+ rand ($ T)
39+ end
3840 @test $ deriv isa $ T
39- @test isapprox ( $ deriv, finitediff ($ M.$ f, goo), rtol= 0.05 )
41+ @test $ deriv ≈ finitediff ($ M.$ f, goo) rtol= 1e-3 atol = 1e-3
4042 # test for 2pi functions
41- if " mod2pi " == string ( $ M. $ f )
42- goo = $ (fourπ) + $ modifier
43- @test $ T ( NaN ) === $ deriv
43+ if $ (f === :mod2pi )
44+ goo = 4 * pi
45+ @test NaN === $ deriv
4446 end
4547 end
4648 end
@@ -49,17 +51,28 @@ for (M, f, arity) in DiffRules.diffrules(; filter_modules=nothing)
4951 derivs = DiffRules. diffrule (M, f, :foo , :bar )
5052 @eval begin
5153 let
52- if " mod" == string ($ M.$ f)
53- foo, bar = rand ($ T) + 13 , rand ($ T) + 5 # make sure x/y is not integer
54+ foo, bar = if $ (f === :mod )
55+ rand () + 13 , rand () + 5 # make sure x/y is not integer
56+ elseif $ (f === :polygamma )
57+ rand (1 : 10 ), rand () # only supports integers as first arguments
58+ elseif $ (f in (:bessely , :besselyx ))
59+ # avoid singularities with finite differencing
60+ rand (), rand () + 0.5
61+ elseif $ (f === :log )
62+ # avoid singularities with finite differencing
63+ rand () + 1.5 , rand ()
64+ elseif $ (f === :^ )
65+ # avoid singularities with finite differencing
66+ rand () + 0.5 , rand ()
5467 else
55- foo, bar = rand (1 : 10 ), rand ($ T )
68+ rand (), rand ()
5669 end
5770 dx, dy = $ (derivs[1 ]), $ (derivs[2 ])
5871 if ! (isnan (dx))
59- @test isapprox (dx, finitediff (z -> $ M.$ f (z, bar), float ( foo)), rtol= 0.05 )
72+ @test dx ≈ finitediff (z -> $ M.$ f (z, bar), foo) rtol= 1e-3 atol = 1e-3
6073 end
6174 if ! (isnan (dy))
62- @test isapprox (dy, finitediff (z -> $ M.$ f (foo, z), bar), rtol= 0.05 )
75+ @test dy ≈ finitediff (z -> $ M.$ f (foo, z), bar) rtol= 1e-3 atol = 1e-3
6376 end
6477 end
6578 end
0 commit comments