Skip to content

Commit 253d305

Browse files
authored
don't propagate NaN/Inf if Partials are zero (#179)
* don't propagate NaN/Inf if Partials are zero * fix Calculus.jl test failure on v0.4 * add NaN-safe mode switch * add documentation for NaN-safe mode
1 parent 43ee7d8 commit 253d305

37 files changed

Lines changed: 1067 additions & 818 deletions

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ script:
1010
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
1111
- if (julia -e 'VERSION < v"0.5" && exit(1)'); then
1212
julia -e 'include(joinpath(JULIA_HOME, Base.DATAROOTDIR, "julia", "build_sysimg.jl")); build_sysimg(force=true)';
13-
julia -e 'Pkg.clone(pwd()); Pkg.build("ForwardDiff"); Pkg.test("ForwardDiff"; coverage=true)';
13+
julia -e 'Pkg.clone(pwd()); Pkg.build("ForwardDiff"); Pkg.checkout("DiffBase"); Pkg.test("ForwardDiff"; coverage=true)';
1414
julia -O3 -e 'include(joinpath(Pkg.dir("ForwardDiff"), "test/SIMDTest.jl"))';
1515
else
16-
julia -e 'Pkg.clone(pwd()); Pkg.build("ForwardDiff"); Pkg.test("ForwardDiff"; coverage=true)';
16+
julia -e 'Pkg.clone(pwd()); Pkg.build("ForwardDiff"); Pkg.checkout("DiffBase"); Pkg.test("ForwardDiff"; coverage=true)';
1717
fi
1818
after_success:
1919
- julia -e 'cd(Pkg.dir("ForwardDiff")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'

docs/_rst/source/advanced_usage.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,43 @@ Note that it is usually best to pick a chunk size which divides evenly into the
117117
dimension. Otherwise, ForwardDiff has to construct and utilize an extra "remainder" chunk to
118118
complete the calculation.
119119

120+
Fixing issues with NaN/Inf return values
121+
----------------------------------------
122+
123+
ForwardDiff's default behavior is to return ``NaN`` for undefined derivatives (or otherwise
124+
mirror the behavior of the function in ``Base``, if it would return an error). This is
125+
usually the correct thing to do, but in some cases can erroneously "poison" values which
126+
aren't sensitive to the input and thus cause ForwardDiff to incorrectly return ``NaN`` or
127+
``Inf`` derivatives. For example:
128+
129+
.. code-block:: julia
130+
131+
# the dual number's perturbation component is zero, so this
132+
# variable should not propagate derivative information
133+
julia> log(ForwardDiff.Dual(0.0, 0.0))
134+
Dual(-Inf,NaN) # oops, this NaN should be 0.0
135+
136+
Here, ForwardDiff computes the derivative of ``log(0.0)`` as ``NaN`` and then propagates
137+
this derivative by multiplying it by the perturbation component. Usually, ForwardDiff can
138+
rely on the identity ``x * 0.0 == 0.0`` to prevent the derivatives from propagating when
139+
the perturbation component is ``0.0``. However, this identity doesn't hold if ``isnan(y)``
140+
or ``isinf(y)``, in which case a ``NaN`` derivative will be propagated instead.
141+
142+
It is possible to fix this behavior by checking that the perturbation component is zero
143+
before attempting to propagate derivative information, but this check can noticeably
144+
decrease performance (~5%-10% on our benchmarks).
145+
146+
In order to preserve performance in the majority of use cases, ForwardDiff disables this
147+
check by default. If your code is affected by this ``NaN`` behvaior, you can enable
148+
ForwardDiff's ``NaN``-safe mode by setting ``NANSAFE_MODE_ENABLED`` to ``true`` in
149+
ForwardDiff's source (this constant is located in ``src/ForwardDiff.jl`` in the
150+
package's directory).
151+
152+
In the future, we plan on allowing users and downstream library authors to dynamically
153+
enable ``NaN``-safe mode via the ``AbstractConfig`` API (see `the relevant issue
154+
<https://github.com/JuliaDiff/ForwardDiff.jl/issues/181>`_).
155+
156+
120157
Hessian of a vector-valued function
121158
-----------------------------------
122159

docs/_sources/advanced_usage.txt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,43 @@ Note that it is usually best to pick a chunk size which divides evenly into the
117117
dimension. Otherwise, ForwardDiff has to construct and utilize an extra "remainder" chunk to
118118
complete the calculation.
119119

