#pragma ident "$Id: VectorOperators.hpp 3140 2012-06-18 15:03:02Z susancummins $"



/**
 * @file VectorOperators.hpp
 * Vector operators, including arithmetic, trig, cross, RMS, etc
 */

#ifndef GPSTK_VECTOR_OPERATORS_HPP
#define GPSTK_VECTOR_OPERATORS_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
//
//============================================================================

namespace gpstk
{

 /** @addtogroup VectorGroup */
   //@{

#define VecBaseNewUnaryOperator(func) \
      /** performs func on each element of x, returning a new vector */ \
   template <class T, class BaseClass> \
   Vector<T> func(const ConstVectorBase<T, BaseClass>& x) \
      { \
         BaseClass toReturn(x.size()); \
         size_t i; for (i=0; i < x.size(); i++) toReturn[i] = func(x[i]); \
         return toReturn; \
      }

//   VecBaseNewUnaryOperator(-)
   VecBaseNewUnaryOperator(abs)
      VecBaseNewUnaryOperator(acos)
      VecBaseNewUnaryOperator(asin)
      VecBaseNewUnaryOperator(atan)
      VecBaseNewUnaryOperator(cos)
      VecBaseNewUnaryOperator(cosh)
      VecBaseNewUnaryOperator(exp)
      VecBaseNewUnaryOperator(log)
      VecBaseNewUnaryOperator(log10)
      VecBaseNewUnaryOperator(sinh)
      VecBaseNewUnaryOperator(sin)
      VecBaseNewUnaryOperator(sqrt)
      VecBaseNewUnaryOperator(tan)
      VecBaseNewUnaryOperator(tanh)

#define VecBaseNewBinaryOperator(func, retval) \
/** returns a retval with each element the result of l[i] func r[i] */ \
template <class T, class BaseClass, class BaseClass2> \
retval operator func(const ConstVectorBase<T, BaseClass>& l, \
            const ConstVectorBase<T, BaseClass2>& r) \
{ \
   if (l.size() != r.size()) \
   { \
      VectorException e("Unequal lengths vectors"); \
      GPSTK_THROW(e); \
   } \
   retval toReturn(l.size()); \
   size_t i; \
   for (i=0; i < l.size(); i++) toReturn[i] = l[i] func r[i]; \
   return toReturn; \
} \
/** returns a retval with each element the result of l[i] func (scalar)r */ \
template <class T, class BaseClass> \
retval operator func(const ConstVectorBase<T, BaseClass>& l, const T r) \
{ \
   retval toReturn(l.size()); \
   size_t i; \
   for (i=0; i < l.size(); i++) toReturn[i] = l[i] func r; \
   return toReturn; \
} \
/** returns a retval with each element the result of (scalar)l func r[i] */ \
template <class T, class BaseClass> \
retval operator func(const T l, const ConstVectorBase<T, BaseClass>& r) \
{ \
   retval toReturn(r.size()); \
   size_t i; \
   for (i=0; i < r.size(); i++) toReturn[i] = l func r[i]; \
   return toReturn; \
} 

      VecBaseNewBinaryOperator(*, Vector<T>)
      VecBaseNewBinaryOperator(/, Vector<T>)
      VecBaseNewBinaryOperator(%, Vector<T>)
      VecBaseNewBinaryOperator(+, Vector<T>)
      VecBaseNewBinaryOperator(-, Vector<T>)
      VecBaseNewBinaryOperator(^, Vector<T>)
      VecBaseNewBinaryOperator(&, Vector<T>)
      VecBaseNewBinaryOperator(|, Vector<T>)

      VecBaseNewBinaryOperator(==, Vector<bool>)
      VecBaseNewBinaryOperator(<, Vector<bool>)
      VecBaseNewBinaryOperator(>, Vector<bool>)
      VecBaseNewBinaryOperator(!=, Vector<bool>)
      VecBaseNewBinaryOperator(<=, Vector<bool>)
      VecBaseNewBinaryOperator(>=, Vector<bool>)

#define VecBaseNewBinaryTranscendentalOperator(func, retval) \
/** performs func between each element of l and r, returning a retval */ \
   template <class T, class BaseClass, class BaseClass2> \
   retval func(const ConstVectorBase<T, BaseClass>& l, \
               const ConstVectorBase<T, BaseClass2>& r) \
   { \
      retval toReturn(l.size()); \
      size_t i; \
      for (i=0; i < l.size(); i++) toReturn[i] = func(l[i], r[i]); \
      return toReturn; \
   } \
/** performs func between each element of l and (scalar)r, returning a retval */ \
template <class T, class BaseClass> \
retval func(const ConstVectorBase<T, BaseClass>& l, const T r) \
{ \
   retval toReturn(l.size()); \
   size_t i; \
   for (i=0; i < l.size(); i++) toReturn[i] = func(l[i], r); \
   return toReturn; \
} \
/** performs func between (scalar)l and each element of r, returning a retval */ \
template <class T, class BaseClass> \
retval func(const T l, const ConstVectorBase<T, BaseClass>& r) \
{ \
   retval toReturn(r.size()); \
   size_t i; \
   for (i=0; i < r.size(); i++) toReturn[i] = func(l, r[i]); \
   return toReturn; \
} 

      VecBaseNewBinaryTranscendentalOperator(atan, Vector<T>)
      VecBaseNewBinaryTranscendentalOperator(pow, Vector<T>)

/** finds the cross product between l and r */
      template <class T, class BaseClass, class BaseClass2> 
   Vector<T> cross(const ConstVectorBase<T, BaseClass>& l, 
                const ConstVectorBase<T, BaseClass2>& r) throw(VectorException)
{ 
   if ((l.size() != 3) && (r.size() != 3))
   {
      VectorException e("Cross product requires vectors of size 3");
      GPSTK_THROW(e);
   }
   BaseClass toReturn(3);
   toReturn[0] = l[1] * r[2] - l[2] * r[1];
   toReturn[1] = l[2] * r[0] - l[0] * r[2];
   toReturn[2] = l[0] * r[1] - l[1] * r[0];
   return toReturn;
} 

/** returns a new vector with the normalized version of l */
template <class T, class BaseClass>
Vector<T> normalize(const ConstVectorBase<T, BaseClass>& l) 
{ return l / norm(l); } 

/** returns the root-sum-square of the elements of l */
template <class T, class BaseClass>
T RSS(const ConstVectorBase<T, BaseClass>& l) 
{ return norm(l); } 

/** returns the root-mean-square of the elements of l */
template <class T, class BaseClass>
T RMS(const ConstVectorBase<T, BaseClass>& l) 
{ return norm(l)/SQRT(T(l.size())); } 

   //@}
 
}  // namespace

#endif


