3326 lines
103 KiB
C++
3326 lines
103 KiB
C++
// ____ ______ __
|
|
// / __ \ / ____// /
|
|
// / /_/ // / / /
|
|
// / ____// /___ / /___ 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 (≥ 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 (≥ 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 (≥ 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
|