//     ____   ______ __
//    / __ \ / ____// /
//   / /_/ // /    / /
//  / ____// /___ / /___   PixInsight Class Library
// /_/     \____//_____/   PCL 2.4.23
// ----------------------------------------------------------------------------
// pcl/Vector.h - Released 2022-03-12T18:59:29Z
// ----------------------------------------------------------------------------
// This file is part of the PixInsight Class Library (PCL).
// PCL is a multiplatform C++ framework for development of PixInsight modules.
//
// Copyright (c) 2003-2022 Pleiades Astrophoto S.L. All Rights Reserved.
//
// Redistribution and use in both source and binary forms, with or without
// modification, is permitted provided that the following conditions are met:
//
// 1. All redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. All redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
//    of their contributors, may be used to endorse or promote products derived
//    from this software without specific prior written permission. For written
//    permission, please contact info@pixinsight.com.
//
// 4. All products derived from this software, in any form whatsoever, must
//    reproduce the following acknowledgment in the end-user documentation
//    and/or other materials provided with the product:
//
//    "This product is based on software from the PixInsight project, developed
//    by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
//
//    Alternatively, if that is where third-party acknowledgments normally
//    appear, this acknowledgment must be reproduced in the product itself.
//
// THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
// INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
// DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------------------

#ifndef __PCL_Vector_h
#define __PCL_Vector_h

/// \file pcl/Vector.h

#include <pcl/Defs.h>
#include <pcl/Diagnostics.h>

#include <pcl/Container.h>
#include <pcl/Exception.h>
#include <pcl/ReferenceCounter.h>
#include <pcl/Search.h>
#include <pcl/Sort.h>
#include <pcl/Utility.h>

#ifndef __PCL_NO_VECTOR_STATISTICS
#  include <pcl/Selection.h>
#endif

#ifndef __PCL_NO_VECTOR_INSTANTIATE
#  include <pcl/Complex.h>
#endif

namespace pcl
{

// ----------------------------------------------------------------------------

/*!
 * \class GenericVector
 * \brief Generic vector of arbitrary length.
 *
 * %GenericVector is a lightweight template class implementing a vector of
 * arbitrary length. This class provides the following main features:
 *
 * \li Implicit data sharing with reference counting and copy-on-write
 * functionality. %GenericVector instances can safely be passed as function
 * return values and by-value function arguments.
 *
 * \li Thread-safe. %GenericVector instances can safely be accessed from
 * multiple threads. The reference counter implements atomic reference and
 * dereference operations.
 *
 * \li Efficient vector storage and access to vector elements. Vector
 * elements are allocated as a single, contiguous memory block.
 *
 * \li Support for a large set of vector operations, including scalar-to-vector
 * and vector-to-vector arithmetic operations, dot and cross products.
 *
 * \li Calculation of a variety of descriptive statistics of vector components.
 *
 * \sa GenericMatrix, \ref vector_operators, \ref vector_types
 */
template <typename T>
class PCL_CLASS GenericVector : public DirectContainer<T>
{
public:

   /*!
    * Represents a scalar.
    */
   typedef T                        scalar;

   /*!
    * Represents a vector component.
    */
   typedef T                        component;

   /*!
    * Represents a mutable vector iterator.
    */
   typedef T*                       iterator;

   /*!
    * Represents an immutable vector iterator.
    */
   typedef const T*                 const_iterator;

   /*!
    * Constructs an empty vector. An empty vector has no components and its
    * length is zero.
    */
   GenericVector()
   {
      m_data = new Data;
   }

   /*!
    * Constructs an uninitialized vector of the specified length.
    *
    * \param len     Number of vector components (&ge; 0).
    *
    * This constructor does not initialize vector components. The newly created
    * vector will contain unpredictable values.
    */
   GenericVector( int len )
   {
      PCL_PRECONDITION( len >= 0 )
      m_data = new Data( len );
   }

   /*!
    * Constructs a vector and fills it with a constant component value.
    *
    * \param x       Initial value for all vector components.
    * \param len     Number of vector components (&ge; 0).
    */
   GenericVector( const component& x, int len )
   {
      PCL_PRECONDITION( len >= 0 )
      m_data = new Data( len );
            iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
      PCL_IVDEP
      for ( ; i < j; ++i )
         *i = x;
   }

   /*!
    * Constructs a vector and initializes it with component values taken from a
    * static array.
    *
    * \param a       Address of the first item of a static array for
    *                initialization of vector components. The array must provide
    *                at least \a len consecutive items.
    *
    * \param len     Number of vector components (&ge; 0).
    */
   template <typename T1>
   GenericVector( const T1* a, int len )
   {
      PCL_PRECONDITION( len >= 0 )
      m_data = new Data( len );
      if ( a != nullptr )
      {
               iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
         const T1*      __restrict__ k = a;
         PCL_IVDEP
         for ( ; i < j; ++i, ++k )
            *i = component( *k );
      }
   }

   /*!
    * Constructs a vector and initializes it with component values taken from
    * the specified initializer list \a c.
    *
    * This constructor is equivalent to:
    *
    * \code GenericVector( c.begin(), int( c.size() ) ) \endcode
    */
   template <typename T1>
   GenericVector( std::initializer_list<T1> c )
      : GenericVector( c.begin(), int( c.size() ) )
   {
   }

   /*!
    * Constructs a three-component vector initialized with the specified \a x,
    * \a y and \a z component values.
    */
   template <typename T1>
   GenericVector( const T1& x, const T1& y, const T1& z )
   {
      m_data = new Data( 3 );
      iterator v = m_data->Begin();
      *v++ = component( x );
      *v++ = component( y );
      *v   = component( z );
   }

   /*!
    * Constructs a four-component vector initialized with the specified \a x,
    * \a y, \a z and \a t component values.
    */
   template <typename T1>
   GenericVector( const T1& x, const T1& y, const T1& z, const T1& t )
   {
      m_data = new Data( 4 );
      iterator v = m_data->Begin();
      *v++ = component( x );
      *v++ = component( y );
      *v++ = component( z );
      *v   = component( t );
   }

   /*!
    * Copy constructor. This object references the same data that is being
    * referenced by the specified vector \a x.
    */
   GenericVector( const GenericVector& x )
      : m_data( x.m_data )
   {
      m_data->Attach();
   }

   /*!
    * Move constructor.
    */
   GenericVector( GenericVector&& x )
      : m_data( x.m_data )
   {
      x.m_data = nullptr;
   }

   /*!
    * Constructs a vector and initializes it with component values taken from
    * an instance \a x of a different vector template instantiation.
    *
    * This constructor is equivalent to:
    *
    * \code GenericVector( x.Begin(), x.Length() ) \endcode
    */
   template <typename T1>
   GenericVector( const GenericVector<T1>& x )
      : GenericVector( x.Begin(), x.Length() )
   {
   }

   /*!
    * Destroys a %GenericVector object. This destructor dereferences the vector
    * data. If the vector data becomes unreferenced, it is destroyed and
    * deallocated immediately.
    */
   virtual ~GenericVector()
   {
      if ( m_data != nullptr )
      {
         DetachFromData();
         m_data = nullptr;
      }
   }

   /*!
    * Deallocates vector data, yielding an empty vector.
    */
   void Clear()
   {
      if ( !IsEmpty() )
         if ( m_data->IsUnique() )
            m_data->Deallocate();
         else
         {
            Data* newData = new Data( 0 );
            DetachFromData();
            m_data = newData;
         }
   }

   /*!
    * Copy assignment operator. Returns a reference to this object.
    *
    * See the Assign() member function for more information.
    */
   GenericVector& operator =( const GenericVector& x )
   {
      Assign( x );
      return *this;
   }

   /*!
    * Assigns a vector \a x to this object.
    *
    * If this instance and the specified source instance \a x reference
    * different vector data, the data previously referenced by this object is
    * dereferenced. If the previous data becomes unreferenced, it is destroyed
    * and deallocated. Then the data being referenced by \a x is also
    * referenced by this object.
    *
    * If this instance and the specified source instance \a x already reference
    * the same vector data, then this function does nothing.
    */
   void Assign( const GenericVector& x )
   {
      x.m_data->Attach();
      DetachFromData();
      m_data = x.m_data;
   }

   /*!
    * Move assignment operator. Returns a reference to this object.
    *
    * See the Transfer() member function for more information.
    */
   GenericVector& operator =( GenericVector&& x )
   {
      Transfer( x );
      return *this;
   }

   /*!
    * Transfers data from another vector \a x to this object.
    *
    * Decrements the reference counter of the current vector data. If the data
    * becomes unreferenced, it is destroyed and deallocated. The vector data
    * referenced by the source object \a x is then transferred to this object,
    * and the source object \a x is left as an invalid empty vector.
    *
    * \warning The source vector \a x will be an invalid object after calling
    * this function, and hence should be destroyed immediately. Any attempt to
    * access an invalid object will most likely lead to a crash.
    */
   void Transfer( GenericVector& x )
   {
      DetachFromData();
      m_data = x.m_data;
      x.m_data = nullptr;
   }

   /*!
    * Transfers data from another vector \a x to this object.
    *
    * Decrements the reference counter of the current vector data. If the data
    * becomes unreferenced, it is destroyed and deallocated. The vector data
    * referenced by the source object \a x is then transferred to this object,
    * and the source object \a x is left as an invalid empty vector.
    *
    * \warning The source vector \a x will be an invalid object after calling
    * this function, and hence should be destroyed immediately. Any attempt to
    * access an invalid object will most likely lead to a crash.
    */
   void Transfer( GenericVector&& x )
   {
      DetachFromData();
      m_data = x.m_data;
      x.m_data = nullptr;
   }

   /*!
    * Exchanges two vectors \a x1 and \a x2.
    *
    * This function is efficient because it simply swaps the internal vector
    * data pointers owned by the objects.
    */
   friend void Swap( GenericVector& x1, GenericVector& x2 ) noexcept
   {
      pcl::Swap( x1.m_data, x2.m_data );
   }

   /*!
    * Assigns a constant scalar \a x to all components of this vector. Returns
    * a reference to this object.
    *
    * Before assigning a constant value to all vector components, this function
    * ensures that this instance uniquely references its vector data,
    * generating a new vector data block if necessary.
    */
   GenericVector& operator =( const scalar& x )
   {
      if ( !IsUnique() )
      {
         Data* newData = new Data( m_data->Length() );
         DetachFromData();
         m_data = newData;
      }
            iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
      PCL_IVDEP
      for ( ; i < j; ++i )
         *i = x;
      return *this;
   }

   /*!
    * Vector addition/assignment. Adds each component of the specified vector
    * \a x to the corresponding component of this vector. Returns a reference
    * to this object.
    *
    * Before operating vector components, this function ensures that this
    * instance uniquely references its vector data, generating a duplicate if
    * necessary.
    *
    * If the specified vectors are incompatible for component-wise operations
    * (because the length of \a x is less than the length of this object), this
    * function throws an appropriate Error exception.
    */
   GenericVector& operator +=( const GenericVector& x )
   {
      if ( x.Length() < Length() )
         throw Error( "Invalid vector addition." );
      EnsureUnique();
            iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
      const_iterator __restrict__ k = x.Begin();
      PCL_IVDEP
      for ( ; i < j; ++i, ++k )
         *i += *k;
      return *this;
   }

