Files
tenmon/3rdparty/include/pcl/Complex.h
T
2022-04-12 08:17:18 +02:00

1111 lines
30 KiB
C++

// ____ ______ __
// / __ \ / ____// /
// / /_/ // / / /
// / ____// /___ / /___ PixInsight Class Library
// /_/ \____//_____/ PCL 2.4.23
// ----------------------------------------------------------------------------
// pcl/Complex.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_Complex_h
#define __PCL_Complex_h
/// \file pcl/Complex.h
#include <pcl/Defs.h>
#include <pcl/Diagnostics.h>
#include <pcl/Constants.h>
#include <pcl/Math.h>
#include <pcl/Relational.h>
namespace pcl
{
// ----------------------------------------------------------------------------
#define real C[0]
#define imag C[1]
/*!
* \class Complex
* \brief Generic complex number
*
* %Complex is a careful implementation of complex numbers, including efficient
* computations of complex arithmetic and transcendental functions.
*
* When instantiated for the \c double and \c float types, the generated
* classes are binary-compatible with the C99 complex standard structure.
*/
template <typename T>
class PCL_CLASS Complex
{
public:
/*!
* Represents a component of a complex number: real or imaginary part.
*/
typedef T component;
/*!
* Constructs an uninitialized complex number. The real and imaginary
* components will have unpredictable values.
*/
Complex() = default;
/*!
* Constructs a complex number with the specified real and imaginary parts.
*/
Complex( T r, T i = 0 ) noexcept
{
real = r;
imag = i;
}
/*!
* Nontrivial copy constructor.
*/
template <typename T1>
Complex( const Complex<T1>& c ) noexcept
{
real = T( c.Real() );
imag = T( c.Imag() );
}
/*!
* Returns a copy of the real component of this complex number.
*/
constexpr T Real() const noexcept
{
return real;
}
/*!
* Returns a reference to the real component of this complex number.
*/
T& Real() noexcept
{
return real;
}
/*!
* Returns a copy of the imaginary component of this complex number.
*/
constexpr T Imag() const noexcept
{
return imag;
}
/*!
* Returns a reference to the imaginary component of this complex number.
*/
T& Imag() noexcept
{
return imag;
}
/*!
* Returns true iff the imaginary part of this complex number is zero.
*/
constexpr bool IsReal() const noexcept
{
return imag == 0;
}
/*!
* Assignment operator. Returns a reference to this complex number.
*/
template <typename T1>
Complex<T>& operator =( const Complex<T1>& c ) noexcept
{
real = T( c.Real() ), imag = T( c.Imag() );
return *this;
}
/*!
* Assignment/sum operator. Adds the specified complex number \a c to this.
* Returns a reference to this complex number.
*/
template <typename T1>
Complex<T>& operator +=( const Complex<T1>& c ) noexcept
{
real += c.Real(), imag += c.Imag();
return *this;
}
/*!
* Assignment/subtract operator. Subtracts the specified complex number \a c
* from this. Returns a reference to this complex number.
*/
template <typename T1>
Complex<T>& operator -=( const Complex<T1>& c ) noexcept
{
real -= c.Real(), imag -= c.Imag();
return *this;
}
/*!
* Assignment/multiply operator. Multiplies this complex number by the
* specified complex \a c. Returns a reference to this complex number.
*/
template <typename T1>
Complex<T>& operator *=( const Complex<T1>& c ) noexcept
{
T t = T( real*c.Real() - imag*c.Imag() );
imag = T( imag*c.Real() + real*c.Imag() );
real = t;
return *this;
}
/*!
* Assignment/divide operator. Divides this complex number by the specified
* complex \a c. Returns a reference to this complex number.
*/
template <typename T1>
Complex<T>& operator /=( const Complex<T1>& c ) noexcept
{
T r, d, t;
if ( pcl::Abs( c.Real() ) >= pcl::Abs( c.Imag() ) )
{
PCL_PRECONDITION( c.Real() != 0 )
r = T( c.Imag()/c.Real() );
d = T( c.Real() + r*c.Imag() );
t = T( (real + r*imag)/d );
imag = (imag - r*real)/d;
}
else
{
PCL_PRECONDITION( c.Imag() != 0 )
r = T( c.Real()/c.Imag() );
d = T( c.Imag() + r*c.Real() );
t = T( (real*r + imag)/d );
imag = (imag*r - real)/d;
}
real = t;
return *this;
}
/*!
* Assigns a real number to this complex number. The specified scalar \a x
* is assigned to the real component, and the imaginary component is set to
* zero. Returns a reference to this complex number.
*/
template <typename T1>
Complex<T>& operator =( T1 x ) noexcept
{
real = x, imag = 0;
return *this;
}
/*!
* Adds a real number to this complex number. The specified scalar \a x is
* added to the real component. Returns a reference to this complex number.
*/
template <typename T1>
Complex<T>& operator +=( T1 x ) noexcept
{
real += x;
return *this;
}
/*!
* Subtracts a real number from this complex number. The specified scalar \a x
* is subtracted from the real component. Returns a reference to this
* complex number.
*/
template <typename T1>
Complex<T>& operator -=( T1 x ) noexcept
{
real -= x;
return *this;
}
/*!
* Multiplies this complex number by a real number. The real component is
* multiplied by the specified scalar \a x. Returns a reference to this
* complex number.
*/
template <typename T1>
Complex<T>& operator *=( T1 x ) noexcept
{
real *= x, imag *= x;
return *this;
}
/*!
* Divides this complex number by a real number. The real component is
* divided by the specified scalar \a x. Returns a reference to this complex
* number.
*/
template <typename T1>
Complex<T>& operator /=( T1 x ) noexcept
{
PCL_PRECONDITION( x != 0 )
real /= x, imag /= x;
return *this;
}
/*!
* Unary plus operator. Returns a copy of this complex number.
*/
Complex<T> operator +() const noexcept
{
return *this;
}
/*!
* Unary minus operator. Returns a complex number symmetric to this.
*
* This function is equivalent to:
* Complex<T>( -Real(), -Imag() )
*/
Complex<T> operator -() const noexcept
{
return Complex<T>( -real, -imag );
}
/*!
* Complex conjugate. This function is equivalent to:
* Complex<T>( Real(), -Imag() )
*/
Complex<T> Conj() const noexcept
{
return Complex<T>( real, -imag );
}
/*!
* Complex conjugate. This operator is a synonym for Conj().
*/
Complex<T> operator ~() const noexcept
{
return Conj();
}
/*!
* Assigns to this complex number its complex conjugate. This function
* changes the sign of the imaginary part of this complex number.
*/
void SetConj() noexcept
{
imag = -imag;
}
/*!
* Complex magnitude (modulus).
*
* Accurate results are guaranteed even for large ratios between the real
* and complex components.
*/
T Mag() const noexcept
{
T r = pcl::Abs( real );
T i = pcl::Abs( imag );
T m;
if ( r == 0 )
m = i;
else if ( i == 0 )
m = r;
else
{
bool q = r < i;
m = q ? r/i : i/r;
m = (q ? i : r) * pcl::Sqrt( 1 + m*m );
}
return m;
}
/*!
* Explicit conversion operator to double.
*
* Returns the complex magnitude or modulus of this complex number, so this
* operator is equivalent to Mag() const.
*/
explicit operator double() const noexcept
{
return double( Mag() );
}
/*!
* Complex norm.
* This function is equivalent to: Real()*Real() + Imag()*Imag().
*/
constexpr T Norm() const noexcept
{
return real*real + imag*imag;
}
/*!
* Complex argument.
* Returns the arc whose tangent is Imag()/Real(). When both real and
* imaginary components are zero, this function returns zero.
*/
constexpr T Arg() const noexcept
{
// Degenerate cases (real=0) are correctly handled by real ArcTan(). For
// the undefined case real=imag=0, we silently return zero. Should we
// throw an exception instead?
return (real != 0 || imag != 0) ? pcl::ArcTan( imag, real ) : 0;
}
private:
/*
* C99 binary-compatible complex components.
*/
T C[ 2 ]; // C[0] = real, C[1] = imaginary
};
#undef real
#undef imag
/*
* ### N.B.: Template class Complex<T> cannot have virtual member functions.
* This is because sizeof( Complex<T> ) _must_ be equal to 2*sizeof( T ).
*/
template <typename T>
struct PCL_AssertComplexSize
{
static_assert( sizeof( Complex<T> ) == 2*sizeof( T ), "Invalid sizeof( Complex<> )" );
};
// ----------------------------------------------------------------------------
/*!
* \defgroup complex_arithmetic_ops Complex Arithmetic Operators
*/
/*!
* \defgroup complex_basic_functions Complex Basic Functions
*/
/*!
* Complex absolute value. This function returns the complex magnitude of the
* specified complex number \a c.
* \ingroup complex_basic_functions
*/
template <typename T> inline
T Abs( const Complex<T>& c ) noexcept
{
return c.Mag();
}
/*!
* Returns a complex number from its polar coordinates: radial distance \a r
* and polar angle theta. The polar angle theta is given by its sine and
* cosine, \a stheta and \a ctheta, respectively.
* \ingroup complex_basic_functions
*/
template <typename T> inline
Complex<T> Polar( T r, T stheta, T ctheta ) noexcept
{
return Complex<T>( r*ctheta, r*stheta );
}
/*!
* Returns a complex number from its polar coordinates: radial distance \a r
* and polar angle \a theta. The polar angle is specified in radians.
* \ingroup complex_basic_functions
*/
template <typename T> inline
Complex<T> Polar( T r, T theta ) noexcept
{
return Polar( r, pcl::Sin( theta ), pcl::Cos( theta ) );
}
// ----------------------------------------------------------------------------
/*!
* Complex addition. Returns the sum of two complex numbers \a c1 and \a c2.
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T1> operator +( const Complex<T1>& c1, const Complex<T2>& c2 ) noexcept
{
return Complex<T1>( T1( c1.Real() + c2.Real() ),
T1( c1.Imag() + c2.Imag() ) );
}
/*!
* Complex addition. Returns the sum of a complex number \a c and a real \a x.
*
* \note The commutativity of complex-real addition is implemented by the
* existence of this function along with operator +( T1, const Complex<T2>& ).
*
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T1> operator +( const Complex<T1>& c, T2 x ) noexcept
{
return Complex<T1>( T1( c.Real()+x ), c.Imag() );
}
/*!
* Complex addition. Returns the sum of a real number \a x and a complex \a c.
*
* \note The commutativity of complex-real addition is implemented by the
* existence of this function along with operator +( const Complex<T1>&, T2 ).
*
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T2> operator +( T1 x, const Complex<T2>& c ) noexcept
{
return c + x;
}
/*!
* Complex subtraction. Returns the difference between two complex numbers
* \a c1 and \a c2.
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T1> operator -( const Complex<T1>& c1, const Complex<T2>& c2 ) noexcept
{
return Complex<T1>( T1( c1.Real() - c2.Real() ),
T1( c1.Imag() - c2.Imag() ) );
}
/*!
* Complex subtraction. Returns the difference between a complex number \a c
* and a real \a x.
*
* \note The noncommutativity of complex-real subtraction is implemented by
* the existence of this function along with
* operator -( T1, const Complex<T2>& ).
*
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T1> operator -( const Complex<T1>& c, T2 x ) noexcept
{
return Complex<T1>( T1( c.Real()-x ), c.Imag() );
}
/*!
* Complex subtraction. Returns the difference between a real number \a x
* and a complex \a c.
*
* \note The noncommutativity of complex-real subtraction is implemented by
* the existence of this function along with
* operator -( const Complex<T1>&, T2 ).
*
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T2> operator -( T1 x, const Complex<T2>& c ) noexcept
{
return Complex<T2>( T2( x-c.Real() ), -c.Imag() );
}
/*!
* Complex multiplication. Returns the multiplication of two complex numbers
* \a c1 and \a c2.
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T1> operator *( const Complex<T1>& c1, const Complex<T2>& c2 ) noexcept
{
return Complex<T1>( T1( c1.Real()*c2.Real() - c1.Imag()*c2.Imag() ),
T1( c1.Imag()*c2.Real() + c1.Real()*c2.Imag() ) );
}
/*!
* Complex multiplication. Returns the multiplication of a complex number \a c
* and a real \a x.
*
* \note The commutativity of complex-real multiplication is implemented by the
* existence of this function along with
* operator *( T1, const Complex<T2>& ).
*
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T1> operator *( const Complex<T1>& c, T2 x ) noexcept
{
return Complex<T1>( T1( c.Real()*x ), c.Imag()*x );
}
/*!
* Complex multiplication. Returns the multiplication of a real number \a x and
* a complex \a c.
*
* \note The commutativity of complex-real multiplication is implemented by the
* existence of this function along with
* operator *( const Complex<T1>&, T2 ).
*
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T2> operator *( T1 x, const Complex<T2>& c ) noexcept
{
return c * x;
}
/*!
* Complex division. Returns the division between two complex numbers
* \a c1 and \a c2.
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T1> operator /( const Complex<T1>& c1, const Complex<T2>& c2 ) noexcept
{
Complex<T1> c;
T2 r, d;
if ( pcl::Abs( c2.Real() ) >= pcl::Abs( c2.Imag() ) )
{
PCL_PRECONDITION( c2.Real() != 0 )
r = c2.Imag() / c2.Real();
d = c2.Real() + r*c2.Imag();
c.Real() = T1( (c1.Real() + r*c1.Imag())/d );
c.Imag() = T1( (c1.Imag() - r*c1.Real())/d );
}
else
{
PCL_PRECONDITION( c2.Imag() != 0 )
r = c2.Real() / c2.Imag();
d = c2.Imag() + r*c2.Real();
c.Real() = T1( (c1.Real()*r + c1.Imag())/d );
c.Imag() = T1( (c1.Imag()*r - c1.Real())/d );
}
return c;
}
/*!
* Complex division. Returns the division of a complex number \a c
* by a real \a x.
*
* \note The noncommutativity of complex-real division is implemented by the
* existence of this function along with
* operator /( T1, const Complex<T2>& ).
*
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T1> operator /( const Complex<T1>& c, T2 x ) noexcept
{
PCL_PRECONDITION( x != 0 )
return Complex<T1>( T1( c.Real()/x ), T1( c.Imag()/x ) );
}
/*!
* Complex division. Returns the division of a real number \a x and a
* complex \a c.
*
* \note The noncommutativity of complex-real division is implemented by the
* existence of this function along with
* operator /( const Complex<T1>&, T2 ).
*
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T2> operator /( T1 x, const Complex<T2>& c ) noexcept
{
// return Complex( x, 0 )/c;
Complex<T2> c3;
T2 r, d;
if ( pcl::Abs( c.Real() ) >= pcl::Abs( c.Imag() ) )
{
PCL_PRECONDITION( c.Real() != 0 )
r = c.Imag()/c.Real();
d = c.Real() + r*c.Imag();
c3.Real() = T2( x/d );
c3.Imag() = T2( -((r*x)/d) );
}
else
{
PCL_PRECONDITION( c.Imag() != 0 )
r = c.Real()/c.Imag();
d = c.Imag() + r*c.Real();
c3.Real() = T2( (r*x)/d );
c3.Imag() = T2( -(x/d) );
}
return c3;
}
// ----------------------------------------------------------------------------
/*!
* Complex square root.
* \ingroup complex_basic_functions
*/
template <typename T> inline
Complex<T> Sqrt( const Complex<T>& c ) noexcept
{
if ( c.Real() == 0 && c.Imag() == 0 )
return Complex<T>( 0 );
Complex<T> c1;
T m, r = pcl::Abs( c.Real() ), i = pcl::Abs( c.Imag() );
if ( r >= i )
{
PCL_PRECONDITION( r != 0 )
T t = i/r;
m = pcl::Sqrt( r ) * pcl::Sqrt( (1 + pcl::Sqrt( 1 + t*t ))/2 );
}
else
{
PCL_PRECONDITION( i != 0 )
T t = r/i;
m = pcl::Sqrt( i ) * pcl::Sqrt( (t + pcl::Sqrt( 1 + t*t ))/2 );
}
if ( c.Real() >= 0 )
{
c1.Real() = m;
c1.Imag() = c.Imag()/(m+m);
}
else
{
c1.Imag() = (c.Imag() >= 0) ? m : -m;
c1.Real() = c.Imag()/(c1.Imag()+c1.Imag());
}
return c1;
}
/*!
* Complex exponential function.
* \ingroup complex_basic_functions
*/
template <typename T> inline
Complex<T> Exp( const Complex<T>& c ) noexcept
{
T x = pcl::Exp( c.Real() );
return Complex<T>( x*pcl::Cos( c.Imag() ), x*pcl::Sin( c.Imag() ) );
}
/*!
* Complex natural (base e) logarithm.
* \ingroup complex_basic_functions
*/
template <typename T> inline
Complex<T> Ln( const Complex<T>& c ) noexcept
{
return Complex<T>( pcl::Ln( c.Mag() ), c.Arg() );
}
/*!
* Complex base 10 logarithm.
* \ingroup complex_basic_functions
*/
template <typename T> inline
Complex<T> Log( const Complex<T>& c ) noexcept
{
return pcl::Const<T>::log10e() * pcl::Ln( c );
}
// ----------------------------------------------------------------------------
/*!
* Complex exponentiation. Returns a complex number \a c raised to a real \a x.
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T1> Pow( const Complex<T1>& c, T2 x ) noexcept
{
if ( c.Imag() == 0 )
return Complex<T1>( pcl::Pow( c.Real(), T1( x ) ) );
else
return pcl::Exp( T1( x )*pcl::Ln( c ) );
}
/*!
* Complex exponentiation. Returns a real number \a x raised to a complex \a c.
* \ingroup complex_arithmetic_ops
*/
template <typename T1, class T2> inline
Complex<T2> Pow( T1 x, const Complex<T2>& c ) noexcept
{
if ( c.Imag() == 0 )
return Complex<T2>( pcl::Pow( T2( x ), c.Real() ) );
else
return pcl::Exp( c*pcl::Ln( T2( x ) ) );
}
/*!
* Complex exponentiation. Returns a complex number \a c1 raised to a
* complex \a c2.
* \ingroup complex_arithmetic_ops
*/
template <typename T> inline
Complex<T> Pow( const Complex<T>& c1, const Complex<T>& c2 ) noexcept
{
if ( c2.Imag() == 0 )
return pcl::Pow( c1, c2.Real() );
else if ( c1.Imag() == 0 )
return Complex<T>( pcl::Pow( c1.Real(), c2 ) );
else
return pcl::Exp( c2*pcl::Ln( c1 ) );
}
// ----------------------------------------------------------------------------
/*!
* \defgroup complex_transcendental_ops Complex Transcendental Functions
*/
/*!
* Complex sine.
* \ingroup complex_transcendental_ops
*/
template <typename T> inline
Complex<T> Sin( const Complex<T>& c ) noexcept
{
return Complex<T>( pcl::Sin( c.Real() )*pcl::Cosh( c.Imag() ),
pcl::Cos( c.Real() )*pcl::Sinh( c.Imag() ) );
}
/*!
* Complex cosine.
* \ingroup complex_transcendental_ops
*/
template <typename T> inline
Complex<T> Cos( const Complex<T>& c ) noexcept
{
return Complex<T>( pcl::Cos( c.Real() )*pcl::Cosh( c.Imag() ),
-pcl::Sin( c.Real() )*pcl::Sinh( c.Imag() ) );
}
/*!
* Complex tangent.
* \ingroup complex_transcendental_ops
*/
template <typename T> inline
Complex<T> Tan( const Complex<T>& c ) noexcept
{
return pcl::Sin( c )/pcl::Cos( c );
}
/*!
* Complex hyperbolic sine.
* \ingroup complex_transcendental_ops
*/
template <typename T> inline
Complex<T> Sinh( const Complex<T>& c ) noexcept
{
return Complex<T>( pcl::Sinh( c.Real() )*pcl::Cos( c.Imag() ),
pcl::Cosh( c.Real() )*pcl::Sin( c.Imag() ) );
}
/*!
* Complex hyperbolic cosine.
* \ingroup complex_transcendental_ops
*/
template <typename T> inline
Complex<T> Cosh( const Complex<T>& c ) noexcept
{
return Complex<T>( pcl::Cosh( c.Real() )*pcl::Cos( c.Imag() ),
pcl::Sinh( c.Real() )*pcl::Sin( c.Imag() ) );
}
/*!
* Complex hyperbolic tangent.
* \ingroup complex_transcendental_ops
*/
template <typename T> inline
Complex<T> Tanh( const Complex<T>& c ) noexcept
{
return pcl::Sinh( c )/pcl::Cosh( c );
}
// ----------------------------------------------------------------------------
/*!
* \defgroup complex_relational_ops Complex Relational Operators
*
* The elements of the complex plane don't follow any particular "natural"
* order. Of course, our definitions of the <, <=, > and >= operators for
* complex numbers are completely arbitrary: we just compare complex
* magnitudes. This effectively sorts complex numbers by concentric circles
* around the origin.
*/
/*!
* Returns true iff two complex numbers \a c1 and \a c2 are equal.
* \ingroup complex_relational_ops
*/
template <typename T1, class T2> inline
bool operator ==( const Complex<T1>& c1, const Complex<T2>& c2 ) noexcept
{
return c1.Real() == c2.Real() && c1.Imag() == c2.Imag();
}
/*!
* Returns true iff a complex number \a c is equal to a real \a x.
* \ingroup complex_relational_ops
*/
template <typename T1, class T2> inline
bool operator ==( const Complex<T1>& c, T2 x ) noexcept
{
return c.Real() == x && c.Imag() == T1( 0 );
}
/*!
* Returns true iff a real number \a x is equal to a complex \a c.
* \ingroup complex_relational_ops
*/
template <typename T1, class T2> inline
bool operator ==( T1 x, const Complex<T2>& c ) noexcept
{
return c == x;
}
/*!
* Returns true iff a complex number \a c1 is less than other complex \a c2.
* \ingroup complex_relational_ops
*/
template <typename T1, class T2> inline
bool operator <( const Complex<T1>& c1, const Complex<T2>& c2 ) noexcept
{
return c1.Mag() < c2.Mag();
}
/*!
* Returns true iff a complex number \a c is less than a real number \a x.
* \ingroup complex_relational_ops
*/
template <typename T1, class T2> inline
bool operator <( const Complex<T1>& c, T2 x ) noexcept
{
return c.Mag() < pcl::Abs( x );
}
/*!
* Returns true iff a real number \a x is less than a complex number \a c.
* \ingroup complex_relational_ops
*/
template <typename T1, class T2> inline
bool operator <( T1 x, const Complex<T2>& c ) noexcept
{
return pcl::Abs( x ) < c.Mag();
}
// ----------------------------------------------------------------------------
/*!
* \defgroup complex_rounding_functions Complex Rounding Functions
*/
/*!
* Complex rounding. Returns a complex number whose components are the
* components of a specified complex \a c rounded to their nearest integers.
* \ingroup complex_rounding_functions
*/
template <typename T> inline
Complex<T> Round( const Complex<T>& c ) noexcept
{
return Complex<T>( pcl::Round( c.Real() ), pcl::Round( c.Imag() ) );
}
/*!
* Complex rounding. Returns a complex number whose components are the
* components of a specified complex \a c rounded to the specified number of
* decimal digits \a n.
* \ingroup complex_rounding_functions
*/
template <typename T> inline
Complex<T> Round( const Complex<T>& c, int n ) noexcept
{
PCL_PRECONDITION( n >= 0 )
return Complex<T>( pcl::Round( c.Real(), n ), pcl::Round( c.Imag(), n ) );
}
// ----------------------------------------------------------------------------
/*!
* \defgroup phase_matrices Phase Matrices Computation Algorithms
*/
/*!
* Phase correlation matrix.
*
* \param[out] i Address of the first element in the output phase
* correlation matrix.
*
* \param j Address of the ending element in the output phase
* correlation matrix.
*
* \param a Address of the first element in the first operand matrix.
*
* \param b Address of the first element in the second operand matrix.
*
* This routine will compute and store the set of contiguous matrix elements at
* i, i+1, ..., j-1. The total number of computed elements in the output phase
* correlation matrix is equal to j-i. The \a i, \a a and \a b matrices must
* provide storage for at least j-i complex numbers.
*
* \ingroup phase_matrices
*/
template <typename T> inline
void PhaseCorrelationMatrix( Complex<T>* __restrict__ i, const Complex<T>* __restrict__ j,
const Complex<T>* __restrict__ a, const Complex<T>* __restrict__ b ) noexcept
{
const T tiny = T( 1.0e-20 );
for ( ; i < j; ++i, ++a, ++b )
{
Complex<T> n = *a * ~*b;
*i = n/Max( tiny, Abs( n ) );
}
}
/*!
* Cross power spectrum matrix.
*
* \param[out] i Address of the first element in the output cross power
* spectrum matrix.
*
* \param j Address of the ending element in the output cross power
* spectrum matrix.
*
* \param a Address of the first element in the first operand matrix.
*
* \param b Address of the first element in the second operand matrix.
*
* This routine will compute and store the set of contiguous matrix elements at
* i, i+1, ..., j-1. The total number of computed elements in the output cross
* power spectrum matrix is equal to j-i. The \a i, \a a and \a b matrices must
* provide storage for at least j-i complex numbers.
*
* \ingroup phase_matrices
*/
template <typename T> inline
void CrossPowerSpectrumMatrix( Complex<T>* __restrict__ i, const Complex<T>* __restrict__ j,
const Complex<T>* __restrict__ a, const Complex<T>* __restrict__ b ) noexcept
{
const T tiny = T( 1.0e-20 );
for ( ; i < j; ++i, ++a, ++b )
*i = (*b * ~*a)/Max( tiny, Abs( *a ) * Abs( *b ) );
}
//
// Stream extraction/insertion.
//
/* ### PCL 2.x: Add these along with pcl::DataStream, etc...
template <class S, typename T> inline
S& operator >>( S& s, Complex<T>& c )
{
return s >> c.Real() >> c.Imag();
}
template <class S, typename T> inline
S& operator <<( S& s, const Complex<T>& c )
{
return s << c.Real() << c.Imag();
}
*/
// ----------------------------------------------------------------------------
#ifndef __PCL_NO_COMPLEX_INSTANTIATE
/*!
* \defgroup complex_types Complex Number Types
*/
/*!
* \class pcl::Complex32
* \ingroup complex_types
* \brief A complex number whose components are 32-bit floating point real
* numbers.
*
* Complex32 is a template instantiation of Complex for the \c float type.
*/
typedef Complex<float> Complex32;
/*!
* \class pcl::fcomplex
* \ingroup complex_types
* \brief A complex number whose components are 32-bit floating point real
* numbers.
*
* fcomplex is an alias for Complex32. It is a template instantiation of
* Complex for the \c float type.
*/
typedef Complex32 fcomplex;
/*!
* \class pcl::Complex64
* \ingroup complex_types
* \brief A complex number whose components are 64-bit floating point real
* numbers.
*
* Complex64 is a template instantiation of Complex for the \c double type.
*/
typedef Complex<double> Complex64;
/*!
* \class pcl::dcomplex
* \ingroup complex_types
* \brief A complex number whose components are 64-bit floating point real
* numbers.
*
* dcomplex is an alias for Complex64. It is a template instantiation of
* Complex for the \c double type.
*/
typedef Complex64 dcomplex;
/*!
* \class pcl::complex
* \ingroup complex_types
* \brief A complex number whose components are 64-bit floating point real
* numbers.
*
* complex is an alias for dcomplex. It is a template instantiation of Complex
* for the \c double type.
*/
typedef dcomplex complex;
#endif // __PCL_NO_COMPLEX_INSTANTIATE
// ----------------------------------------------------------------------------
} // pcl
#endif // __PCL_Complex_h
// ----------------------------------------------------------------------------
// EOF pcl/Complex.h - Released 2022-03-12T18:59:29Z