From 56db68f880765eed9be24582ac78e7d18d09f885 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Wed, 26 Apr 2017 16:24:37 -0400 Subject: [PATCH 1/8] utilize DiffBase's diffrule API to define generic math operations on Duals --- REQUIRE | 3 +- src/ForwardDiff.jl | 25 +------ src/dual.jl | 174 ++++++++++++++++++++++++++------------------- test/REQUIRE | 1 + 4 files changed, 106 insertions(+), 97 deletions(-) create mode 100644 test/REQUIRE diff --git a/REQUIRE b/REQUIRE index db757995..c3e8865e 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,6 +1,7 @@ julia 0.6- StaticArrays 0.5.0 DiffBase 0.0.3 -Calculus 0.2.0 NaNMath 0.2.2 SpecialFunctions 0.1.0 +RealInterface 0.0.1 +CommonSubexpressions 0.0.1 diff --git a/src/ForwardDiff.jl b/src/ForwardDiff.jl index fc86116f..1f4058cd 100644 --- a/src/ForwardDiff.jl +++ b/src/ForwardDiff.jl @@ -6,40 +6,19 @@ using DiffBase using DiffBase: DiffResult using StaticArrays -import Calculus import NaNMath import SpecialFunctions -import Base.Threads +import RealInterface +import CommonSubexpressions ############################# # types/functions/constants # ############################# -# NaN-safe mode switch # -#----------------------# - const NANSAFE_MODE_ENABLED = false -# function generation # -#---------------------# - -const AUTO_DEFINED_UNARY_FUNCS = map(first, Calculus.symbolic_derivatives_1arg()) - -const NANMATH_FUNCS = (:sin, :cos, :tan, :asin, :acos, :acosh, - :atanh, :log, :log2, :log10, :lgamma, :log1p) - -const SPECIAL_FUNCS = (:erf, :erfc, :erfinv, :erfcinv, :erfi, :erfcx, - :dawson, :digamma, :eta, :zeta, :airyai, :airyaiprime, - :airybi, :airybiprime, :airyaix, :besselj, :besselj0, - :besselj1, :besseljx, :bessely, :bessely0, :bessely1, - :besselyx, :besselh, :hankelh1, :hankelh1x, :hankelh2, - :hankelh2x, :besseli, :besselix, :besselk, :besselkx) - const REAL_TYPES = (AbstractFloat, Irrational, Integer, Rational, Real) -# chunk settings # -#----------------# - const DEFAULT_CHUNK_THRESHOLD = 10 struct Chunk{N} end diff --git a/src/dual.jl b/src/dual.jl index af01c9d3..e3b083b7 100644 --- a/src/dual.jl +++ b/src/dual.jl @@ -83,9 +83,9 @@ end @inline tagtype(::Dual{T,V,N}) where {T,V,N} = T @inline tagtype(::Type{Dual{T,V,N}}) where {T,V,N} = T -##################################### -# N-ary Operation Definition Macros # -##################################### +#################################### +# N-ary Operation Definition Tools # +#################################### macro define_binary_dual_op(f, xy_body, x_body, y_body) defs = quote @@ -158,6 +158,57 @@ macro define_ternary_dual_op(f, xyz_body, xy_body, xz_body, yz_body, x_body, y_b return esc(defs) end +function unary_dual_definition(M, f) + work = CommonSubexpressions.cse(quote + val = $(f)(x) + deriv = $(DiffBase.diffrule(f, :x)) + end) + return quote + @inline function ($M).$(f)(d::Dual{T}) where T + x = value(d) + $work + return Dual{T}(val, deriv * partials(d)) + end + end +end + +function binary_dual_definition(M, f) + dvx, dvy = DiffBase.diffrule(f, :vx, :vy) + xy_work = CommonSubexpressions.cse(quote + val = $(f)(vx, vy) + dvx = $dvx + dvy = $dvy + end) + x_work = CommonSubexpressions.cse(quote + val = $(f)(vx, vy) + dvx = $dvx + end) + y_work = CommonSubexpressions.cse(quote + val = $(f)(vx, vy) + dvy = $dvy + end) + return quote + @define_binary_dual_op( + ($M).$(f), + begin + vx, vy = value(x), value(y) + $xy_work + return Dual{T}(val, _mul_partials(partials(x), partials(y), dvx, dvy)) + end, + begin + vx, vy = value(x), value(y) + $x_work + return Dual{T}(val, dvx * partials(x)) + end, + begin + vx, vy = value(x), value(y) + $y_work + return Dual{T}(val, dvy * partials(y)) + end + ) + end +end + ##################### # Generic Functions # ##################### @@ -211,7 +262,11 @@ end isconstant(d::Dual) = iszero(partials(d)) -for pred in (:isequal, :(==), :isless, :(<=), :<) +for pred in RealInterface.UNARY_PREDICATES + @eval Base.$(pred)(d::Dual) = $(pred)(value(d)) +end + +for pred in RealInterface.BINARY_PREDICATES @eval begin @define_binary_dual_op( Base.$(pred), @@ -222,14 +277,6 @@ for pred in (:isequal, :(==), :isless, :(<=), :<) end end -Base.isnan(d::Dual) = isnan(value(d)) -Base.isfinite(d::Dual) = isfinite(value(d)) -Base.isinf(d::Dual) = isinf(value(d)) -Base.isreal(d::Dual) = isreal(value(d)) -Base.isinteger(d::Dual) = isinteger(value(d)) -Base.iseven(d::Dual) = iseven(value(d)) -Base.isodd(d::Dual) = isodd(value(d)) - ######################## # Promotion/Conversion # ######################## @@ -258,9 +305,9 @@ Base.promote_array_type(F, ::Type{<:AbstractFloat}, ::Type{<:Dual}, ::Type{P}) w Base.float(d::Dual{T,V,N}) where {T,V,N} = Dual{T,promote_type(V, Float16),N}(d) Base.AbstractFloat(d::Dual{T,V,N}) where {T,V,N} = Dual{T,promote_type(V, Float16),N}(d) -######## -# Math # -######## +############## +# Arithmetic # +############## # Addition/Subtraction # #----------------------# @@ -345,77 +392,55 @@ for f in (:(Base.:^), :(NaNMath.pow)) end end -# Unary Math Functions # -#--------------------- # - -function to_nanmath(x::Expr) - if x.head == :call - funsym = Expr(:., :NaNMath, Base.Meta.quot(x.args[1])) - return Expr(:call, funsym, [to_nanmath(z) for z in x.args[2:end]]...) - else - return Expr(:call, [to_nanmath(z) for z in x.args]...) - end -end - -to_nanmath(x) = x +################################### +# General Mathematical Operations # +################################### @inline Base.conj(d::Dual) = d + @inline Base.transpose(d::Dual) = d + @inline Base.ctranspose(d::Dual) = d + @inline Base.abs(d::Dual) = signbit(value(d)) ? -d : d -for fsym in AUTO_DEFINED_UNARY_FUNCS - v = :v - deriv = Calculus.differentiate(:($(fsym)($v)), v) - - # exp and sqrt are manually defined below - if !(in(fsym, (:exp, :sqrt))) - funcs = Vector{Expr}(0) - is_special_function = in(fsym, SPECIAL_FUNCS) - is_special_function && push!(funcs, :(SpecialFunctions.$(fsym))) - (!(is_special_function) || VERSION < v"0.6.0-dev.2767") && push!(funcs, :(Base.$(fsym))) - for func in funcs - @eval begin - @inline function $(func)(d::Dual{T}) where T - $(v) = value(d) - return Dual{T}($(func)($v), $(deriv) * partials(d)) - end - end - end - end +for f in RealInterface.UNARY_MATH + DiffBase.hasdiffrule(f, 1) && eval(unary_dual_definition(Base, f)) +end - # extend corresponding NaNMath methods - if fsym in NANMATH_FUNCS - nan_deriv = to_nanmath(deriv) - @eval begin - @inline function NaNMath.$(fsym)(d::Dual{T}) where T - v = value(d) - return Dual{T}(NaNMath.$(fsym)($v), $(nan_deriv) * partials(d)) +for f in RealInterface.UNARY_SPECIAL_MATH + DiffBase.hasdiffrule(f, 1) && eval(unary_dual_definition(SpecialFunctions, f)) +end + +for f in RealInterface.BINARY_SPECIAL_MATH + DiffBase.hasdiffrule(f, 2) && eval(binary_dual_definition(SpecialFunctions, f)) +end + +function to_nanmath!(x) + if isa(x, Expr) + if x.head == :call + f = x.args[1] + if in(f, RealInterface.UNARY_NAN_MATH) || in(f, RealInterface.BINARY_NAN_MATH) + x.args[1] = :(NaNMath.$f) end + foreach(to_nanmath!, x.args[2:end]) + else + foreach(to_nanmath!, x.args) end end + return x +end + +for f in RealInterface.UNARY_NAN_MATH + DiffBase.hasdiffrule(f, 1) && eval(to_nanmath!(unary_dual_definition(NaNMath, f))) end ################# # Special Cases # ################# -# exp - -@inline function Base.exp(d::Dual{T}) where T - expv = exp(value(d)) - return Dual{T}(expv, expv * partials(d)) -end - -# sqrt - -@inline function Base.sqrt(d::Dual{T}) where T - sqrtv = sqrt(value(d)) - deriv = inv(sqrtv + sqrtv) - return Dual{T}(sqrtv, deriv * partials(d)) -end - -# hypot +# hypot # +#-------# @inline function calc_hypot(x, y, ::Type{T}) where T vx = value(x) @@ -451,7 +476,8 @@ end calc_hypot(x, y, z, T), ) -# atan2 +# atan2 # +#-------# @inline function calc_atan2(y, x, ::Type{T}) where T z = y / x @@ -468,7 +494,8 @@ end calc_atan2(x, y, T) ) -# fma +# fma # +#-----# @generated function calc_fma_xyz(x::Dual{T,<:Real,N}, y::Dual{T,<:Real,N}, @@ -509,7 +536,8 @@ end Dual{T}(fma(x, y, value(z)), partials(z)) # z_body ) -# sincos +# sincos # +#--------# @inline sincos(x) = (sin(x), cos(x)) diff --git a/test/REQUIRE b/test/REQUIRE new file mode 100644 index 00000000..a200ff4a --- /dev/null +++ b/test/REQUIRE @@ -0,0 +1 @@ +Calculus 0.2.0 From f36a54b00f83d23444d1a057d696322a365223ec Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Fri, 28 Apr 2017 15:46:33 -0400 Subject: [PATCH 2/8] require DiffBase 0.2.0 --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index c3e8865e..c3182712 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,6 +1,6 @@ julia 0.6- StaticArrays 0.5.0 -DiffBase 0.0.3 +DiffBase 0.2.0 NaNMath 0.2.2 SpecialFunctions 0.1.0 RealInterface 0.0.1 From 9e403b9fc864d7e9e4d8e98f27674c1b5d2f3a90 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Sat, 29 Apr 2017 12:47:00 -0400 Subject: [PATCH 3/8] add docs for new Dual auto-definition mechanism --- docs/_rst/source/contributing.rst | 78 +++++++------------------------ docs/_sources/contributing.txt | 78 +++++++------------------------ docs/contributing.html | 75 +++++++---------------------- docs/index.html | 3 +- docs/searchindex.js | 2 +- 5 files changed, 55 insertions(+), 181 deletions(-) diff --git a/docs/_rst/source/contributing.rst b/docs/_rst/source/contributing.rst index 7de30bdc..45fbc6ad 100644 --- a/docs/_rst/source/contributing.rst +++ b/docs/_rst/source/contributing.rst @@ -12,68 +12,26 @@ If you're new GitHub, here's an outline of the workflow you should use: 3. Apply your code changes to the branch on your fork 4. When you're done, submit a PR to ForwardDiff to merge your fork into ForwardDiff's master branch. -Manually Optimizing Unary Functions ------------------------------------ +Adding New Derivative Definitions +--------------------------------- -To see a list of functions to pick from, look at ``ForwardDiff.AUTO_DEFINED_UNARY_FUNCS``: +In general, new derivative implementations for ``Dual`` are automatically defined via +simple symbolic rules. ForwardDiff accomplishes this by looping over the `the function names +listed in the RealInterface package`_, and for every function (and relevant arity), it +attempts to generate a ``Dual`` definition by applying the `symbolic rules provided by the +DiffBase package`_. Conveniently, these auto-generated definitions are also automatically +tested. -.. code-block:: julia +Thus, in order to add a new derivative implementation for ``Dual``, you should do the +following: - julia> import ForwardDiff +1. Make sure the name of the function is appropriately listed in the RealInterface package +2. Define the appropriate derivative rule(s) in DiffBase +3. Check that calling the function on ``Dual`` instances delivers the desired result. - julia> ForwardDiff.AUTO_DEFINED_UNARY_FUNCS - 57-element Array{Symbol,1}: - :sqrt - :cbrt - :abs2 - :inv - :log - :log10 - :log2 - :log1p - :exp - :exp2 - :expm1 - :sin - :cos - :tan - ⋮ +Depending on which the arity of your function and its category in RealInterface, +ForwardDiff's auto-definition mechanism might need to be expanded to include it. +If this is the case, ForwardDiff's maintainers can help you out. -Some of these functions may have already been manually optimized. To see what functions have -already been done, go to ``src/dual.jl`` and scroll down to the ``Special Cases`` section. - -The functions in ``ForwardDiff.AUTO_DEFINED_UNARY_FUNCS`` are automatically tested as part -of ForwardDiff's test suite, so you don't need to write tests yourself. You can test your -changes by running ``Pkg.test("ForwardDiff")``. - -If everything passes, you can submit a PR to the ForwardDiff repository to share your work! - -Implementing New Functions --------------------------- - -Unary Functions Via Calculus.jl -+++++++++++++++++++++++++++++++ - -The easiest way to add support for a new function is actually to define a derivative rule -for the function in Calculus's `symbolic differentiation code`_, which ForwardDiff then uses -to generate the function's definition on ``Dual`` numbers. To accomplish this: - -1. Open an issue in ForwardDiff with the title "Supporting f(x)" (obviously replacing "f(x)"" with the function you wish to support). -2. Open a PR to Calculus that adds the relevant differentiation rule(s) and tests. In the PR's description, be sure to mention the relevant ForwardDiff issue such that GitHub links the two. -3. Once the PR to Calculus is accepted, we can check to make sure that the function works appropriately in ForwardDiff. If it does, then you're done, and the issue in ForwardDiff can be considered resolved! - -.. _`symbolic differentiation code`: https://github.com/johnmyleswhite/Calculus.jl/blob/master/src/differentiate.jl#L115 - -Manually Adding Functions to ForwardDiff -++++++++++++++++++++++++++++++++++++++++ - -Some functions aren't suitable for auto-definition via the Calculus package. An example of -such a function is the non-unary function ``atan2``, which is defined manually in -``ForwardDiff/src/dual.jl``. - -The process for manually adding functions to ForwardDiff without going through Calculus.jl -is essentially the same as the process for manually optimizing existing functions, with the -additional requirement that you'll have to write the tests yourself. New tests for ``Dual`` -numbers can be placed in `DualTest.jl`_. - -.. _`DualTest.jl`: https://github.com/JuliaDiff/ForwardDiff.jl/tree/master/test/DualTest.jl +.. _`the function names listed in the RealInterface package`: https://github.com/jrevels/RealInterface.jl +.. _`symbolic rules provided by the DiffBase package`: https://github.com/JuliaDiff/DiffBase.jl/blob/master/src/rules.jl diff --git a/docs/_sources/contributing.txt b/docs/_sources/contributing.txt index 7de30bdc..45fbc6ad 100644 --- a/docs/_sources/contributing.txt +++ b/docs/_sources/contributing.txt @@ -12,68 +12,26 @@ If you're new GitHub, here's an outline of the workflow you should use: 3. Apply your code changes to the branch on your fork 4. When you're done, submit a PR to ForwardDiff to merge your fork into ForwardDiff's master branch. -Manually Optimizing Unary Functions ------------------------------------ +Adding New Derivative Definitions +--------------------------------- -To see a list of functions to pick from, look at ``ForwardDiff.AUTO_DEFINED_UNARY_FUNCS``: +In general, new derivative implementations for ``Dual`` are automatically defined via +simple symbolic rules. ForwardDiff accomplishes this by looping over the `the function names +listed in the RealInterface package`_, and for every function (and relevant arity), it +attempts to generate a ``Dual`` definition by applying the `symbolic rules provided by the +DiffBase package`_. Conveniently, these auto-generated definitions are also automatically +tested. -.. code-block:: julia +Thus, in order to add a new derivative implementation for ``Dual``, you should do the +following: - julia> import ForwardDiff +1. Make sure the name of the function is appropriately listed in the RealInterface package +2. Define the appropriate derivative rule(s) in DiffBase +3. Check that calling the function on ``Dual`` instances delivers the desired result. - julia> ForwardDiff.AUTO_DEFINED_UNARY_FUNCS - 57-element Array{Symbol,1}: - :sqrt - :cbrt - :abs2 - :inv - :log - :log10 - :log2 - :log1p - :exp - :exp2 - :expm1 - :sin - :cos - :tan - ⋮ +Depending on which the arity of your function and its category in RealInterface, +ForwardDiff's auto-definition mechanism might need to be expanded to include it. +If this is the case, ForwardDiff's maintainers can help you out. -Some of these functions may have already been manually optimized. To see what functions have -already been done, go to ``src/dual.jl`` and scroll down to the ``Special Cases`` section. - -The functions in ``ForwardDiff.AUTO_DEFINED_UNARY_FUNCS`` are automatically tested as part -of ForwardDiff's test suite, so you don't need to write tests yourself. You can test your -changes by running ``Pkg.test("ForwardDiff")``. - -If everything passes, you can submit a PR to the ForwardDiff repository to share your work! - -Implementing New Functions --------------------------- - -Unary Functions Via Calculus.jl -+++++++++++++++++++++++++++++++ - -The easiest way to add support for a new function is actually to define a derivative rule -for the function in Calculus's `symbolic differentiation code`_, which ForwardDiff then uses -to generate the function's definition on ``Dual`` numbers. To accomplish this: - -1. Open an issue in ForwardDiff with the title "Supporting f(x)" (obviously replacing "f(x)"" with the function you wish to support). -2. Open a PR to Calculus that adds the relevant differentiation rule(s) and tests. In the PR's description, be sure to mention the relevant ForwardDiff issue such that GitHub links the two. -3. Once the PR to Calculus is accepted, we can check to make sure that the function works appropriately in ForwardDiff. If it does, then you're done, and the issue in ForwardDiff can be considered resolved! - -.. _`symbolic differentiation code`: https://github.com/johnmyleswhite/Calculus.jl/blob/master/src/differentiate.jl#L115 - -Manually Adding Functions to ForwardDiff -++++++++++++++++++++++++++++++++++++++++ - -Some functions aren't suitable for auto-definition via the Calculus package. An example of -such a function is the non-unary function ``atan2``, which is defined manually in -``ForwardDiff/src/dual.jl``. - -The process for manually adding functions to ForwardDiff without going through Calculus.jl -is essentially the same as the process for manually optimizing existing functions, with the -additional requirement that you'll have to write the tests yourself. New tests for ``Dual`` -numbers can be placed in `DualTest.jl`_. - -.. _`DualTest.jl`: https://github.com/JuliaDiff/ForwardDiff.jl/tree/master/test/DualTest.jl +.. _`the function names listed in the RealInterface package`: https://github.com/jrevels/RealInterface.jl +.. _`symbolic rules provided by the DiffBase package`: https://github.com/JuliaDiff/DiffBase.jl/blob/master/src/rules.jl diff --git a/docs/contributing.html b/docs/contributing.html index 5a1973b7..3de8605e 100644 --- a/docs/contributing.html +++ b/docs/contributing.html @@ -92,12 +92,7 @@ @@ -156,60 +151,24 @@

