1111 lines
30 KiB
C++
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
|