2011-11-14 10 views
11

Sto facendo una buona quantità di programmazione scientifica e ho fatto ottime esperienze con entrambe le unità Boost.Units, che fornisce un'analisi dimensionale in fase di compilazione per le quantità (ad esempio quantità di tag con unità e cattura così molti errori con l'analisi classica della dimensione fisica) e usa Eigen 2 per l'algebra lineare.Combinare una libreria algebra lineare con Boost :: Units

Tuttavia, Eigen non ha alcun concetto di unità e mentre è possibile impostare le quantità scalari nelle matrici per Eigen, si prevede che la moltiplicazione di due quantità restituisca lo stesso tipo, che ovviamente non è vero per le unità. Ad esempio, codice come:

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

non funziona, anche se è logicamente corretto.

Esiste una libreria di matrici che supporti le unità? So che questo sarebbe stato notoriamente difficile da implementare in passato, e C++ 11 e decltype renderà tutto molto più semplice, ma sicuramente è stato possibile con C++ 03 e le specializzazioni dei modelli.

risposta

7

Credo che Blitz ++ supporti gran parte della funzionalità Boost.Units.

Edit dal PO: Per il riferimento è il codice di prova completa con cui ho testato la funzionalità Blitz moltiplicazione matriciale:

#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

Per la cronaca, perché ho dovuto cercare un po 'me stesso: [The blitz manual 3.7.1] (http://www.oonumerics.org/blitz/docs/blitz_3.html#SEC90) spiega come promuovere l'utente tipi definiti. Grazie per il suggerimento. – thiton

1

Si dovrebbe controllare questa pagina Wiki: http://eigen.tuxfamily.org/dox-devel/TopicCustomizingEigen.html

Eigen richiede un po 'di lavoro per uso diverso da quello dei tipi di dati primitivi, ma è generalmente possibile.

+2

Grazie per il suggerimento. Aveva letto la pagina e seguito i suggerimenti. Il punto è, l'operatore + funziona bene, ma ad es. l'operatore * è errato, perché il metro * è * non * un metro. – thiton

0

La difficoltà di utilizzare l'opzione standard libreria plugin Eigen, è che gli operatori esistenti +, -, *, ecc. devono essere sostituiti per le quantità di unità boost da utilizzare.

Ad esempio, per un'unità Boost tipo personalizzato per funzionare con l'operatore * si moltiplicano, per un CUSTOM_TYPE arbitrario, deve assomigliare a questo:

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

Notate come il tipo di ritorno non è lo stesso di i tipi di input. Qui usi il template helper multiply_typeof_helper per creare il tipo di ritorno. Questo perché moltiplicando i metri con i secondi non otterrai una quantità di entrambe le unità. Tuttavia, l'operatore Eigen * predefinito restituirà lo stesso "tipo" di quello degli input: questo è il problema.

L'altra opzione è incorporare la matrice Eigen all'interno della quantità, anziché incorporare la quantità all'interno della matrice.

Problemi correlati