Объединение библиотеки линейной алгебры с Boost :: Units - PullRequest
12 голосов
/ 14 ноября 2011

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

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

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 ]

7 голосов
/ 14 ноября 2011

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

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

#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;
}
1 голос
/ 14 ноября 2011

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

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

0 голосов
/ 28 мая 2016

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

Например, чтобы пользовательский тип блоков Boost работал с оператором * 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 * по умолчанию вернет тот же «тип», что и у входов - это проблема.

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

...