Spec-Zone.ru › Eigen3

Использование пользовательских скалярных типов

По умолчанию, Eigen в настоящее время поддерживает стандартные типы с плавающей точкой (float, double, std::complex<float>, std::complex<double>, long double), а также все встроенные целочисленные типы (например, int, unsigned int, short, и т.д.), и bool. На системах x86-64, long double позволяет локально принудительно использовать регистры x87 с расширенной точностью (по сравнению с SSE).

Для добавления поддержки пользовательского типа T необходимо:

  1. убедиться, что базовые операторы (+,-,*,/, и т.д.) поддерживаются типом T
  2. добавить специализацию структуры Eigen::NumTraits<T> (см. NumTraits)
  3. определить математические функции, имеющие смысл для вашего типа. Это включает стандартные функции, такие как sqrt, pow, sin, tan, conj, real, imag и т.д., а также abs2, которая является специфической для Eigen. (см. файл Eigen/src/Core/MathFunctions.h)

Математические функции должны быть определены в том же пространстве имён, что и T, или в пространстве имён std, хотя второй подход не рекомендуется.

Вот конкретный пример добавления поддержки типа adouble из библиотеки Adolc. Adolc — это библиотека автоматического дифференцирования. Тип adouble представляет собой вещественное значение, отслеживающее значения любого количества частных производных.

#ifndef ADOLCSUPPORT_H
#define ADOLCSUPPORT_H
 
#define ADOLC_TAPELESS
#include <adolc/adouble.h>
#include <Eigen/Core>
 
namespace Eigen {
 
template<> struct NumTraits<adtl::adouble>
 : NumTraits<double> // permits to get the epsilon, dummy_precision, lowest, highest functions
{
  typedef adtl::adouble Real;
  typedef adtl::adouble NonInteger;
  typedef adtl::adouble Nested;
 
  enum {
    IsComplex = 0,
    IsInteger = 0,
    IsSigned = 1,
    RequireInitialization = 1,
    ReadCost = 1,
    AddCost = 3,
    MulCost = 3
  };
};
 
}
 
namespace adtl {
 
inline const adouble& conj(const adouble& x)  { return x; }
inline const adouble& real(const adouble& x)  { return x; }
inline adouble imag(const adouble&)    { return 0.; }
inline adouble abs(const adouble&  x)  { return fabs(x); }
inline adouble abs2(const adouble& x)  { return x*x; }
 
}
 
#endif // ADOLCSUPPORT_H

Этот другой пример добавляет поддержку типа mpq_class из GMP. Он демонстрирует, как можно изменить способ, которым Eigen выбирает лучший главный элемент при LU-разложении. Выбирается коэффициент с наивысшим значением оценки, где оценка по умолчанию — абсолютное значение числа, но мы можем определить другую оценку, например, для предпочтения главных элементов с более компактным представлением (это пример, а не рекомендация). Обратите внимание, что оценки должны быть всегда неотрицательными, и только нулю разрешается иметь оценку ноль. Кроме того, это может плохо взаимодействовать с порогами для неточных скалярных типов.

#include <gmpxx.h>
#include <Eigen/Core>
#include <boost/operators.hpp>
 
namespace Eigen {
  template<> struct NumTraits<mpq_class> : GenericNumTraits<mpq_class>
  {
    typedef mpq_class Real;
    typedef mpq_class NonInteger;
    typedef mpq_class Nested;
 
    static inline Real epsilon() { return 0; }
    static inline Real dummy_precision() { return 0; }
    static inline int digits10() { return 0; }
 
    enum {
      IsInteger = 0,
      IsSigned = 1,
      IsComplex = 0,
      RequireInitialization = 1,
      ReadCost = 6,
      AddCost = 150,
      MulCost = 100
    };
  };
 
  namespace internal {
 
    template<> struct scalar_score_coeff_op<mpq_class> {
      struct result_type : boost::totally_ordered1<result_type> {
        std::size_t len;
        result_type(int i = 0) : len(i) {} // Eigen uses Score(0) and Score()
        result_type(mpq_class const& q) :
          len(mpz_size(q.get_num_mpz_t())+
              mpz_size(q.get_den_mpz_t())-1) {}
        friend bool operator<(result_type x, result_type y) {
          // 0 is the worst possible pivot
          if (x.len == 0) return y.len > 0;
          if (y.len == 0) return false;
          // Prefer a pivot with a small representation
          return x.len > y.len;
        }
        friend bool operator==(result_type x, result_type y) {
          // Only used to test if the score is 0
          return x.len == y.len;
        }
      };
      result_type operator()(mpq_class const& x) const { return x; }
    };
  }
}

© Eigen.
Licensed under the MPL2 License.
https://eigen.tuxfamily.org/dox/TopicCustomizing_CustomScalar.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API