   /*!
    * Vector subtraction/assignment. Subtracts each component of the specified
    * vector \a x from the corresponding component of this vector. Returns a
    * reference to this object.
    *
    * Before operating vector components, this function ensures that this
    * instance uniquely references its vector data, generating a duplicate if
    * necessary.
    *
    * If the specified vectors are incompatible for component-wise operations
    * (because the length of \a x is less than the length of this object), this
    * function throws an appropriate Error exception.
    */
   GenericVector& operator -=( const GenericVector& x )
   {
      if ( x.Length() < Length() )
         throw Error( "Invalid vector subtraction." );
      EnsureUnique();
            iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
      const_iterator __restrict__ k = x.Begin();
      PCL_IVDEP
      for ( ; i < j; ++i, ++k )
         *i -= *k;
      return *this;
   }

   /*!
    * Component-wise vector multiplication/assignment. Multiplies each
    * component of this vector by the corresponding component of the specified
    * vector \a x. Returns a reference to this object.
    *
    * Before operating vector components, this function ensures that this
    * instance uniquely references its vector data, generating a duplicate if
    * necessary.
    *
    * If the specified vectors are incompatible for component-wise operations
    * (because the length of \a x is less than the length of this object), this
    * function throws an appropriate Error exception.
    */
   GenericVector& operator *=( const GenericVector& x )
   {
      if ( x.Length() < Length() )
         throw Error( "Invalid vector multiplication." );
      EnsureUnique();
            iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
      const_iterator __restrict__ k = x.Begin();
      PCL_IVDEP
      for ( ; i < j; ++i, ++k )
         *i *= *k;
      return *this;
   }

   /*!
    * Component-wise vector division/assignment. Divides each component of this
    * vector by the corresponding component of the specified vector \a x.
    * Returns a reference to this object.
    *
    * Before operating vector components, this function ensures that this
    * instance uniquely references its vector data, generating a duplicate if
    * necessary.
    *
    * If the specified vectors are incompatible for component-wise operations
    * (because the length of \a x is less than the length of this object), this
    * function throws an appropriate Error exception.
    *
    * \note Make sure that no component of the specified divisor vector \a x is
    * zero or insignificant, or calling this member function will lead to
    * division(s) by zero.
    */
   GenericVector& operator /=( const GenericVector& x )
   {
      if ( x.Length() < Length() )
         throw Error( "Invalid vector division." );
      EnsureUnique();
            iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
      const_iterator __restrict__ k = x.Begin();
      PCL_IVDEP
      for ( ; i < j; ++i, ++k )
         *i /= *k;
      return *this;
   }

#define IMPLEMENT_SCALAR_ASSIGN_OP( op )                                      \
      if ( IsUnique() )                                                       \
      {                                                                       \
               iterator __restrict__ i = m_data->Begin();                     \
         const_iterator __restrict__ j = m_data->End();                       \
         PCL_IVDEP                                                            \
         for ( ; i < j; ++i )                                                 \
            *i op##= x;                                                       \
      }                                                                       \
      else                                                                    \
      {                                                                       \
         Data* newData = new Data( m_data->Length() );                        \
         const_iterator __restrict__ i = m_data->Begin();                     \
         const_iterator __restrict__ j = m_data->End();                       \
               iterator __restrict__ k = newData->Begin();                    \
         PCL_IVDEP                                                            \
         for ( ; i < j; ++i, ++k )                                            \
            *k = *i op x;                                                     \
         DetachFromData();                                                    \
         m_data = newData;                                                    \
      }                                                                       \
      return *this;

   /*!
    * Adds a constant scalar \a x to all components of this vector. Returns a
    * reference to this object.
    *
    * Before adding a constant value to all vector components, this function
    * ensures that this instance uniquely references its vector data,
    * generating a duplicate if necessary.
    */
   GenericVector& operator +=( const scalar& x )
   {
      IMPLEMENT_SCALAR_ASSIGN_OP( + )
   }

   /*!
    * Subtracts a constant scalar \a x from all components of this vector.
    * Returns a reference to this object.
    *
    * Before subtracting a constant value from all vector components, this
    * function ensures that this instance uniquely references its vector data,
    * generating a duplicate if necessary.
    */
   GenericVector& operator -=( const scalar& x )
   {
      IMPLEMENT_SCALAR_ASSIGN_OP( - )
   }

   /*!
    * Multiplies all components of this vector by a constant scalar \a x.
    * Returns a reference to this object.
    *
    * Before multiplying all vector components by a constant value, this
    * function ensures that this instance uniquely references its vector data,
    * generating a duplicate if necessary.
    */
   GenericVector& operator *=( const scalar& x )
   {
      IMPLEMENT_SCALAR_ASSIGN_OP( * )
   }

   /*!
    * Divides all components of this vector by a constant scalar \a x. Returns
    * a reference to this object.
    *
    * Before dividing all vector components by a constant value, this function
    * ensures that this instance uniquely references its vector data,
    * generating a duplicate if necessary.
    */
   GenericVector& operator /=( const scalar& x )
   {
      IMPLEMENT_SCALAR_ASSIGN_OP( / )
   }

   /*!
    * Raises all components of this vector to a constant scalar \a x. Returns
    * a reference to this object.
    *
    * Before raising all vector components to a constant value, this function
    * ensures that this instance uniquely references its vector data,
    * generating a duplicate if necessary.
    */
   GenericVector& operator ^=( const scalar& x )
   {
      if ( IsUnique() )
      {
               iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
         PCL_IVDEP
         for ( ; i < j; ++i )
            *i = pcl::Pow( *i, x );
      }
      else
      {
         Data* newData = new Data( m_data->Length() );
         const_iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
               iterator __restrict__ k = newData->Begin();
         PCL_IVDEP
         for ( ; i < j; ++i, ++k )
            *k = pcl::Pow( *i, x );
         DetachFromData();
         m_data = newData;
      }
      return *this;
   }

#undef IMPLEMENT_SCALAR_ASSIGN_OP

   /*!
    * Returns the dot product of this vector and a vector \a v.
    *
    * \note For performance reasons, this function does not check whether the
    * specified vector has at least the same number of components as this
    * vector. If that condition does not hold, this function will invoke
    * undefined behavior.
    */
   scalar Dot( const GenericVector& v ) const noexcept
   {
      PCL_PRECONDITION( v.Length() >= Length() )
      scalar r = scalar( 0 );
      const_iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
      const_iterator __restrict__ k = v.Begin();
      PCL_IVDEP
      for ( ; i < j; ++i, ++k )
         r += scalar( *i ) * scalar( *k );
      return r;
   }

   /*!
    * Returns the cross product of this vector and a vector \a v2.
    *
    * \note The cross product is only defined for vectors of three components.
    * For performance reasons, this function does not check vector lengths. For
    * vectors of length < 3, this function will invoke undefined behavior.
    */
   GenericVector Cross( const GenericVector& v2 ) const
   {
      PCL_PRECONDITION( Length() == 3 && v2.Length() == 3 )
      component x1 = *At( 0 );
      component y1 = *At( 1 );
      component z1 = *At( 2 );
      component x2 = v2[0];
      component y2 = v2[1];
      component z2 = v2[2];
      return GenericVector( y1*z2 - z1*y2,
                            z1*x2 - x1*z2,
                            x1*y2 - y1*x2 );
   }

   /*!
    * Unary sign reversal operator: returns a vector with the components of
    * this vector multiplied by -1.
    */
   GenericVector operator -() const
   {
      GenericVector R( m_data->Length() );
      const_iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
            iterator __restrict__ k = R.Begin();
      PCL_IVDEP
      for ( ; i < j; ++i, ++k )
         *k = -*i;
      return R;
   }

   /*!
    * Reverses the sign of all components of this vector.
    *
    * Before performing its task, this function ensures that this instance
    * uniquely references its vector data, generating a duplicate if necessary.
    */
   void ReverseSign()
   {
      if ( IsUnique() )
      {
               iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
         PCL_IVDEP
         for ( ; i < j; ++i )
            *i = -*i;
      }
      else
      {
         Data* newData = new Data( m_data->Length() );
         const_iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
               iterator __restrict__ k = newData->Begin();
         PCL_IVDEP
         for ( ; i < j; ++i, ++k )
            *k = -*i;
         DetachFromData();
         m_data = newData;
      }
   }

   /*!
    * Returns the square of this vector. The result is a new vector of the same
    * length where each component is the square of its counterpart in this
    * vector.
    */
   GenericVector Sqr() const
   {
      GenericVector R( m_data->Length() );
      const_iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
            iterator __restrict__ k = R.Begin();
      PCL_IVDEP
      for ( ; i < j; ++i, ++k )
         *k = *i * *i;
      return R;
   }

   /*!
    * Replaces all components of this vector with their squares.
    *
    * Before performing its task, this function ensures that this instance
    * uniquely references its vector data, generating a duplicate if necessary.
    */
   void SetSqr()
   {
      if ( IsUnique() )
      {
               iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
         PCL_IVDEP
         for ( ; i < j; ++i )
            *i *= *i;
      }
      else
      {
         Data* newData = new Data( m_data->Length() );
         const_iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
               iterator __restrict__ k = newData->Begin();
         PCL_IVDEP
         for ( ; i < j; ++i, ++k )
            *k = *i * *i;
         DetachFromData();
         m_data = newData;
      }
   }

   /*!
    * Returns the square root of this vector. The result is a new vector of the
    * same length where each component is the square root of its counterpart in
    * this vector.
    */
   GenericVector Sqrt() const
   {
      GenericVector R( m_data->Length() );
      const_iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
            iterator __restrict__ k = R.Begin();
      PCL_IVDEP
      for ( ; i < j; ++i, ++k )
         *k = pcl::Sqrt( *i );
      return R;
   }

   /*!
    * Replaces all components of this vector with their square roots.
    *
    * Before performing its task, this function ensures that this instance
    * uniquely references its vector data, generating a duplicate if necessary.
    */
   void SetSqrt()
   {
      if ( IsUnique() )
      {
               iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
         for ( ; i < j; ++i )
            *i = pcl::Sqrt( *i );
      }
      else
      {
         Data* newData = new Data( m_data->Length() );
         const_iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
               iterator __restrict__ k = newData->Begin();
         PCL_IVDEP
         for ( ; i < j; ++i, ++k )
            *k = pcl::Sqrt( *i );
         DetachFromData();
         m_data = newData;
      }
   }

   /*!
    * Returns the absolute value of this vector. The result is a new vector of
    * the same length where each component is the absolute value of its
    * counterpart in this vector.
    */
   GenericVector Abs() const
   {
      GenericVector R( m_data->Length() );
      const_iterator __restrict__ i = m_data->Begin();
      const_iterator __restrict__ j = m_data->End();
            iterator __restrict__ k = R.Begin();
      PCL_IVDEP
      for ( ; i < j; ++i, ++k )
         *k = pcl::Abs( *i );
      return R;
   }

