Home | History | Annotate | Download | only in test
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008 Gael Guennebaud <g.gael (at) free.fr>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 #include "main.h"
     11 #include <Eigen/Dense>
     12 
     13 #define NUMBER_DIRECTIONS 16
     14 #include <unsupported/Eigen/AdolcForward>
     15 
     16 template<typename Vector>
     17 EIGEN_DONT_INLINE typename Vector::Scalar foo(const Vector& p)
     18 {
     19   typedef typename Vector::Scalar Scalar;
     20   return (p-Vector(Scalar(-1),Scalar(1.))).norm() + (p.array().sqrt().abs() * p.array().sin()).sum() + p.dot(p);
     21 }
     22 
     23 template<typename _Scalar, int NX=Dynamic, int NY=Dynamic>
     24 struct TestFunc1
     25 {
     26   typedef _Scalar Scalar;
     27   enum {
     28     InputsAtCompileTime = NX,
     29     ValuesAtCompileTime = NY
     30   };
     31   typedef Matrix<Scalar,InputsAtCompileTime,1> InputType;
     32   typedef Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
     33   typedef Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType;
     34 
     35   int m_inputs, m_values;
     36 
     37   TestFunc1() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {}
     38   TestFunc1(int inputs, int values) : m_inputs(inputs), m_values(values) {}
     39 
     40   int inputs() const { return m_inputs; }
     41   int values() const { return m_values; }
     42 
     43   template<typename T>
     44   void operator() (const Matrix<T,InputsAtCompileTime,1>& x, Matrix<T,ValuesAtCompileTime,1>* _v) const
     45   {
     46     Matrix<T,ValuesAtCompileTime,1>& v = *_v;
     47 
     48     v[0] = 2 * x[0] * x[0] + x[0] * x[1];
     49     v[1] = 3 * x[1] * x[0] + 0.5 * x[1] * x[1];
     50     if(inputs()>2)
     51     {
     52       v[0] += 0.5 * x[2];
     53       v[1] += x[2];
     54     }
     55     if(values()>2)
     56     {
     57       v[2] = 3 * x[1] * x[0] * x[0];
     58     }
     59     if (inputs()>2 && values()>2)
     60       v[2] *= x[2];
     61   }
     62 
     63   void operator() (const InputType& x, ValueType* v, JacobianType* _j) const
     64   {
     65     (*this)(x, v);
     66 
     67     if(_j)
     68     {
     69       JacobianType& j = *_j;
     70 
     71       j(0,0) = 4 * x[0] + x[1];
     72       j(1,0) = 3 * x[1];
     73 
     74       j(0,1) = x[0];
     75       j(1,1) = 3 * x[0] + 2 * 0.5 * x[1];
     76 
     77       if (inputs()>2)
     78       {
     79         j(0,2) = 0.5;
     80         j(1,2) = 1;
     81       }
     82       if(values()>2)
     83       {
     84         j(2,0) = 3 * x[1] * 2 * x[0];
     85         j(2,1) = 3 * x[0] * x[0];
     86       }
     87       if (inputs()>2 && values()>2)
     88       {
     89         j(2,0) *= x[2];
     90         j(2,1) *= x[2];
     91 
     92         j(2,2) = 3 * x[1] * x[0] * x[0];
     93         j(2,2) = 3 * x[1] * x[0] * x[0];
     94       }
     95     }
     96   }
     97 };
     98 
     99 template<typename Func> void adolc_forward_jacobian(const Func& f)
    100 {
    101     typename Func::InputType x = Func::InputType::Random(f.inputs());
    102     typename Func::ValueType y(f.values()), yref(f.values());
    103     typename Func::JacobianType j(f.values(),f.inputs()), jref(f.values(),f.inputs());
    104 
    105     jref.setZero();
    106     yref.setZero();
    107     f(x,&yref,&jref);
    108 //     std::cerr << y.transpose() << "\n\n";;
    109 //     std::cerr << j << "\n\n";;
    110 
    111     j.setZero();
    112     y.setZero();
    113     AdolcForwardJacobian<Func> autoj(f);
    114     autoj(x, &y, &j);
    115 //     std::cerr << y.transpose() << "\n\n";;
    116 //     std::cerr << j << "\n\n";;
    117 
    118     VERIFY_IS_APPROX(y, yref);
    119     VERIFY_IS_APPROX(j, jref);
    120 }
    121 
    122 void test_forward_adolc()
    123 {
    124   adtl::setNumDir(NUMBER_DIRECTIONS);
    125 
    126   for(int i = 0; i < g_repeat; i++) {
    127     CALL_SUBTEST(( adolc_forward_jacobian(TestFunc1<double,2,2>()) ));
    128     CALL_SUBTEST(( adolc_forward_jacobian(TestFunc1<double,2,3>()) ));
    129     CALL_SUBTEST(( adolc_forward_jacobian(TestFunc1<double,3,2>()) ));
    130     CALL_SUBTEST(( adolc_forward_jacobian(TestFunc1<double,3,3>()) ));
    131     CALL_SUBTEST(( adolc_forward_jacobian(TestFunc1<double>(3,3)) ));
    132   }
    133 
    134   {
    135     // simple instanciation tests
    136     Matrix<adtl::adouble,2,1> x;
    137     foo(x);
    138     Matrix<adtl::adouble,Dynamic,Dynamic> A(4,4);;
    139     A.selfadjointView<Lower>().eigenvalues();
    140   }
    141 }
    142