120+
Fixing issues with NaN/Inf return values
121+
----------------------------------------
122+
123+
ForwardDiff's default behavior is to return ``NaN`` for undefined derivatives (or otherwise
124+
mirror the behavior of the function in ``Base``, if it would return an error). This is
125+
usually the correct thing to do, but in some cases can erroneously "poison" values which
126+
aren't sensitive to the input and thus cause ForwardDiff to incorrectly return ``NaN`` or
127+
``Inf`` derivatives. For example:
128+
129+
.. code-block:: julia
130+
131+
# the dual number's perturbation component is zero, so this
132+
# variable should not propagate derivative information
133+
julia> log(ForwardDiff.Dual(0.0, 0.0))
134+
Dual(-Inf,NaN) # oops, this NaN should be 0.0
135+
136+
Here, ForwardDiff computes the derivative of ``log(0.0)`` as ``NaN`` and then propagates
137+
this derivative by multiplying it by the perturbation component. Usually, ForwardDiff can
138+
rely on the identity ``x * 0.0 == 0.0`` to prevent the derivatives from propagating when
139+
the perturbation component is ``0.0``. However, this identity doesn't hold if ``isnan(y)``
140+
or ``isinf(y)``, in which case a ``NaN`` derivative will be propagated instead.
141+
142+
It is possible to fix this behavior by checking that the perturbation component is zero
143+
before attempting to propagate derivative information, but this check can noticeably
144+
decrease performance (~5%-10% on our benchmarks).
145+
146+
In order to preserve performance in the majority of use cases, ForwardDiff disables this
147+
check by default. If your code is affected by this ``NaN`` behvaior, you can enable
148+
ForwardDiff's ``NaN``-safe mode by setting ``NANSAFE_MODE_ENABLED`` to ``true`` in
149+
ForwardDiff's source (this constant is located in ``src/ForwardDiff.jl`` in the
150+
package's directory).
151+
152+
In the future, we plan on allowing users and downstream library authors to dynamically
153+
enable ``NaN``-safe mode via the ``AbstractConfig`` API (see `the relevant issue
154+
<https://github.com/JuliaDiff/ForwardDiff.jl/issues/181>`_).
155+
156+
120157
Hessian of a vector-valued function
121158
-----------------------------------
122159

docs/_static/basic.css

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Sphinx stylesheet -- basic theme.
66
*
7-
* :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
7+
* :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
88
* :license: BSD, see LICENSE for details.
99
*
1010
*/
@@ -52,6 +52,8 @@ div.sphinxsidebar {
5252
width: 230px;
5353
margin-left: -100%;
5454
font-size: 90%;
55+
word-wrap: break-word;
56+
overflow-wrap : break-word;
5557
}
5658

5759
div.sphinxsidebar ul {
@@ -83,10 +85,6 @@ div.sphinxsidebar #searchbox input[type="text"] {
8385
width: 170px;
8486
}
8587

86-
div.sphinxsidebar #searchbox input[type="submit"] {
87-
width: 30px;
88-
}
89-
9088
img {
9189
border: 0;
9290
max-width: 100%;
@@ -187,6 +185,13 @@ div.genindex-jumpbox {
187185

188186
/* -- general body styles --------------------------------------------------- */
189187

188+
div.body p, div.body dd, div.body li, div.body blockquote {
189+
-moz-hyphens: auto;
190+
-ms-hyphens: auto;
191+
-webkit-hyphens: auto;
192+
hyphens: auto;
193+
}
194+
190195
a.headerlink {
191196
visibility: hidden;
192197
}

docs/_static/css/theme.css

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/_static/doctools.js

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Sphinx JavaScript utilities for all documentation.
66
*
7-
* :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
7+
* :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
88
* :license: BSD, see LICENSE for details.
99
*
1010
*/
@@ -124,6 +124,7 @@ var Documentation = {
124124
this.fixFirefoxAnchorBug();
125125
this.highlightSearchWords();
126126
this.initIndexTable();
127+
127128
},
128129

129130
/**
@@ -252,6 +253,29 @@ var Documentation = {
252253
});
253254
var url = parts.join('/');
254255
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
256+
},
257+
258+
initOnKeyListeners: function() {
259+
$(document).keyup(function(event) {
260+
var activeElementType = document.activeElement.tagName;
261+
// don't navigate when in search box or textarea
262+
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
263+
switch (event.keyCode) {
264+
case 37: // left
265+
var prevHref = $('link[rel="prev"]').prop('href');
266+
if (prevHref) {
267+
window.location.href = prevHref;
268+
return false;
269+
}
270+
case 39: // right
271+
var nextHref = $('link[rel="next"]').prop('href');
272+
if (nextHref) {
273+
window.location.href = nextHref;
274+
return false;
275+
}
276+
}
277+
}
278+
});
255279
}
256280
};
257281

@@ -260,4 +284,4 @@ _ = Documentation.gettext;
260284

261285
$(document).ready(function() {
262286
Documentation.init();
263-
});
287+
});
18.8 KB
Binary file not shown.
82.6 KB
Binary file not shown.

docs/_static/fonts/Inconsolata.ttf

-61.7 KB
Binary file not shown.

docs/_static/fonts/Lato-Bold.ttf

38.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)