Объединение библиотеки линейной алгебры с 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 * по умолчанию будет возвращать тот же" тип", что и у входных данных - это проблема.
другой вариант-внедрить собственную матрицу внутри количества, а не внедрять количество внутри Матрицы.