QuantityCluster.h

Go to the documentation of this file.
00001 
00005 /* Copyright (C) 2003 - 2009, Bernd Speiser */
00006 /* This file is part of Quantity.
00007 
00008 Quantity is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 Quantity is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017   
00018 You should have received a copy of the GNU General Public License
00019 along with this program; if not, write to the Free Software
00020 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00021 02111-1307, USA.
00022 */
00023 
00024 #ifndef _QuantityCluster_h
00025 #define _QuantityCluster_h
00026 
00027 // Quantity includes
00028 #include "Quantity/Quantity.h"
00029 
00030 // Loki includes
00031 #include "loki/HierarchyGenerators.h"
00032 
00033 // STL includes
00034 #include <vector>
00035 
00036 // BOOST includes
00037 #include <boost/serialization/vector.hpp>
00038 #include <boost/serialization/base_object.hpp>
00039 
00040 namespace quantity {
00041 
00043 //
00044 //  the Vector base class
00045 //
00047 
00049 
00052 template<typename Q> class Vector;
00053 
00055 
00060 template<typename QT, typename ST> class Vector<Quantity<QT, ST> >
00061   {
00062     private:
00064       typedef Quantity<QT, ST> BQ;
00065 
00066     public:
00068       virtual int size (void) const = 0;
00069 
00071       virtual ~Vector (void) {}
00072 
00074       friend class boost::serialization::access;
00075 
00077 
00079   private:
00080       template<typename Archive>
00081         void serialize (Archive &ar, const unsigned int ) 
00082         {
00083         }
00084 
00085   };
00086 
00088 //
00089 //  the QuantityVector 
00090 //
00092 
00094 
00102 template<template<typename, typename> class M, typename BQ, 
00103   typename DQ = DerivedQuantity<typename BQ::QuantityType, typename BQ::DU, typename BQ::DDQ> > 
00104     class QuantityVector;
00105 
00107 
00117 template<template<typename, typename> class M, typename QT, typename ST, typename SU, typename DQT> 
00118   class QuantityVector<M, Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > 
00119     : public Vector<Quantity<QT, ST> >
00120   {
00121       private:
00123 //  typedef M<Quantity<QT, ST>, DerivedQuantity<QT, SU, DQT> > Q;
00124 
00126 
00128         typedef typename QuantityTraits<QT>::Dimension DIM;
00129 
00131 
00133       typedef typename QuantityTraits<QT>::UnitType UT;
00134 
00136 
00138       typedef typename QuantityTraits<QT>::UnitList UL;
00139 
00141 
00143       typedef typename QuantityTraits<QT>::DefaultUnit DU;
00144 
00146 
00149         typedef Quantity<QT, ST> BQ;
00150 
00152       typedef Vector<Quantity<QT, ST> > VEC;
00153 
00154     public:
00156 
00159       typedef M<BQ, DerivedQuantity<QT, SU, DQT> > V;
00160 
00162 
00164   typedef QuantityVector<M, BQ, DerivedQuantity<QT, SU, DQT> > QV;
00165 
00167 
00169       typedef ST StorageType;
00170 
00172       typedef typename unit::CheckUnit<unit::Unit<UT>, SU>::Check StorageUnit;
00173 
00174     private:
00176       std::vector<ST> _values;
00177 
00178     public:
00180       QuantityVector (void) {}
00181 
00183 
00189 /*
00190     template<class NU>
00191       QuantityVector (const QuantityVector<M, BQ, NU> &new_vector) 
00192       {
00193         typename DerivedQuantityTraits<QT, DQT>::StorageUnit unit;
00194         int size = new_vector.size ();
00195         _values.reserve (size);
00196 
00197         for (int i = 0; i < size; i++)
00198           _values.push_back (new_vector[i].value (unit));
00199       }
00200 */
00201 
00203 
00205       QuantityVector & operator= (const QuantityVector &new_vector)
00206       {
00207         if (this != &new_vector)
00208         {
00209           VEC::operator= (new_vector);
00210           _values = new_vector._values;
00211         }       
00212 
00213         return *this;
00214       }
00215 
00217 
00221     template<typename SSU, typename SDQT>
00222       QuantityVector & operator= (const QuantityVector<M, BQ, DerivedQuantity<QT, SSU, SDQT> > &new_vector)
00223       {
00224         VEC::operator= (new_vector);
00225 
00226         int size = new_vector.size ();
00227 
00228         _values.empty ();
00229 
00230         _values.reserve (size);
00231 
00232         for (int i = 0; i < size; i++)
00233           _values.push_back(Reverse<StorageUnit, typename BQ::StorageType>::VAL 
00234            (Standardize<SSU, typename BQ::StorageType>::VAL (new_vector[i].value ())));
00235 
00236         return *this;
00237       }
00238 
00240 
00244       bool operator== (const QV &vector) const
00245       {
00246         return ((size () == vector.size ()) 
00247                                           && (_values == vector._values));
00248       }
00249 
00251 
00255       int size (void) const {return _values.size ();}
00256 
00258 
00263       template<template<typename, typename> class Q1, typename QT1, 
00264                                              typename ST1, typename SSU, typename SDQT> 
00265         void push_back (const Q1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SSU, SDQT> > &new_quantity)
00266           {_values.push_back (Reverse<StorageUnit, ST>::VAL
00267             (Standardize<typename
00268               CheckAgainstAllUnits<typename Q1<Quantity<QT1, ST1>, 
00269                 DerivedQuantity<QT1, SSU, SDQT> >::StorageUnit, typename Loki::TL::Append<UL, 
00270                   unit::NonPrefixable<unit::GenericUnitBase<DIM>, unit::GenericUnit> 
00271                      >::Result >::RET, ST>::VAL (new_quantity.value ())));}
00272 
00274 
00278       template<template<typename, typename> class Q1, typename QT1, 
00279                                                 typename ST1, typename SSU, typename SDQT> 
00280         void insert (const Q1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SSU, SDQT> > &new_quantity, 
00281                                                          const int index)
00282           {if (index >= 0 && index < size ())
00283             {typename std::vector<ST>::iterator pos 
00284                                              = _values.begin () + index;
00285               _values.insert (pos, Reverse<StorageUnit, ST>::VAL
00286                 (Standardize<typename
00287                    CheckAgainstAllUnits<typename Q1<Quantity<QT1, ST1>, 
00288                      DerivedQuantity<QT1, SSU, SDQT> >::StorageUnit,
00289                   typename Loki::TL::Append<UL,
00290                     unit::NonPrefixable<unit::GenericUnitBase<DIM>, 
00291                         unit::GenericUnit> >::Result >::RET, ST>::VAL
00292                                               (new_quantity.value ())));
00293             }
00294           else
00295             {throw VectorOutOfBounds();}
00296         }                                                    
00297 
00299 
00304       template<template<typename, typename> class Q1, typename QT1, 
00305                                             typename ST1, typename SSU, typename SDQT>
00306         void replace 
00307           (const Q1<Quantity<QT1, ST1>, DerivedQuantity<QT1, SSU, SDQT> > &new_quantity, 
00308                                                                         const int index)
00309           {if (index >= 0 && index < size ())
00310             {_values[index] = Reverse<StorageUnit, ST>::VAL
00311               (Standardize<typename
00312                 CheckAgainstAllUnits<typename Q1<Quantity<QT1, ST1>, 
00313                   DerivedQuantity<QT1, SSU, SDQT> >::StorageUnit,
00314                 typename Loki::TL::Append<UL,
00315                   unit::NonPrefixable<unit::GenericUnitBase<DIM>,
00316                       unit::GenericUnit> >::Result >::RET, ST>::VAL
00317                                                (new_quantity.value ()));
00318             }
00319           else
00320             {throw VectorOutOfBounds();}
00321         }                                                    
00322 
00324 
00326     void erase (const int index)
00327     {
00328       if (index >= 0 && index < size ())
00329       {
00330         typename std::vector<ST>::iterator pos = _values.begin () + index;
00331         _values.erase (pos);
00332       }
00333       else
00334       {throw VectorOutOfBounds();}
00335     }                                                    
00336 
00338     void clear (void) {_values.clear ();}
00339 
00341 
00343     std::vector<ST> values (void) {return _values;}   
00344 
00346 
00348       V value (const int index) const
00349         {if (index >= 0 && index < size ())
00350           {return V (_values[index]);}
00351          else
00352           {throw VectorOutOfBounds();}
00353         }                                                    
00354 
00356 
00359       V operator[] (const int index) const {return value (index);}
00360 
00362 
00366       template<typename NU>
00367         M<Quantity<QT, ST>, DerivedQuantity<QT, NU, DQT> > 
00368           value (const int index, const NU &) const
00369             {return M<Quantity<QT, ST>, DerivedQuantity<QT, NU, DQT> > (value (index));}
00370 
00372 
00375       V max (void) const
00376         {
00377           ST max_val = _values[0];
00378           typename std::vector<ST>::const_iterator index;
00379 
00380           for (index = _values.begin (); index < _values.end (); 
00381                                                                 index++)
00382             max_val = ((max_val < *index) ? *index : max_val);
00383           
00384           return V (max_val);
00385         }
00386 
00388 
00392 /*
00393       template<typename NU>
00394         M<Quantity<QT, ST>, DQT1> max (const NU &unit) const 
00395                                                {return (max ()) (unit);}
00396 */
00397 
00399 
00402       V min (void) const
00403         {
00404           ST min_val = _values[0];
00405           typename std::vector<ST>::const_iterator index;
00406 
00407           for (index = _values.begin (); index < _values.end (); 
00408                                                                 index++)
00409             min_val = ((min_val < *index) ? min_val : *index);
00410           
00411           return V (min_val);
00412         }
00413 
00415 
00419 /*
00420       template<class NU>
00421         M<Quantity<QT, ST>, NU> min (const NU &unit) const 
00422                                             {return (min ()) (unit);}
00423 */
00424 
00425  private:
00427       friend class boost::serialization::access;
00428 
00430 
00432       template<typename Archive>
00433         void serialize (Archive &ar, const unsigned int )
00434         {
00435           ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(VEC);
00436           ar & BOOST_SERIALIZATION_NVP(_values);
00437         }
00438 
00439   };
00440 
00442 
00445 template<class L> class QuantityVectorTuple;
00446 
00448 //
00449 //  helper classes and structs for the QuantityVector tuples
00450 //
00452 
00454 
00459 template<class TL> struct GetVar;
00460 
00462 
00468 template<class Head, class Tail>
00469   struct GetVar<Loki::Typelist<Head, Tail> >
00470 {
00471   private:
00472     typedef typename GetVar<Tail>::Result L1;
00473 
00474   public:
00475     typedef Loki::Typelist<typename Head::V, L1> Result;
00476 };
00477 
00479 
00482 template<>
00483   struct GetVar<Loki::NullType>
00484 {
00485   typedef Loki::NullType Result;
00486 };
00487 
00489 
00492 template<int N, class L>
00493   class AddVal
00494   {
00495     public:
00497       static void addval (QuantityVectorTuple<L> &tuple, 
00498         const typename QuantityVectorTuple<L>::QTuple &new_values)
00499         {Loki::Field<N-1>(tuple.vectors).push_back 
00500                                          (Loki::Field<N-1>(new_values));
00501          AddVal<N-1, L>::addval (tuple, new_values);
00502         }
00503 
00505       static void addval (QuantityVectorTuple<L> &tuple, 
00506         const typename QuantityVectorTuple<L>::QTuple 
00507                                      &new_values, const int index)
00508         {Loki::Field<N-1>(tuple.vectors).insert 
00509                                   (Loki::Field<N-1>(new_values), index);
00510          AddVal<N-1, L>::addval (tuple, new_values, index);
00511         }
00512   };
00513 
00515 
00518 template<class L>
00519   class AddVal<0, L>
00520   {
00521     public:
00522       static void addval (QuantityVectorTuple<L> &,
00523              const typename QuantityVectorTuple<L>::QTuple &) {};
00524 
00525       static void addval (QuantityVectorTuple<L> &,
00526         const typename QuantityVectorTuple<L>::QTuple &, const int) {};
00527   };
00528 
00530 
00533 template<int N, class L>
00534   class EraVal
00535   {
00536     public:
00538       static void eraval (QuantityVectorTuple<L> &tuple, 
00539                                                         const int index)
00540         {Loki::Field<N-1>(tuple.vectors).erase (index);
00541          EraVal<N-1, L>::eraval (tuple, index);
00542         }
00543   };
00544 
00546 
00549 template<class L>
00550   class EraVal<0, L>
00551   {
00552     public:
00553       static void eraval (QuantityVectorTuple<L> &, const int) {};
00554   };
00555 
00557 
00560 template<int N, class L>
00561   class GetVal
00562   {
00563     public:
00565       static typename QuantityVectorTuple<L>::QTuple getval 
00566         (const QuantityVectorTuple<L> &tuple,
00567           typename QuantityVectorTuple<L>::QTuple 
00568                                                &values, const int index)
00569         {Loki::Field<N-1>(values) 
00570                                = Loki::Field<N-1>(tuple.vectors)[index];
00571          return GetVal<N-1, L>::getval (tuple, values, index);
00572         }
00573   };
00574 
00576 
00579 template<class L>
00580   class GetVal<0, L>
00581   {
00582     public:
00583       static typename QuantityVectorTuple<L>::QTuple getval 
00584         (const QuantityVectorTuple<L> &,
00585           typename QuantityVectorTuple<L>::QTuple 
00586                               &values, const int) {return values;}
00587   };
00588 
00590 
00592 template<int N, class L>
00593   class CmpVec
00594   {
00595     public:
00596       static bool cmpVec
00597         (const QuantityVectorTuple<L> &tuple1, 
00598                                    const QuantityVectorTuple<L> &tuple2)
00599       {
00600         if (Loki::Field<N-1>(tuple1.vectors) 
00601                                     == Loki::Field<N-1>(tuple2.vectors))
00602           return CmpVec<N-1, L>::cmpVec (tuple1, tuple2);
00603 
00604         else
00605           return false;
00606       }
00607   };
00608 
00610 
00613 template<class L>
00614   class CmpVec<0, L>
00615   {
00616     public:
00617       static bool cmpVec 
00618         (const QuantityVectorTuple<L> &, const QuantityVectorTuple<L> &)
00619                                                           {return true;}
00620   };
00621 
00623 
00626 template<int N, class L, typename Archive>
00627   class SaveVec
00628   {
00629     public:
00630       static void saveVec
00631         (const QuantityVectorTuple<L> &tuple, Archive &ar) 
00632       {
00633         SaveVec<N-1,L,Archive>::saveVec (tuple, ar);
00634         typename Loki::TL::TypeAt<L, N-1>::Result 
00635                               vec = Loki::Field<N-1>(tuple.vectors);
00636         ar << BOOST_SERIALIZATION_NVP(vec);
00637       }
00638   };
00639 
00641 
00644 template<class L, typename Archive>
00645   class SaveVec<0, L, Archive>
00646   {
00647     public:
00648       static void saveVec (const QuantityVectorTuple<L> &, Archive &) {}
00649   };
00650 
00652 
00659 template<int N, class L, typename Archive>
00660   class LoadVec
00661   {
00662     public:
00663       static void loadVec
00664         (QuantityVectorTuple<L> &tuple, Archive &ar, int &_size) 
00665       {
00666         LoadVec<N-1,L,Archive>::loadVec (tuple, ar, _size);
00667         typename Loki::TL::TypeAt<L, N-1>::Result 
00668                               vec;
00669         ar >> BOOST_SERIALIZATION_NVP(vec);
00670         if (vec.size () == _size)
00671           Loki::Field<N-1>(tuple.vectors) = vec;
00672         else
00673           {throw VectorSizeError("vector has wrong size!");}
00674       }
00675   };
00676 
00678 
00681 template<class L, typename Archive>
00682   class LoadVec<0, L, Archive>
00683   {
00684     public:
00685       static void loadVec (QuantityVectorTuple<L> &, Archive &, int &) {}
00686   };
00687 
00689 /* primary template
00690 */
00691 template <class V, class QVT> struct CheckVariableInVectorTuple;
00692 
00694 
00696 template<template<typename, typename> class T, typename V, typename QT, 
00697                                 typename ST, typename SU, typename LTail>
00698   struct CheckVariableInVectorTuple<V,
00699     Loki::Typelist<QuantityVector<T, Quantity <QT, ST>, SU>, LTail> >
00700   {
00701     private:
00702       typedef typename BSUtilities::IF<BSUtilities::SameType<V,
00703         typename QuantityVector<T, Quantity<QT, ST>, SU>::V>::sameType,
00704           QuantityVector<T, Quantity<QT, ST>, SU>,
00705            typename CheckVariableInVectorTuple<V, LTail>::RET>::RET RET;
00706   };
00707 
00709 
00715 template<typename V>
00716   struct CheckVariableInVectorTuple<V, Loki::NullType>
00717   {
00718     typedef VariableError<true> RET;
00719   };
00720 
00722 //
00723 //  the QuantityVector tuple
00724 //
00726 
00728 
00735 template<template<typename, typename> class T, typename QT,
00736                              typename ST, typename SU, typename LTail>
00737   class QuantityVectorTuple<Loki::Typelist<
00738       QuantityVector<T, Quantity<QT, ST>, SU>, LTail> >
00739   {
00740   private:
00742     typedef Loki::Typelist<QuantityVector<T, Quantity<QT, ST>, SU>, LTail> L;
00743 
00745     typedef QuantityVectorTuple<L> QVT;
00746 
00748     Loki::Tuple<L> vectors;
00749 
00750   public:
00752 
00756     typedef Loki::Tuple<typename GetVar<L>::Result> QTuple;
00757 
00759 
00761       bool operator== (const QuantityVectorTuple &tuple) const
00762         {return CmpVec<Loki::TL::Length<L>::value, L>::cmpVec 
00763                                                         (*this, tuple);}
00764 
00766     int number (void) const {return Loki::TL::Length<L>::value;}
00767 
00769 /*  all vectors have the same size, return value determined from
00770     first vector.
00771 */
00772     int size (void) const {return Loki::Field<0>(vectors).size ();}
00773 
00774 
00776 /*  uses data from a QTuple; uses helper class AddVal.
00777 */
00778     void push_back (const QTuple &new_values)
00779     {
00780       AddVal<Loki::TL::Length<L>::value, L>::addval (*this, new_values);
00781     }
00782 
00784 /*  uses data from a QTuple; uses helper class AddVal.
00785 */
00786     void insert (const QTuple &new_values, const int index)
00787     {
00788       AddVal<Loki::TL::Length<L>::value, L>::addval 
00789                                              (*this, new_values, index);
00790     }
00791 
00793 
00795     void erase (const int index)
00796     {
00797       EraVal<Loki::TL::Length<L>::value, L>::eraval (*this, index);
00798     }
00799 
00801 
00804     template<int I>
00805       typename Loki::TL::TypeAt<L, I>::Result::V 
00806                                   value (const unsigned int index) const
00807                       {return (Loki::Field<I>((*this).vectors))[index];}
00808 
00810 
00829     template<int I, class NU>
00830       T<typename Loki::TL::TypeAt<L, I>::Result::V::BQ, NU> 
00831         value (const int index, const NU &unit) const
00832           {return 
00833                ((Loki::Field<I>((*this).vectors)).value (index))(unit);}
00834 
00836 
00840     QTuple operator[] (const int index) const
00841     {
00842       QTuple values;
00843       return GetVal<Loki::TL::Length<L>::value, L>::getval 
00844                                                  (*this, values, index);
00845     }
00846 
00848 
00850     QTuple values (const int index) const {return (*this)[index];}
00851 
00853     template<int I>
00854       QuantityVector<T, typename Loki::TL::TypeAt<L, I>::Result::V::BQ,
00855         typename Loki::TL::TypeAt<L, I>::Result::V::Unit> 
00856                                      getVector (Loki::Int2Type<I>) const
00857       {return QuantityVector<T, 
00858         typename Loki::TL::TypeAt<L, I>::Result::V::BQ,
00859           typename Loki::TL::TypeAt<L, I>::Result::V::Unit> 
00860                                      (Loki::Field<I>((*this).vectors));}
00861 
00863     template<int N, class L1> friend class AddVal;
00864      
00865     template<int N, class L1> friend class GetVal;
00866      
00867     template<int N, class L1> friend class EraVal;
00868      
00869     template<int N, class L1> friend class CmpVec;
00870      
00871     template<int N, class L1> friend class Copy;
00872      
00873     template<int N, class L1> friend class Assign;
00874 
00875     template<int N, class L1, typename Archive> friend class SaveVec;
00876     template<int N, class L1, typename Archive> friend class LoadVec;
00877 
00878  private:
00880       friend class boost::serialization::access;
00881 
00883 
00891       template<typename Archive>
00892         void save (Archive &ar, const unsigned int ) const
00893         {
00894           int _size = size ();
00895           ar << BOOST_SERIALIZATION_NVP (_size);
00896           SaveVec<Loki::TL::Length<L>::value, L, Archive>
00897                                          ::saveVec (*this, ar);
00898         }
00899 
00901 
00909       template<typename Archive>
00910         void load (Archive &ar, const unsigned int )
00911         {
00912           int _size;
00913           ar >> BOOST_SERIALIZATION_NVP (_size);
00914           LoadVec<Loki::TL::Length<L>::value, L, Archive>
00915                                          ::loadVec (*this, ar, _size);
00916         }
00917 
00918 BOOST_SERIALIZATION_SPLIT_MEMBER()
00919 
00920   };
00921 
00922 }
00923 
00924 #endif /* _QuantityCluster */

Generated on Mon Jul 27 15:55:45 2009 for Quantities by  doxygen 1.5.3