How to Contribute -

Manually Optimizing Unary Functions

-

To see a list of functions to pick from, look at ForwardDiff.AUTO_DEFINED_UNARY_FUNCS:

-
julia> import ForwardDiff
-
-julia> ForwardDiff.AUTO_DEFINED_UNARY_FUNCS
-57-element Array{Symbol,1}:
- :sqrt
- :cbrt
- :abs2
- :inv
- :log
- :log10
- :log2
- :log1p
- :exp
- :exp2
- :expm1
- :sin
- :cos
- :tan
- 
-
-
-

Some of these functions may have already been manually optimized. To see what functions have -already been done, go to src/dual.jl and scroll down to the Special Cases section.

-

The functions in ForwardDiff.AUTO_DEFINED_UNARY_FUNCS are automatically tested as part -of ForwardDiff’s test suite, so you don’t need to write tests yourself. You can test your -changes by running Pkg.test("ForwardDiff").

-

If everything passes, you can submit a PR to the ForwardDiff repository to share your work!

- -
-

Implementing New Functions

-
-

Unary Functions Via Calculus.jl

-

The easiest way to add support for a new function is actually to define a derivative rule -for the function in Calculus’s symbolic differentiation code, which ForwardDiff then uses -to generate the function’s definition on Dual numbers. To accomplish this:

