VectorBase.hpp

Go to the documentation of this file.
00001 #pragma ident "$Id: VectorBase.hpp 3140 2012-06-18 15:03:02Z susancummins $"
00002 
00003 
00004 
00010 #ifndef GPSTK_VECTOR_BASE_HPP
00011 #define GPSTK_VECTOR_BASE_HPP
00012 
00013 //============================================================================
00014 //
00015 //  This file is part of GPSTk, the GPS Toolkit.
00016 //
00017 //  The GPSTk is free software; you can redistribute it and/or modify
00018 //  it under the terms of the GNU Lesser General Public License as published
00019 //  by the Free Software Foundation; either version 2.1 of the License, or
00020 //  any later version.
00021 //
00022 //  The GPSTk is distributed in the hope that it will be useful,
00023 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 //  GNU Lesser General Public License for more details.
00026 //
00027 //  You should have received a copy of the GNU Lesser General Public
00028 //  License along with GPSTk; if not, write to the Free Software Foundation,
00029 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00030 //  
00031 //  Copyright 2004, The University of Texas at Austin
00032 //
00033 //============================================================================
00034 
00035 #include <valarray>
00036 #include "Exception.hpp"
00037 
00038 #include "MathBase.hpp"
00039 
00040 namespace gpstk
00041 {
00044  
00047 NEW_EXCEPTION_CLASS(VectorException, gpstk::Exception);
00048 
00049 /*
00050  * There were two overriding philosophies to the vector and matrix classes:
00051  *
00052  * The concept of "const" and "reference" (i.e. changable) vector
00053  * and matrix types both exist, so that any Const* type could not be altered
00054  * while Ref* types can.  This allowed one to add the slice classes that 
00055  * let you use a subset of a vector and modify (or not if it's const) the
00056  * original vector.  Furthermore, it allowed slice and non-slice classes
00057  * to interoperate through the ConstVectorBase or ConstMatrixBase classes, so, for 
00058  * example, operator* only needs to be written in terms of ConstVectorBase to
00059  * work correctly with Vector, VectorSlice and ConstVectorSlice.
00060  * 
00061  * Remember that a slice MUST refer to a vector or matrix; you cannot have
00062  * a slice independent of a base vector or matrix.
00063  *
00064  * In the future:
00065  *
00066  * - Change the math operators to template expressions.
00067  * - Add general slices and diagonal matrix slices.
00068  * - Make range checking more consistent.
00069  * - Make operator= and copy constructors consistent between const and
00070  *   non-const versions.
00071  * - Reevaluate the need for default slice constructors...?
00072  * - find a way for LUD and SVD to use the template type of the parameters
00073  *   rather than specified when the object is created.
00074  * - come up with a policy for when zeroize() will be used before results
00075  *   are returned.
00076  *
00077  * @warning MSVC cant deal with cmath header.  
00078  * Changes to accomidate this may break complex!
00079  */
00080 
00085    template <class T, class BaseClass>
00086    class ConstVectorBase
00087    {
00088    public:
00090       explicit ConstVectorBase() {}
00091 
00093       size_t size() const
00094          { return static_cast<const BaseClass*>(this)->size(); }
00096       T operator[] (size_t i) const 
00097          { return constVectorRef(i); }
00099       T operator() (size_t i) const 
00100          { return constVectorRef(i); }
00101 
00102    protected:
00104       inline T constVectorRef(size_t i) const
00105          throw(VectorException)
00106          {
00107             const BaseClass& b = static_cast<const BaseClass&>(*this);
00108 #ifdef RANGECHECK
00109             if (i >= b.size())
00110             {
00111                VectorException e("Invalid ConstVectorBase index");
00112                GPSTK_THROW(e);
00113             }
00114 #endif
00115             return b[i];
00116          }
00117    };
00118 
00122    class RefVectorBaseHelper
00123    {
00124    public:
00127       static double zeroTolerance;
00128    };
00129 
00133    template <class T, class BaseClass>
00134    class RefVectorBase : public ConstVectorBase<T, BaseClass>,
00135                       public RefVectorBaseHelper
00136    {
00137    public:
00139       explicit RefVectorBase() {}
00141       T& operator[] (size_t i) 
00142          { return vecRef(i); }
00144       T& operator() (size_t i) 
00145          { return vecRef(i); }
00148       BaseClass& zeroize()
00149          {
00150             BaseClass& me = static_cast<BaseClass&>(*this); 
00151             size_t i;
00152             for (i = 0; i < me.size(); i++)
00153                if (ABS(me[i]) < zeroTolerance)
00154                   me[i] = T(0);
00155             return me;
00156          }
00157 
00158 #define VecBaseArrayAssignMacroDontCheckRange(func) \
00159    BaseClass& me = static_cast<BaseClass&>(*this); \
00160    size_t i; for (i=0; i < me.size(); i++) { \
00161       me[i] func x[i]; \
00162    } \
00163    return me;
00164 
00165 #ifdef RANGECHECK
00166 #define VecBaseArrayAssignMacro(func) \
00167    BaseClass& me = static_cast<BaseClass&>(*this); \
00168    if (x.size() != me.size()) \
00169       { \
00170          VectorException e("Unequal lengths for vectors"); \
00171          GPSTK_THROW(e); \
00172       } \
00173    size_t i; for (i=0; i < me.size(); i++) me[i] func x[i]; \
00174    return me;
00175 #else
00176 #define VecBaseArrayAssignMacro(func) \
00177 VecBaseArrayAssignMacroDontCheckRange(func)
00178 #endif
00179 
00180 #define VecBaseAtomicAssignMacro(func) \
00181    BaseClass& me = static_cast<BaseClass&>(*this); \
00182    size_t i; for (i=0; i < me.size(); i++) me[i] func x; \
00183    return me;
00184 
00185 #define VecBaseNewAssignOperator(funcName, op) \
00186  \
00187    template <class E> BaseClass& funcName(const ConstVectorBase<T, E>& x) \
00188       { VecBaseArrayAssignMacro(op) } \
00189  \
00190    BaseClass& funcName(const std::valarray<T>& x) \
00191       { VecBaseArrayAssignMacro(op) } \
00192  \
00193    BaseClass& funcName(const T* x) \
00194       { VecBaseArrayAssignMacroDontCheckRange(op) } \
00195  \
00196    BaseClass& funcName(T x) \
00197       { VecBaseAtomicAssignMacro(op) }
00198 
00204       VecBaseNewAssignOperator(assignFrom, =);
00205       VecBaseNewAssignOperator(operator+=, +=);
00206       VecBaseNewAssignOperator(operator-=, -=);
00207       VecBaseNewAssignOperator(operator*=, *=);
00208       VecBaseNewAssignOperator(operator/=, /=);
00209 
00210       //   // unary minus: multiplies each element of this vector by -1.
00211       //BaseClass& operator-()
00212       //   {
00213       //      const T x=T(-1);
00214       //      VecBaseAtomicAssignMacro(*=);
00215       //   }
00216       // unary minus must not return an l-value
00217 
00219       const BaseClass operator-() const
00220       {
00221          const T x=T(-1);
00222          BaseClass me = static_cast<BaseClass>(*this);
00223          size_t i;
00224          for (i=0; i < me.size(); i++) me(i) *= x;
00225          return me;
00226       }
00227 
00228    protected:
00230       inline T& vecRef(size_t i) 
00231          throw(VectorException)
00232          {
00233             BaseClass& b = static_cast<BaseClass&>(*this);
00234 #ifdef RANGECHECK
00235             if (i >= b.size())
00236             {
00237                VectorException e("Invalid VectorBase index");
00238                GPSTK_THROW(e);
00239             }
00240 #endif
00241             return b[i]; 
00242          }
00243    };
00244 
00248    template <class BaseClass>
00249    class VectorSliceBase
00250    {
00251    public:
00253       explicit VectorSliceBase() {}
00254 
00256       size_t size() const
00257          { return static_cast<const BaseClass*>(this)->size(); }
00259       size_t start() const
00260          { return static_cast<const BaseClass*>(this)->start(); }
00262       size_t stride() const
00263          { return static_cast<const BaseClass*>(this)->stride(); }
00264 
00265    protected:
00267       inline void vecSliceCheck(size_t sourceSize) const
00268          throw(VectorException)
00269          {
00270 #ifdef RANGECHECK
00271                // sanity checks...
00272             if ( (start() >= sourceSize) ||
00273                  ((start() + (size() - 1) * stride()) >= sourceSize) )
00274             {
00275                VectorException e("Invalid range for slice");
00276                GPSTK_THROW(e);
00277             }
00278 #endif
00279          }
00280    };
00281 
00286    template <class T, class BaseClass>
00287    class ConstVectorSliceBase : public VectorSliceBase<BaseClass>,
00288                              public ConstVectorBase<T, BaseClass>
00289    {
00290 public:
00291    explicit ConstVectorSliceBase() {}
00292 };
00293 
00298 template <class T, class BaseClass>
00299 class RefVectorSliceBase : public VectorSliceBase<BaseClass>,
00300                         public RefVectorBase<T, BaseClass>
00301 {
00302 public:
00303    explicit RefVectorSliceBase() {}
00304 };
00305 
00307 
00308 }  // namespace gpstk
00309 
00310 #include "VectorBaseOperators.hpp"
00311 
00312 #endif //GPSTK_VECTOR_BASE_HPP

Generated on Fri May 24 03:31:14 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1