103 lines
2.8 KiB
C++
103 lines
2.8 KiB
C++
|
|
#include "../AutomaticDifferentiation.hpp"
|
||
|
|
|
||
|
|
#include <iostream>
|
||
|
|
#include <iomanip>
|
||
|
|
using std::cout;
|
||
|
|
using std::endl;
|
||
|
|
using std::setw;
|
||
|
|
#define PRINT_VAR(x) std::cout << #x << "\t= " << std::setprecision(16) << (x) << std::endl
|
||
|
|
#define PRINT_DUAL(x) std::cout << #x << "\t= " << std::fixed << std::setprecision(4) << std::setw(10) << (x).a << ", " << std::setw(10) << (x).b << std::endl
|
||
|
|
|
||
|
|
template<typename T>
|
||
|
|
T f(const T & x)
|
||
|
|
{
|
||
|
|
// return T(1.) + x + x*x + T(1.)/x + log(x);
|
||
|
|
return 1 + x + x*x + 1/x + log(x);
|
||
|
|
}
|
||
|
|
|
||
|
|
template<typename T>
|
||
|
|
T df(const T & x)
|
||
|
|
{
|
||
|
|
return 2*x + 1 + 1.0/x - 1/pow(x, 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
template<typename T>
|
||
|
|
T ddf(const T & x)
|
||
|
|
{
|
||
|
|
return 2 - 1/pow(x, 2) + 2/pow(x, 3);
|
||
|
|
}
|
||
|
|
|
||
|
|
struct fFunctor
|
||
|
|
{
|
||
|
|
template<typename Scalar>
|
||
|
|
Scalar operator()(Scalar const& x) {return f(x);}
|
||
|
|
};
|
||
|
|
|
||
|
|
CREATE_GRAD_FUNCTION_OBJECT(f, GradF);
|
||
|
|
|
||
|
|
CREATE_GRAD_FUNCTION_OBJECT_FUNCTOR(fFunctor, GradF_funct);
|
||
|
|
CREATE_GRAD_FUNCTION_OBJECT_FUNCTOR(GradF_funct, Grad2F_funct);
|
||
|
|
|
||
|
|
int main()
|
||
|
|
{
|
||
|
|
cout.precision(16);
|
||
|
|
double xdbl = 1.5;
|
||
|
|
|
||
|
|
{
|
||
|
|
cout << "Analytical\n";
|
||
|
|
cout << "f(x) = " << f(xdbl) << endl;
|
||
|
|
cout << "df(x)/dx = " << df(xdbl) << endl;
|
||
|
|
cout << "d²f(x)/dx² = " << ddf(xdbl) << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 1st derivative forward
|
||
|
|
{
|
||
|
|
using Fd = Dual<double>;
|
||
|
|
Fd x = xdbl;
|
||
|
|
x.diff(0);
|
||
|
|
Fd y = f(x);
|
||
|
|
cout << "\nForward\n";
|
||
|
|
cout << "f(x) = " << y.a << endl;
|
||
|
|
cout << "df(x)/dx = " << y.d(0) << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
// first derivative using the gradient functor
|
||
|
|
{
|
||
|
|
GradFunc gradf(f<Dual<double>>, xdbl);
|
||
|
|
|
||
|
|
double fx, dfdx;
|
||
|
|
gradf.get_f_grad(xdbl, fx, dfdx);
|
||
|
|
|
||
|
|
cout << "\nForward using gradient function object\n";
|
||
|
|
cout << "f(x) = " << fx << endl;
|
||
|
|
cout << "df(x)/dx = " << dfdx << endl;
|
||
|
|
cout << "df(x)/dx = " << gradf(xdbl) << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
// first derivative using the gradient functor created through the macro
|
||
|
|
{
|
||
|
|
// GradF<double> gradf;
|
||
|
|
GradF gradf;
|
||
|
|
// GradFunc gradf(f<Dual<double>>, xdbl);
|
||
|
|
|
||
|
|
double fx, dfdx;
|
||
|
|
gradf.get_f_grad(xdbl, fx, dfdx);
|
||
|
|
|
||
|
|
cout << "\nForward using gradient function object created using the macro\n";
|
||
|
|
cout << "f(x) = " << fx << endl;
|
||
|
|
cout << "df(x)/dx = " << dfdx << endl;
|
||
|
|
cout << "df(x)/dx = " << gradf(xdbl) << endl;
|
||
|
|
|
||
|
|
{
|
||
|
|
GradF_funct gradf_funct;
|
||
|
|
Grad2F_funct grad2f_funct;
|
||
|
|
PRINT_VAR(gradf(1.5f));
|
||
|
|
PRINT_VAR(gradf_funct(1.5));
|
||
|
|
// PRINT_VAR(grad2f_funct(1.5));// for this to work, the operator+-*/(A, Dual<B>) must not be defined (conflict with operator from valarray)
|
||
|
|
// third order does not work anyway (can't convert a double to Dual<Dual<Dual<double>>>...)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|