casacore
Chebyshev.h
Go to the documentation of this file.
1 //# Chebyshev.h A function class that defines a Chebyshev polynomial
2 //# Copyright (C) 2000,2001,2002,2003,2005
3 //# Associated Universities, Inc. Washington DC, USA.
4 //#
5 //# This library is free software; you can redistribute it and/or modify it
6 //# under the terms of the GNU Library General Public License as published by
7 //# the Free Software Foundation; either version 2 of the License, or (at your
8 //# option) any later version.
9 //#
10 //# This library is distributed in the hope that it will be useful, but WITHOUT
11 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 //# License for more details.
14 //#
15 //# You should have received a copy of the GNU Library General Public License
16 //# along with this library; if not, write to the Free Software Foundation,
17 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 //#
19 //# Correspondence concerning AIPS++ should be addressed as follows:
20 //# Internet email: aips2-request@nrao.edu.
21 //# Postal address: AIPS++ Project Office
22 //# National Radio Astronomy Observatory
23 //# 520 Edgemont Road
24 //# Charlottesville, VA 22903-2475 USA
25 //#
26 //#! ========================================================================
27 //# $Id$
28 
29 #ifndef SCIMATH_CHEBYSHEV_H
30 #define SCIMATH_CHEBYSHEV_H
31 
32 #include <casacore/casa/aips.h>
33 #include <casacore/scimath/Functionals/ChebyshevParam.h>
34 #include <casacore/scimath/Functionals/Function1D.h>
35 #include <casacore/scimath/Mathematics/AutoDiff.h>
36 #include <casacore/scimath/Mathematics/AutoDiffMath.h>
37 
38 namespace casacore { //# NAMESPACE CASACORE - BEGIN
39 
40 //# Forward Declarations
41 
42 // <summary> A function class that defines a Chebyshev polynomial
43 // </summary>
44 
45 // <use visibility=export>
46 
47 // <reviewed reviewer="wbrouw" date="2001/11/12" tests="tChebyshev" demos="">
48 // </reviewed>
49 
50 // <prerequisite>
51 // <li> <linkto class=Function>Function</linkto>
52 // </prerequisite>
53 //
54 // <etymology>
55 // This class is named after Chebyshev Type I polynomials
56 // </etymology>
57 //
58 // <synopsis>
59 // This class allows one to form and evaluate a function as a
60 // Chebyshev series, a linear combination of so-called Chebyshev
61 // polynomials.
62 //
63 // This class's implementation is split into two parts:
64 // the parent class <linkto class="ChebyshevParam">ChebyshevParam&lt;T&gt;</linkto>,
65 // which manages the function's parameters, and this class, which handles
66 // how the function is evaluated. Thus, be sure to also consult
67 // <linkto class="ChebyshevParam">ChebyshevParam&lt;T&gt;</linkto> for
68 // the full interface of this function.
69 //
70 // <ANCHOR NAME="Chebyshev:about">
71 // <H3>About Chebyshev Polynomials</H3></ANCHOR>
72 //
73 // Chebyshev polynomials are a special type of ultraspheric polynomials
74 // that are useful in such contexts as numerical analysis and circuit
75 // design. They form an orthogobnal set.
76 // A (type I) Chebyshev polynomial, T_n, is generated via the
77 // equation:
78 // <srcblock>
79 // T_n(x) = cos n(arccos x)
80 // </srcblock>
81 // Through clever use of trigometric identities, one can express T_n
82 // as a real polynomial expression of the form
83 // <srcblock>
84 // n
85 // T_n(x) = SUM C_i t^i
86 // i=0
87 // </srcblock>
88 // The low order polynomials look like this:
89 // <srcblock>
90 // T_0 = 1
91 // T_1 = x
92 // T_2 = 2x^2 - 1
93 // T_3 = 4x^3 - 3x
94 // T_4 = 8x^4 - 8x^2 + 1
95 // T_5 = 16x^5 - 20x^3 + 5x
96 // </srcblock>
97 // Higher order polynomials satisfy the recurrance relation,
98 // <srcblock>
99 // T_(n+1) = 2xT_(n) - T_(n-1).
100 // </srcblock>
101 //
102 // A common use of Chebyshev polynomials is in approximating
103 // functions. In particular, any function that is approximated by
104 // a power series,
105 // <srcblock>
106 // f(x) ~ SUM P_i x^i,
107 // </srcblock>
108 // over the interval [-1, 1] can be approximated by a linear
109 // combination of Chebyshev polynomials:
110 // <srcblock>
111 // f(x) ~ SUM C_i T_i(x),
112 // </srcblock>
113 // where C_i is the set of so-called Chebyshev coefficients.
114 //
115 // Approximating a function with Chebyshev polynomials has some
116 // important advantages. For one, if the function is well approximated
117 // by a converging power series, one can obtain an equally accurate
118 // estimate using fewer terms of the corresponding Chebyshev series.
119 // More important, though, is the property over the interval [-1, 1],
120 // each polynomial has a domain of [-1, 1]; thus, the series is nicely
121 // bounded. And because of this bounded property, approximations
122 // calculated from a Chebyshev series are less susceptible to machine
123 // rounding errors than the equivalent power series.
124 //
125 // <ANCHOR NAME="Chebyshev:using">
126 // <H3>Using the Chebyshev Function class</H3></ANCHOR>
127 //
128 // With a simple change of variable, it is possible to approximate a
129 // continuous function over any restricted interval using a
130 // Chebyshev series. This documention refers to this interval as the
131 // <em>Chebyshev interval</em> (set with the
132 // <linkto class="ChebyshevParam">setInterval()</linkto> function). The
133 // other important input parameters, of course, include the
134 // coefficients of the polynomials.
135 //
136 // Like all Functions, the Chebyshev series is evaluated via the
137 // function operator, <src>operator()</src>. If the input value is
138 // within the range set by
139 // <linkto class="ChebyshevParam">setInterval()</linkto>, it is
140 // transformed to the range [-1, 1] via,
141 // <srcblock>
142 // y = x - (min + max)/2) / ((max - min)/2)
143 // </srcblock>
144 // The series is then evaluated with the coefficients set either at
145 // construction or via setCoefficients(). The value that is returned
146 // when the input value is outside the Chebyshev interval depends on
147 // the out-of-interval mode (set via
148 // <linkto class="ChebyshevParam">setOutOfIntervalMode()</linkto>). The
149 // default mode is to return a default value which can be set via
150 // <linkto class="ChebyshevParam">setDefault()</linkto>. The supported
151 // modes are identified by the
152 // enumeration OutOfIntervalMode; see the
153 // <linkto class="ChebyshevParam">documentation for ChebyshevParam</linkto>
154 // for a detailed description of these modes. In practice, though, it is
155 // expected that this class will be configured for the interval of interest.
156 //
157 // The derivative of a Chebyshev series with respect to the independent
158 // variable (i.e. the argument <src>x</src>) is easily calculated analytically
159 // and can be expressed as another Chebyshev series; this is what the
160 // <src>derivative()</src> function returns. However, the more general way to
161 // obtain derivatives is via the <linkto class="AutoDiff">AutoDiff</linkto>
162 // templated type.
163 //
164 // </synopsis>
165 //
166 // <example>
167 // In this example, a 2nd order Chebyshev polynomial series is
168 // created.
169 // <srcblock>
170 // // set coeffs to desired values
171 // Vector<Double> coeffs(3, 1);
172 //
173 // // configure the function
174 // Chebyshev<Double> cheb;
175 // cheb.setInterval(-0.8, 7.2);
176 // cheb.setDefault(1.0);
177 // cheb.setCoefficients(coeffs);
178 //
179 // // evaluate the function as necessary
180 // Double z = cheb(-0.5); // -0.5 is within range, z = 0.78625
181 // z = cheb(4.2); // 4.2 is within range, z = 0.375
182 // z = cheb(-3); // -3 is out of the interval, z = 1
183 // </srcblock>
184 //
185 // The next example illustrates how to use the
186 // <linkto class="AutoDiff">AutoDiff</linkto> class to simultaneously
187 // calculate derivatives. Here, we replace the Double type with
188 // AutoDiff<Double>.
189 // <srcblock>
190 // Chebyshev<AutoDiffA<Double> > cheb;
191 // cheb.setDefault(AutoDiffA<Double>(1));
192 // cheb.setInterval(AutoDiffA<Double>(-0.8), AutoDiffA<Double>(7.2));
193 //
194 // // we'll track derivatives with respect to x and each of our
195 // // coefficients; for a second-order series, this makes 4
196 // // derivatives total. x will be the first variable; the
197 // // coefficients will the 2nd-4th variables
198 // cheb.setCoefficient(0, AutoDiffA<Double>(3.1, 4, 1)); // c0 = 3.1
199 // cheb.setCoefficient(1, AutoDiffA<Double>(2.4, 4, 2)); // c1 = 2.4
200 // cheb.setCoefficient(2, AutoDiffA<Double>(0.5, 4, 3)); // c2 = 0.5
201 //
202 // // now evaluate the function
203 // AutoDiffA<Double> x(1.2, 4, 0); // x = 1.2
204 // AutoDiffA<Double> y = cheb(x); // y = 1.65
205 // Double dydx = y.derivative(0); // dy/dx = 0.35
206 // Double dydc1 = y.derivative(2); // dy/dc1 = -0.5
207 // </srcblock>
208 // </example>
209 //
210 // <motivation>
211 // This class was created to support systematic errors in the simulator tool.
212 // It can be used by Jones matrix classes to vary gains in a predictable way,
213 // mimicing natural processes of the atmosphere or instrumental effects.
214 // </motivation>
215 
216 // <templating arg=T>
217 // <li> T should have standard numerical operators. Current
218 // implementation only tested for real types (and their AutoDiffs).
219 // </templating>
220 
221 // <thrown>
222 // <li> Assertion in debug mode if attempt is made to address incorrect
223 // coefficients
224 // </thrown>
225 //
226 // <todo asof="2001/08/22">
227 // <li> It would be helpful to be able to convert to and from the
228 // Polynomial<T> type; this would be supported via a function,
229 // Polynomial<T> polynomial(), and constructor,
230 // Chebyshev(Polynomial<T>)
231 // </todo>
232 
233 template<class T>
235 public:
236 
237  //# Constructors
238  // create a zero-th order Chebyshev polynomial with the first coefficient
239  // equal to zero. The bounded domain is [T(-1), T(1)]. The
240  // OutOfDomainMode is CONSTANT, and the default value is T(0).
242 
243  // create an n-th order Chebyshev polynomial with the coefficients
244  // equal to zero. The bounded domain is [T(-1), T(1)]. The
245  // OutOfDomainMode is CONSTANT, and the default value is T(0).
246  explicit Chebyshev(const uInt n) : ChebyshevParamModeImpl<T>(n) {}
247 
248  // create a zero-th order Chebyshev polynomical with the first coefficient
249  // equal to one.
250  // min is the minimum value of its Chebyshev interval, and
251  // max is the maximum value.
252  // mode sets the behavior of the function outside the Chebyshev interval
253  // (see setOutOfIntervalMode() and OutOfIntervalMode enumeration
254  // definition for details).
255  // defval is the value returned when the function is evaluated outside
256  // the Chebyshev interval and mode=CONSTANT.
257  Chebyshev(const T &min, const T &max,
258  const typename ChebyshevEnums::
259  OutOfIntervalMode mode=ChebyshevEnums::CONSTANT,
260  const T &defval=T(0)) :
261  ChebyshevParamModeImpl<T>(min, max, mode, defval) {}
262 
263  // create a fully specified Chebyshev polynomial.
264  // coeffs holds the coefficients of the Chebyshev polynomial (see
265  // setCoefficients() for details).
266  // min is the minimum value of its canonical range, and
267  // max is the maximum value.
268  // mode sets the behavior of the function outside the Chebyshev interval
269  // (see setOutOfIntervalMode() and OutOfIntervalMode enumeration
270  // definition for details).
271  // defval is the value returned when the function is evaluated outside
272  // the canonical range and mode=CONSTANT.
273  Chebyshev(const Vector<T> &coeffs, const T &min, const T &max,
274  const typename ChebyshevEnums::
275  OutOfIntervalMode mode=ChebyshevEnums::CONSTANT,
276  const T &defval=T(0)) :
277  ChebyshevParamModeImpl<T>(coeffs, min, max, mode, defval) {}
278 
279  // create a fully specified Chebyshev polynomial.
280  // config is a record that contains the non-coefficient data
281  // that configures this class.
282  // The fields recognized by this class are those documented for the
283  // <linkto class="ChebyshevParam">ChebyshevPara::setMode()</linkto>
284  // function.
285  // <group>
287  ChebyshevParamModeImpl<T>(order, mode) { }
288  Chebyshev(const Vector<T> &coeffs, const RecordInterface& mode) :
289  ChebyshevParamModeImpl<T>(coeffs, mode) { }
290  // </group>
291 
292  // create a deep copy of another Chebyshev polynomial
293  // <group>
294  Chebyshev(const Chebyshev &other) : ChebyshevParamModeImpl<T>(other) {}
295  // </group>
296 
297  // make this instance a (deep) copy of another Chebyshev polynomial
299  ChebyshevParam<T>::operator=(other); return *this; }
300 
301  // Destructor
302  virtual ~Chebyshev() {}
303 
304  //# Operators
305  // Evaluate the Chebyshev at <src>x</src>.
306  virtual T eval(const typename FunctionTraits<T>::ArgType *x) const;
307 
308  //# Member functions
309  // Return the Chebyshev polynomial which is the derivative of this one
310  // (with respect to the argument <src>x</src>).
312 
313  // Create a new copy of this object. The caller is responsible
314  // for deleting the pointer.
315  // <group>
316  virtual Function<T> *clone() const { return new Chebyshev<T>(*this); }
317  // </group>
318 
319 };
320 
321 
322 } //# NAMESPACE CASACORE - END
323 
324 #ifndef CASACORE_NO_AUTO_TEMPLATES
325 #include <casacore/scimath/Functionals/Chebyshev.tcc>
326 #endif //# CASACORE_NO_AUTO_TEMPLATES
327 #endif
@ CONSTANT
return a constant, default value.
A ChebyshevParam with the get/setMode implementation.
uInt order() const
return the order of this polynomial.
ChebyshevParam< T > & operator=(const ChebyshevParam< T > &other)
make a (deep) copy of another Chebyshev polynomial
Chebyshev< T > derivative() const
Return the Chebyshev polynomial which is the derivative of this one (with respect to the argument x).
Chebyshev()
create a zero-th order Chebyshev polynomial with the first coefficient equal to zero.
Definition: Chebyshev.h:241
Chebyshev(const uInt n)
create an n-th order Chebyshev polynomial with the coefficients equal to zero.
Definition: Chebyshev.h:246
virtual ~Chebyshev()
Destructor.
Definition: Chebyshev.h:302
Chebyshev(const T &min, const T &max, const typename ChebyshevEnums::OutOfIntervalMode mode=ChebyshevEnums::CONSTANT, const T &defval=T(0))
create a zero-th order Chebyshev polynomical with the first coefficient equal to one.
Definition: Chebyshev.h:257
Chebyshev< T > & operator=(const Chebyshev< T > &other)
make this instance a (deep) copy of another Chebyshev polynomial
Definition: Chebyshev.h:298
Chebyshev(const Vector< T > &coeffs, const RecordInterface &mode)
Definition: Chebyshev.h:288
Chebyshev(const Vector< T > &coeffs, const T &min, const T &max, const typename ChebyshevEnums::OutOfIntervalMode mode=ChebyshevEnums::CONSTANT, const T &defval=T(0))
create a fully specified Chebyshev polynomial.
Definition: Chebyshev.h:273
Chebyshev(const Chebyshev &other)
create a deep copy of another Chebyshev polynomial
Definition: Chebyshev.h:294
virtual Function< T > * clone() const
Create a new copy of this object.
Definition: Chebyshev.h:316
virtual T eval(const typename FunctionTraits< T >::ArgType *x) const
Evaluate the Chebyshev at x.
Chebyshev(uInt order, const RecordInterface &mode)
create a fully specified Chebyshev polynomial.
Definition: Chebyshev.h:286
T ArgType
Type for arguments.
this file contains all the compiler specific defines
Definition: mainpage.dox:28
LatticeExprNode max(const LatticeExprNode &left, const LatticeExprNode &right)
unsigned int uInt
Definition: aipstype.h:51
LatticeExprNode min(const LatticeExprNode &left, const LatticeExprNode &right)