946 lines
31 KiB
C++
946 lines
31 KiB
C++
// ____ ______ __
|
|
// / __ \ / ____// /
|
|
// / /_/ // / / /
|
|
// / ____// /___ / /___ PixInsight Class Library
|
|
// /_/ \____//_____/ PCL 2.4.23
|
|
// ----------------------------------------------------------------------------
|
|
// pcl/ChebyshevFit.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_ChebyshevFit_h
|
|
#define __PCL_ChebyshevFit_h
|
|
|
|
/// \file pcl/ChebyshevFit.h
|
|
|
|
#include <pcl/Defs.h>
|
|
|
|
#include <pcl/Constants.h>
|
|
#include <pcl/ErrorHandler.h>
|
|
#include <pcl/Exception.h>
|
|
#include <pcl/MultiVector.h>
|
|
|
|
namespace pcl
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
template <typename Tx, typename Ty> class GenericScalarChebyshevFit;
|
|
|
|
/*!
|
|
* \class GenericChebyshevFit
|
|
* \brief Approximation of vector-valued functions by Chebyshev polynomial
|
|
* expansions.
|
|
*
|
|
* %GenericChebyshevFit approximates a smooth, vector-valued function f(x) in a
|
|
* given interval [a,b] by expansion with a set of truncated series of
|
|
* Chebyshev polynomials. As is well known, the Chebyshev expansion:
|
|
*
|
|
* T(x) = Sum_i( ci*Ti(x) ),
|
|
*
|
|
* where i belongs to [0,∞), Ti(x) is the Chebyshev polynomial of the ith
|
|
* degree, and the ci's are polynomial coefficients, is very close to the
|
|
* optimal approximating polynomial that minimizes the error |T(x) - f(x)|,
|
|
* where x varies over the fitting interval [a,b].
|
|
*
|
|
* For functions converging strongly after a given series length n, one can
|
|
* truncate the Chebyshev series to a smaller length m < n to obtain an
|
|
* approximating polynomial with a maximum error close to |Tm+1(x)|.
|
|
*
|
|
* In addition to Chebyshev expansion, truncation and approximation, this class
|
|
* also implements generation of Chebyshev polynomials to approximate the
|
|
* first derivative and indefinite integral of the fitted function.
|
|
*
|
|
* The template argument Tx represents the type of the independent variable, or
|
|
* the type of the argument x of the fitted function y = f(x). The template
|
|
* argument Ty represents the type of a component of the value y of the fitted
|
|
* function.
|
|
*/
|
|
template <typename Tx, typename Ty>
|
|
class GenericChebyshevFit
|
|
{
|
|
public:
|
|
|
|
/*!
|
|
* Represents an ordered list of Chebyshev polynomial coefficients.
|
|
*/
|
|
typedef GenericVector<Ty> coefficients;
|
|
|
|
/*!
|
|
* Represents a set of ordered lists of Chebyshev polynomial coefficients.
|
|
*/
|
|
typedef GenericMultiVector<Ty> coefficient_series;
|
|
|
|
/*!
|
|
* Represents a function value.
|
|
*/
|
|
typedef GenericVector<Ty> function_value;
|
|
|
|
/*!
|
|
* Represents a set of function values.
|
|
*/
|
|
typedef GenericMultiVector<Ty> function_values;
|
|
|
|
/*!
|
|
* Constructs a truncated Chebyshev polynomial expansion with \a n
|
|
* coefficients to approximate the specified N-dimensional, vector-valued
|
|
* function \a f in the interval [\a x1,\a x2] of the independent variable.
|
|
*
|
|
* The function \a f will be called \a n times and should have the following
|
|
* prototype (or equivalent by means of suitable type conversions and/or
|
|
* default arguments):
|
|
*
|
|
* GenericVector<Ty> f( Tx )
|
|
*
|
|
* where the length of a returned vector must be equal to \a N.
|
|
*
|
|
* The expansion process will compute n^2 + n cosines, which may dominate the
|
|
* complexity of the process if the function \a f is comparatively fast.
|
|
*
|
|
* The interval [\a x1,\a x2] must not be empty or insignificant with
|
|
* respect to the machine epsilon. If that happens, this constructor will
|
|
* throw an appropriate Error exception. The interval bounds can be
|
|
* specified in any order, that is, \a x2 can legally be < \a x1; in such
|
|
* case the bounds will be implicitly swapped by this constructor.
|
|
*
|
|
* The interval [\a x1,\a x2] will be also the valid range of evaluation for
|
|
* this object, which can be retrieved with LowerBound() and UpperBound().
|
|
* See also the Evaluate() member function.
|
|
*
|
|
* The length \a n of the polynomial coefficient series should be ≥ 2. If
|
|
* \a n ≤ 1, the specified value will be ignored and \a n = 2 will be
|
|
* forced. Typically, a relatively large series length should be used, say
|
|
* between 30 and 100 coefficients, depending on the rate and amplitude of
|
|
* function variations within the fitting interval. The polynomial expansion
|
|
* can be further truncated to approximate the function to the desired error
|
|
* bound. See the Truncate() and Evaluate() member functions for details.
|
|
*/
|
|
template <class F>
|
|
GenericChebyshevFit( F f, Tx x1, Tx x2, int N, int n )
|
|
: dx( Abs( x2 - x1 ) )
|
|
, x0( (x1 + x2)/2 )
|
|
, m( Max( 2, n ), Max( 1, N ) )
|
|
{
|
|
PCL_PRECONDITION( N > 0 )
|
|
PCL_PRECONDITION( n > 1 )
|
|
if ( 1 + dx == 1 )
|
|
throw Error( "GenericChebyshevFit: Empty or insignificant function evaluation interval." );
|
|
N = m.Length();
|
|
n = m[0];
|
|
Tx dx2 = dx/2;
|
|
function_values y( n, N );
|
|
for ( int j = 0; j < n; ++j )
|
|
y[j] = f( x0 + Cos( Const<Ty>::pi()*(j + 0.5)/n )*dx2 );
|
|
c = coefficient_series( N, n );
|
|
Ty k = 2.0/n;
|
|
for ( int i = 0; i < N; ++i )
|
|
for ( int j = 0; j < n; ++j )
|
|
{
|
|
Ty s = Ty( 0 );
|
|
for ( int k = 0; k < n; ++k )
|
|
s += y[k][i] * Cos( Const<Ty>::pi()*j*(k + 0.5)/n );
|
|
c[i][j] = k*s;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* Constructs a truncated Chebyshev polynomial expansion from the specified
|
|
* coefficient series \a ck to approximate a vector-valued function in the
|
|
* interval [\a x1,\a x2] of the independent variable. The dimension of the
|
|
* approximated function and the coefficient series lengths are acquired
|
|
* from the specified container \a ck.
|
|
*
|
|
* This constructor performs basic coherence and structural integrity checks
|
|
* on the specified parameters, and throws the appropriate Error exception
|
|
* if it detects any problem. However, the validity of polynomial expansion
|
|
* coefficients cannot be verified; ensuring it is the responsibility of the
|
|
* caller.
|
|
*/
|
|
GenericChebyshevFit( const coefficient_series& ck, Tx x1, Tx x2 )
|
|
: dx( Abs( x2 - x1 ) )
|
|
, x0( (x1 + x2)/2 )
|
|
, c( ck )
|
|
, m( int( ck.Length() ) )
|
|
{
|
|
if ( 1 + dx == 1 )
|
|
throw Error( "GenericChebyshevFit: Empty or insignificant function evaluation interval." );
|
|
if ( c.IsEmpty() )
|
|
throw Error( "GenericChebyshevFit: Empty polynomial expansion." );
|
|
for ( int i = 0; i < m.Length(); ++i )
|
|
if ( (m[i] = c[i].Length()) < 1 )
|
|
throw Error( "GenericChebyshevFit: Invalid coefficient series for dimension " + String( i ) + '.' );
|
|
}
|
|
|
|
/*!
|
|
* Default constructor.
|
|
*
|
|
* Constructs an invalid, uninitialized object that cannot be used to
|
|
* perform function evaluations. A default-constructed %GenericChebyshevFit
|
|
* object should be assigned with an already initialized instance in order
|
|
* to become operative.
|
|
*
|
|
* \sa IsValid()
|
|
*/
|
|
GenericChebyshevFit() = default;
|
|
|
|
/*!
|
|
* Copy constructor.
|
|
*/
|
|
GenericChebyshevFit( const GenericChebyshevFit& ) = default;
|
|
|
|
/*!
|
|
* Move constructor.
|
|
*/
|
|
GenericChebyshevFit( GenericChebyshevFit&& ) = default;
|
|
|
|
/*!
|
|
* Copy assignment operator. Returns a reference to this object.
|
|
*/
|
|
GenericChebyshevFit& operator =( const GenericChebyshevFit& ) = default;
|
|
|
|
/*!
|
|
* Move assignment operator. Returns a reference to this object.
|
|
*/
|
|
GenericChebyshevFit& operator =( GenericChebyshevFit&& ) = default;
|
|
|
|
/*!
|
|
* Returns true if this object has been correctly initialized and can be
|
|
* used to perform function evaluations. Returns false if this is an
|
|
* uninitialized, default-constructed object
|
|
*/
|
|
bool IsValid() const
|
|
{
|
|
return !c.IsEmpty();
|
|
}
|
|
|
|
/*!
|
|
* Returns the lower bound of this Chebyshev fit. This is the smallest value
|
|
* of the independent variable for which the function has been fitted, and
|
|
* hence the smallest value for which this object can be legally evaluated
|
|
* for function approximation.
|
|
*
|
|
* \sa UpperBound()
|
|
*/
|
|
Tx LowerBound() const
|
|
{
|
|
return x0 - dx/2;
|
|
}
|
|
|
|
/*!
|
|
* Returns the upper bound of this Chebyshev fit. This is the largest value
|
|
* of the independent variable for which the function has been fitted, and
|
|
* hence the largest value for which this object can be legally evaluated
|
|
* for function approximation.
|
|
*
|
|
* \sa LowerBound()
|
|
*/
|
|
Tx UpperBound() const
|
|
{
|
|
return x0 + dx/2;
|
|
}
|
|
|
|
/*!
|
|
* Returns the number of components in the (vector-valued) dependent
|
|
* variable. This is the number of vector components in a fitted or
|
|
* approximated function value.
|
|
*/
|
|
int NumberOfComponents() const
|
|
{
|
|
return m.Length();
|
|
}
|
|
|
|
/*!
|
|
* Returns the number of coefficients in the generated Chebyshev polynomial
|
|
* expansion for the specified zero-based vector component index \a i. This
|
|
* is the number of coefficients that was specified or acquired in a class
|
|
* constructor.
|
|
*
|
|
* \sa TruncatedLength()
|
|
*/
|
|
int Length( int i = 0 ) const
|
|
{
|
|
PCL_PRECONDITION( i >= 0 && i < NumberOfComponents() )
|
|
return c[i].Length();
|
|
}
|
|
|
|
/*!
|
|
* Returns the number of coefficients in the truncated Chebyshev polynomial
|
|
* expansion for the specified zero-based vector component index \a i.
|
|
*
|
|
* If \a i < 0, returns the largest number of polynomial coefficients among
|
|
* all vector components.
|
|
*
|
|
* \sa Truncate(), Length()
|
|
*/
|
|
int TruncatedLength( int i = -1 ) const
|
|
{
|
|
PCL_PRECONDITION( i < 0 || i < NumberOfComponents() )
|
|
if ( i < 0 )
|
|
return m.MaxComponent();
|
|
return m[i];
|
|
}
|
|
|
|
/*!
|
|
* Returns the total number of coefficients in this Chebyshev polynomial
|
|
* expansion, or the sum of computed coefficients for all vector components.
|
|
*
|
|
* \sa NumberOfTruncatedCoefficients()
|
|
*/
|
|
int NumberOfCoefficients() const
|
|
{
|
|
int N = 0;
|
|
for ( int i = 0; i < NumberOfComponents(); ++i )
|
|
N += c[i].Length();
|
|
return N;
|
|
}
|
|
|
|
/*!
|
|
* Returns the total number of coefficients in the truncated Chebyshev
|
|
* polynomial expansion, or the sum of the lengths of the truncated
|
|
* coefficients series for all vector components.
|
|
*
|
|
* \sa NumberOfCoefficients()
|
|
*/
|
|
int NumberOfTruncatedCoefficients() const
|
|
{
|
|
return m.Sum();
|
|
}
|
|
|
|
/*!
|
|
* Returns true iff the Chebyshev polynomial expansion has been truncated
|
|
* for the specified zero-based vector component index \a i.
|
|
*
|
|
* If \a i < 0, returns true iff the expansions have been truncated for all
|
|
* vector components.
|
|
*
|
|
* \sa Truncate(), TruncatedLength()
|
|
*/
|
|
bool IsTruncated( int i = -1 ) const
|
|
{
|
|
PCL_PRECONDITION( i < 0 || i < NumberOfComponents() )
|
|
if ( i < 0 )
|
|
return m.MaxComponent() < Length();
|
|
return m[i] < c[i].Length();
|
|
}
|
|
|
|
/*!
|
|
* Returns an estimate of the maximum error in the truncated Chebyshev
|
|
* polynomial expansion for the specified zero-based vector component index
|
|
* \a i.
|
|
*
|
|
* If \a i < 0, returns the largest expansion error estimate among all
|
|
* vector components.
|
|
*
|
|
* \sa Truncate()
|
|
*/
|
|
Ty TruncationError( int i = -1 ) const
|
|
{
|
|
PCL_PRECONDITION( i < 0 || i < NumberOfComponents() )
|
|
if ( i < 0 )
|
|
{
|
|
int N = NumberOfComponents();
|
|
function_value e( N );
|
|
for ( int j = 0; j < N; ++j )
|
|
e[j] = TruncationError( j );
|
|
return e.MaxComponent();
|
|
}
|
|
if ( m[i] < c[i].Length() )
|
|
{
|
|
Ty e = Ty( 0 );
|
|
for ( int j = c[i].Length(); --j >= m[i]; )
|
|
e += Abs( c[i][j] );
|
|
return e;
|
|
}
|
|
return Abs( c[i][c[i].Length()-1] );
|
|
}
|
|
|
|
/*!
|
|
* Attempts to truncate the Chebyshev polynomial expansion for the specified
|
|
* maximum error \a e. Returns \c true iff the expansion could be truncated
|
|
* successfully for all vector components of the fitted function.
|
|
*
|
|
* If n is the length of a fitted polynomial series, this function finds a
|
|
* truncated length 1 < m ≤ n such that:
|
|
*
|
|
* Sum_i( |ci| ) < e
|
|
*
|
|
* where ci is a polynomial coefficient and the zero-based subindex i is in
|
|
* the interval [m,n-1].
|
|
*
|
|
* The truncated Chebyshev expansion will approximate the fitted function
|
|
* component with a maximum error close to ±|e| within the fitting
|
|
* interval.
|
|
*
|
|
* The optional parameter \a mmin is the minimum allowed length of a
|
|
* coefficient series. The value of this parameter is 2 by default, which is
|
|
* the minimum number of Chebyshev coefficients in a series expansion.
|
|
* Specifying a value greater than 2 can be useful sometimes to impose
|
|
* stricter accuracy constraints on the truncated series.
|
|
*
|
|
* This member function does not remove any polynomial coefficients, so the
|
|
* original polynomial expansion remains intact. This means that the fitted
|
|
* polynomials can be truncated successively to achieve different error
|
|
* bounds, as required.
|
|
*
|
|
* If the polynomial series cannot be truncated to achieve the required
|
|
* tolerance in all function components (that is, if either all coefficients
|
|
* for a given component are larger than \a e in absolute value, or n = 2),
|
|
* this function forces m = n for the components where the requested
|
|
* truncation is not feasible, yielding the original, untruncated Chebyshev
|
|
* polynomials for those components. In such case this function returns
|
|
* \c false.
|
|
*/
|
|
bool Truncate( Ty e, int mmin = 2 )
|
|
{
|
|
e = Abs( e );
|
|
mmin = Max( 2, mmin );
|
|
int N = NumberOfComponents();
|
|
int tc = 0;
|
|
for ( int i = 0; i < N; ++i )
|
|
{
|
|
Ty s = Ty( 0 );
|
|
for ( m[i] = c[i].Length(); m[i] > mmin; --m[i] )
|
|
if ( (s += Abs( c[i][m[i]-1] )) >= e )
|
|
break;
|
|
if ( m[i] < c[i].Length() )
|
|
++tc;
|
|
}
|
|
return tc == N;
|
|
}
|
|
|
|
/*!
|
|
* Returns a reference to the immutable set of Chebyshev polynomial
|
|
* expansion coefficients in this object.
|
|
*/
|
|
const coefficient_series& Coefficients() const
|
|
{
|
|
return c;
|
|
}
|
|
|
|
/*!
|
|
* Evaluates the truncated Chebyshev polynomial expansion for the specified
|
|
* value \a x of the independent variable, and returns the approximated
|
|
* function value.
|
|
*
|
|
* The specified evaluation point \a x must lie within the fitting interval,
|
|
* given by LowerBound() and UpperBound(), which was specified as the \a x1
|
|
* and \a x2 arguments when the function was initially fitted by the class
|
|
* constructor. For performance reasons, this precondition is not verified
|
|
* by this member function. If an out-of-range evaluation point is
|
|
* specified, this function will return an unpredictable result.
|
|
*
|
|
* If the polynomial series has been truncated by calling Truncate(), this
|
|
* function evaluates the current truncated Chebyshev expansions instead of
|
|
* the original ones.
|
|
*
|
|
* \sa operator ()()
|
|
*/
|
|
function_value Evaluate( Tx x ) const
|
|
{
|
|
PCL_PRECONDITION( x >= LowerBound() )
|
|
PCL_PRECONDITION( x <= UpperBound() )
|
|
const Ty y0 = Ty( 2*(x - x0)/dx );
|
|
const Ty y2 = 2*y0;
|
|
function_value y( NumberOfComponents() );
|
|
for ( int i = 0; i < y.Length(); ++i )
|
|
{
|
|
Ty d0 = Ty( 0 );
|
|
Ty d1 = Ty( 0 );
|
|
const Ty* k = c[i].At( m[i] );
|
|
for ( int j = m[i]; --j > 0; )
|
|
{
|
|
Ty d = d1;
|
|
d1 = y2*d1 - d0 + *--k;
|
|
d0 = d;
|
|
}
|
|
y[i] = y0*d1 - d0 + *--k/2;
|
|
}
|
|
return y;
|
|
}
|
|
|
|
/*!
|
|
* A synonym for Evaluate().
|
|
*/
|
|
function_value operator ()( Tx x ) const
|
|
{
|
|
return Evaluate( x );
|
|
}
|
|
|
|
/*!
|
|
* Returns a %GenericChebyshevFit object that approximates the derivative of
|
|
* the function fitted by this object.
|
|
*
|
|
* The returned object can be used to evaluate the derivative within the
|
|
* fitting interval of this object, defined by LowerBound() and
|
|
* UpperBound().
|
|
*
|
|
* The returned object will always own Chebyshev polynomials with the length
|
|
* of the originally fitted series, \e not of the current truncated lengths,
|
|
* if the polynomial expansions have been truncated.
|
|
*
|
|
* \sa Integral()
|
|
*/
|
|
GenericChebyshevFit Derivative() const
|
|
{
|
|
int N = NumberOfComponents();
|
|
GenericChebyshevFit ch1;
|
|
ch1.dx = dx;
|
|
ch1.x0 = x0;
|
|
ch1.c = coefficient_series( N );
|
|
ch1.m = IVector( N );
|
|
for ( int i = 0; i < N; ++i )
|
|
{
|
|
int n = Max( 1, c[i].Length()-1 );
|
|
ch1.c[i] = coefficients( n );
|
|
ch1.m[i] = n;
|
|
if ( n > 1 )
|
|
{
|
|
ch1.c[i][n-1] = 2*n*c[i][n];
|
|
ch1.c[i][n-2] = 2*(n-1)*c[i][n-1];
|
|
for ( int j = n-3; j >= 0; --j )
|
|
ch1.c[i][j] = ch1.c[i][j+2] + 2*(j+1)*c[i][j+1];
|
|
ch1.c[i] *= Ty( 2 )/dx;
|
|
}
|
|
else
|
|
ch1.c[i] = Ty( 0 );
|
|
}
|
|
return ch1;
|
|
}
|
|
|
|
/*!
|
|
* Returns a %GenericChebyshevFit object that approximates the indefinite
|
|
* integral of the function fitted by this object.
|
|
*
|
|
* The returned object can be used to evaluate the integral within the
|
|
* fitting interval of this object, as defined by LowerBound() and
|
|
* UpperBound(). The constant of integration is set to a value such that the
|
|
* integral is zero at the lower fitting bound.
|
|
*
|
|
* The returned object will always own Chebyshev polynomials with the length
|
|
* of the originally fitted series, \e not of the current truncated lengths,
|
|
* if the polynomial expansions have been truncated.
|
|
*
|
|
* \sa Derivative()
|
|
*/
|
|
GenericChebyshevFit Integral() const
|
|
{
|
|
int N = NumberOfComponents();
|
|
GenericChebyshevFit ch;
|
|
ch.dx = dx;
|
|
ch.x0 = x0;
|
|
ch.c = coefficient_series( N );
|
|
ch.m = IVector( N );
|
|
for ( int i = 0; i < N; ++i )
|
|
{
|
|
int n = c[i].Length();
|
|
ch.c[i] = coefficients( n );
|
|
ch.m[i] = n;
|
|
if ( n > 1 )
|
|
{
|
|
const Ty k = Ty( dx )/4;
|
|
Ty s = Ty( 0 );
|
|
int f = 1;
|
|
for ( int j = 1; j < n-1; ++j, f = -f )
|
|
s += f*(ch.c[i][j] = k*(c[i][j-1] - c[i][j+1])/j);
|
|
ch.c[i][0] = 2*(s + f*(ch.c[i][n-1] = k*c[i][n-2]/(n-1)));
|
|
}
|
|
else
|
|
ch.c[i] = Ty( 0 );
|
|
}
|
|
return ch;
|
|
}
|
|
|
|
private:
|
|
|
|
Tx dx; // x2 - x1
|
|
Tx x0; // (x1 + x2)/2
|
|
coefficient_series c; // Chebyshev polynomial coefficients
|
|
IVector m; // length of the truncated coefficient series
|
|
|
|
friend class GenericScalarChebyshevFit<Tx,Ty>;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/*!
|
|
* \class GenericScalarChebyshevFit
|
|
* \brief Approximation of scalar-valued functions by Chebyshev polynomial
|
|
* expansion.
|
|
*
|
|
* %GenericScalarChebyshevFit approximates a smooth, scalar-valued function
|
|
* f(x) in a given interval [a,b] by expansion with a single truncated series
|
|
* of Chebyshev polynomials. %GenericScalarChebyshevFit is a convenient
|
|
* specialization of GenericChebyshevFit for functions returning a single
|
|
* value; refer to the parent class for complete information.
|
|
*/
|
|
template <typename Tx, typename Ty>
|
|
class GenericScalarChebyshevFit : public GenericChebyshevFit<Tx,Ty>
|
|
{
|
|
public:
|
|
|
|
/*!
|
|
* Constructs a truncated Chebyshev polynomial expansion with \a n
|
|
* coefficients to approximate the specified N-dimensional, scalar-valued
|
|
* function \a f in the interval [\a x1,\a x2] of the independent variable.
|
|
*
|
|
* See GenericChebyshevFit::GenericChebyshevFit() for detailed information.
|
|
*/
|
|
template <class F>
|
|
GenericScalarChebyshevFit( F f, Tx x1, Tx x2, int n )
|
|
: GenericChebyshevFit<Tx,Ty>( [f]( Tx x ){ return GenericVector<Ty>( f( x ), 1 ); }, x1, x2, 1, n )
|
|
{
|
|
}
|
|
|
|
/*!
|
|
* Default constructor.
|
|
*
|
|
* Constructs an invalid, uninitialized object that cannot be used to
|
|
* perform function evaluations. A default-constructed
|
|
* %GenericScalarChebyshevFit object should be assigned with an already
|
|
* initialized instance in order to become operative.
|
|
*
|
|
* \sa IsValid()
|
|
*/
|
|
GenericScalarChebyshevFit() = default;
|
|
|
|
/*!
|
|
* Copy constructor.
|
|
*/
|
|
GenericScalarChebyshevFit( const GenericScalarChebyshevFit& ) = default;
|
|
|
|
/*!
|
|
* Move constructor.
|
|
*/
|
|
GenericScalarChebyshevFit( GenericScalarChebyshevFit&& ) = default;
|
|
|
|
/*!
|
|
* Copy assignment operator.
|
|
*/
|
|
GenericScalarChebyshevFit& operator =( const GenericScalarChebyshevFit& ) = default;
|
|
|
|
/*!
|
|
* Move assignment operator.
|
|
*/
|
|
GenericScalarChebyshevFit& operator =( GenericScalarChebyshevFit&& ) = default;
|
|
|
|
/*!
|
|
* Returns the number of coefficients in the truncated Chebyshev polynomial
|
|
* expansion.
|
|
*
|
|
* \sa Truncate(), Length()
|
|
*/
|
|
int TruncatedLength() const
|
|
{
|
|
return GenericChebyshevFit<Tx,Ty>::TruncatedLength( 0 );
|
|
}
|
|
|
|
/*!
|
|
* Returns true iff the Chebyshev polynomial expansion has been truncated.
|
|
*
|
|
* \sa Truncate(), TruncatedLength()
|
|
*/
|
|
bool IsTruncated() const
|
|
{
|
|
return GenericChebyshevFit<Tx,Ty>::IsTruncated( 0 );
|
|
}
|
|
|
|
/*!
|
|
* Returns an estimate of the maximum error in the truncated Chebyshev
|
|
* polynomial expansion.
|
|
*
|
|
* \sa Truncate()
|
|
*/
|
|
Ty TruncationError() const
|
|
{
|
|
return GenericChebyshevFit<Tx,Ty>::TruncationError( 0 );
|
|
}
|
|
|
|
/*!
|
|
* Evaluates the truncated Chebyshev polynomial expansion for the specified
|
|
* value \a x of the independent variable, and returns the approximated
|
|
* function value.
|
|
*
|
|
* \sa operator ()()
|
|
*/
|
|
Ty Evaluate( Tx x ) const
|
|
{
|
|
return GenericChebyshevFit<Tx,Ty>::Evaluate( x )[0];
|
|
}
|
|
|
|
/*!
|
|
* A synonym for Evaluate().
|
|
*/
|
|
Ty operator ()( Tx x ) const
|
|
{
|
|
return Evaluate( x );
|
|
}
|
|
|
|
/*!
|
|
* Returns a %GenericChebyshevFit object that approximates the derivative of
|
|
* the function fitted by this object.
|
|
*
|
|
* See GenericChebyshevFit::Derivative() for detailed information.
|
|
*
|
|
* \sa Integral()
|
|
*/
|
|
GenericScalarChebyshevFit Derivative() const
|
|
{
|
|
return GenericChebyshevFit<Tx,Ty>::Derivative();
|
|
}
|
|
|
|
/*!
|
|
* Returns a %GenericChebyshevFit object that approximates the indefinite
|
|
* integral of the function fitted by this object.
|
|
*
|
|
* See GenericChebyshevFit::Integral() for detailed information.
|
|
*
|
|
* \sa Derivative()
|
|
*/
|
|
GenericScalarChebyshevFit Integral() const
|
|
{
|
|
return GenericChebyshevFit<Tx,Ty>::Integral();
|
|
}
|
|
|
|
private:
|
|
|
|
/*!
|
|
* \internal
|
|
* Private constructor from the base class.
|
|
*/
|
|
GenericScalarChebyshevFit( const GenericChebyshevFit<Tx,Ty>& T )
|
|
: GenericChebyshevFit<Tx,Ty>()
|
|
{
|
|
this->dx = T.dx;
|
|
this->x0 = T.x0;
|
|
this->c = typename GenericChebyshevFit<Tx,Ty>::coefficient_series( 1 );
|
|
this->c[0] = T.c[0];
|
|
this->m = IVector( 1 );
|
|
this->m[0] = T.m[0];
|
|
}
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifndef __PCL_NO_CHEBYSHEV_FIT_INSTANTIATE
|
|
|
|
/*!
|
|
* \defgroup chebyshev_fit_types Chebyshev Fit Types
|
|
*/
|
|
|
|
/*!
|
|
* \class pcl::F32ChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 32-bit floating point Chebyshev function approximation.
|
|
*
|
|
* %F32ChebyshevFit is a template instantiation of GenericChebyshevFit for the
|
|
* \c float type.
|
|
*/
|
|
typedef GenericChebyshevFit<float, float> F32ChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::FChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 32-bit floating point Chebyshev function approximation.
|
|
*
|
|
* %FChebyshevFit is an alias for F32ChebyshevFit. It is a template
|
|
* instantiation of GenericChebyshevFit for the \c float type.
|
|
*/
|
|
typedef F32ChebyshevFit FChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::F64ChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 64-bit floating point Chebyshev function approximation.
|
|
*
|
|
* %F64ChebyshevFit is a template instantiation of GenericChebyshevFit for the
|
|
* \c double type.
|
|
*/
|
|
typedef GenericChebyshevFit<double, double> F64ChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::DChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 64-bit floating point Chebyshev function approximation.
|
|
*
|
|
* %DChebyshevFit is an alias for F64ChebyshevFit. It is a template
|
|
* instantiation of GenericChebyshevFit for the \c double type.
|
|
*/
|
|
typedef F64ChebyshevFit DChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::ChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 64-bit floating point Chebyshev function approximation.
|
|
*
|
|
* %ChebyshevFit is an alias for DChebyshevFit. It is a template instantiation
|
|
* of GenericChebyshevFit for the \c double type.
|
|
*/
|
|
typedef DChebyshevFit ChebyshevFit;
|
|
|
|
#ifndef _MSC_VER
|
|
|
|
/*!
|
|
* \class pcl::F80ChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 80-bit extended precision floating point Chebyshev function
|
|
* approximation.
|
|
*
|
|
* %F80ChebyshevFit is a template instantiation of GenericChebyshevFit for the
|
|
* \c long \c double type.
|
|
*
|
|
* \note This template instantiation is not available on Windows with Visual
|
|
* C++ compilers.
|
|
*/
|
|
typedef GenericChebyshevFit<long double, long double> F80ChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::LDChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 80-bit extended precision floating point Chebyshev function
|
|
* approximation.
|
|
*
|
|
* %LDChebyshevFit is an alias for F80ChebyshevFit. It is a template
|
|
* instantiation of GenericChebyshevFit for the \c long \c double type.
|
|
*
|
|
* \note This template instantiation is not available on Windows with Visual
|
|
* C++ compilers.
|
|
*/
|
|
typedef F80ChebyshevFit LDChebyshevFit;
|
|
|
|
#endif // !_MSC_VER
|
|
|
|
/*!
|
|
* \class pcl::F32ScalarChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 32-bit floating point scalar Chebyshev function approximation.
|
|
*
|
|
* %F32ScalarChebyshevFit is a template instantiation of
|
|
* GenericScalarChebyshevFit for the \c float type.
|
|
*/
|
|
typedef GenericScalarChebyshevFit<float, float> F32ScalarChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::FScalarChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 32-bit floating point scalar Chebyshev function approximation.
|
|
*
|
|
* %FScalarChebyshevFit is an alias for F32ScalarChebyshevFit. It is a template
|
|
* instantiation of GenericScalarChebyshevFit for the \c float type.
|
|
*/
|
|
typedef F32ScalarChebyshevFit FScalarChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::F64ScalarChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 64-bit floating point scalar Chebyshev function approximation.
|
|
*
|
|
* %F64ScalarChebyshevFit is a template instantiation of
|
|
* GenericScalarChebyshevFit for the \c double type.
|
|
*/
|
|
typedef GenericScalarChebyshevFit<double, double> F64ScalarChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::DScalarChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 64-bit floating point scalar Chebyshev function approximation.
|
|
*
|
|
* %DScalarChebyshevFit is an alias for F64ScalarChebyshevFit. It is a template
|
|
* instantiation of GenericScalarChebyshevFit for the \c double type.
|
|
*/
|
|
typedef F64ScalarChebyshevFit DScalarChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::ScalarChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 64-bit floating point scalar Chebyshev function approximation.
|
|
*
|
|
* %ScalarChebyshevFit is an alias for DScalarChebyshevFit. It is a template
|
|
* instantiation of GenericScalarChebyshevFit for the \c double type.
|
|
*/
|
|
typedef DScalarChebyshevFit ScalarChebyshevFit;
|
|
|
|
#ifndef _MSC_VER
|
|
|
|
/*!
|
|
* \class pcl::F80ScalarChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 80-bit extended precision floating point scalar Chebyshev function
|
|
* approximation.
|
|
*
|
|
* %F80ScalarChebyshevFit is a template instantiation of
|
|
* GenericScalarChebyshevFit for the \c long \c double type.
|
|
*
|
|
* \note This template instantiation is not available on Windows with Visual
|
|
* C++ compilers.
|
|
*/
|
|
typedef GenericScalarChebyshevFit<long double, long double> F80ScalarChebyshevFit;
|
|
|
|
/*!
|
|
* \class pcl::LDScalarChebyshevFit
|
|
* \ingroup chebyshev_fit_types
|
|
* \brief 80-bit extended precision floating point scalar Chebyshev function
|
|
* approximation.
|
|
*
|
|
* %LDScalarChebyshevFit is an alias for F80ScalarChebyshevFit. It is a
|
|
* template instantiation of GenericScalarChebyshevFit for the \c long
|
|
* \c double type.
|
|
*
|
|
* \note This template instantiation is not available on Windows with Visual
|
|
* C++ compilers.
|
|
*/
|
|
typedef F80ScalarChebyshevFit LDScalarChebyshevFit;
|
|
|
|
#endif // !_MSC_VER
|
|
|
|
#endif // !__PCL_NO_CHEBYSHEV_FIT_INSTANTIATE
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
} // pcl
|
|
|
|
#endif // __PCL_ChebyshevFit_h
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// EOF pcl/ChebyshevFit.h - Released 2022-03-12T18:59:29Z
|