#include #include #include #include using std::cout; using std::endl; using namespace Eigen; template T fct1(const T & x) { return cos(x) + sqrt(x) + cbrt(sin(x)) + exp(-x*x)/log(x) + atanh(5*x) - 2*csc(x); } template T dfct1(const T & x) { return -2*x*exp(-pow(x, 2))/log(x) - sin(x) + 2*cot(x)*csc(x) + (1.0/3.0)*cos(x)/pow(sin(x), 2.0/3.0) + 5/(-25*pow(x, 2) + 1) - exp(-pow(x, 2))/(x*pow(log(x), 2)) + (1.0/2.0)/sqrt(x); } template struct Fct1 { T operator()(const T & x) { return fct1(x); } }; template T fct2(const T & x, const T & y, const T & z) { T two(2); return 2*sqrt(x)*sqrt(y)/log(sin(z)) + sqrt(y) + exp(-pow(x, two) - pow(y, two) - pow(z, two))/(log(x)*log(y)*log(z)) + cbrt(sin(z))*tan(y) + cos(x) + 2*atanh(5*x)*csc(y); } template T dfct2dx(const T & x, const T & y, const T & z) { T two(2); return -2*x*exp(-pow(x, two) - pow(y, two) - pow(z, two))/(log(x)*log(y)*log(z)) - sin(x) + 10*csc(y)/(-25*pow(x, two) + 1) - exp(-pow(x, two) - pow(y, two) - pow(z, two))/(x*pow(log(x), two)*log(y)*log(z)) + sqrt(y)/(sqrt(x)*log(sin(z))); } template T dfct2dy(const T & x, const T & y, const T & z) { T two(2); return sqrt(x)/(sqrt(y)*log(sin(z))) - 2*y*exp(-pow(x, two) - pow(y, two) - pow(z, two))/(log(x)*log(y)*log(z)) + (pow(tan(y), two) + 1)*cbrt(sin(z)) - 2*cot(y)*atanh(5*x)*csc(y) - exp(-pow(x, two) - pow(y, two) - pow(z, two))/(y*log(x)*pow(log(y), two)*log(z)) + (1.0/2.0)/sqrt(y); } template T dfct2dz(const T & x, const T & y, const T & z) { T two(2); return -2*sqrt(x)*sqrt(y)*cos(z)/(pow(log(sin(z)), two)*sin(z)) - 2*z*exp(-pow(x, two) - pow(y, two) - pow(z, two))/(log(x)*log(y)*log(z)) + (1.0/3.0)*cos(z)*tan(y)/pow(sin(z), 2.0/3.0) - exp(-pow(x, two) - pow(y, two) - pow(z, two))/(z*log(x)*log(y)*pow(log(z), two)); } void test_derivatives(); int main() { {// C++14 version { PRINT_STR("\nStatic\n"); { DualS a; PRINT_VAR(a.a); PRINT_VAR(a.b.transpose()); } { DualS a(3.14); PRINT_VAR(a.a); PRINT_VAR(a.b.transpose()); } { DualS a(3.14, {1.,2.,3.}); PRINT_VAR(a.a); PRINT_VAR(a.b.transpose()); } { DualS a(3.14, {1.,2.,3.}), b(2.71, {-1., 3., 4.}); auto c = a + b; PRINT_VAR(a.a); PRINT_VAR(a.b.transpose()); PRINT_VAR(b.a); PRINT_VAR(b.b.transpose()); PRINT_VAR(c.a); PRINT_VAR(c.b.transpose()); } { double af = 3.14, bf = 2.71; DualS a(af, {1.,0.}), b(bf, {0., 1.}); PRINT_VAR((a+b).a); PRINT_VAR((a+b).b.transpose()); PRINT_VAR((a-b).a); PRINT_VAR((a-b).b.transpose()); PRINT_VAR((a*b).a); PRINT_VAR((a*b).b.transpose()); PRINT_VAR((a/b).a); PRINT_VAR((a/b).b.transpose()); PRINT_VAR(((a+b)*(a+b)).a); PRINT_VAR(((a+b)*(a+b)).b.transpose()); PRINT_VAR((sqrt(a)*sqrt(b)).b.transpose()); PRINT_VAR((1.0/2.0)*sqrt(bf)/sqrt(af)); PRINT_VAR((1.0/2.0)*sqrt(af)/sqrt(bf)); } } { PRINT_STR("\nDynamic\n"); { DualD a; PRINT_VAR(a.a); PRINT_VAR(a.b.transpose()); } { DualD a(3.14); PRINT_VAR(a.a); PRINT_VAR(a.b.transpose()); } { DualD::VectorT ab(3); ab << 1.,2.,3.; DualD a(3.14, ab); PRINT_VAR(a.a); PRINT_VAR(a.b.transpose()); } { DualD::VectorT ab(3); ab << 1.,2.,3.; DualD::VectorT bb(3); bb << -1.,3.,4.; DualD a(3.14, ab), b(2.71, bb); auto c = a + b; PRINT_VAR(a.a); PRINT_VAR(a.b.transpose()); PRINT_VAR(b.a); PRINT_VAR(b.b.transpose()); PRINT_VAR(c.a); PRINT_VAR(c.b.transpose()); } { double af = 3.14, bf = 2.71; DualD::VectorT ab(3); ab << 1.,2.,3.; DualD::VectorT bb(3); bb << -1.,3.,4.; DualD a(af, ab), b(bf, bb); auto c = (1 + 3*a) + b*2 + 1/b + (3 - a); PRINT_VAR(a.a); PRINT_VAR(a.b.transpose()); PRINT_VAR(b.a); PRINT_VAR(b.b.transpose()); PRINT_VAR(c.a); PRINT_VAR(c.b.transpose()); assert(c.a == ((1 + 3*af) + bf*2 + 1/bf + (3 - af))); } { double af = 3.14, bf = 2.71; DualD a(af), b(bf); a.diff(0); a.diff(1); PRINT_VAR((a+b).a); PRINT_VAR((a+b).b.transpose()); PRINT_VAR((a-b).a); PRINT_VAR((a-b).b.transpose()); PRINT_VAR((a*b).a); PRINT_VAR((a*b).b.transpose()); PRINT_VAR((a/b).a); PRINT_VAR((a/b).b.transpose()); PRINT_VAR(((a+b)*(a+b)).a); PRINT_VAR(((a+b)*(a+b)).b.transpose()); PRINT_VAR((sqrt(a)*sqrt(b)).b.transpose()); PRINT_VAR((1.0/2.0)*sqrt(bf)/sqrt(af)); PRINT_VAR((1.0/2.0)*sqrt(af)/sqrt(bf)); } } #if 0 {// should throw an compile-time assertion Dual a; } #endif #if 0 { DualD ad; DualS as; ad.b.resize(5); as.b.resize(5);// should throw an compile-time error } #endif } test_derivatives(); return 0; } #define PRINT_F_DF(Term) cout << #Term << "\t: " << (Term).x() << "\t" << (Term).d(0) << "\n" void test_derivatives() { cout.precision(16); using S = double; constexpr S tol = 1e-12; { PRINT_STR("--------------------------------"); DualS x(.1); x.diff(0); PRINT_VAR(x); PRINT_F_DF(cos(x)); PRINT_F_DF(sin(x)); PRINT_F_DF(tan(x)); PRINT_F_DF(sec(x)); PRINT_F_DF(csc(x)); PRINT_F_DF(cot(x)); PRINT_F_DF(sqrt(x)); PRINT_F_DF(cbrt(x)); PRINT_F_DF(exp(x)); PRINT_F_DF(2*exp(x)); PRINT_F_DF(exp(2*x)); } #if 1 {// univariate PRINT_STR("--------------------------------"); using D = DualS; S xf = 0.1; D x(xf); x.diff(0); PRINT_VAR(fct1(x)); PRINT_VAR(fct1(xf)); PRINT_VAR(fct1(x).d(0)); PRINT_VAR(dfct1(xf)); assert(fabs(fct1(x).x() - fct1(xf)) < tol); assert(fabs(fct1(x).d(0) - dfct1(xf)) < tol); } #endif #if 1 { using D = DualS; S xf = 0.11, yf = .12, zf = .13; D x(xf); x.diff(0); D y(yf); y.diff(1); D z(zf); z.diff(2); D fxyz = fct2(x, y, z); assert(x.a == xf); assert(y.a == yf); assert(z.a == zf); PRINT_VAR(fxyz); PRINT_VAR(fxyz.d(0)); PRINT_VAR(fxyz.d(1)); PRINT_VAR(fxyz.d(2)); PRINT_VAR(dfct2dx(xf, yf, zf)); PRINT_VAR(dfct2dy(xf, yf, zf)); PRINT_VAR(dfct2dz(xf, yf, zf)); // CHECK(fabs(fxyz.d(0) - dfct2dx(xf, yf, zf)) < tol); // CHECK(fabs(fxyz.d(1) - dfct2dy(xf, yf, zf)) < tol); // CHECK(fabs(fxyz.d(2) - dfct2dz(xf, yf, zf)) < tol); } #endif }