Created
January 27, 2024 18:00
-
-
Save alecjacobson/5580f88c83a063bf7d3ed310b784ed3c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/autodiff/autodiff/issues/179 | |
#define FORWARD | |
#ifdef FORWARD | |
#include <autodiff/forward/dual.hpp> | |
#else | |
#include <autodiff/reverse/var.hpp> | |
#endif | |
#include <complex> | |
template <typename T> T f(const T & x) | |
{ | |
// "clever" branch to avoid 0/0 at x=0 | |
// Breaks autodiff::reverse::var | |
if(x == 0.0) | |
return 1.0; | |
else | |
//return (sin(x)/x + x*(x-1.0); | |
// Causes complex-step to require h>1e-161 | |
return (sin(x) + x*x*(x-1.0))/x; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
for( double x : {1.5, 1.0, 0.0} ) | |
{ | |
double y = f(x); | |
#ifdef FORWARD | |
// dual number version | |
autodiff::dual x_ad = x; | |
autodiff::dual y_ad = f(x); | |
double dydx_ad = autodiff::derivative( f<autodiff::dual>, autodiff::wrt(x_ad), autodiff::at(x_ad)); | |
#else | |
autodiff::var x_ad = x; | |
autodiff::var y_ad = f(x_ad); | |
autodiff::var dydx_ad = autodiff::derivatives(y_ad, wrt(x_ad))[0]; | |
#endif | |
std::complex<double> x_cs; | |
x_cs.real(x); | |
// https://mdolab.engin.umich.edu/wiki/guide-complex-step-derivative-approximation | |
// recommends 1e-200. That's fun but a bad idea. | |
x_cs.imag(1e-161); | |
double dydx_cs = f(x_cs).imag()/1e-161; | |
double dydx_fd = (f(x+1e-8) - f(x-1e-8))/(2*1e-8); | |
printf("f(%g) = %g\n f'_ad = %0.17f\n f'_cs = %0.17f\n f'_fd = %0.17f\n", | |
(double)x,y,(double)dydx_ad,dydx_cs,(double)dydx_fd); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment