Объединение библиотеки линейной алгебры с Boost:: Units

Я делаю хорошее количество научного программирования и сделал очень хороший опыт с обоими Boost.Единицы, которая обеспечивает компиляционный размерный анализ для величин (т. е. помечает величины с единицами и тем самым улавливает много ошибок с классическим анализом физической размерности) и использование Eigen 2 для линейной алгебры.

однако Eigen не имеет понятия единиц, и, хотя вы можете установить скалярные величины в матрицах для Eigen, он ожидает, что умножение двух количества дают один и тот же тип, что, очевидно, неверно для единиц. Например, код типа:

using boost::units::quantity;
namespace si = boost::units::si;
Eigen::Matrix< quantity< si::length >, 2, 1 > meter_vector;
quantity< si::area > norm = meter_vector.squaredNorm();

не работает, хотя это логически правильно.

есть ли матричная библиотека, поддерживающая единицы? Я знаю, что это было бы, как известно, трудно реализовать в прошлом, а C++11 и decltype сделает это намного проще, но это, безусловно, было возможно с C++03 и специализациями шаблонов.

3 ответов


Я считаю, что Blitz++ поддерживает большую часть Boost.Функциональность блоков.

редактировать OP: для справки вот полный тестовый код, с помощью которого я тестировал функциональность умножения матрицы Блица:

#include <blitz/array.h>
#include <boost/units/systems/si/area.hpp>
#include <boost/units/systems/si/length.hpp>
#include <boost/units/quantity.hpp>

using boost::units::quantity;
namespace si = boost::units::si;

namespace blitz {
template< typename U1, typename T1, typename U2, typename T2>
struct Multiply< quantity<U1,T1>, quantity<U2,T2> >
{
    typedef typename boost::units::multiply_typeof_helper< quantity<U1,T1>, quantity<U2,T2> >::type T_numtype;

    static inline T_numtype apply( quantity<U1,T1> a, quantity<U2,T2> b ) { return a*b; }
};

}

using namespace blitz;

int main() {
    Array< quantity<si::length>, 1 > matrix;
    Array< quantity<si::area>, 1 > area;
    area = matrix * matrix;
    return 0;
}

вы должны проверить эту страницу Wiki: http://eigen.tuxfamily.org/dox-devel/TopicCustomizingEigen.html

Eigen требует некоторой работы для использования, кроме примитивных типов данных, но это обычно возможно.


сложность использования стандартной опции плагина библиотеки Eigen заключается в том, что существующие операторы+, -, * и т. д. должны быть заменены для используемых количеств единиц усиления.

например, для пользовательского типа Boost units для работы с оператором * multiply, для произвольного CUSTOM_TYPE он должен выглядеть так:

template<class X,class Y>
CUSTOM_TYPE<typename boost::units::multiply_typeof_helper<X,Y>::type>
operator*(const CUSTOM_TYPE<X>& x,const CUSTOM_TYPE<Y>& y)
{
    typedef typename boost::units::multiply_typeof_helper<X,Y>::type    type;

    return CUSTOM_TYPE<type>( ... );
}

обратите внимание, что тип возврата не совпадает с типами ввода. Здесь вы используете помощник шаблона multiply_typeof_helper для создания возвращаемый тип. Это потому, что умножение метров с секундами не даст вам количество ни одной единицы. Однако оператор Eigen * по умолчанию будет возвращать тот же" тип", что и у входных данных - это проблема.

другой вариант-внедрить собственную матрицу внутри количества, а не внедрять количество внутри Матрицы.