diff --git a/Project.toml b/Project.toml index fc3dfd5..769ec33 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "DiffRules" uuid = "b552c78f-8df3-52c6-915a-8e097449b14b" -version = "1.8.0" +version = "1.9.0" [deps] LogExpFunctions = "2ab3a3ac-af41-5b50-aa03-7779005ae688" diff --git a/src/rules.jl b/src/rules.jl index 9ed53ec..ebc1ac7 100644 --- a/src/rules.jl +++ b/src/rules.jl @@ -86,6 +86,7 @@ _abs_deriv(x) = signbit(x) ? -one(x) : one(x) @define_diffrule Base.atan(x, y) = :( $y / ($x^2 + $y^2) ), :( -$x / ($x^2 + $y^2) ) @define_diffrule Base.hypot(x, y) = :( $x / hypot($x, $y) ), :( $y / hypot($x, $y) ) @define_diffrule Base.log(b, x) = :( log($x) * inv(-log($b)^2 * $b) ), :( inv($x) / log($b) ) +@define_diffrule Base.ldexp(x, y) = :( exp2($y) ), :NaN @define_diffrule Base.mod(x, y) = :( first(promote(ifelse(isinteger($x / $y), NaN, 1), NaN)) ), :( z = $x / $y; first(promote(ifelse(isinteger(z), NaN, -floor(z)), NaN)) ) @define_diffrule Base.rem(x, y) = :( first(promote(ifelse(isinteger($x / $y), NaN, 1), NaN)) ), :( z = $x / $y; first(promote(ifelse(isinteger(z), NaN, -trunc(z)), NaN)) ) diff --git a/test/runtests.jl b/test/runtests.jl index c27fdd0..072c962 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,10 +13,10 @@ end @testset "DiffRules" begin @testset "check rules" begin -non_numeric_arg_functions = [(:Base, :rem2pi, 2), (:Base, :ifelse, 3)] +non_diffeable_arg_functions = [(:Base, :rem2pi, 2), (:Base, :ldexp, 2), (:Base, :ifelse, 3)] for (M, f, arity) in DiffRules.diffrules(; filter_modules=nothing) - (M, f, arity) ∈ non_numeric_arg_functions && continue + (M, f, arity) ∈ non_diffeable_arg_functions && continue if arity == 1 @test DiffRules.hasdiffrule(M, f, 1) deriv = DiffRules.diffrule(M, f, :goo) @@ -95,6 +95,23 @@ for xtype in [:Float64, :BigFloat, :Int64] end end end + +# Treat ldexp separately because of its integer second argument: +derivs = DiffRules.diffrule(:Base, :ldexp, :x, :y) +for xtype in [:Float64, :BigFloat] + for ytype in [:Integer, :UInt64, :Int64] + @eval begin + let + x = rand($xtype) + y = $ytype(rand(1 : 10)) + dx, dy = $(derivs[1]), $(derivs[2]) + @test isapprox(dx, finitediff(z -> ldexp(z, y), x), rtol=0.05) + @test isnan(dy) + end + end + end +end + end @testset "diffrules" begin