text: #pragma ident "$Id$"
  
  
  
  /**
   * @file Vector.hpp
   * Classes for Vector, both constant and modifiable
   */
  
  #ifndef GPSTK_VECTOR_HPP
  #define GPSTK_VECTOR_HPP
  
  //============================================================================
  //
  //  This file is part of GPSTk, the GPS Toolkit.
  //
  //  The GPSTk is free software; you can redistribute it and/or modify
  //  it under the terms of the GNU Lesser General Public License as published
  //  by the Free Software Foundation; either version 2.1 of the License, or
  //  any later version.
  //
  //  The GPSTk is distributed in the hope that it will be useful,
  //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  //  GNU Lesser General Public License for more details.
  //
  //  You should have received a copy of the GNU Lesser General Public
  //  License along with GPSTk; if not, write to the Free Software Foundation,
  //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  //
  //  Copyright 2004, The University of Texas at Austin
  //
  //============================================================================
  
  #include <limits>
  #include <vector>
  #include "VectorBase.hpp"
  
  namespace gpstk
  {
  /** @addtogroup VectorGroup */
  //@{
  
  // forward declaration
  template <class T> class VectorSlice;
  
  /**
   * This class pretty much duplicates std::valarray<T> except it's fully
   * STL container compliant.  Remember that operators +=, -=, *= and /=
   * are provided by RefVectorBase.
   *
   * @sa matvectest.cpp for examples
   */
  template <class T>
  class Vector : public RefVectorBase<T, Vector<T> >
  {
  public:
      /// STL value type
      typedef T value_type;
      /// STL reference type
      typedef T& reference;
      /// STL const reference type
      typedef const T& const_reference;
      /// STL iterator type
      typedef T* iterator;
      /// STL const iterator type
      typedef const T* const_iterator;
  
      /// Default constructor
      Vector() : v(NULL), s(0) {}
      /// Constructor given an initial size.
      Vector(size_t siz) : s(siz)
          //: v(new T[siz]), s(siz)
      {
          v = new T[siz];
          if(!v)
          {
              VectorException e("Vector(size_t) failed to allocate");
              GPSTK_THROW(e);
          }
      }
      /**
       * Constructor given an initial size and default value for all elements.
       */
      Vector(size_t siz, const T defaultValue) : s(siz)
          //: v(new T[siz]), s(siz)
      {
          v = new T[siz];
          if(!v)
          {
              VectorException e("Vector<T>(size_t, const T) failed to allocate");
              GPSTK_THROW(e);
          }
          this->assignFrom(defaultValue);
      }
      /**
       * Copy constructor from a ConstVectorBase type.
       */
      template <class E>
      Vector(const ConstVectorBase<T, E>& r) : s(r.size())
          //: v(new T[r.size()]), s(r.size())
      {
          v = new T[r.size()];
          if(!v)
          {
              VectorException e("Vector<T>(ConstVectorBase) failed to allocate");
              GPSTK_THROW(e);
          }
          this->assignFrom(r);
      }
      /**
       * Copy constructor.
       */
      Vector(const Vector& r) : s(r.s)
          //: v(new T[r.s]), s(r.s)
      {
          v = new T[r.s];
          if(!v)
          {
              VectorException e("Vector(Vector) failed to allocate");
              GPSTK_THROW(e);
          }
          this->assignFrom(r);
      }
      /**
       * Valarray constructor
       */
      Vector(const std::valarray<T>& r) : s(r.size())
          //: v(new T[r.size()]), s(r.size())
      {
          v = new T[r.size()];
          if(!v)
          {
              VectorException e("Vector(valarray) failed to allocate");
              GPSTK_THROW(e);
          }
          this->assignFrom(r);
      }
  
      /// subvector constructor
      template <class E>
      Vector(const ConstVectorBase<T, E>& vec,
             size_t top,
             size_t num) : v(NULL),s(0)
      {
          // sanity checks...
          if ( top >= vec.size() ||
                  top + num > vec.size())
          {
              VectorException e("Invalid dimensions or size for Vector(VectorBase)");
              GPSTK_THROW(e);
          }
  
          v = new T[num];
          if(!v)
          {
              VectorException e("Vector(subvector) failed to allocate");
              GPSTK_THROW(e);
          }
          size_t i;
          for(i = 0; i < num; i++)
              v[i] = vec(top+i);
          s = num;
      }
  
      /// Destructor
      ~Vector()
      {
          if (v)
              delete [] v;
      }
  
      /// STL iterator begin
      iterator begin()
      {
          return v;
      }
      /// STL const iterator begin
      const_iterator begin() const
      {
          return v;
      }
      /// STL iterator end
      iterator end()
      {
          return v + s;
      }
      /// STL const iterator end
      const_iterator end() const
      {
          return v + s;
      }
      /// STL front
      value_type front()
      {
          return v[s-1];
      }
      /// STL const front
      const_reference front() const
      {
          return v[s-1];
      }
      /// STL empty
      bool empty() const
      {
          return size() == 0;
      }
      /// STL size
      size_t size() const
      {
          return s;
      }
      /// STL max_size
      size_t max_size() const
      {
          return std::numeric_limits<size_t>().max();
      }
  
      /// Non-const operator []
      T& operator[] (size_t i)
      {
          return v[i];
      }
      /// Const operator []
      T operator[] (size_t i) const
      {
          return v[i];
      }
      /// Non-const operator ()
      T& operator() (size_t i)
      {
          return v[i];
      }
      /// Const operator ()
      T operator() (size_t i) const
      {
          return v[i];
      }
  
      /// Like valarray, lets you do vec[slice] to get a VectorSlice.
      VectorSlice<T> operator[] (const std::slice& sli)
      {
          return VectorSlice<T>(*this, sli);
      }
  
      /// *this will be resized if it isn't as large as x.
      Vector& operator=(const Vector& x)
      {
          resize(x.s);
          return this->assignFrom(x);
      }
  
      /// *this will be resized if it isn't as large as x.
      template <class E>
      Vector& operator=(const ConstVectorBase<T, E>& x)
      {
          resize(x.size());
          return this->assignFrom(x);
      }
  
      /// *this will be resized if it isn't as large as x.
      Vector& operator=(const std::valarray<T>& x)
      {
          resize(x.size());
          return this->assignFrom(x);
      }
      /// Only (*this).size() elements will be assigned.
      Vector& operator=(const T x)
      {
          return this->assignFrom(x);
      }
      /// Only (*this).size() elements will be assigned.
      Vector& operator=(const T* x)
      {
          return this->assignFrom(x);
      }
  
      /// *this will be cleared and resized as necessary
      inline Vector& operator=(const std::vector<T>& x)
      {
          size_t i;
          size_t vs = x.size();
          (*this).resize(vs);
  
          for (i = 0; i < vs; i++)
              (*this)[i] = x[i];
  
          return (*this);
      }
  
      /// Resizes the vector.  if index > size, the vector will be
      /// erased and the contents destroyed.
      Vector& resize(const size_t index)
      {
          if (index > s)
          {
              if (v)
                  delete [] v;
              v = new T[index];
              if(!v)
              {
                  VectorException e("Vector.resize(size_t) failed to allocate");
                  GPSTK_THROW(e);
              }
          }
          s = index;
          return *this;
      }
  
      /// resize with new default value
      Vector& resize(const size_t index, const T defaultValue)
      {
          resize(index);
          size_t i;
          for(i = 0; i < s; i++)
              v[i] = defaultValue;
          return *this;
      }
  
      // convert the gpstk vector to std vector
      std::vector<T> toStdVector()
      {
          std::vector<T> v;
          for(size_t i = 0; i < s; i++)
              v.push_back(v[i] );
          return v;
      }
  
      inline Vector& operator<<(const Vector& b)
      {
          size_t i;
          size_t vs = this->size();
          size_t bs = b.size();
          size_t rows = vs + bs;
          Vector<T> toReturn(rows);
  
          for (i = 0; i < vs; i++)
              toReturn[i] = (*this)[i];
  
          for (i = 0; i < bs; i++)
              toReturn[i+vs] = b[i];
  
          (*this) = toReturn;
  
          return (*this);
      }
  
      /// Returns the concatenation of this Vector and a scalar of type T
      inline Vector& operator<<(const T &b)
      {
          return (*this) << Vector(1,b);
      }
  
      /// Returns the concatenation of this Vector and Vector b
      inline Vector operator&&(const Vector &b)
      {
          size_t i;
          size_t vs = this->size();
          size_t bs = b.size();
          size_t rows = vs + bs;
          Vector<T> toReturn(rows);
  
          for (i = 0; i < vs; i++)
              toReturn[i] = (*this)[i];
  
          for (i = 0; i < bs; i++)
              toReturn[i+vs] = b[i];
  
          return toReturn;
      }
  
      /// Returns the concatenation of this Vector and a scalar of type T
      inline Vector operator&&(const T &b)
      {
          size_t i;
          size_t vs = this->size();
          size_t rows = vs + 1;
          Vector<T> toReturn(rows);
  
          for (i = 0; i < vs; i++)
              toReturn[i] = (*this)[i];
  
          toReturn[rows - 1] = b;
  
          return toReturn;
      }
  
  private:
  
      // a good optimizer will remove this function call
      // if RANGECHECK isn't defined.  remember that
      // range checking affects EVERY operation
      inline bool rangeCheck(const size_t index) const
      {
  #ifdef RANGECHECK
          return (index < s);
  #else
          return true;
  #endif
      }
  
      /// The vector
      T* v;
      /// The size of the vector.
      size_t s;
  };
  // end class Vector<T>
  
  /**
   * A slice of Vector<T> that can be modified.
   * @warning Remember that (VectorSlice = VectorSlice) will
   * assign elements to the VectorSlice, not copy the VectorSlice internal data!
   */
  template <class T>
  class VectorSlice : public RefVectorSliceBase<T, VectorSlice<T> >
  {
  public:
      /// Default constructor
      VectorSlice()
          : v(NULL), s(std::slice(0,0,0))
      { }
  
      /// Makes a slice of the whole vector
      VectorSlice(Vector<T>& vv)
          : v(&vv), s(std::slice(0,vv.size(),1))
      { }
  
      /// Makes a slice of the vector with the given std::slice.
      VectorSlice(Vector<T>& vv, const std::slice& ss)
          : v(&vv), s(ss)
      {
          vecSliceCheck(vv.size());
      }
  
      /// Assign the elements of this slice from another vector.
      template <class V>
      VectorSlice& operator=(const ConstVectorBase<T, V>& x)
      {
          return this->assignFrom(x);
      }
  
      /// Assign the elements of this slice from a valarray.
      VectorSlice& operator=(const std::valarray<T>& x)
      {
          return this->assignFrom(x);
      }
  
      /// Assign all the elements of this slice to x.
      VectorSlice& operator=(const T x)
      {
          return this->assignFrom(x);
      }
  
      /// Assign (*this).size() elements from x to (*this).
      VectorSlice& operator=(const T* x)
      {
          return this->assignFrom(x);
      }
  
      /// Returns the modifiable i'th element of the slice.
      T& operator[] (size_t i)
      {
          return (*v)[start() + i * stride()];
      }
      /// Returns the const i'th element of the slice.
      T operator[] (size_t i) const
      {
          return (*v)[start() + i * stride()];
      }
      /// Returns the modifiable i'th element of the slice.
      T& operator() (size_t i)
      {
          return (*v)[start() + i * stride()];
      }
      /// Returns the const i'th element of the slice.
      T operator() (size_t i) const
      {
          return (*v)[start() + i * stride()];
      }
  
      /// returns the number of elements in the slice
      inline size_t size() const
      {
          return s.size();
      }
      /// returns the index in the vector of the first element.
      inline size_t start() const
      {
          return s.start();
      }
      /// returns the number of elements to skip between (*this)[i] and
      /// (*this)[i+1]
      inline size_t stride() const
      {
          return s.stride();
      }
  private:
      /// the vector used as a source for the slice
      Vector<T>* v;
      /// the slice specification.
      std::slice s;
  };
  
  /**
   * A Vector<T> slice that doesn't allow modification.
   */
  template <class T>
  class ConstVectorSlice : public ConstVectorSliceBase<T, ConstVectorSlice<T> >
  {
  public:
      /// default constructor
      ConstVectorSlice()
          : v(NULL), s(std::slice(0,0,0))
      { }
  
      /// Makes a slice of the whole vector
      ConstVectorSlice(const Vector<T>& vv)
          : v(&vv), s(std::slice(0,vv.size(),1))
      { }
  
      /// Uses the given slice and vector.
      ConstVectorSlice(const Vector<T>& vv, const std::slice& ss)
          : v(&vv), s(ss)
      {
          vecSliceCheck(vv.size());
      }
  
      /// Returns a const version of the i'th slice element.
      T operator[] (size_t i) const
      {
          return (*v)[start() + i * stride()];
      }
      /// Returns a const version of the i'th slice element.
      T operator() (size_t i) const
      {
          return (*v)[start() + i * stride()];
      }
  
      /// returns the number of elements in the slice
      inline size_t size() const
      {
          return s.size();
      }
      /// returns the index in the vector of the first element.
      inline size_t start() const
      {
          return s.start();
      }
      /// returns the number of elements to skip between (*this)[i] and
      /// (*this)[i+1]
      inline size_t stride() const
      {
          return s.stride();
      }
  
  private:
      /// Vectortor used as a source for this slice.
      const Vector<T>* v;
      /// the slice specification.
      std::slice s;
  };
  
  //@}
  
  }  // namespace
  
  #include "VectorOperators.hpp"
  
  #endif
  