+
+

Adding New Derivative Definitions

+

In general, new derivative implementations for Dual are automatically defined via +simple symbolic rules. ForwardDiff accomplishes this by looping over the the function names +listed in the RealInterface package, and for every function (and relevant arity), it +attempts to generate a Dual definition by applying the symbolic rules provided by the +DiffBase package. Conveniently, these auto-generated definitions are also automatically +tested.

+

Thus, in order to add a new derivative implementation for Dual, you should do the +following:

    -
  1. Open an issue in ForwardDiff with the title “Supporting f(x)” (obviously replacing “f(x)”” with the function you wish to support).
  2. -
  3. Open a PR to Calculus that adds the relevant differentiation rule(s) and tests. In the PR’s description, be sure to mention the relevant ForwardDiff issue such that GitHub links the two.
  4. -
  5. Once the PR to Calculus is accepted, we can check to make sure that the function works appropriately in ForwardDiff. If it does, then you’re done, and the issue in ForwardDiff can be considered resolved!
  6. +
  7. Make sure the name of the function is appropriately listed in the RealInterface package
  8. +
  9. Define the appropriate derivative rule(s) in DiffBase
  10. +
  11. Check that calling the function on Dual instances delivers the desired result.
-
-
-

Manually Adding Functions to ForwardDiff

-

Some functions aren’t suitable for auto-definition via the Calculus package. An example of -such a function is the non-unary function atan2, which is defined manually in -ForwardDiff/src/dual.jl.