   /*!
    * Replaces all components of this vector with their absolute values.
    *
    * Before performing its task, this function ensures that this instance
    * uniquely references its vector data, generating a duplicate if necessary.
    */
   void SetAbs()
   {
      if ( IsUnique() )
      {
               iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
         PCL_IVDEP
         for ( ; i < j; ++i )
            *i = pcl::Abs( *i );
      }
      else
      {
         Data* newData = new Data( m_data->Length() );
         const_iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
               iterator __restrict__ k = newData->Begin();
         PCL_IVDEP
         for ( ; i < j; ++i, ++k )
            *k = pcl::Abs( *i );
         DetachFromData();
         m_data = newData;
      }
   }

   /*!
    * Returns the norm of this vector. For any real p > 0, the norm N of a
    * vector v is given by:
    *
    * N = sum( abs( x )^p )^(1/p)
    *
    * for all vector components x of v.
    *
    * \sa L1Norm(), L2Norm()
    */
   scalar Norm( double p ) const noexcept
   {
      return pcl::Norm( m_data->Begin(), m_data->End(), p );
   }

   /*!
    * Returns the L1 norm (or Manhattan norm) of this vector. The L1 norm is
    * the sum of the absolute values of all vector components.
    */
   scalar L1Norm() const noexcept
   {
      return pcl::L1Norm( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the L2 norm (or Euclidean norm) of this vector. The L2 norm is
    * the square root of the sum of squared vector components.
    */
   scalar L2Norm() const noexcept
   {
      return pcl::L2Norm( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the L2 norm (or Euclidean norm) of this vector. This function is
    * a synonym for L2Norm().
    */
   scalar Norm() const noexcept
   {
      return L2Norm();
   }

   /*!
    * Returns a unit vector with the same direction as this vector. A unit
    * vector has a norm (or magnitude) of 1.
    */
   GenericVector Unit() const
   {
      GenericVector R( *this );
      scalar N = L2Norm();
      if ( scalar( 1 ) + N > scalar( 1 ) )
         R /= N;
      return R;
   }

   /*!
    * Transforms this vector to a unit vector with the same direction. A unit
    * vector has a norm (or magnitude) of 1.
    */
   void SetUnit()
   {
      scalar N = L2Norm();
      if ( scalar( 1 ) + N > scalar( 1 ) )
         (void)operator /=( N );
   }

   /*!
    * Sorts the components of this vector in ascending order.
    */
   void Sort()
   {
      EnsureUnique();
      pcl::Sort( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns a sorted copy of this vector.
    */
   GenericVector Sorted() const
   {
      GenericVector R( *this );
      R.Sort();
      return R;
   }

   /*!
    * Sorts the components of this vector in reverse (descending) order.
    */
   void ReverseSort()
   {
      EnsureUnique();
      pcl::Sort( m_data->Begin(), m_data->End(),
                 []( const scalar& a, const scalar& b ){ return b < a; } );
   }

   /*!
    * Returns a reverse sorted copy of this vector.
    */
   GenericVector ReverseSorted() const
   {
      GenericVector R( *this );
      R.ReverseSort();
      return R;
   }

   /*!
    * Sorts the components of this vector in ascending order. Ordering of
    * vector components is defined such that for any pair a, b of vector
    * components, the specified binary predicate p( a, b ) is true if a
    * precedes b.
    */
   template <class BP>
   void Sort( BP p )
   {
      EnsureUnique();
      pcl::Sort( m_data->Begin(), m_data->End(), p );
   }

   /*!
    * Returns a sorted copy of this vector, where ordering of vector components
    * is defined by the specified binary predicate \a p. See Sort( BP p ).
    */
   template <class BP>
   GenericVector Sorted( BP p ) const
   {
      GenericVector R( *this );
      R.Sort( p );
      return R;
   }

   /*!
    * Returns the index of the first vector element with the specified value
    * \a x, or -1 if this vector does not contain such value.
    */
   int Find( const component& x ) const noexcept
   {
      const_iterator p = pcl::LinearSearch( m_data->Begin(), m_data->End(), x );
      return (p != m_data->End()) ? int( p - m_data->Begin() ) : -1;
   }

   /*!
    * Returns the index of the first vector element with the specified value
    * \a x, or -1 if this vector does not contain such value.
    * This function is an alias to Find().
    */
   int FindFirst( const component& x ) const noexcept
   {
      return Find( x );
   }

   /*!
    * Returns the index of the last vector element with the specified value
    * \a x, or -1 if this vector does not contain such value.
    */
   int FindLast( const component& x ) const noexcept
   {
      const_iterator p = pcl::LinearSearchLast( m_data->Begin(), m_data->End(), x );
      return (p != m_data->End()) ? int( p - m_data->Begin() ) : -1;
   }

   /*!
    * Returns true iff this vector contains the specified value \a x.
    */
   bool Contains( const component& x ) const noexcept
   {
      return pcl::LinearSearch( m_data->Begin(), m_data->End(), x ) != m_data->End();
   }

#ifndef __PCL_NO_VECTOR_STATISTICS

   /*!
    * Returns the index of the smallest vector component.
    *
    * For empty vectors, this function returns zero. For vectors where the
    * smallest component occurs more than once, this function returns the index
    * of the first occurrence.
    */
   int IndexOfSmallestComponent() const noexcept
   {
      return int( pcl::MinItem( m_data->Begin(), m_data->End() ) - m_data->Begin() );
   }

   /*!
    * Returns the index of the largest vector component.
    *
    * For empty vectors, this function returns zero. For vectors where the
    * largest component occurs more than once, this function returns the index
    * of the first occurrence.
    */
   int IndexOfLargestComponent() const noexcept
   {
      return int( pcl::MaxItem( m_data->Begin(), m_data->End() ) - m_data->Begin() );
   }

   /*!
    * Returns the index of the last occurrence of the smallest vector
    * component.
    *
    * For empty vectors, this function returns zero. For vectors where the
    * smallest component occurs more than once, this function returns the index
    * of the last occurrence.
    */
   int IndexOfLastSmallestComponent() const noexcept
   {
      iterator i = m_data->Begin();
      if ( m_data->Length() > 0 )
         for ( iterator j = m_data->Begin(); ++j < m_data->End(); )
            if ( *j <= *i )
               i = j;
      return i - m_data->Begin();
   }

   /*!
    * Returns the index of the last occurrence of the largest vector
    * component.
    *
    * For empty vectors, this function returns zero. For vectors where the
    * largest component occurs more than once, this function returns the index
    * of the last occurrence.
    */
   int IndexOfLastLargestComponent() const noexcept
   {
      iterator i = m_data->Begin();
      if ( m_data->Length() > 0 )
         for ( iterator j = m_data->Begin(); ++j < m_data->End(); )
            if ( *i <= *j )
               i = j;
      return i - m_data->Begin();
   }

   /*!
    * Returns the index of the smallest nonzero vector component.
    *
    * For empty vectors, this function returns zero. For vectors where the
    * smallest nonzero component occurs more than once, this function returns
    * the index of the first occurrence.
    */
   int IndexOfSmallestNonzeroComponent() const noexcept
   {
      iterator i = m_data->Begin();
      if ( m_data->Length() > 0 )
         for ( iterator j = m_data->Begin(); ++j < m_data->End(); )
            if ( *j != component( 0 ) )
               if ( *j < *i )
                  i = j;
      return i - m_data->Begin();
   }

   /*!
    * Returns the index of the last occurrence of the smallest nonzero vector
    * component.
    *
    * For empty vectors, this function returns zero. For vectors where the
    * smallest nonzero component occurs more than once, this function returns
    * the index of the last occurrence.
    */
   int IndexOfLastSmallestNonzeroComponent() const noexcept
   {
      iterator i = m_data->Begin();
      if ( m_data->Length() > 0 )
         for ( iterator j = m_data->Begin(); ++j < m_data->End(); )
            if ( *j != component( 0 ) )
               if ( *j <= *i )
                  i = j;
      return i - m_data->Begin();
   }

   /*!
    * Returns the value of the smallest vector component.
    * For empty vectors, this function returns zero conventionally.
    */
   component MinComponent() const noexcept
   {
      if ( m_data->Length() > 0 )
         return *pcl::MinItem( m_data->Begin(), m_data->End() );
      return component( 0 );
   }

   /*!
    * Returns the value of the largest vector component.
    * For empty vectors, this function returns zero conventionally.
    */
   component MaxComponent() const noexcept
   {
      if ( m_data->Length() > 0 )
         return *pcl::MaxItem( m_data->Begin(), m_data->End() );
      return component( 0 );
   }

   /*!
    * Returns the \a kth order statistic of the sample in this vector.
    *
    * Before selecting the specified vector component, this function ensures
    * that this instance uniquely references its vector data, generating a
    * duplicate if necessary.
    *
    * The specified index \a k must be valid, that is, it must be in the range
    * [0,Length()-1]. If a value of \a k outside the valid range is specified,
    * or equivalently, if this function is called for an empty vector, this
    * member function will invoke undefined behavior.
    *
    * \note This function uses a \e destructive selection algorithm: it alters
    * the order in the sequence of vector components. For a nondestructive
    * version, see the const version of this member function.
    */
   component OrderStatistic( int k )
   {
      PCL_PRECONDITION( !IsEmpty() )
      PCL_PRECONDITION( k >= 0 && k < m_data->Length() )
      EnsureUnique();
      return *pcl::Select( m_data->Begin(), m_data->End(), k );
   }

   /*!
    * Returns the \a kth order statistic of the sample in this vector, without
    * modifying this instance.
    *
    * The specified index \a k must be valid, that is, it must be in the range
    * [0,Length()-1]. If a value of \a k outside the valid range is specified,
    * or equivalently, if this function is called for an empty vector, this
    * member function will invoke undefined behavior.
    *
    * This is a \e nondestructive selection routine that doesn't modify the
    * order of existing vector components. To achieve that goal, this routine
    * simply generates a temporary working vector as a copy of this object,
    * then calls its OrderStatistic() member function to obtain the function's
    * return value.
    */
   component OrderStatistic( int k ) const
   {
      return GenericVector( *this ).OrderStatistic( k );
   }

   /*!
    * Returns the sum of vector components.
    * For empty vectors, this function returns zero.
    */
   double Sum() const noexcept
   {
      return pcl::Sum( m_data->Begin(), m_data->End() );
   }

   /*!
    * Computes the sum of vector components using a numerically stable
    * summation algorithm to minimize roundoff error.
    *
    * For empty vectors, this function returns zero.
    */
   double StableSum() const noexcept
   {
      return pcl::StableSum( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the sum of the absolute values of all vector components.
    * For empty vectors, this function returns zero.
    */
   double Modulus() const noexcept
   {
      return pcl::Modulus( m_data->Begin(), m_data->End() );
   }

   /*!
    * Computes the sum of the absolute values of all vector components using a
    * numerically stable summation algorithm to minimize roundoff error.
    *
    * For empty vectors, this function returns zero.
    */
   double StableModulus() const noexcept
   {
      return pcl::StableModulus( m_data->Begin(), m_data->End() );
   }

   /*!
    * Computes the sum of the squares of all vector components.
    * For empty vectors, this function returns zero.
    */
   double SumOfSquares() const noexcept
   {
      return pcl::SumOfSquares( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the sum of the squares of all vector components using a
    * numerically stable summation algorithm to minimize roundoff error.
    *
    * For empty vectors, this function returns zero.
    */
   double StableSumOfSquares() const noexcept
   {
      return pcl::StableSumOfSquares( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the mean of the values in this vector.
    * For empty vectors, this function returns zero.
    */
   double Mean() const
   {
      return pcl::Mean( m_data->Begin(), m_data->End() );
   }

   /*!
    * Computes the mean of the values in this vector using a numerically stable
    * summation algorithm to minimize roundoff error.
    *
    * For empty vectors, this function returns zero.
    */
   double StableMean() const noexcept
   {
      return pcl::StableMean( m_data->Begin(), m_data->End() );
   }

   /*!
    * Computes the two-sided, asymmetric trimmed mean of the values in this
    * vector. See pcl::TrimmedMean() for a complete description of the
    * implemented algorithm with information on function parameters.
    *
    * For empty vectors, this function returns zero.
    */
   double TrimmedMean( distance_type l = 1, distance_type h = 1 ) const noexcept
   {
      return pcl::TrimmedMean( m_data->Begin(), m_data->End(), l, h );
   }

   /*!
    * Computes the two-sided, asymmetric trimmed mean of the squared values in
    * this vector. See pcl::TrimmedMeanOfSquares() for a complete description
    * of the implemented algorithm with information on function parameters.
    *
    * For empty vectors, this function returns zero.
    */
   double TrimmedMeanOfSquares( distance_type l = 1, distance_type h = 1 ) const noexcept
   {
      return pcl::TrimmedMeanOfSquares( m_data->Begin(), m_data->End(), l, h );
   }

   /*!
    * Returns the variance from the mean for the values in this vector.
    *
    * For vectors with less than two components, this function returns zero.
    */
   double Variance() const noexcept
   {
      return pcl::Variance( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the standard deviation from the mean for the values in this
    * vector.
    *
    * For vectors with less than two components, this function returns zero.
    */
   double StdDev() const noexcept
   {
      return pcl::StdDev( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the median of the values in this vector.
    *
    * For vectors of length < 2, this function returns zero conventionally.
    */
   double Median() const
   {
      return pcl::Median( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the average absolute deviation with respect to the specified
    * \a center value.
    *
    * When the median of the vector elements is used as the center value, this
    * function returns the average absolute deviation from the median, which is
    * a well-known estimator of dispersion.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \note To make the average absolute deviation about the median consistent
    * with the standard deviation of a normal distribution, it must be
    * multiplied by the constant 1.2533.
    */
   double AvgDev( double center ) const noexcept
   {
      return pcl::AvgDev( m_data->Begin(), m_data->End(), center );
   }

   /*!
    * Computes the average absolute deviation with respect to the specified
    * \a center value, using a numerically stable summation algorithm to
    * minimize roundoff error.
    *
    * When the median of the vector elements is used as the center value, this
    * function returns the average absolute deviation from the median, which is
    * a well-known estimator of dispersion.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \note To make the average absolute deviation about the median consistent
    * with the standard deviation of a normal distribution, it must be
    * multiplied by the constant 1.2533.
    */
   double StableAvgDev( double center ) const noexcept
   {
      return pcl::StableAvgDev( m_data->Begin(), m_data->End(), center );
   }

   /*!
    * Returns the average absolute deviation from the median.
    *
    * The mean absolute deviation from the median is a well-known estimator of
    * dispersion.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \note To make the average absolute deviation about the median consistent
    * with the standard deviation of a normal distribution, it must be
    * multiplied by the constant 1.2533.
    */
   double AvgDev() const
   {
      return pcl::AvgDev( m_data->Begin(), m_data->End() );
   }

   /*!
    * Computes the average absolute deviation from the median using a
    * numerically stable summation algorithm to minimize roundoff error.
    *
    * The mean absolute deviation from the median is a well-known estimator of
    * dispersion.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \note To make the average absolute deviation about the median consistent
    * with the standard deviation of a normal distribution, it must be
    * multiplied by the constant 1.2533.
    */
   double StableAvgDev() const
   {
      return pcl::StableAvgDev( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the two-sided average absolute deviation with respect to the
    * specified \a center value.
    *
    * See AvgDev( double ) for more information.
    */
   TwoSidedEstimate TwoSidedAvgDev( double center ) const noexcept
   {
      return pcl::TwoSidedAvgDev( m_data->Begin(), m_data->End(), center );
   }

   /*!
    * Returns the two-sided average absolute deviation from the median.
    *
    * See AvgDev() for more information.
    */
   TwoSidedEstimate TwoSidedAvgDev() const
   {
      return pcl::TwoSidedAvgDev( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the median absolute deviation (MAD) with respect to the specified
    * \a center value.
    *
    * The MAD is a well-known robust estimator of scale.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \note To make the MAD estimator consistent with the standard deviation of
    * a normal distribution, it must be multiplied by the constant 1.4826.
    */
   double MAD( double center ) const
   {
      return pcl::MAD( m_data->Begin(), m_data->End(), center );
   }

   /*!
    * Returns the median absolute deviation from the median (MAD).
    *
    * The MAD is a well-known robust estimator of scale.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \note To make the MAD estimator consistent with the standard deviation of
    * a normal distribution, it must be multiplied by the constant 1.4826.
    */
   double MAD() const
   {
      return pcl::MAD( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the two-sided median absolute deviation (MAD) with respect to the
    * specified \a center value.
    *
    * See MAD( double ) for more information.
    */
   TwoSidedEstimate TwoSidedMAD( double center ) const
   {
      return pcl::TwoSidedMAD( m_data->Begin(), m_data->End(), center );
   }

   /*!
    * Returns the two-sided median absolute deviation from the median (MAD).
    *
    * See MAD() for more information.
    */
   TwoSidedEstimate TwoSidedMAD() const
   {
      return pcl::TwoSidedMAD( m_data->Begin(), m_data->End() );
   }

   /*!
    * Returns the biweight midvariance (BWMV).
    *
    * \param center  Reference center value. Normally, the median of the vector
    *                components should be used.
    *
    * \param sigma   A reference estimate of dispersion. Normally, the median
    *                absolute deviation from the median (MAD) of the vector
    *                components should be used.
    *
    * \param k       Rejection limit in sigma units. The default value is k=9.
    *
    * \param reducedLength    If true, reduce the sample size to exclude
    *                rejected vector components. This tends to approximate the
    *                true dispersion of the data more accurately for relatively
    *                small samples, or samples with large amounts of outliers.
    *                Note that this departs from the standard definition of
    *                biweight midvariance, where the total number of data items
    *                is used to scale the variance estimate. If false, use the
    *                full vector length, including rejected components, which
    *                gives a standard biweight midvariance estimate.
    *
    * The square root of the biweight midvariance is a robust estimator of
    * scale. It is an efficient estimator with respect to many statistical
    * distributions (about 87% Gaussian efficiency), and appears to have a
    * breakdown point close to 0.5 (the same as MAD).
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \b References
    *
    * Rand R. Wilcox (2017), <em>Introduction to Robust Estimation and
    * Hypothesis Testing, 4th Edition</em>, Elsevier Inc., Section 3.12.1.
    */
   double BiweightMidvariance( double center, double sigma, int k = 9, bool reducedLength = false ) const noexcept
   {
      return pcl::BiweightMidvariance( m_data->Begin(), m_data->End(), center, sigma, k, reducedLength );
   }

   /*!
    * Returns the biweight midvariance (BWMV) with respect to the median and
    * the median absolute deviation from the median (MAD).
    *
    * \param k       Rejection limit in sigma units. The default value is k=9.
    *
    * \param reducedLength    If true, reduce the sample size to exclude
    *                rejected vector components. This tends to approximate the
    *                true dispersion of the data more accurately for relatively
    *                small samples, or samples with large amounts of outliers.
    *                Note that this departs from the standard definition of
    *                biweight midvariance, where the total number of data items
    *                is used to scale the variance estimate. If false, use the
    *                full vector length, including rejected components, which
    *                gives a standard biweight midvariance estimate.
    *
    * The square root of the biweight midvariance is a robust estimator of
    * scale. It is an efficient estimator with respect to many statistical
    * distributions (about 87% Gaussian efficiency), and appears to have a
    * breakdown point close to 0.5 (the same as MAD).
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \b References
    *
    * Rand R. Wilcox (2017), <em>Introduction to Robust Estimation and
    * Hypothesis Testing, 4th Edition</em>, Elsevier Inc., Section 3.12.1.
    */
   double BiweightMidvariance( int k = 9, bool reducedLength = false ) const
   {
      double center = Median();
      return BiweightMidvariance( center, MAD( center ), k, reducedLength );
   }

   /*!
    * Returns the two-sided biweight midvariance (BWMV).
    *
    * \param center  Reference center value. Normally, the median of the vector
    *                components should be used.
    *
    * \param sigma   A two-sided reference estimate of dispersion. Normally,
    *                the two-sided median absolute deviation from the median
    *                (MAD) of the vector components should be used. See the
    *                TwoSidedMAD() member function.
    *
    * See BiweightMidvariance( double, double, int, bool ) for more information
    * on the rest of parameters and references.
    */
   TwoSidedEstimate TwoSidedBiweightMidvariance( double center, const TwoSidedEstimate& sigma,
                                                 int k = 9, bool reducedLength = false ) const noexcept
   {
      return pcl::TwoSidedBiweightMidvariance( m_data->Begin(), m_data->End(), center, sigma, k, reducedLength );
   }

   /*!
    * Returns the two-sided biweight midvariance (BWMV) with respect to the
    * median and the two-sided median absolute deviation from the median (MAD).
    *
    * See BiweightMidvariance( int, bool ) for more information and references.
    */
   TwoSidedEstimate TwoSidedBiweightMidvariance( int k = 9, bool reducedLength = false ) const
   {
      double center = Median();
      return TwoSidedBiweightMidvariance( center, TwoSidedMAD( center ), k, reducedLength );
   }

   /*!
    * Returns a percentage bend midvariance (PBMV).
    *
    * \param center  Reference center value. Normally, the median of the vector
    *                components should be used.
    *
    * \param beta    Rejection parameter in the [0,0.5] range. Higher values
    *                improve robustness to outliers (i.e., increase the
    *                breakdown point of the estimator) at the expense of a
    *                lower efficiency. The default value is beta=0.2.
    *
    * The square root of the percentage bend midvariance is a robust estimator
    * of scale. With the default beta=0.2, its Gaussian efficiency is 67%. With
    * beta=0.1, its efficiency is 85% but its breakdown is only 0.1.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \b References
    *
    * Rand R. Wilcox (2017), <em>Introduction to Robust Estimation and
    * Hypothesis Testing, 4th Edition</em>, Elsevier Inc., Section 3.12.3.
    */
   double BendMidvariance( double center, double beta = 0.2 ) const
   {
      return pcl::BendMidvariance( m_data->Begin(), m_data->End(), center, beta );
   }

   /*!
    * Returns a percentage bend midvariance (PBMV) with respect to the median.
    *
    * \param beta    Rejection parameter in the [0,0.5] range. Higher values
    *                improve robustness to outliers (i.e., increase the
    *                breakdown point of the estimator) at the expense of a
    *                lower efficiency. The default value is beta=0.2.
    *
    * The square root of the percentage bend midvariance is a robust estimator
    * of scale. With the default beta=0.2, its Gaussian efficiency is 67%. With
    * beta=0.1, its efficiency is 85% but its breakdown is only 0.1.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * \b References
    *
    * Rand R. Wilcox (2017), <em>Introduction to Robust Estimation and
    * Hypothesis Testing, 4th Edition</em>, Elsevier Inc., Section 3.12.3.
    */
   double BendMidvariance( double beta = 0.2 ) const
   {
      return pcl::BendMidvariance( m_data->Begin(), m_data->End(), Median(), beta );
   }

   /*!
    * Returns the Sn scale estimator of Rousseeuw and Croux:
    *
    * <pre>
    * Sn = c * low_median( high_median( |x_i - x_j| ) )
    * </pre>
    *
    * where low_median() is the order statistic of rank (n + 1)/2, and
    * high_median() is the order statistic of rank n/2 + 1.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * The constant c = 1.1926 must be used to make the Sn estimator converge to
    * the standard deviation of a pure normal distribution. However, this
    * implementation does not apply it (it uses c=1 implicitly), for
    * consistency with other implementations of scale estimators.
    *
    * \b References
    *
    * P.J. Rousseeuw and C. Croux (1993), <em>Alternatives to the Median
    * Absolute Deviation,</em> Journal of the American Statistical Association,
    * Vol. 88, pp. 1273-1283.
    */
   double Sn() const
   {
      GenericVector v( *this );
      return pcl::Sn( v.Begin(), v.End() );
   }

   /*!
    * Returns the Qn scale estimator of Rousseeuw and Croux:
    *
    * <pre>
    * Qn = c * first_quartile( |x_i - x_j| : i < j )
    * </pre>
    *
    * where first_quartile() is the order statistic of rank (n + 1)/4.
    *
    * For vectors with less than two components, this function returns zero.
    *
    * The constant c = 2.2219 must be used to make the Qn estimator converge to
    * the standard deviation of a pure normal distribution. However, this
    * implementation does not apply it (it uses c=1 implicitly), for consistency
    * with other implementations of scale estimators.
    *
    * \b References
    *
    * P.J. Rousseeuw and C. Croux (1993), <em>Alternatives to the Median
    * Absolute Deviation,</em> Journal of the American Statistical Association,
    * Vol. 88, pp. 1273-1283.
    */
   double Qn() const
   {
      GenericVector v( *this );
      return pcl::Qn( v.Begin(), v.End() );
   }

#endif   // !__PCL_NO_VECTOR_STATISTICS

   /*!
    * Returns a 64-bit non-cryptographic hash value computed for this vector.
    *
    * This function calls pcl::Hash64() for the internal vector data.
    *
    * The \a seed parameter can be used to generate repeatable hash values. It
    * can also be set to a random value in compromised environments.
    */
   uint64 Hash64( uint64 seed = 0 ) const noexcept
   {
      return pcl::Hash64( m_data->Begin(), m_data->Size(), seed );
   }

   /*!
    * Returns a 32-bit non-cryptographic hash value computed for this vector.
    *
    * This function calls pcl::Hash32() for the internal vector data.
    *
    * The \a seed parameter can be used to generate repeatable hash values. It
    * can also be set to a random value in compromised environments.
    */
   uint32 Hash32( uint32 seed = 0 ) const noexcept
   {
      return pcl::Hash32( m_data->Begin(), m_data->Size(), seed );
   }

   /*!
    * Returns a non-cryptographic hash value computed for this vector. This
    * function is a synonym for Hash64().
    */
   uint64 Hash( uint64 seed = 0 ) const noexcept
   {
      return Hash64( seed );
   }

   /*!
    * Returns true iff this instance uniquely references its vector data.
    */
   bool IsUnique() const noexcept
   {
      return m_data->IsUnique();
   }

   /*!
    * Returns true iff this instance references (shares) the same vector data as
    * another instance \a x.
    */
   bool IsAliasOf( const GenericVector& x ) const noexcept
   {
      return m_data == x.m_data;
   }

   /*!
    * Ensures that this instance uniquely references its vector data.
    *
    * If necessary, this member function generates a duplicate of the vector
    * data, references it, and then decrements the reference counter of the
    * original vector data.
    */
   void EnsureUnique()
   {
      if ( !IsUnique() )
      {
         Data* newData = new Data( m_data->Length() );
         const_iterator __restrict__ i = m_data->Begin();
         const_iterator __restrict__ j = m_data->End();
               iterator __restrict__ k = newData->Begin();
         PCL_IVDEP
         for ( ; i < j; ++i, ++k )
            *k = *i;
         DetachFromData();
         m_data = newData;
      }
   }

   /*!
    * Returns the number of components in this vector. If this object is an
    * empty vector, this member function returns zero.
    */
   int Length() const noexcept
   {
      return m_data->Length();
   }

   /*!
    * Returns the total number of bytes required to store the data contained in
    * this vector.
    */
   size_type Size() const noexcept
   {
      return m_data->Size();
   }

   /*!
    * Returns true only if this vector is valid. A vector is valid if it
    * references an internal vector structure, even if it is an empty vector.
    *
    * In general, all %GenericVector objects are valid with only two
    * exceptions:
    *
    * \li Objects that have been move-copied or move-assigned to other vectors.
    * \li Objects that have been invalidated explicitly by calling Transfer().
    *
    * An invalid vector object cannot be used and should be destroyed
    * immediately. Invalid vectors are always destroyed automatically during
    * move construction and move assignment operations.
    */
   bool IsValid() const noexcept
   {
      return m_data != nullptr;
   }

   /*!
    * Returns true iff this is an empty vector. An empty vector has no
    * components, and hence its length is zero.
    */
   bool IsEmpty() const noexcept
   {
      return Length() == 0;
   }

   /*!
    * Returns true iff this vector is not empty. This operator is equivalent to:
    *
    * \code !IsEmpty(); \endcode
    */
   operator bool() const noexcept
   {
      return !IsEmpty();
   }

   /*!
    * Equality operator. Returns true if this vector is equal to another vector
    * \a x. Two vectors are equal if both have the same length and identical
    * component values.
    */
   bool operator ==( const GenericVector& x ) const noexcept
   {
      return IsAliasOf( x ) || SameLength( x ) && pcl::Equal( Begin(), x.Begin(), x.End() );
   }

   /*!
    * Less than relational operator. Returns true if this vector is less than
    * another vector \a x.
    *
    * In this operator, vector comparisons are performed component-wise,
    * irrespective of vector lengths, until either two vector components differ
    * or until the end of one of the vectors is reached. In the latter case,
    * the shortest vector is the lesser one.
    */
   bool operator <( const GenericVector& x ) const noexcept
   {
      return !IsAliasOf( x ) && pcl::Compare( Begin(), End(), x.Begin(), x.End() ) < 0;
   }

   /*!
    * Returns true iff this vector has the same length as other vector \a x.
    */
   bool SameLength( const GenericVector& x ) const noexcept
   {
      return Length() == x.Length();
   }

   /*!
    * Returns a mutable vector iterator pointing to the \a i-th component of
    * this vector.
    *
    * Before returning, this function ensures that this instance uniquely
    * references its vector data.
    */
   iterator At( int i )
   {
      EnsureUnique();
      return m_data->At( i );
   }

   /*!
    * Returns an immutable vector iterator pointing to the \a i-th component of
    * this vector.
    */
   const_iterator At( int i ) const noexcept
   {
      return m_data->At( i );
   }

   /*!
    * Returns a mutable vector iterator pointing to the first vector component,
    * i.e. to the component at index 0 of this vector.
    *
    * All vector components are guaranteed to be stored at consecutive
    * locations addressable from the iterator returned by this function.
    *
    * Before returning, this function ensures that this instance uniquely
    * references its vector data.
    */
   iterator Begin()
   {
      EnsureUnique();
      return m_data->Begin();
   }

   /*!
    * Returns an immutable vector iterator pointing to the first vector
    * component, i.e. to the component at index 0 of this vector.
    *
    * All vector components are guaranteed to be stored at consecutive
    * locations addressable from the iterator returned by this function.
    */
   const_iterator Begin() const noexcept
   {
      return m_data->Begin();
   }

   /*!
    * A synonym for Begin() const.
    */
   const_iterator ConstBegin() const noexcept
   {
      return Begin();
   }

   /*!
    * Returns a mutable vector iterator pointing to the first vector component,
    * i.e. to the component at index 0 of this vector.
    *
    * This member function is a convenience alias to Begin().
    */
   iterator operator *()
   {
      return Begin();
   }

   /*!
    * Returns an immutable vector iterator pointing to the first vector
    * component, i.e. to the component at index 0 of this vector.
    *
    * This member function is a convenience alias to Begin() const.
    */
   const_iterator operator *() const noexcept
   {
      return Begin();
   }

   /*!
    * Returns a mutable iterator past the last vector component, i.e. a
    * pointer to a (nonexistent) component located at index=Length().
    *
    * All vector components are guaranteed to be stored in reverse order at
    * consecutive locations addressable from the iterator returned by this
    * function.
    *
    * Before returning, this function ensures that this instance uniquely
    * references its vector data.
    */
   iterator End()
   {
      EnsureUnique();
      return m_data->End();
   }

   /*!
    * Returns an immutable iterator past the last vector component, i.e. a
    * pointer to a (nonexistent) component located at index=Length().
    *
    * All vector components are guaranteed to be stored in reverse order at
    * consecutive locations addressable from the iterator returned by this
    * function.
    */
   const_iterator End() const noexcept
   {
      return m_data->End();
   }

   /*!
    * A synonym for End() const.
    */
   const_iterator ConstEnd() const noexcept
   {
      return End();
   }

   /*!
    * Returns a reference to the mutable vector component at the specified
    * index \a i. Vector indices are relative to zero.
    *
    * Before returning, this function ensures that this instance uniquely
    * references its vector data.
    */
   component& operator []( int i )
   {
      return *At( i );
   }

   /*!
    * Returns a reference to the immutable vector component at the specified
    * index \a i. Vector indices are relative to zero.
    */
   const component& operator []( int i ) const noexcept
   {
      return *At( i );
   }

   /*!
    * Returns a pointer to the first component in this vector.
    *
    * The returned pointer can be used as a common C array, where all vector
    * components are guaranteed to be stored consecutively starting from the
    * pointer returned by this function.
    *
    * This member function does nothing to ensure that this instance uniquely
    * references its vector data. Consequently, the caller must take into
    * account that all modifications made to vector components accessed through
    * the value returned by this function will apply to all instances sharing
    * the same vector data.
    *
    * This function can be used to perform fast operations on vector components
    * avoiding the overhead caused by deep copies of vector data, when such
    * copies are not necessary. Typically this happens when two or more threads
    * work simultaneously on non-overlapping regions of the same vector.
    */
   iterator DataPtr() noexcept
   {
      return m_data->v;
   }

   /*!
    * Returns a pointer to the \a ith component in this vector.
    *
    * All vector components are guaranteed to be stored at consecutive
    * locations addressable from the iterator returned by this function.
    *
    * This member function does not ensure that the data referenced by this
    * vector is unique. See DataPtr() for more information on how to use this
    * member function.
    */
   iterator ComponentPtr( int i ) noexcept
   {
      return m_data->At( i );
   }

#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS
   /*!
    * STL-compatible iteration. Equivalent to Begin().
    */
   iterator begin()
   {
      return Begin();
   }

   /*!
    * STL-compatible iteration. Equivalent to Begin() const.
    */
   const_iterator begin() const noexcept
   {
      return Begin();
   }

   /*!
    * STL-compatible iteration. Equivalent to End().
    */
   iterator end()
   {
      return End();
   }

   /*!
    * STL-compatible iteration. Equivalent to End() const.
    */
   const_iterator end() const noexcept
   {
      return End();
   }
#endif   // !__PCL_NO_STL_COMPATIBLE_ITERATORS

   /*!
    * Computes spherical coordinates from this three-component vector.
    *
    * \param[out] lon   Reference to a variable where the computed longitude
    *                   in radians, in the range [-pi,+pi], will be stored. If
    *                   the vector points to one pole, that is, if *lat is
    *                   either -pi/2 or +pi/2, the computed longitude will be
    *                   zero.
    *
    * \param[out] lat   Reference to a variable where the computed latitude
    *                   in radians, in the range [-pi/2,+pi/2], will be stored.
    *
    * This function requires a vector with at least three coordinates. For
    * performance reasons, the vector length is not verified.
    *
    * The returned coordinates lie on a sphere of unit radius, that is, only
    * the direction of the input vector is taken into account, never its
    * magnitude.
    *
    * \sa ToSpherical2Pi(), FromSpherical()
    */
   template <typename T1, typename T2>
   void ToSpherical( T1& lon, T2& lat ) const noexcept
   {
      PCL_PRECONDITION( Length() >= 3 )
      double x = *At( 0 );
      double y = *At( 1 );
      double z = *At( 2 );
      double m2 = x*x + y*y;
      lon = T1( (m2 == 0) ? 0.0 : ArcTan( y, x ) );
      lat = T2( (z == 0)  ? 0.0 : ArcTan( z, pcl::Sqrt( m2 ) ) );
   }

   /*!
    * Computes spherical coordinates from this three-component vector.
    *
    * This function is identical to ToSpherical(), but the output longitude
    * component is normalized to the range [0,2pi) in radians.
    *
    * \sa ToSpherical(), FromSpherical()
    */
   template <typename T1, typename T2>
   void ToSpherical2Pi( T1& lon, T2& lat ) const noexcept
   {
      ToSpherical( lon, lat );
      if ( lon < 0 )
         lon += TwoPi();
   }

   /*!
    * Returns a three-component vector with rectangular coordinates computed
    * from spherical coordinates, given by their sines and cosines
    *
    * \param slon  Sine of the longitude.
    * \param clon  Cosine of the longitude.
    * \param slat  Sine of the latitude.
    * \param clat  Cosine of the latitude.
    *
    * The returned vector contains the <em>direction cosines</em> for the
    * specified position on the sphere. It is a unit vector (unit magnitude)
    * pointing from the center of the sphere to the specified location.
    *
    * \sa ToSpherical(), ToSpherical2Pi()
    */
   static GenericVector FromSpherical( double slon, double clon, double slat, double clat )
   {
      return GenericVector( clon*clat, slon*clat, slat );
   }

   /*!
    * Returns a three-component vector with rectangular coordinates computed
    * from the specified spherical coordinates.
    *
    * \param lon  Longitude in radians.
    * \param lat  Latitude in radians.
    *
    * The returned vector contains the <em>direction cosines</em> for the
    * specified position on the sphere. It is a unit vector (unit magnitude)
    * pointing from the center of the sphere to the specified location.
    *
    * \sa ToSpherical()
    */
   template <typename T1, typename T2>
   static GenericVector FromSpherical( const T1& lon, const T2& lat )
   {
      double slon, clon, slat, clat;
      SinCos( double( lon ), slon, clon );
      SinCos( double( lat ), slat, clat );
      return FromSpherical( slon, clon, slat, clat );
   }

   /*!
    * Returns the angle between this vector and another vector \a v, with both
    * vectors being defined in two-dimensional space.
    *
    * The returned value is the angle between both vectors in radians, in the
    * range [-pi,+pi].
    *
    * \note This member function is only defined for vectors of two components.
    * For performance reasons, this condition is not verified; if it doesn't
    * hold, this function will invoke undefined behavior.
    */
   double Angle2D( const GenericVector& v ) const noexcept
   {
      /*
       * https://stackoverflow.com/questions/14066933/direct-way-of-computing-clockwise-angle-between-2-vectors
       * https://stackoverflow.com/questions/243945/calculating-a-2d-vectors-cross-product
       */
      component x1 = *At( 0 );
      component y1 = *At( 1 );
      component x2 = v[0];
      component y2 = v[1];
      return ArcTan( x1*y2 - y1*x2, Dot( v ) );
   }

   /*!
    * Returns the angle between this vector and another vector \a v, with both
    * vectors being defined in three-dimensional space.
    *
    * The returned value is the angle between both vectors in radians, in the
    * range [0,pi].
    *
    * \note This member function is only defined for vectors of three
    * components. For performance reasons, this condition is not verified; if
    * it doesn't hold, this function will invoke undefined behavior.
    */
   double Angle3D( const GenericVector& v ) const noexcept
   {
      /*
       * https://stackoverflow.com/questions/14066933/direct-way-of-computing-clockwise-angle-between-2-vectors
       */
      return ArcTan( Cross( v ).L2Norm(), Dot( v ) );
   }

   /*!
    * Returns the angle between this vector and another vector \a v, being both
    * vectors defined in three-dimensional space, with sign determined by the
    * direction of an additional 3D vector \a n.
    *
    * The returned value is the angle between both vectors in radians, in the
    * range [-pi,+pi]. The angle is positive if this vector is clockwise with
    * respect to the direction of \a n, negative otherwise.
    *
    * \note This member function is only defined for vectors of three
    * components. For performance reasons, this condition is not verified; if
    * it doesn't hold, this function will invoke undefined behavior.
    */
   double Angle3D( const GenericVector& v, const GenericVector& n ) const
   {
      /*
       * https://stackoverflow.com/questions/14066933/direct-way-of-computing-clockwise-angle-between-2-vectors
       */
      GenericVector c = Cross( v );
      return ArcTan( (((n * c) >= 0) ? 1 : -1) * c.L2Norm(), Dot( v ) );
   }

   /*!
    * Generates a sequence of string tokens separated with the specified
    * \a separator string. Returns a reference to the target string \a s.
    *
    * For each vector component, this function appends a string representation
    * (known as a \e token) to the target string \a s. If the vector has more
    * than one component, successive tokens are separated with the specified
    * \a separator.
    *
    * The string type S must have a meaningful %Append() member function and
    * type conversion semantics to transform a vector component to a string.
    * The standard String and IsoString PCL classes provide the required
    * functionality for most scalar types, although it is probably better to
    * use String::ToSeparated() and IsoString::ToSeparated() instead of calling
    * these functions directly.
    */
   template <class S, typename SP>
   S& ToSeparated( S& s, SP separator ) const
   {
      const_iterator i = m_data->Begin(), j = m_data->End();
      if ( i < j )
      {
         s.Append( S( *i ) );
         if ( ++i < j )
            do
            {
               s.Append( separator );
               s.Append( S( *i ) );
            }
            while ( ++i < j );
      }
      return s;
   }

   /*!
    * Generates a sequence of string tokens separated with the specified
    * \a separator string by calling an \a append function. Returns a reference
    * to the target string \a s.
    *
    * For each vector component x, this function appends a string
    * representation (known as a \e token) to the target string \a s by calling
    * the \a append function:
    *
    *\code append( s, S( x ) ); \endcode
    *
    * If the vector has more than one component, successive tokens are
    * separated by calling:
    *
    * \code append( s, S( separator ) ); \endcode
    *
    * The string type S must have type conversion semantics to transform a
    * vector component to a string. The standard String and IsoString PCL
    * classes provide the required functionality for most scalar types,
    * although it is probably better to use String::ToSeparated() and
    * IsoString::ToSeparated() instead of calling these functions directly.
    */
   template <class S, typename SP, class AF>
   S& ToSeparated( S& s, SP separator, AF append ) const
   {
      const_iterator i = m_data->Begin(), j = m_data->End();
      if ( i < j )
      {
         append( s, S( *i ) );
         if ( ++i < j )
         {
            S p( separator );
            do
            {
               append( s, p );
               append( s, S( *i ) );
            }
            while ( ++i < j );
         }
      }
      return s;
   }

   /*!
    * Generates a comma-separated sequence of string tokens. Returns a
    * reference to the target string \a s.
    *
    * This function is equivalent to:
    *
    * \code ToSeparated( s, ',' ); \endcode
    */
   template <class S>
   S& ToCommaSeparated( S& s ) const
   {
      return ToSeparated( s, ',' );
   }

   /*!
    * Generates a space-separated sequence of string tokens. Returns a
    * reference to the target string \a s.
    *
    * This function is equivalent to:
    *
    * \code ToSeparated( s, ' ' ); \endcode
    */
   template <class S>
   S& ToSpaceSeparated( S& s ) const
   {
      return ToSeparated( s, ' ' );
   }

   /*!
    * Generates a tabulator-separated sequence of string tokens. Returns a
    * reference to the target string \a s.
    *
    * This function is equivalent to:
    *
    * \code ToSeparated( s, '\t' ); \endcode
    */
   template <class S>
   S& ToTabSeparated( S& s ) const
   {
      return ToSeparated( s, '\t' );
   }

private:

   /*!
    * \struct Data
    * \internal
    * Reference-counted vector data structure.
    */
   struct Data : public ReferenceCounter
   {
      int        n = 0;       //!< The vector length
      component* v = nullptr; //!< The vector components

      Data() = default;

      Data( int len )
      {
         if ( len > 0 )
            Allocate( len );
      }

      ~Data()
      {
         Deallocate();
      }

      int Length() const noexcept
      {
         return n;
      }

      size_type Size() const noexcept
      {
         return size_type( n )*sizeof( component );
      }

      iterator At( int i ) const noexcept
      {
         return v + i;
      }

      iterator Begin() const noexcept
      {
//          if ( likely( std::is_scalar<component>::value ) )
//             return reinterpret_cast<iterator>( PCL_ASSUME_ALIGNED_32( v ) );
         return v;
      }

      iterator End() const noexcept
      {
         return At( n );
      }

      void Allocate( int len )
      {
         n = len;
         if ( likely( std::is_scalar<component>::value ) )
         {
            v = reinterpret_cast<component*>( PCL_ALIGNED_MALLOC( Size(), 32 ) );
            if ( unlikely( v == nullptr ) )
            {
               n = 0;
               throw std::bad_alloc();
            }
         }
         else
            v = new component[ len ];
      }

      void Deallocate()
      {
         PCL_PRECONDITION( refCount == 0 )
         if ( likely( std::is_scalar<component>::value ) )
            PCL_ALIGNED_FREE( v );
         else
            delete [] v;
         v = nullptr;
         n = 0;
      }
   };

   /*!
    * \internal
    * The reference-counted vector data.
    */
   Data* m_data = nullptr;

   /*!
    * \internal
    * Dereferences vector data and disposes it if it becomes garbage.
    */
   void DetachFromData()
   {
      if ( !m_data->Detach() )
         delete m_data;
   }
};

// ----------------------------------------------------------------------------

/*!
 * \defgroup vector_operators Vector Operators
 *
 * This section includes scalar-to-vector and vector-to-vector arithmetic
 * operator functions that are not members of the GenericVector template class.
 */

/*!
 * Returns the sum of two vectors \a A and \a B.
 *
 * If the specified vectors are incompatible for vector addition (because \a B
 * has less components than \a A), this function throws an Error exception.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator +( const GenericVector<T>& A, const GenericVector<T>& B )
{
   int n = A.Length();
   if ( B.Length() < n )
      throw Error( "Invalid vector addition." );
   GenericVector<T> R( n );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   if ( likely( !A.IsAliasOf( B ) ) )
   {
      typename GenericVector<T>::const_iterator __restrict__ b = B.Begin();
      PCL_IVDEP
      for ( ; a < c; ++a, ++b, ++r )
         *r = *a + *b;
   }
   else
   {
      PCL_IVDEP
      for ( ; a < c; ++a, ++r )
         *r = *a + *a;
   }
   return R;
}

/*!
 * Returns the sum of two vectors \a A (rvalue reference) and \a B.
 *
 * If the specified vectors are incompatible for vector addition (because \a B
 * has less components than \a A), this function throws an Error exception.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator +( GenericVector<T>&& A, const GenericVector<T>& B )
{
   A += B;
   return std::move( A );
}

/*!
 * Returns the sum of two vectors \a A and \a B (rvalue reference).
 *
 * If the specified vectors are incompatible for vector addition (because \a B
 * has less components than \a A), this function throws an Error exception.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator +( const GenericVector<T>& A, GenericVector<T>&& B )
{
   B += A;
   return std::move( B );
}

/*!
 * Returns the sum of two vectors \a A (rvalue reference) and \a B (rvalue
 * reference).
 *
 * If the specified vectors are incompatible for vector addition (because \a B
 * has less components than \a A), this function throws an Error exception.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator +( GenericVector<T>&& A, GenericVector<T>&& B )
{
   A += B;
   return std::move( A );
}

/*!
 * Returns the sum of a vector \a A and a scalar \a x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator +( const GenericVector<T>& A, const S& x )
{
   GenericVector<T> R( A.Length() );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a, ++r )
      *r = *a + x;
   return R;
}

/*!
 * Returns the sum of a vector \a A (rvalue reference) and a scalar \a x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator +( GenericVector<T>&& A, const S& x )
{
   A += typename GenericVector<T>::scalar( x );
   return std::move( A );
}

/*!
 * Returns the sum of a scalar \a x and a vector \a A.
 *
 * This function exists to implement the commutative property of
 * scalar-to-vector addition; it is equivalent to A + x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator +( const S& x, const GenericVector<T>& A )
{
   return A + x;
}

/*!
 * Returns the sum of a scalar \a x and a vector \a A (rvalue reference).
 *
 * This function exists to implement the commutative property of
 * scalar-to-vector addition; it is equivalent to A + x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator +( const S& x, GenericVector<T>&& A )
{
   A += typename GenericVector<T>::scalar( x );
   return std::move( A );
}

// ----------------------------------------------------------------------------

/*!
 * Returns the result of subtracting a vector \a B from another vector \a A.
 *
 * If the specified vectors are incompatible for vector addition (because \a B
 * has less components than \a A), this function throws an Error exception.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator -( const GenericVector<T>& A, const GenericVector<T>& B )
{
   int n = A.Length();
   if ( B.Length() < n )
      throw Error( "Invalid vector subtraction." );

   GenericVector<T> R( n );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   if ( likely( !A.IsAliasOf( B ) ) )
   {
      typename GenericVector<T>::const_iterator __restrict__ b = B.Begin();
      PCL_IVDEP
      for ( ; a < c; ++a, ++b, ++r )
         *r = *a - *b;
   }
   else
   {
      PCL_IVDEP
      for ( ; a < c; ++a, ++r )
         *r = *a - *a;
   }
   return R;
}

/*!
 * Returns the result of subtracting a vector \a B from another vector \a A
 * (rvalue reference).
 *
 * If the specified vectors are incompatible for vector addition (because \a B
 * has less components than \a A), this function throws an Error exception.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator -( GenericVector<T>&& A, const GenericVector<T>& B )
{
   A -= B;
   return std::move( A );
}

/*!
 * Returns the result of subtracting a vector \a B (rvalue reference) from
 * another vector \a A.
 *
 * If the specified vectors are incompatible for vector addition (because \a A
 * has less components than \a B), this function throws an Error exception.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator -( const GenericVector<T>& A, GenericVector<T>&& B )
{
   if ( A.Length() < B.Length() )
      throw Error( "Invalid vector subtraction." );

   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::iterator       __restrict__ b = B.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = B.End();
   PCL_IVDEP
   for ( ; b < c; ++a, ++b )
      *b = *a - *b;
   return std::move( B );
}

/*!
 * Returns the result of subtracting a vector \a B (rvalue reference) from
 * another vector \a A (rvalue reference).
 *
 * If the specified vectors are incompatible for vector addition (because \a B
 * has less components than \a A), this function throws an Error exception.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator -( GenericVector<T>&& A, GenericVector<T>&& B )
{
   A -= B;
   return std::move( A );
}

/*!
 * Returns the subtraction of a scalar \a x from a vector \a A.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator -( const GenericVector<T>& A, const S& x )
{
   GenericVector<T> R( A.Length() );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a, ++r )
      *r = *a - x;
   return R;
}

/*!
 * Returns the subtraction of a scalar \a x from a vector \a A (rvalue
 * reference).
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator -( GenericVector<T>&& A, const S& x )
{
   A -= typename GenericVector<T>::scalar( x );
   return std::move( A );
}

/*!
 * Returns the subtraction of a vector \a A from a scalar \a x.
 *
 * This function exists because scalar-to-vector subtraction is not a
 * commutative operation. A - x is not equal to x - A (the resulting vector
 * components have the same magnitudes but opposite signs).
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator -( const S& x, const GenericVector<T>& A )
{
   GenericVector<T> R( A.Length() );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a, ++r )
      *r = x - *a;
   return R;
}

/*!
 * Returns the subtraction of a vector \a A (rvalue reference) from a scalar
 * \a x.
 *
 * This function exists because scalar-to-vector subtraction is not a
 * commutative operation. A - x is not equal to x - A (the resulting vector
 * components have the same magnitudes but opposite signs).
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator -( const S& x, GenericVector<T>&& A )
{
   typename GenericVector<T>::iterator       __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a )
      *a = x - *a;
   return std::move( A );
}

// ----------------------------------------------------------------------------

/*!
 * Returns the cross product of two vectors \a A and \a B.
 *
 * \note The cross product is only defined for vectors of three components. For
 * performance reasons, this function does not check vector lengths. For
 * vectors of length < 3, this function will invoke undefined behavior.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator ^( const GenericVector<T>& A, const GenericVector<T>& B )
{
   PCL_PRECONDITION( A.Length() == 3 && B.Length() == 3 )
   return GenericVector<T>( A[1]*B[2] - A[2]*B[1],
                            A[2]*B[0] - A[0]*B[2],
                            A[0]*B[1] - A[1]*B[0] );
}

/*!
 * Returns the cross product of two vectors \a A (rvalue reference) and \a B.
 *
 * \note The cross product is only defined for vectors of three components. For
 * performance reasons, this function does not check vector lengths. For
 * vectors of length < 3, this function will invoke undefined behavior.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator ^( GenericVector<T>&& A, const GenericVector<T>& B )
{
   T x = A[1]*B[2] - A[2]*B[1],
     y = A[2]*B[0] - A[0]*B[2],
     z = A[0]*B[1] - A[1]*B[0];
   typename GenericVector<T>::iterator a = A.Begin();
   a[0] = x; a[1] = y; a[2] = z;
   return std::move( A );
}

/*!
 * Returns the cross product of two vectors \a A and \a B (rvalue reference).
 *
 * \note The cross product is only defined for vectors of three components. For
 * performance reasons, this function does not check vector lengths. For
 * vectors of length < 3, this function will invoke undefined behavior.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator ^( const GenericVector<T>& A, GenericVector<T>&& B )
{
   T x = A[1]*B[2] - A[2]*B[1],
     y = A[2]*B[0] - A[0]*B[2],
     z = A[0]*B[1] - A[1]*B[0];
   typename GenericVector<T>::iterator b = B.Begin();
   b[0] = x; b[1] = y; b[2] = z;
   return std::move( B );
}

/*!
 * Returns the cross product of two vectors \a A (rvalue reference) and \a B
 * (rvalue reference).
 *
 * \note The cross product is only defined for vectors of three components. For
 * performance reasons, this function does not check vector lengths. For
 * vectors of length < 3, this function will invoke undefined behavior.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator ^( GenericVector<T>&& A, GenericVector<T>&& B )
{
   T x = A[1]*B[2] - A[2]*B[1],
     y = A[2]*B[0] - A[0]*B[2],
     z = A[0]*B[1] - A[1]*B[0];
   typename GenericVector<T>::iterator a = A.Begin();
   a[0] = x; a[1] = y; a[2] = z;
   return std::move( A );
}

// ----------------------------------------------------------------------------

/*!
 * Returns the dot product of two vectors \a A and \a B.
 *
 * \note For performance reasons, this function does not check whether the
 * specified vectors have compatible lengths; in case \a B has less components
 * than \a A, this function will invoke undefined behavior.
 * \ingroup vector_operators
 */
template <typename T> inline
T operator *( const GenericVector<T>& A, const GenericVector<T>& B ) noexcept
{
   PCL_PRECONDITION( B.Length() >= A.Length() )
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   T r = T( 0 );
   if ( likely( !A.IsAliasOf( B ) ) )
   {
      typename GenericVector<T>::const_iterator __restrict__ b = B.Begin();
      PCL_IVDEP
      for ( ; a < c; ++a, ++b )
         r += *a * *b;
   }
   else
   {
      PCL_IVDEP
      for ( ; a < c; ++a )
         r += *a * *a;
   }
   return r;
}

// ----------------------------------------------------------------------------

/*!
 * Returns the product of a vector \a A by a scalar \a x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator *( const GenericVector<T>& A, const S& x )
{
   GenericVector<T> R( A.Length() );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a, ++r )
      *r = *a * x;
   return R;
}

/*!
 * Returns the product of a vector \a A (rvalue reference) by a scalar \a x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator *( GenericVector<T>&& A, const S& x )
{
   A *= typename GenericVector<T>::scalar( x );
   return std::move( A );
}

/*!
 * Returns the product of a scalar \a x and a vector \a A.
 *
 * This function exists to implement the commutative property of
 * scalar-to-vector multiplication. It is equivalent to A * x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator *( const S& x, const GenericVector<T>& A )
{
   return A * x;
}

/*!
 * Returns the product of a scalar \a x and a vector \a A (rvalue reference).
 *
 * This function exists to implement the commutative property of
 * scalar-to-vector multiplication. It is equivalent to A * x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator *( const S& x, GenericVector<T>&& A )
{
   A *= typename GenericVector<T>::scalar( x );
   return std::move( A );
}

// ----------------------------------------------------------------------------

/*!
 * Returns the result of dividing a vector \a A by a scalar \a x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator /( const GenericVector<T>& A, const S& x )
{
   GenericVector<T> R( A.Length() );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a, ++r )
      *r = *a / x;
   return R;
}

/*!
 * Returns the result of dividing a vector \a A (rvalue reference) by a scalar
 * \a x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator /( GenericVector<T>&& A, const S& x )
{
   A /= typename GenericVector<T>::scalar( x );
   return std::move( A );
}

/*!
 * Returns the result of dividing a scalar \a x by a vector \a A.
 *
 * This function exists because scalar-to-vector division is not a
 * commutative operation. A/x is not equal to x/A.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator /( const S& x, const GenericVector<T>& A )
{
   GenericVector<T> R( A.Length() );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a, ++r )
      *r = x / *a;
   return R;
}

/*!
 * Returns the result of dividing a scalar \a x by a vector \a A (rvalue
 * reference).
 *
 * This function exists because scalar-to-vector division is not a
 * commutative operation. A/x is not equal to x/A.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator /( const S& x, GenericVector<T>&& A )
{
   typename GenericVector<T>::iterator       __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a )
      *a = x / *a;
   return std::move( A );
}

/*!
 * Returns the result of the element wise division of a vector \a A by another
 * vector \a B.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator /( const GenericVector<T>& A, const GenericVector<T>& B )
{
   int n = A.Length();
   if ( B.Length() < n )
      throw Error( "Invalid vector division." );

   GenericVector<T> R( n );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   if ( likely( !A.IsAliasOf( B ) ) )
   {
      typename GenericVector<T>::const_iterator __restrict__ b = B.Begin();
      PCL_IVDEP
      for ( ; a < c; ++a, ++b, ++r )
         *r = *a / *b;
   }
   else
   {
      PCL_IVDEP
      for ( ; a < c; ++a, ++r )
         *r = *a / *a;
   }
   return R;
}

/*!
 * Returns the result of the element-wise division of an r-value reference to a
 * vector \a A by a vector \a B.
 * \ingroup vector_operators
 */
template <typename T> inline
GenericVector<T> operator /( GenericVector<T>&& A, const GenericVector<T>& B )
{
   return A /= B;
}

// ----------------------------------------------------------------------------

/*!
 * Returns the result of raising a vector \a A to a scalar \a x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator ^( const GenericVector<T>& A, const S& x )
{
   GenericVector<T> R( A.Length() );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a, ++r )
      *r = pcl::Pow( *a, x );
   return R;
}

/*!
 * Returns the result of raising a vector \a A (rvalue reference) to a scalar
 * \a x.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator ^( GenericVector<T>&& A, const S& x )
{
   A ^= typename GenericVector<T>::scalar( x );
   return std::move( A );
}

/*!
 * Returns the result of raising a scalar \a x to a vector \a A.
 *
 * This function exists because scalar-to-vector exponentiation is not a
 * commutative operation. A^x is not equal to x^A.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator ^( const S& x, const GenericVector<T>& A )
{
   GenericVector<T> R( A.Length() );
   typename GenericVector<T>::iterator       __restrict__ r = R.Begin();
   typename GenericVector<T>::const_iterator __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a, ++r )
      *r = pcl::Pow( x, *a );
   return R;
}

/*!
 * Returns the result of raising a scalar \a x to a vector \a A (rvalue
 * reference).
 *
 * This function exists because scalar-to-vector exponentiation is not a
 * commutative operation. A^x is not equal to x^A.
 * \ingroup vector_operators
 */
template <typename T, typename S> inline
GenericVector<T> operator ^( const S& x, GenericVector<T>&& A )
{
   typename GenericVector<T>::iterator       __restrict__ a = A.Begin();
   typename GenericVector<T>::const_iterator __restrict__ c = A.End();
   PCL_IVDEP
   for ( ; a < c; ++a )
      *a = pcl::Pow( x, *a );
   return std::move( A );
}

// ----------------------------------------------------------------------------

#ifndef __PCL_NO_VECTOR_INSTANTIATE

/*!
 * \defgroup vector_types Vector Types
 */

/*!
 * \class pcl::I8Vector
 * \ingroup vector_types
 * \brief 8-bit signed integer vector.
 *
 * %I8Vector is a template instantiation of GenericVector for \c int8.
 */
typedef GenericVector<int8>         I8Vector;

/*!
 * \class pcl::CharVector
 * \ingroup vector_types
 * \brief 8-bit signed integer vector.
 *
 * %CharVector is an alias for I8Vector. It is a template instantiation of
 * GenericVector for \c int8.
 */
typedef I8Vector                    CharVector;

/*!
 * \class pcl::UI8Vector
 * \ingroup vector_types
 * \brief 8-bit unsigned integer vector.
 *
 * %UI8Vector is a template instantiation of GenericVector for \c uint8.
 */
typedef GenericVector<uint8>        UI8Vector;

/*!
 * \class pcl::ByteVector
 * \ingroup vector_types
 * \brief 8-bit unsigned integer vector.
 *
 * %ByteVector is an alias for UI8Vector. It is a template instantiation of
 * GenericVector for \c uint8.
 */
typedef UI8Vector                   ByteVector;

/*!
 * \class pcl::I16Vector
 * \ingroup vector_types
 * \brief 16-bit signed integer vector.
 *
 * %I16Vector is a template instantiation of GenericVector for \c int16.
 */
typedef GenericVector<int16>        I16Vector;

/*!
 * \class pcl::UI16Vector
 * \ingroup vector_types
 * \brief 16-bit unsigned integer vector.
 *
 * %UI16Vector is a template instantiation of GenericVector for \c uint16.
 */
typedef GenericVector<uint16>       UI16Vector;

/*!
 * \class pcl::I32Vector
 * \ingroup vector_types
 * \brief 32-bit signed integer vector.
 *
 * %I32Vector is a template instantiation of GenericVector for \c int32.
 */
typedef GenericVector<int32>        I32Vector;

/*!
 * \class pcl::IVector
 * \ingroup vector_types
 * \brief 32-bit signed integer vector.
 *
 * %IVector is an alias for I32Vector. It is a template instantiation of
 * GenericVector for \c int32.
 */
typedef I32Vector                   IVector;

/*!
 * \class pcl::UI32Vector
 * \ingroup vector_types
 * \brief 32-bit unsigned integer vector.
 *
 * %UI32Vector is a template instantiation of GenericVector for \c uint32.
 */
typedef GenericVector<uint32>       UI32Vector;

/*!
 * \class pcl::UIVector
 * \ingroup vector_types
 * \brief 32-bit unsigned integer vector.
 *
 * %UIVector is an alias for UI32Vector. It is a template instantiation of
 * GenericVector for \c uint32.
 */
typedef UI32Vector                  UIVector;

/*!
 * \class pcl::I64Vector
 * \ingroup vector_types
 * \brief 64-bit integer vector.
 *
 * %I64Vector is a template instantiation of GenericVector for \c int64.
 */
typedef GenericVector<int64>        I64Vector;

/*!
 * \class pcl::UI64Vector
 * \ingroup vector_types
 * \brief 64-bit unsigned integer vector.
 *
 * %UI64Vector is a template instantiation of GenericVector for \c uint64.
 */
typedef GenericVector<uint64>       UI64Vector;

/*!
 * \class pcl::SzVector
 * \ingroup vector_types
 * \brief size_type integer vector.
 *
 * %SzVector is a template instantiation of GenericVector for \c size_type.
 */
typedef GenericVector<size_type>    SzVector;

/*!
 * \class pcl::F32Vector
 * \ingroup vector_types
 * \brief 32-bit floating point real vector.
 *
 * %F32Vector is a template instantiation of GenericVector for \c float.
 */
typedef GenericVector<float>        F32Vector;

/*!
 * \class pcl::FVector
 * \ingroup vector_types
 * \brief 32-bit floating point real vector.
 *
 * %FVector is an alias for F32Vector. It is a template instantiation of
 * GenericVector for \c float.
 */
typedef F32Vector                   FVector;

/*!
 * \class pcl::F64Vector
 * \ingroup vector_types
 * \brief 64-bit floating point real vector.
 *
 * %F64Vector is a template instantiation of GenericVector for \c double.
 */
typedef GenericVector<double>       F64Vector;

/*!
 * \class pcl::DVector
 * \ingroup vector_types
 * \brief 64-bit floating point real vector.
 *
 * %DVector is an alias for F64Vector. It is a template instantiation of
 * GenericVector for \c double.
 */
typedef F64Vector                   DVector;

/*!
 * \class pcl::Vector
 * \ingroup vector_types
 * \brief 64-bit floating point real vector.
 *
 * %Vector is an alias for DVector. It is a template instantiation of
 * GenericVector for \c double.
 */
typedef DVector                     Vector;

/*!
 * \class pcl::C32Vector
 * \ingroup vector_types
 * \brief 32-bit floating point complex vector.
 *
 * %C32Vector is a template instantiation of GenericVector for \c Complex32.
 */
typedef GenericVector<Complex32>    C32Vector;

/*!
 * \class pcl::C64Vector
 * \ingroup vector_types
 * \brief 64-bit floating point complex vector.
 *
 * %C64Vector is a template instantiation of GenericVector for \c Complex64.
 */
typedef GenericVector<Complex64>    C64Vector;

#ifndef _MSC_VER

/*!
 * \class pcl::F80Vector
 * \ingroup vector_types
 * \brief 80-bit extended precision floating point real vector.
 *
 * %F80Vector is a template instantiation of GenericVector for \c long
 * \c double.
 *
 * \note This template instantiation is not available on Windows with Visual
 * C++ compilers.
 */
typedef GenericVector<long double>  F80Vector;

/*!
 * \class pcl::LDVector
 * \ingroup vector_types
 * \brief 80-bit extended precision floating point real vector.
 *
 * %LDVector is an alias for F80Vector. It is a template instantiation of
 * GenericVector for \c long \c double.
 *
 * \note This template instantiation is not available on Windows with Visual
 * C++ compilers.
 */
typedef F80Vector                   LDVector;

#endif   // !_MSC_VER

#endif   // !__PCL_NO_VECTOR_INSTANTIATE

// ----------------------------------------------------------------------------

} // pcl

#endif   // __PCL_Vector_h

// ----------------------------------------------------------------------------
// EOF pcl/Vector.h - Released 2022-03-12T18:59:29Z
