PCL
ChebyshevFit.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.7.0
6 // ----------------------------------------------------------------------------
7 // pcl/ChebyshevFit.h - Released 2024-06-18T15:48:54Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2024 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_ChebyshevFit_h
53 #define __PCL_ChebyshevFit_h
54 
56 
57 #include <pcl/Defs.h>
58 
59 #include <pcl/Constants.h>
60 #include <pcl/ErrorHandler.h>
61 #include <pcl/Exception.h>
62 #include <pcl/MultiVector.h>
63 
64 namespace pcl
65 {
66 
67 // ----------------------------------------------------------------------------
68 
69 template <typename Tx, typename Ty> class GenericScalarChebyshevFit;
70 
100 template <typename Tx, typename Ty>
102 {
103 public:
104 
109 
114 
119 
124 
159  template <class F>
160  GenericChebyshevFit( F f, Tx x1, Tx x2, int N, int n )
161  : dx( Abs( x2 - x1 ) )
162  , x0( (x1 + x2)/2 )
163  , m( Max( 2, n ), Max( 1, N ) )
164  {
165  PCL_PRECONDITION( N > 0 )
166  PCL_PRECONDITION( n > 1 )
167  if ( 1 + dx == 1 )
168  throw Error( "GenericChebyshevFit: Empty or insignificant function evaluation interval." );
169  N = m.Length();
170  n = m[0];
171  Tx dx2 = dx/2;
172  function_values y( n, N );
173  for ( int j = 0; j < n; ++j )
174  y[j] = f( x0 + Cos( Const<Ty>::pi()*(j + 0.5)/n )*dx2 );
175  c = coefficient_series( N, n );
176  Ty k = 2.0/n;
177  for ( int i = 0; i < N; ++i )
178  for ( int j = 0; j < n; ++j )
179  {
180  Ty s = Ty( 0 );
181  for ( int k = 0; k < n; ++k )
182  s += y[k][i] * Cos( Const<Ty>::pi()*j*(k + 0.5)/n );
183  c[i][j] = k*s;
184  }
185  }
186 
200  GenericChebyshevFit( const coefficient_series& ck, Tx x1, Tx x2 )
201  : dx( Abs( x2 - x1 ) )
202  , x0( (x1 + x2)/2 )
203  , c( ck )
204  , m( int( ck.Length() ) )
205  {
206  if ( 1 + dx == 1 )
207  throw Error( "GenericChebyshevFit: Empty or insignificant function evaluation interval." );
208  if ( c.IsEmpty() )
209  throw Error( "GenericChebyshevFit: Empty polynomial expansion." );
210  for ( int i = 0; i < m.Length(); ++i )
211  if ( (m[i] = c[i].Length()) < 1 )
212  throw Error( "GenericChebyshevFit: Invalid coefficient series for dimension " + String( i ) + '.' );
213  }
214 
225  GenericChebyshevFit() = default;
226 
231 
236 
241 
246 
252  bool IsValid() const
253  {
254  return !c.IsEmpty();
255  }
256 
265  Tx LowerBound() const
266  {
267  return x0 - dx/2;
268  }
269 
278  Tx UpperBound() const
279  {
280  return x0 + dx/2;
281  }
282 
288  int NumberOfComponents() const
289  {
290  return m.Length();
291  }
292 
301  int Length( int i = 0 ) const
302  {
303  PCL_PRECONDITION( i >= 0 && i < NumberOfComponents() )
304  return c[i].Length();
305  }
306 
316  int TruncatedLength( int i = -1 ) const
317  {
318  PCL_PRECONDITION( i < 0 || i < NumberOfComponents() )
319  if ( i < 0 )
320  return m.MaxComponent();
321  return m[i];
322  }
323 
331  {
332  int N = 0;
333  for ( int i = 0; i < NumberOfComponents(); ++i )
334  N += c[i].Length();
335  return N;
336  }
337 
346  {
347  return m.Sum();
348  }
349 
359  bool IsTruncated( int i = -1 ) const
360  {
361  PCL_PRECONDITION( i < 0 || i < NumberOfComponents() )
362  if ( i < 0 )
363  return m.MaxComponent() < Length();
364  return m[i] < c[i].Length();
365  }
366 
377  Ty TruncationError( int i = -1 ) const
378  {
379  PCL_PRECONDITION( i < 0 || i < NumberOfComponents() )
380  if ( i < 0 )
381  {
382  int N = NumberOfComponents();
383  function_value e( N );
384  for ( int j = 0; j < N; ++j )
385  e[j] = TruncationError( j );
386  return e.MaxComponent();
387  }
388  if ( m[i] < c[i].Length() )
389  {
390  Ty e = Ty( 0 );
391  for ( int j = c[i].Length(); --j >= m[i]; )
392  e += Abs( c[i][j] );
393  return e;
394  }
395  return Abs( c[i][c[i].Length()-1] );
396  }
397 
436  bool Truncate( Ty e, int mmin = 2 )
437  {
438  e = Abs( e );
439  mmin = Max( 2, mmin );
440  int N = NumberOfComponents();
441  int tc = 0;
442  for ( int i = 0; i < N; ++i )
443  {
444  Ty s = Ty( 0 );
445  for ( m[i] = c[i].Length(); m[i] > mmin; --m[i] )
446  if ( (s += Abs( c[i][m[i]-1] )) >= e )
447  break;
448  if ( m[i] < c[i].Length() )
449  ++tc;
450  }
451  return tc == N;
452  }
453 
467  bool Truncate( const coefficients& eps, int mmin = 2 )
468  {
469  mmin = Max( 2, mmin );
470  int N = NumberOfComponents();
471  int tc = 0;
472  for ( int i = 0; i < N; ++i )
473  {
474  Ty e = Abs( eps[i] );
475  Ty s = Ty( 0 );
476  for ( m[i] = c[i].Length(); m[i] > mmin; --m[i] )
477  if ( (s += Abs( c[i][m[i]-1] )) >= e )
478  break;
479  if ( m[i] < c[i].Length() )
480  ++tc;
481  }
482  return tc == N;
483  }
484 
490  {
491  return c;
492  }
493 
512  function_value Evaluate( Tx x ) const
513  {
514  PCL_PRECONDITION( x >= LowerBound() )
515  PCL_PRECONDITION( x <= UpperBound() )
516  const Ty y0 = Ty( 2*(x - x0)/dx );
517  const Ty y2 = 2*y0;
519  for ( int i = 0; i < y.Length(); ++i )
520  {
521  Ty d0 = Ty( 0 );
522  Ty d1 = Ty( 0 );
523  const Ty* k = c[i].At( m[i] );
524  for ( int j = m[i]; --j > 0; )
525  {
526  Ty d = d1;
527  d1 = y2*d1 - d0 + *--k;
528  d0 = d;
529  }
530  y[i] = y0*d1 - d0 + *--k/2;
531  }
532  return y;
533  }
534 
539  {
540  return Evaluate( x );
541  }
542 
558  {
559  int N = NumberOfComponents();
561  ch1.dx = dx;
562  ch1.x0 = x0;
563  ch1.c = coefficient_series( N );
564  ch1.m = IVector( N );
565  for ( int i = 0; i < N; ++i )
566  {
567  int n = Max( 1, c[i].Length()-1 );
568  ch1.c[i] = coefficients( n );
569  ch1.m[i] = n;
570  if ( n > 1 )
571  {
572  ch1.c[i][n-1] = 2*n*c[i][n];
573  ch1.c[i][n-2] = 2*(n-1)*c[i][n-1];
574  for ( int j = n-3; j >= 0; --j )
575  ch1.c[i][j] = ch1.c[i][j+2] + 2*(j+1)*c[i][j+1];
576  ch1.c[i] *= Ty( 2 )/dx;
577  }
578  else
579  ch1.c[i] = Ty( 0 );
580  }
581  return ch1;
582  }
583 
600  {
601  int N = NumberOfComponents();
603  ch.dx = dx;
604  ch.x0 = x0;
605  ch.c = coefficient_series( N );
606  ch.m = IVector( N );
607  for ( int i = 0; i < N; ++i )
608  {
609  int n = c[i].Length();
610  ch.c[i] = coefficients( n );
611  ch.m[i] = n;
612  if ( n > 1 )
613  {
614  const Ty k = Ty( dx )/4;
615  Ty s = Ty( 0 );
616  int f = 1;
617  for ( int j = 1; j < n-1; ++j, f = -f )
618  s += f*(ch.c[i][j] = k*(c[i][j-1] - c[i][j+1])/j);
619  ch.c[i][0] = 2*(s + f*(ch.c[i][n-1] = k*c[i][n-2]/(n-1)));
620  }
621  else
622  ch.c[i] = Ty( 0 );
623  }
624  return ch;
625  }
626 
627 private:
628 
629  Tx dx; // x2 - x1
630  Tx x0; // (x1 + x2)/2
631  coefficient_series c; // Chebyshev polynomial coefficients
632  IVector m; // length of the truncated coefficient series
633 
634  friend class GenericScalarChebyshevFit<Tx,Ty>;
635 };
636 
637 // ----------------------------------------------------------------------------
638 
650 template <typename Tx, typename Ty>
652 {
653 public:
654 
662  template <class F>
663  GenericScalarChebyshevFit( F f, Tx x1, Tx x2, int n )
664  : GenericChebyshevFit<Tx,Ty>( [f]( Tx x ){ return GenericVector<Ty>( f( x ), 1 ); }, x1, x2, 1, n )
665  {
666  }
667 
679 
684 
689 
694 
699 
706  int TruncatedLength() const
707  {
709  }
710 
716  bool IsTruncated() const
717  {
719  }
720 
727  Ty TruncationError() const
728  {
730  }
731 
739  Ty Evaluate( Tx x ) const
740  {
742  }
743 
747  Ty operator ()( Tx x ) const
748  {
749  return Evaluate( x );
750  }
751 
761  {
763  }
764 
774  {
776  }
777 
778 private:
779 
785  : GenericChebyshevFit<Tx,Ty>()
786  {
787  this->dx = T.dx;
788  this->x0 = T.x0;
789  this->c = typename GenericChebyshevFit<Tx,Ty>::coefficient_series( 1 );
790  this->c[0] = T.c[0];
791  this->m = IVector( 1 );
792  this->m[0] = T.m[0];
793  }
794 };
795 
796 // ----------------------------------------------------------------------------
797 
798 #ifndef __PCL_NO_CHEBYSHEV_FIT_INSTANTIATE
799 
812 using F32ChebyshevFit = GenericChebyshevFit<float, float>;
813 
823 
832 using F64ChebyshevFit = GenericChebyshevFit<double, double>;
833 
843 
853 
854 #ifndef _MSC_VER
855 
868 using F80ChebyshevFit = GenericChebyshevFit<long double, long double>;
869 
883 
884 #endif // !_MSC_VER
885 
894 using F32ScalarChebyshevFit = GenericScalarChebyshevFit<float, float>;
895 
905 
914 using F64ScalarChebyshevFit = GenericScalarChebyshevFit<double, double>;
915 
925 
935 
936 #ifndef _MSC_VER
937 
950 using F80ScalarChebyshevFit = GenericScalarChebyshevFit<long double, long double>;
951 
966 
967 #endif // !_MSC_VER
968 
969 #endif // !__PCL_NO_CHEBYSHEV_FIT_INSTANTIATE
970 
971 // ----------------------------------------------------------------------------
972 
973 } // pcl
974 
975 #endif // __PCL_ChebyshevFit_h
976 
977 // ----------------------------------------------------------------------------
978 // EOF pcl/ChebyshevFit.h - Released 2024-06-18T15:48:54Z
bool IsEmpty() const noexcept
Definition: Array.h:312
iterator At(size_type i)
Definition: Array.h:355
size_type Length() const noexcept
Definition: Array.h:266
64-bit floating point Chebyshev function approximation.
Fundamental numeric constants.
Definition: Constants.h:73
64-bit floating point Chebyshev function approximation.
64-bit floating point scalar Chebyshev function approximation.
A simple exception with an associated error message.
Definition: Exception.h:239
32-bit floating point Chebyshev function approximation.
32-bit floating point scalar Chebyshev function approximation.
64-bit floating point Chebyshev function approximation.
64-bit floating point scalar Chebyshev function approximation.
80-bit extended precision floating point Chebyshev function approximation.
80-bit extended precision floating point scalar Chebyshev function approximation.
32-bit floating point Chebyshev function approximation.
32-bit floating point scalar Chebyshev function approximation.
Approximation of vector-valued functions by Chebyshev polynomial expansions.
Definition: ChebyshevFit.h:102
int NumberOfCoefficients() const
Definition: ChebyshevFit.h:330
GenericChebyshevFit Integral() const
Definition: ChebyshevFit.h:599
const coefficient_series & Coefficients() const
Definition: ChebyshevFit.h:489
int NumberOfTruncatedCoefficients() const
Definition: ChebyshevFit.h:345
Ty TruncationError(int i=-1) const
Definition: ChebyshevFit.h:377
GenericChebyshevFit Derivative() const
Definition: ChebyshevFit.h:557
GenericChebyshevFit & operator=(const GenericChebyshevFit &)=default
function_value Evaluate(Tx x) const
Definition: ChebyshevFit.h:512
function_value operator()(Tx x) const
Definition: ChebyshevFit.h:538
GenericChebyshevFit(const GenericChebyshevFit &)=default
GenericChebyshevFit(GenericChebyshevFit &&)=default
GenericVector< Ty > coefficients
Definition: ChebyshevFit.h:108
GenericChebyshevFit(const coefficient_series &ck, Tx x1, Tx x2)
Definition: ChebyshevFit.h:200
bool IsTruncated(int i=-1) const
Definition: ChebyshevFit.h:359
GenericMultiVector< Ty > coefficient_series
Definition: ChebyshevFit.h:113
bool Truncate(const coefficients &eps, int mmin=2)
Definition: ChebyshevFit.h:467
int TruncatedLength(int i=-1) const
Definition: ChebyshevFit.h:316
int NumberOfComponents() const
Definition: ChebyshevFit.h:288
int Length(int i=0) const
Definition: ChebyshevFit.h:301
bool Truncate(Ty e, int mmin=2)
Definition: ChebyshevFit.h:436
GenericChebyshevFit(F f, Tx x1, Tx x2, int N, int n)
Definition: ChebyshevFit.h:160
Approximation of scalar-valued functions by Chebyshev polynomial expansion.
Definition: ChebyshevFit.h:652
GenericScalarChebyshevFit Derivative() const
Definition: ChebyshevFit.h:760
GenericScalarChebyshevFit(F f, Tx x1, Tx x2, int n)
Definition: ChebyshevFit.h:663
GenericScalarChebyshevFit & operator=(const GenericScalarChebyshevFit &)=default
GenericScalarChebyshevFit Integral() const
Definition: ChebyshevFit.h:773
GenericScalarChebyshevFit(const GenericScalarChebyshevFit &)=default
GenericScalarChebyshevFit(GenericScalarChebyshevFit &&)=default
Generic vector of arbitrary length.
Definition: Vector.h:107
component MaxComponent() const noexcept
Definition: Vector.h:1157
int Length() const noexcept
Definition: Vector.h:1784
double Sum() const noexcept
Definition: Vector.h:1212
80-bit extended precision floating point Chebyshev function approximation.
80-bit extended precision floating point scalar Chebyshev function approximation.
64-bit floating point scalar Chebyshev function approximation.
Unicode (UTF-16) string.
Definition: String.h:8113
T Abs(const Complex< T > &c) noexcept
Definition: Complex.h:429
Complex< T > Cos(const Complex< T > &c) noexcept
Definition: Complex.h:806
constexpr const T & Max(const T &a, const T &b) noexcept
Definition: Utility.h:119
PCL root namespace.
Definition: AbstractImage.h:77