-

The process for manually adding functions to ForwardDiff without going through Calculus.jl -is essentially the same as the process for manually optimizing existing functions, with the -additional requirement that you’ll have to write the tests yourself. New tests for Dual -numbers can be placed in DualTest.jl.

-
+

Depending on which the arity of your function and its category in RealInterface, +ForwardDiff’s auto-definition mechanism might need to be expanded to include it. +If this is the case, ForwardDiff’s maintainers can help you out.

diff --git a/docs/index.html b/docs/index.html index 2adec17e..494015ba 100644 --- a/docs/index.html +++ b/docs/index.html @@ -183,8 +183,7 @@

ForwardDiff.jlHow to Contribute diff --git a/docs/searchindex.js b/docs/searchindex.js index 9313df25..c7c2ffd4 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({envversion:49,filenames:["advanced_usage","basic_api","contributing","how_it_works","index","install","limitations","upgrade"],objects:{ForwardDiff:{GradientConfig:[1,0,1,""],HessianConfig:[1,0,1,""],JacobianConfig:[1,0,1,""],derivative:[1,0,1,""],gradient:[1,0,1,""],hessian:[1,0,1,""],jacobian:[1,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"abstract":3,"break":6,"byte":0,"case":[0,1,2,3],"catch":1,"default":[0,1,7],"export":7,"final":0,"import":2,"long":6,"true":[0,7],"try":0,"void":0,"while":[0,1,4],_70842:0,_70852:0,abil:1,abl:0,about:[3,4,7],abov:[3,7],abs2:2,abstractarrai:[1,6],abstractconfig:0,abstractvector:3,accept:[2,6],accomplish:[0,2],accuraci:4,actual:[0,2],add:[0,2,5],addit:[0,2,3],advantag:4,advis:1,affect:0,after:2,algorithm:4,align:0,all:[0,1,2,6,7],alloc:[0,1],allow:[0,1,3],allresult:7,almost:0,alreadi:2,also:[0,1,6],amen:0,ani:[1,4,6],answer:[0,7],api:0,apply:2,appropri:[0,2],aren:[0,2],arg:[0,1],argument:[1,6],arithmet:0,around:2,arrai:[0,2,6],articl:4,arxiv:4,assert:0,assign:6,assum:[1,3],atan2:2,attempt:0,author:[0,4],auto:2,auto_defined_unary_funcs:2,automat:[0,1,2,3,4,7],avoid:[6,7],awai:3,ax_mul_bx:6,bandwidth:0,base:[0,1,3],basic:0,been:2,befor:0,behavior:[0,3],behvaior:0,below:1,benchmark:0,best:0,better:0,between:7,binari:0,bitcast:0,bitcod:0,blas:6,block:0,both:[3,4],branch:2,brief:2,bring:0,buffer:[0,1],build:0,built:0,bundl:1,calcul:[0,3],call:[0,1,3,6],callabl:4,can:[0,1,2,3,4,6,7],cannot:[1,6],cast:0,caus:0,cbrt:2,central:3,certain:0,cfg10:0,cfg1:0,cfg4:0,cfg:[0,1],chain:3,chang:[2,7],check:[0,2],chunk_siz:7,cite:4,clearer:7,code:[0,2,3,6,7],code_llvm:0,collect:6,comment:6,common:4,compil:0,complet:0,compon:[0,3],compos:[0,3,6,7],comput:[0,1],conflict:7,confus:[1,3],conjunct:0,consid:2,constant:0,construct:[0,1],constructor:[0,1],consult:0,contain:[1,3],conveni:1,copi:0,correct:0,cost:0,could:0,coupl:3,cours:0,creat:4,cross:3,cumprod:0,current:[5,7],data:0,decreas:[0,1],defin:[0,2,7],definit:2,depend:[0,4],deriv:0,derivativeconfig:1,describ:0,descript:2,detail:[3,6,7],develop:4,diffbas:[0,1,7],differ:1,differenc:4,different:0,differenti:[1,2,3,4,6],diffresult:[0,1],dimens:0,dimension:[3,7],directori:0,disabl:0,discuss:3,divid:0,document:[0,4,6,7],doe:[0,1,2,3],doesn:[0,6],don:[2,3],done:2,doubl:0,down:2,downstream:0,drastic:1,dual:[0,2],dualtest:2,dure:0,dynam:0,each:[0,3],easi:[2,3],easiest:2,easili:[0,1],element:[0,2],elementari:3,eltyp:0,emit:0,enabl:[0,3,4],encourag:3,end:[0,3,7],enough:6,entir:[0,3],erron:0,error:[0,7],essenti:[0,2],evalu:[0,3,4],even:0,evenli:0,everyth:2,exactli:1,examin:3,exampl:[0,2,3,6,7],except:6,execut:[0,3],exist:[0,2,7],exp2:2,exp:2,expens:0,explic:0,explicit:6,explicitli:[0,7],explictli:1,expm1:2,extend:3,extern:6,extra:[0,1,3],extract:3,fadd:0,fairli:2,famili:1,familiar:3,featur:[0,3,7],feed:1,fell:0,few:[2,7],field:3,find:4,fine:0,finit:4,first:0,flag:0,flexibl:[1,7],float64:0,follow:[3,4],fork:2,form:[0,1],forward:[3,4],forwarddiff:0,free:0,from:[0,2,3,4],fulli:7,futur:0,gener:[0,2,3,4,6,7],getelementptr:0,github:[2,4],gradient:0,gradientconfig:[0,1,7],guess:0,have:[0,2,3,7],heavili:0,help:7,here:[0,2,3,6,7],hessianconfig:1,hessianresult:7,heurist:0,higher:[0,3,4],highli:1,hold:0,horribl:0,how:0,howev:[0,1],http:4,hyper:3,i32:0,i64:0,ident:0,imag:0,improv:2,inbound:0,incorrectli:0,increas:0,inform:[0,1,3,6],inher:0,inject:6,input:[0,1,3,6],insert:0,instal:5,installat:4,instanc:[1,3],instead:[0,1,6,7],instruct:0,int64:0,intern:7,introduc:3,inv:2,isinf:0,isnan:0,jacobian:0,jacobianconfig:1,job:3,journal:4,julia:[0,2,3,4,5,6],julia_:0,kei:3,kindli:4,know:0,larger:0,lead:7,learn:[0,3,4,7],length:[0,7],less:7,let:[0,3],librari:0,like:[1,3,6],likewis:0,limit:4,link:2,list:[2,6],llvm:0,load:0,local:0,locat:0,log10:2,log1p:2,log2:2,log:[0,2],longer:7,look:[2,3],lubin:4,machin:0,magic:7,mai:[1,2,6],maintain:7,major:0,make:[0,2,3,6],manag:5,mani:0,manual:[0,1],master:2,mathemat:3,matrix:[0,1],mean:6,memori:[0,1],mention:2,merg:2,method:[0,1,4],might:0,mirror:0,mode:[0,3,4],modifi:1,modul:0,more:[0,1,7],multipl:3,multipli:[0,3],multithread:4,multithreadconfig:7,must:[6,7],mutat:[0,7],name:2,namespac:7,nansafe_mode_enabled:0,nativ:4,natur:[3,6],need:[0,2],nest:3,newcom:2,noalia:0,non:[2,4,6],note:[0,1],noth:1,notic:0,now:7,ntupl:3,number:[0,2],numer:3,object:4,obvious:2,occur:7,offici:6,old:7,older:4,omit:1,once:2,one:0,onli:[0,6],oop:0,open:2,oper:0,optim:[0,2],org:4,origin:3,other:[0,1,3,4,7],otherwis:0,our:[0,3,7],out:[0,1,7],outlin:2,outperform:4,output:[0,1,3],output_length:7,over:4,overcom:0,overload:3,overtop:3,own:[0,7],packag:[0,2,3,5,7],page:4,papamark:4,paper:4,paramet:[1,3],pariti:7,part:2,partial:[0,3],pass:[1,2,3],perform:[0,1,4],performantli:3,perhap:0,perturb:[0,1,3],pick:[0,2],pkg:[2,5],place:[0,2,7],plan:0,pleas:0,plethora:3,poison:0,possibl:[0,1],pre:0,prealloc:1,preserv:0,prevent:[0,1,3],primal:0,process:[0,2,3],program:6,propag:[0,6],properti:3,propog:3,proport:0,provid:[0,1,2,3,7],qualifi:7,question:0,rand:0,rather:0,reader:3,real:[1,3,6],realiti:[0,3],realli:4,reason:0,rebuild:0,recomend:1,reduc:[0,1],redund:0,refer:[6,7],rehash:3,reimplement:7,relev:[0,2],reli:0,remain:0,remaind:0,replac:2,repositori:2,repres:3,request:4,requir:[0,1,2,4],reshap:[0,7],resolv:2,resourc:4,ret:0,retriev:[0,4],reus:1,revel:4,revelslubinpapamarkou2016:4,revolv:2,roadblock:6,rosenbrock:0,rule:[2,3,6],run:[0,2,6],runtim:[0,6],sacrif:0,safe:0,sai:0,sake:1,same:2,scope:0,scroll:2,second:[0,1,3],section:[1,2],see:[0,1,2,6,7],seed:[1,3],seen:[0,6],select:[0,1],sensit:0,set:[0,4],sever:[0,1],shape:[0,1],share:2,should:[0,2],show:0,signatur:6,similar:[0,3],simpl:3,simpli:5,sin:[2,3],sinc:[0,7],singl:6,slpvectorizerpass:0,smaller:0,some:[0,2,6,7],sourc:0,special:2,specif:[0,1,6],specifi:1,speed:4,speedup:0,sqrt:2,squar:0,src:[0,2],sret:0,stabil:0,stabl:0,start:0,state:0,storag:[1,6],store:[0,1,3],struct:3,style:6,submit:2,substanti:2,subtyp:6,suit:[0,2],suitabl:2,support:[0,2,3,5,6,7],sure:2,swoop:0,symbol:2,system:0,tag:[0,3],take:[0,1,3,4,7],tan:2,target:[0,1,3,6],task:0,techniqu:[0,4,6],tensor:[0,7],term:3,test:2,than:0,thei:2,them:[1,3,7],thi:[0,1,2,3,4,6,7],thing:0,third:3,though:1,through:[2,6],thu:[0,3,6,7],time:0,titl:[2,4],top:0,transform:7,tune:0,tutori:2,two:[0,2,3],type:0,undefin:0,understand:3,unexport:4,unstabl:0,upgrade:4,url:4,usag:1,use:1,user:[0,1,3,4,6,7],usual:0,usualli:0,util:0,vari:4,variabl:0,vector_hessian:0,version:[0,4],via:0,wai:[0,2,3],want:0,well:[0,3,6],what:[0,2],whatev:2,when:[0,1,2],where:[0,1,3],wherea:0,whether:0,which:[0,1,2,3],wikipedia:4,wish:2,within:[3,6],without:[0,2,3],won:3,word:0,work:[0,1,2],workflow:2,would:[0,3],write:[0,2],written:6,year:4,yield:0,you:[0,1,2,4,7],your:[0,2,4,6],yourself:[1,2],zero:0},titles:["Advanced Usage Guide","Basic ForwardDiff API","How to Contribute","How ForwardDiff Works","ForwardDiff.jl","Installation and Version Requirements","Limitations of ForwardDiff","Upgrading from Older Versions of ForwardDiff"],titleterms:{"function":[0,2,7],"new":2,"public":4,"return":0,abstractconfig:1,access:0,adding:2,advanc:0,api:[1,3,7],basic:1,calculu:2,chunk:[0,7],configur:0,contribut:2,creat:7,deriv:1,differenti:7,dual:3,enabl:7,fix:0,forwarddiff:[1,2,3,4,6,7],from:7,gradient:1,guid:0,hessian:[0,1],higher:7,how:[2,3],implement:[2,3],inf:0,installat:5,issu:0,jacobian:1,limit:6,lower:[0,7],manual:2,multithread:7,nan:0,number:3,older:7,optimiz:2,order:[0,7],requir:5,result:[0,7],retriev:7,set:7,simd:0,size:[0,7],type:1,unari:2,unexport:7,upgrade:7,usage:0,valu:0,vector:0,version:[5,7],via:2,work:3}}) \ No newline at end of file +Search.setIndex({envversion:49,filenames:["basic_api","contributing","index"],objects:{ForwardDiff:{GradientConfig:[0,0,1,""],HessianConfig:[0,0,1,""],JacobianConfig:[0,0,1,""],derivative:[0,0,1,""],gradient:[0,0,1,""],hessian:[0,0,1,""],jacobian:[0,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"case":[0,1],"catch":0,"default":0,"function":[0,1,2],"return":[0,2],"while":[0,2],abil:0,about:2,abstractarrai:0,access:2,accomplish:1,accuraci:2,add:1,advanc:2,advantag:2,advis:0,after:1,algorithm:2,all:[0,1],alloc:0,allow:0,also:[0,1],ani:[0,2],appli:1,apply:1,appropri:1,arg:0,argument:0,ariti:1,around:1,articl:2,arxiv:2,assum:0,attempt:1,author:2,auto:1,automat:[0,1,2],base:0,below:0,both:2,branch:1,brief:1,buffer:0,bundl:0,call:[0,1],callabl:2,can:[0,1,2],cannot:0,categori:1,cfg:0,chang:1,check:1,chunk:[0,2],cite:2,code:1,common:2,comput:0,configur:[0,2],confus:0,construct:0,constructor:0,contain:0,conveni:[0,1],creat:2,decreas:0,defin:1,deliv:1,depend:[1,2],derivativeconfig:0,desir:1,develop:2,diffbas:[0,1],differ:0,differenc:2,differenti:[0,2],diffresult:0,document:2,doe:0,done:1,drastic:0,dual:[1,2],each:[],easi:1,easili:0,element:[],enabl:2,evalu:2,everi:1,exactli:0,expand:1,explictli:0,extra:0,fairli:1,famili:0,feed:0,few:1,find:2,finit:2,fix:2,flexibl:0,follow:[1,2],fork:1,form:0,forward:2,from:2,gener:[1,2],github:[1,2],gradientconfig:0,guid:2,help:1,here:1,hessianconfig:0,higher:2,highli:0,howev:0,http:2,implement:[1,2],improv:1,includ:1,inf:2,inform:0,input:0,installat:2,instanc:[0,1],instead:0,issu:2,jacobianconfig:0,journal:2,julia:2,kindli:2,learn:2,like:0,limit:2,list:1,loop:1,lower:2,lubin:2,mai:0,maintain:1,make:1,manual:0,master:1,matrix:0,mechan:1,memori:0,merg:1,method:[0,2],might:1,mode:2,modifi:0,more:0,multithread:2,name:1,nan:2,nativ:2,need:1,newcom:1,non:2,note:0,noth:0,number:[1,2],object:2,older:2,omit:0,order:[0,1,2],org:2,other:[0,2],out:[0,1],outlin:1,outperform:2,output:0,over:[1,2],packag:1,page:2,papamark:2,paper:2,paramet:0,pass:0,perform:[0,2],perturb:0,possibl:0,prealloc:0,prevent:0,provid:[0,1],real:0,realinterfac:1,realli:2,recomend:0,reduc:0,relev:1,request:2,requir:[0,2],resourc:2,respect:[],result:[0,1,2],retriev:2,reus:0,revel:2,revelslubinpapamarkou2016:2,revolv:1,rule:1,sake:0,second:0,section:[0,1],see:0,seed:0,select:0,set:2,sever:0,shape:0,should:1,simd:2,simpl:1,size:[0,2],specif:0,specifi:0,speed:2,storag:0,store:0,submit:1,substanti:1,sure:1,symbol:1,take:[0,2],target:0,techniqu:2,test:1,thei:1,them:0,thi:[0,1,2],though:0,thu:1,titl:2,tupl:[],tutori:1,unexport:2,upgrade:2,url:2,usag:0,usage:2,use:0,user:[0,2],valu:[0,2],vari:2,vector:[0,2],version:2,via:1,wai:1,whatev:1,when:[0,1],where:0,which:[0,1],wikipedia:2,work:[0,2],workflow:1,write:1,year:2,you:[0,1,2],your:[1,2],yourself:0},titles:["Basic ForwardDiff API","How to Contribute","ForwardDiff.jl"],titleterms:{"new":1,"public":2,abstractconfig:0,adding:1,api:0,basic:0,contribut:1,definit:1,deriv:[0,1],forwarddiff:[0,2],gradient:0,hessian:0,how:1,jacobian:0,type:0}}) \ No newline at end of file From 85592e2529ff9eb1a22b0086628137ee80253f06 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Sat, 29 Apr 2017 13:12:54 -0400 Subject: [PATCH 4/8] add tests for auto-defined Dual methods --- test/DualTest.jl | 86 ++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/test/DualTest.jl b/test/DualTest.jl index c8f91765..264397b0 100644 --- a/test/DualTest.jl +++ b/test/DualTest.jl @@ -308,12 +308,12 @@ for N in (0,3), M in (0,4), V in (Int, Float32) @test Base.promote_array_type(+, V, Dual{Void,Int,N}) == Dual{Void,V,N} end - ######## - # Math # - ######## - + ############## # Arithmetic # - #------------# + ############## + + # Addition/Subtraction # + #----------------------# @test FDNUM + FDNUM2 === Dual(value(FDNUM) + value(FDNUM2), partials(FDNUM) + partials(FDNUM2)) @test FDNUM + PRIMAL === Dual(value(FDNUM) + PRIMAL, partials(FDNUM)) @@ -333,6 +333,9 @@ for N in (0,3), M in (0,4), V in (Int, Float32) @test PRIMAL - NESTED_FDNUM === Dual(PRIMAL - value(NESTED_FDNUM), -(partials(NESTED_FDNUM))) @test -(NESTED_FDNUM) === Dual(-(value(NESTED_FDNUM)), -(partials(NESTED_FDNUM))) + # Multiplication # + #----------------# + @test FDNUM * FDNUM2 === Dual(value(FDNUM) * value(FDNUM2), ForwardDiff._mul_partials(partials(FDNUM), partials(FDNUM2), value(FDNUM2), value(FDNUM))) @test FDNUM * PRIMAL === Dual(value(FDNUM) * PRIMAL, partials(FDNUM) * PRIMAL) @test PRIMAL * FDNUM === Dual(value(FDNUM) * PRIMAL, partials(FDNUM) * PRIMAL) @@ -341,6 +344,9 @@ for N in (0,3), M in (0,4), V in (Int, Float32) @test NESTED_FDNUM * PRIMAL === Dual(value(NESTED_FDNUM) * PRIMAL, partials(NESTED_FDNUM) * PRIMAL) @test PRIMAL * NESTED_FDNUM === Dual(value(NESTED_FDNUM) * PRIMAL, partials(NESTED_FDNUM) * PRIMAL) + # Division # + #----------# + if M > 0 && N > 0 @test Dual{1}(FDNUM) / Dual{1}(PRIMAL) === Dual{1}(FDNUM / PRIMAL) @test Dual{1}(PRIMAL) / Dual{1}(FDNUM) === Dual{1}(PRIMAL / FDNUM) @@ -357,6 +363,9 @@ for N in (0,3), M in (0,4), V in (Int, Float32) @test dual_isapprox(NESTED_FDNUM / PRIMAL, Dual(value(NESTED_FDNUM) / PRIMAL, partials(NESTED_FDNUM) / PRIMAL)) @test dual_isapprox(PRIMAL / NESTED_FDNUM, Dual(PRIMAL / value(NESTED_FDNUM), (-(PRIMAL) / value(NESTED_FDNUM)^2) * partials(NESTED_FDNUM))) + # Exponentiation # + #----------------# + @test dual_isapprox(FDNUM^FDNUM2, exp(FDNUM2 * log(FDNUM))) @test dual_isapprox(FDNUM^PRIMAL, exp(PRIMAL * log(FDNUM))) @test dual_isapprox(PRIMAL^FDNUM, exp(FDNUM * log(PRIMAL))) @@ -367,13 +376,16 @@ for N in (0,3), M in (0,4), V in (Int, Float32) @test partials(NaNMath.pow(Dual(-2.0, 1.0), Dual(2.0, 0.0)), 1) == -4.0 - # Unary Functions # - #-----------------# + ################################### + # General Mathematical Operations # + ################################### @test conj(FDNUM) === FDNUM @test conj(NESTED_FDNUM) === NESTED_FDNUM + @test transpose(FDNUM) === FDNUM @test transpose(NESTED_FDNUM) === NESTED_FDNUM + @test ctranspose(FDNUM) === FDNUM @test ctranspose(NESTED_FDNUM) === NESTED_FDNUM @@ -383,36 +395,40 @@ for N in (0,3), M in (0,4), V in (Int, Float32) @test abs(NESTED_FDNUM) === NESTED_FDNUM if V != Int - UNSUPPORTED_NESTED_FUNCS = (:trigamma, :airyprime, :besselj1, :bessely1) - DOMAIN_ERR_FUNCS = (:asec, :acsc, :asecd, :acscd, :acoth, :acosh) - - for fsym in ForwardDiff.AUTO_DEFINED_UNARY_FUNCS - try - v = :v - deriv = Calculus.differentiate(:($(fsym)($v)), v) - is_nanmath_func = in(fsym, ForwardDiff.NANMATH_FUNCS) - is_special_func = in(fsym, ForwardDiff.SPECIAL_FUNCS) - is_domain_err_func = in(fsym, DOMAIN_ERR_FUNCS) - is_unsupported_nested_func = in(fsym, UNSUPPORTED_NESTED_FUNCS) - tested_funcs = Vector{Expr}(0) - is_nanmath_func && push!(tested_funcs, :(NaNMath.$(fsym))) - is_special_func && push!(tested_funcs, :(SpecialFunctions.$(fsym))) - (!(is_special_func) || VERSION < v"0.6.0-dev.2767") && push!(tested_funcs, :(Base.$(fsym))) - for func in tested_funcs - @eval begin - fdnum = $(is_domain_err_func ? FDNUM + 1 : FDNUM) - $(v) = ForwardDiff.value(fdnum) - @test dual_isapprox($(func)(fdnum), ForwardDiff.Dual($(func)($v), $(deriv) * ForwardDiff.partials(fdnum))) - if $(!(is_unsupported_nested_func)) - nested_fdnum = $(is_domain_err_func ? NESTED_FDNUM + 1 : NESTED_FDNUM) - $(v) = ForwardDiff.value(nested_fdnum) - @test dual_isapprox($(func)(nested_fdnum), ForwardDiff.Dual($(func)($v), $(deriv) * ForwardDiff.partials(nested_fdnum))) - end + for f in vcat(RealInterface.UNARY_MATH, RealInterface.UNARY_SPECIAL_MATH) + if DiffBase.hasdiffrule(f, 1) + deriv = DiffBase.diffrule(f, :x) + modifier = in(f, (:asec, :acsc, :asecd, :acscd, :acosh, :acoth)) ? one(V) : zero(V) + @eval begin + x = rand() + $modifier + dx = $f(Dual(x, one(x))) + @test value(dx) == $f(x) + @test partials(dx, 1) == $deriv + end + end + end + for f in RealInterface.BINARY_SPECIAL_MATH + if DiffBase.hasdiffrule(f, 2) + derivs = DiffBase.diffrule(f, :x, :y) + @eval begin + x, y = rand(1:10), rand() + dx = $f(Dual(x, one(x)), y) + dy = $f(x, Dual(y, one(y))) + actualdx = $(derivs[1]) + actualdy = $(derivs[2]) + @test value(dx) == $f(x, y) + @test value(dy) == value(dx) + if isnan(actualdx) + @test isnan(partials(dx, 1)) + else + @test partials(dx, 1) == actualdx + end + if isnan(actualdy) + @test isnan(partials(dy, 1)) + else + @test partials(dy, 1) == actualdy end end - catch err - warn("Encountered error when testing $(fsym)(::Dual):") - rethrow(err) end end end From 6c814c398df3dd9d15e0234fa9d1acdc8220b570 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Mon, 1 May 2017 13:40:47 -0400 Subject: [PATCH 5/8] do not test Hankel functions which return complex values --- test/DualTest.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/DualTest.jl b/test/DualTest.jl index 264397b0..fbf13ad3 100644 --- a/test/DualTest.jl +++ b/test/DualTest.jl @@ -7,6 +7,7 @@ using ForwardDiff: Partials, Dual, value, partials import NaNMath import Calculus import SpecialFunctions +import RealInterface samerng() = MersenneTwister(1) @@ -408,6 +409,7 @@ for N in (0,3), M in (0,4), V in (Int, Float32) end end for f in RealInterface.BINARY_SPECIAL_MATH + in(f, (:hankelh1, :hankelh1x, :hankelh2, :hankelh2x)) && continue if DiffBase.hasdiffrule(f, 2) derivs = DiffBase.diffrule(f, :x, :y) @eval begin From c27a153fd230c28dfe236194266e74c9c8376cf8 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Mon, 1 May 2017 13:41:29 -0400 Subject: [PATCH 6/8] bump minimum RealInterface version --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index c3182712..fc7174e4 100644 --- a/REQUIRE +++ b/REQUIRE @@ -3,5 +3,5 @@ StaticArrays 0.5.0 DiffBase 0.2.0 NaNMath 0.2.2 SpecialFunctions 0.1.0 -RealInterface 0.0.1 +RealInterface 0.0.2 CommonSubexpressions 0.0.1 From 92a6d4770e5ed6a3a76cbde866d8f4a651df37ec Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Tue, 2 May 2017 10:20:36 -0400 Subject: [PATCH 7/8] fix typo --- docs/_rst/source/contributing.rst | 2 +- docs/_sources/contributing.txt | 2 +- docs/contributing.html | 2 +- docs/searchindex.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/_rst/source/contributing.rst b/docs/_rst/source/contributing.rst index 45fbc6ad..35b5d105 100644 --- a/docs/_rst/source/contributing.rst +++ b/docs/_rst/source/contributing.rst @@ -29,7 +29,7 @@ following: 2. Define the appropriate derivative rule(s) in DiffBase 3. Check that calling the function on ``Dual`` instances delivers the desired result. -Depending on which the arity of your function and its category in RealInterface, +Depending on the arity of your function and its category in RealInterface, ForwardDiff's auto-definition mechanism might need to be expanded to include it. If this is the case, ForwardDiff's maintainers can help you out. diff --git a/docs/_sources/contributing.txt b/docs/_sources/contributing.txt index 45fbc6ad..35b5d105 100644 --- a/docs/_sources/contributing.txt +++ b/docs/_sources/contributing.txt @@ -29,7 +29,7 @@ following: 2. Define the appropriate derivative rule(s) in DiffBase 3. Check that calling the function on ``Dual`` instances delivers the desired result. -Depending on which the arity of your function and its category in RealInterface, +Depending on the arity of your function and its category in RealInterface, ForwardDiff's auto-definition mechanism might need to be expanded to include it. If this is the case, ForwardDiff's maintainers can help you out. diff --git a/docs/contributing.html b/docs/contributing.html index 3de8605e..9ed2601b 100644 --- a/docs/contributing.html +++ b/docs/contributing.html @@ -166,7 +166,7 @@

Adding New Derivative DefinitionsDual instances delivers the desired result. -

Depending on which the arity of your function and its category in RealInterface, +

Depending on the arity of your function and its category in RealInterface, ForwardDiff’s auto-definition mechanism might need to be expanded to include it. If this is the case, ForwardDiff’s maintainers can help you out.

diff --git a/docs/searchindex.js b/docs/searchindex.js index c7c2ffd4..3f441d03 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({envversion:49,filenames:["basic_api","contributing","index"],objects:{ForwardDiff:{GradientConfig:[0,0,1,""],HessianConfig:[0,0,1,""],JacobianConfig:[0,0,1,""],derivative:[0,0,1,""],gradient:[0,0,1,""],hessian:[0,0,1,""],jacobian:[0,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"case":[0,1],"catch":0,"default":0,"function":[0,1,2],"return":[0,2],"while":[0,2],abil:0,about:2,abstractarrai:0,access:2,accomplish:1,accuraci:2,add:1,advanc:2,advantag:2,advis:0,after:1,algorithm:2,all:[0,1],alloc:0,allow:0,also:[0,1],ani:[0,2],appli:1,apply:1,appropri:1,arg:0,argument:0,ariti:1,around:1,articl:2,arxiv:2,assum:0,attempt:1,author:2,auto:1,automat:[0,1,2],base:0,below:0,both:2,branch:1,brief:1,buffer:0,bundl:0,call:[0,1],callabl:2,can:[0,1,2],cannot:0,categori:1,cfg:0,chang:1,check:1,chunk:[0,2],cite:2,code:1,common:2,comput:0,configur:[0,2],confus:0,construct:0,constructor:0,contain:0,conveni:[0,1],creat:2,decreas:0,defin:1,deliv:1,depend:[1,2],derivativeconfig:0,desir:1,develop:2,diffbas:[0,1],differ:0,differenc:2,differenti:[0,2],diffresult:0,document:2,doe:0,done:1,drastic:0,dual:[1,2],each:[],easi:1,easili:0,element:[],enabl:2,evalu:2,everi:1,exactli:0,expand:1,explictli:0,extra:0,fairli:1,famili:0,feed:0,few:1,find:2,finit:2,fix:2,flexibl:0,follow:[1,2],fork:1,form:0,forward:2,from:2,gener:[1,2],github:[1,2],gradientconfig:0,guid:2,help:1,here:1,hessianconfig:0,higher:2,highli:0,howev:0,http:2,implement:[1,2],improv:1,includ:1,inf:2,inform:0,input:0,installat:2,instanc:[0,1],instead:0,issu:2,jacobianconfig:0,journal:2,julia:2,kindli:2,learn:2,like:0,limit:2,list:1,loop:1,lower:2,lubin:2,mai:0,maintain:1,make:1,manual:0,master:1,matrix:0,mechan:1,memori:0,merg:1,method:[0,2],might:1,mode:2,modifi:0,more:0,multithread:2,name:1,nan:2,nativ:2,need:1,newcom:1,non:2,note:0,noth:0,number:[1,2],object:2,older:2,omit:0,order:[0,1,2],org:2,other:[0,2],out:[0,1],outlin:1,outperform:2,output:0,over:[1,2],packag:1,page:2,papamark:2,paper:2,paramet:0,pass:0,perform:[0,2],perturb:0,possibl:0,prealloc:0,prevent:0,provid:[0,1],real:0,realinterfac:1,realli:2,recomend:0,reduc:0,relev:1,request:2,requir:[0,2],resourc:2,respect:[],result:[0,1,2],retriev:2,reus:0,revel:2,revelslubinpapamarkou2016:2,revolv:1,rule:1,sake:0,second:0,section:[0,1],see:0,seed:0,select:0,set:2,sever:0,shape:0,should:1,simd:2,simpl:1,size:[0,2],specif:0,specifi:0,speed:2,storag:0,store:0,submit:1,substanti:1,sure:1,symbol:1,take:[0,2],target:0,techniqu:2,test:1,thei:1,them:0,thi:[0,1,2],though:0,thu:1,titl:2,tupl:[],tutori:1,unexport:2,upgrade:2,url:2,usag:0,usage:2,use:0,user:[0,2],valu:[0,2],vari:2,vector:[0,2],version:2,via:1,wai:1,whatev:1,when:[0,1],where:0,which:[0,1],wikipedia:2,work:[0,2],workflow:1,write:1,year:2,you:[0,1,2],your:[1,2],yourself:0},titles:["Basic ForwardDiff API","How to Contribute","ForwardDiff.jl"],titleterms:{"new":1,"public":2,abstractconfig:0,adding:1,api:0,basic:0,contribut:1,definit:1,deriv:[0,1],forwarddiff:[0,2],gradient:0,hessian:0,how:1,jacobian:0,type:0}}) \ No newline at end of file +Search.setIndex({envversion:49,filenames:["basic_api","contributing","index"],objects:{ForwardDiff:{GradientConfig:[0,0,1,""],HessianConfig:[0,0,1,""],JacobianConfig:[0,0,1,""],derivative:[0,0,1,""],gradient:[0,0,1,""],hessian:[0,0,1,""],jacobian:[0,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"case":[0,1],"catch":0,"default":0,"function":[0,1,2],"return":[0,2],"while":[0,2],abil:0,about:2,abstractarrai:0,access:2,accomplish:1,accuraci:2,add:1,advanc:2,advantag:2,advis:0,after:1,algorithm:2,all:[0,1],alloc:0,allow:0,also:[0,1],ani:[0,2],appli:1,apply:1,appropri:1,arg:0,argument:0,ariti:1,around:1,articl:2,arxiv:2,assum:0,attempt:1,author:2,auto:1,automat:[0,1,2],base:0,below:0,both:2,branch:1,brief:1,buffer:0,bundl:0,call:[0,1],callabl:2,can:[0,1,2],cannot:0,categori:1,cfg:0,chang:1,check:1,chunk:[0,2],cite:2,code:1,common:2,comput:0,configur:[0,2],confus:0,construct:0,constructor:0,contain:0,conveni:[0,1],creat:2,decreas:0,defin:1,deliv:1,depend:[1,2],derivativeconfig:0,desir:1,develop:2,diffbas:[0,1],differ:0,differenc:2,differenti:[0,2],diffresult:0,document:2,doe:0,done:1,drastic:0,dual:[1,2],each:[],easi:1,easili:0,element:[],enabl:2,evalu:2,everi:1,exactli:0,expand:1,explictli:0,extra:0,fairli:1,famili:0,feed:0,few:1,find:2,finit:2,fix:2,flexibl:0,follow:[1,2],fork:1,form:0,forward:2,from:2,gener:[1,2],github:[1,2],gradientconfig:0,guid:2,help:1,here:1,hessianconfig:0,higher:2,highli:0,howev:0,http:2,implement:[1,2],improv:1,includ:1,inf:2,inform:0,input:0,installat:2,instanc:[0,1],instead:0,issu:2,jacobianconfig:0,journal:2,julia:2,kindli:2,learn:2,like:0,limit:2,list:1,loop:1,lower:2,lubin:2,mai:0,maintain:1,make:1,manual:0,master:1,matrix:0,mechan:1,memori:0,merg:1,method:[0,2],might:1,mode:2,modifi:0,more:0,multithread:2,name:1,nan:2,nativ:2,need:1,newcom:1,non:2,note:0,noth:0,number:[1,2],object:2,older:2,omit:0,order:[0,1,2],org:2,other:[0,2],out:[0,1],outlin:1,outperform:2,output:0,over:[1,2],packag:1,page:2,papamark:2,paper:2,paramet:0,pass:0,perform:[0,2],perturb:0,possibl:0,prealloc:0,prevent:0,provid:[0,1],real:0,realinterfac:1,realli:2,recomend:0,reduc:0,relev:1,request:2,requir:[0,2],resourc:2,respect:[],result:[0,1,2],retriev:2,reus:0,revel:2,revelslubinpapamarkou2016:2,revolv:1,rule:1,sake:0,second:0,section:[0,1],see:0,seed:0,select:0,set:2,sever:0,shape:0,should:1,simd:2,simpl:1,size:[0,2],specif:0,specifi:0,speed:2,storag:0,store:0,submit:1,substanti:1,sure:1,symbol:1,take:[0,2],target:0,techniqu:2,test:1,thei:1,them:0,thi:[0,1,2],though:0,thu:1,titl:2,tupl:[],tutori:1,unexport:2,upgrade:2,url:2,usag:0,usage:2,use:0,user:[0,2],valu:[0,2],vari:2,vector:[0,2],version:2,via:1,wai:1,whatev:1,when:[0,1],where:0,which:0,wikipedia:2,work:[0,2],workflow:1,write:1,year:2,you:[0,1,2],your:[1,2],yourself:0},titles:["Basic ForwardDiff API","How to Contribute","ForwardDiff.jl"],titleterms:{"new":1,"public":2,abstractconfig:0,adding:1,api:0,basic:0,contribut:1,definit:1,deriv:[0,1],forwarddiff:[0,2],gradient:0,hessian:0,how:1,jacobian:0,type:0}}) \ No newline at end of file From f7d84e8b8133cc4151b346ec70b7cd2bb110d983 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Tue, 2 May 2017 14:17:19 -0400 Subject: [PATCH 8/8] add missing atan2 test --- test/DualTest.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/DualTest.jl b/test/DualTest.jl index fbf13ad3..2dafd321 100644 --- a/test/DualTest.jl +++ b/test/DualTest.jl @@ -448,6 +448,8 @@ for N in (0,3), M in (0,4), V in (Int, Float32) @test typeof(sqrt(NESTED_FDNUM)) === typeof(NESTED_FDNUM) end + @test dual_isapprox(atan2(abs(FDNUM), abs(FDNUM2)), atan(abs(FDNUM) / abs(FDNUM2))) + @test dual_isapprox(fma(FDNUM, FDNUM2, FDNUM3), Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PRIMAL*PARTIALS2 + PRIMAL2*PARTIALS + PARTIALS3)) @test dual_isapprox(fma(FDNUM, FDNUM2, PRIMAL3), Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PRIMAL*PARTIALS2 + PRIMAL2*PARTIALS)) @test dual_isapprox(fma(PRIMAL, FDNUM2, FDNUM3), Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PRIMAL*PARTIALS2 + PARTIALS3))