2011-11-14 13 views
11

Estoy haciendo una buena cantidad de programación científica y realicé muy buenas experiencias con ambas Boost.Units, que proporciona análisis dimensional en tiempo de compilación para cantidades (es decir, cantidades de etiquetas con unidades y por lo tanto, detecta muchos errores con el análisis de la dimensión física clásica) y el uso de Eigen 2 para el álgebra lineal.Combinación de una biblioteca de álgebra lineal con Boost :: Unidades

Sin embargo, Eigen no tiene ningún concepto de unidades, y aunque puede establecer las cantidades escalares en matrices para Eigen, espera que la multiplicación de dos cantidades produzca el mismo tipo, lo que obviamente no es cierto para las unidades. Por ejemplo, código como:

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(); 

no funciona, aunque es lógicamente correcto.

¿Hay alguna biblioteca de matriz que admita unidades? Sé que esto habría sido notoriamente difícil de implementar en el pasado, y C++ 11 y decltype harán que sea mucho más fácil, pero seguramente fue posible con C++ 03 y especializaciones de plantillas.

Respuesta

7

Creo que Blitz ++ es compatible con muchas de las funcionalidades de Boost.Units.

Editar por la OP: Para la referencia aquí es el código de prueba completo con el que Probé la funcionalidad Blitz de multiplicación de matrices:

#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; 
} 
+0

Para el registro, porque tuve que buscar un poco yo mismo: [The blitz manual 3.7.1] (http://www.oonumerics.org/blitz/docs/blitz_3.html#SEC90) le dice cómo promover el usuario tipos definidos Gracias por la pista. – thiton

1

Usted debe visitar esta página Wiki: http://eigen.tuxfamily.org/dox-devel/TopicCustomizingEigen.html

Eigen requiere algo de trabajo a los usos distintos tipos de datos primitivos, pero es generalmente posible.

+2

Gracias por la pista. Había leído la página y seguido los consejos. El punto es que el operador + funciona bien, pero p. el operador * está mal, porque el medidor * es * no * un medidor. – thiton

0

la dificultad de utilizar la opción de biblioteca de complementos estándar Eigen, es que los operadores existentes +, -, *, etc. deben ser reemplazados por las cantidades de Boost Units que se utilizarán.

Por ejemplo, durante unos amplificadores de tipo personalizado para trabajar con el operador * se multiplican, para un CUSTOM_TYPE arbitraria, tiene que tener este aspecto:

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>(...); 
} 

Note como el tipo de retorno no es lo mismo que los tipos de entrada. Aquí usa la plantilla helper multiply_typeof_helper para crear el tipo de devolución. Esto se debe a que multiplicar metros por segundos no le dará una cantidad de ninguna unidad. Sin embargo, el operador Eigen * predeterminado devolverá el mismo "tipo" que el de las entradas: este es el problema.

La otra opción es insertar la matriz Eigen dentro de la cantidad, en lugar de incrustar la cantidad dentro de la matriz.

Cuestiones relacionadas