casa
$Rev:20696$
|
00001 //# Chebyshev.h A function class that defines a Chebyshev polynomial 00002 //# Copyright (C) 2000,2001,2002,2003,2005 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //#! ======================================================================== 00027 //# $Id: Chebyshev.h 21024 2011-03-01 11:46:18Z gervandiepen $ 00028 00029 #ifndef SCIMATH_CHEBYSHEV_H 00030 #define SCIMATH_CHEBYSHEV_H 00031 00032 #include <casa/aips.h> 00033 #include <scimath/Functionals/ChebyshevParam.h> 00034 #include <scimath/Functionals/Function1D.h> 00035 #include <scimath/Mathematics/AutoDiff.h> 00036 #include <scimath/Mathematics/AutoDiffMath.h> 00037 00038 namespace casa { //# NAMESPACE CASA - BEGIN 00039 00040 //# Forward Declarations 00041 00042 // <summary> A function class that defines a Chebyshev polynomial 00043 // </summary> 00044 00045 // <use visibility=export> 00046 00047 // <reviewed reviewer="wbrouw" date="2001/11/12" tests="tChebyshev" demos=""> 00048 // </reviewed> 00049 00050 // <prerequisite> 00051 // <li> <linkto class=Function>Function</linkto> 00052 // </prerequisite> 00053 // 00054 // <etymology> 00055 // This class is named after Chebyshev Type I polynomials 00056 // </etymology> 00057 // 00058 // <synopsis> 00059 // This class allows one to form and evaluate a function as a 00060 // Chebyshev series, a linear combination of so-called Chebyshev 00061 // polynomials. 00062 // 00063 // This class's implementation is split into two parts: 00064 // the parent class <linkto class="ChebyshevParam">ChebyshevParam<T></linkto>, 00065 // which manages the function's parameters, and this class, which handles 00066 // how the function is evaluated. Thus, be sure to also consult 00067 // <linkto class="ChebyshevParam">ChebyshevParam<T></linkto> for 00068 // the full interface of this function. 00069 // 00070 // <ANCHOR NAME="Chebyshev:about"> 00071 // <H3>About Chebyshev Polynomials</H3></ANCHOR> 00072 // 00073 // Chebyshev polynomials are a special type of ultraspheric polynomials 00074 // that are useful in such contexts as numerical analysis and circuit 00075 // design. They form an orthogobnal set. 00076 // A (type I) Chebyshev polynomial, T_n, is generated via the 00077 // equation: 00078 // <srcblock> 00079 // T_n(x) = cos n(arccos x) 00080 // </srcblock> 00081 // Through clever use of trigometric identities, one can express T_n 00082 // as a real polynomial expression of the form 00083 // <srcblock> 00084 // n 00085 // T_n(x) = SUM C_i t^i 00086 // i=0 00087 // </srcblock> 00088 // The low order polynomials look like this: 00089 // <srcblock> 00090 // T_0 = 1 00091 // T_1 = x 00092 // T_2 = 2x^2 - 1 00093 // T_3 = 4x^3 - 3x 00094 // T_4 = 8x^4 - 8x^2 + 1 00095 // T_5 = 16x^5 - 20x^3 + 5x 00096 // </srcblock> 00097 // Higher order polynomials satisfy the recurrance relation, 00098 // <srcblock> 00099 // T_(n+1) = 2xT_(n) - T_(n-1). 00100 // </srcblock> 00101 // 00102 // A common use of Chebyshev polynomials is in approximating 00103 // functions. In particular, any function that is approximated by 00104 // a power series, 00105 // <srcblock> 00106 // f(x) ~ SUM P_i x^i, 00107 // </srcblock> 00108 // over the interval [-1, 1] can be approximated by a linear 00109 // combination of Chebyshev polynomials: 00110 // <srcblock> 00111 // f(x) ~ SUM C_i T_i(x), 00112 // </srcblock> 00113 // where C_i is the set of so-called Chebyshev coefficients. 00114 // 00115 // Approximating a function with Chebyshev polynomials has some 00116 // important advantages. For one, if the function is well approximated 00117 // by a converging power series, one can obtain an equally accurate 00118 // estimate using fewer terms of the corresponding Chebyshev series. 00119 // More important, though, is the property over the interval [-1, 1], 00120 // each polynomial has a domain of [-1, 1]; thus, the series is nicely 00121 // bounded. And because of this bounded property, approximations 00122 // calculated from a Chebyshev series are less susceptible to machine 00123 // rounding errors than the equivalent power series. 00124 // 00125 // <ANCHOR NAME="Chebyshev:using"> 00126 // <H3>Using the Chebyshev Function class</H3></ANCHOR> 00127 // 00128 // With a simple change of variable, it is possible to approximate a 00129 // continuous function over any restricted interval using a 00130 // Chebyshev series. This documention refers to this interval as the 00131 // <em>Chebyshev interval</em> (set with the 00132 // <linkto class="ChebyshevParam">setInterval()</linkto> function). The 00133 // other important input parameters, of course, include the 00134 // coefficients of the polynomials. 00135 // 00136 // Like all Functions, the Chebyshev series is evaluated via the 00137 // function operator, <src>operator()</src>. If the input value is 00138 // within the range set by 00139 // <linkto class="ChebyshevParam">setInterval()</linkto>, it is 00140 // transformed to the range [-1, 1] via, 00141 // <srcblock> 00142 // y = x - (min + max)/2) / ((max - min)/2) 00143 // </srcblock> 00144 // The series is then evaluated with the coefficients set either at 00145 // construction or via setCoefficients(). The value that is returned 00146 // when the input value is outside the Chebyshev interval depends on 00147 // the out-of-interval mode (set via 00148 // <linkto class="ChebyshevParam">setOutOfIntervalMode()</linkto>). The 00149 // default mode is to return a default value which can be set via 00150 // <linkto class="ChebyshevParam">setDefault()</linkto>. The supported 00151 // modes are identified by the 00152 // enumeration OutOfIntervalMode; see the 00153 // <linkto class="ChebyshevParam">documentation for ChebyshevParam</linkto> 00154 // for a detailed description of these modes. In practice, though, it is 00155 // expected that this class will be configured for the interval of interest. 00156 // 00157 // The derivative of a Chebyshev series with respect to the independent 00158 // variable (i.e. the argument <src>x</src>) is easily calculated analytically 00159 // and can be expressed as another Chebyshev series; this is what the 00160 // <src>derivative()</src> function returns. However, the more general way to 00161 // obtain derivatives is via the <linkto class="AutoDiff">AutoDiff</linkto> 00162 // templated type. 00163 // 00164 // </synopsis> 00165 // 00166 // <example> 00167 // In this example, a 2nd order Chebyshev polynomial series is 00168 // created. 00169 // <srcblock> 00170 // // set coeffs to desired values 00171 // Vector<Double> coeffs(3, 1); 00172 // 00173 // // configure the function 00174 // Chebyshev<Double> cheb; 00175 // cheb.setInterval(-0.8, 7.2); 00176 // cheb.setDefault(1.0); 00177 // cheb.setCoefficients(coeffs); 00178 // 00179 // // evaluate the function as necessary 00180 // Double z = cheb(-0.5); // -0.5 is within range, z = 0.78625 00181 // z = cheb(4.2); // 4.2 is within range, z = 0.375 00182 // z = cheb(-3); // -3 is out of the interval, z = 1 00183 // </srcblock> 00184 // 00185 // The next example illustrates how to use the 00186 // <linkto class="AutoDiff">AutoDiff</linkto> class to simultaneously 00187 // calculate derivatives. Here, we replace the Double type with 00188 // AutoDiff<Double>. 00189 // <srcblock> 00190 // Chebyshev<AutoDiffA<Double> > cheb; 00191 // cheb.setDefault(AutoDiffA<Double>(1)); 00192 // cheb.setInterval(AutoDiffA<Double>(-0.8), AutoDiffA<Double>(7.2)); 00193 // 00194 // // we'll track derivatives with respect to x and each of our 00195 // // coefficients; for a second-order series, this makes 4 00196 // // derivatives total. x will be the first variable; the 00197 // // coefficients will the 2nd-4th variables 00198 // cheb.setCoefficient(0, AutoDiffA<Double>(3.1, 4, 1)); // c0 = 3.1 00199 // cheb.setCoefficient(1, AutoDiffA<Double>(2.4, 4, 2)); // c1 = 2.4 00200 // cheb.setCoefficient(2, AutoDiffA<Double>(0.5, 4, 3)); // c2 = 0.5 00201 // 00202 // // now evaluate the function 00203 // AutoDiffA<Double> x(1.2, 4, 0); // x = 1.2 00204 // AutoDiffA<Double> y = cheb(x); // y = 1.65 00205 // Double dydx = y.derivative(0); // dy/dx = 0.35 00206 // Double dydc1 = y.derivative(2); // dy/dc1 = -0.5 00207 // </srcblock> 00208 // </example> 00209 // 00210 // <motivation> 00211 // This class was created to support systematic errors in the simulator tool. 00212 // It can be used by Jones matrix classes to vary gains in a predictable way, 00213 // mimicing natural processes of the atmosphere or instrumental effects. 00214 // </motivation> 00215 00216 // <templating arg=T> 00217 // <li> T should have standard numerical operators. Current 00218 // implementation only tested for real types (and their AutoDiffs). 00219 // </templating> 00220 00221 // <thrown> 00222 // <li> Assertion in debug mode if attempt is made to address incorrect 00223 // coefficients 00224 // </thrown> 00225 // 00226 // <todo asof="2001/08/22"> 00227 // <li> It would be helpful to be able to convert to and from the 00228 // Polynomial<T> type; this would be supported via a function, 00229 // Polynomial<T> polynomial(), and constructor, 00230 // Chebyshev(Polynomial<T>) 00231 // </todo> 00232 00233 template<class T> 00234 class Chebyshev : public ChebyshevParamModeImpl<T> { 00235 public: 00236 00237 //# Constructors 00238 // create a zero-th order Chebyshev polynomial with the first coefficient 00239 // equal to zero. The bounded domain is [T(-1), T(1)]. The 00240 // OutOfDomainMode is CONSTANT, and the default value is T(0). 00241 Chebyshev() : ChebyshevParamModeImpl<T>() {} 00242 00243 // create an n-th order Chebyshev polynomial with the coefficients 00244 // equal to zero. The bounded domain is [T(-1), T(1)]. The 00245 // OutOfDomainMode is CONSTANT, and the default value is T(0). 00246 explicit Chebyshev(const uInt n) : ChebyshevParamModeImpl<T>(n) {} 00247 00248 // create a zero-th order Chebyshev polynomical with the first coefficient 00249 // equal to one. 00250 // min is the minimum value of its Chebyshev interval, and 00251 // max is the maximum value. 00252 // mode sets the behavior of the function outside the Chebyshev interval 00253 // (see setOutOfIntervalMode() and OutOfIntervalMode enumeration 00254 // definition for details). 00255 // defval is the value returned when the function is evaluated outside 00256 // the Chebyshev interval and mode=CONSTANT. 00257 Chebyshev(const T &min, const T &max, 00258 const typename ChebyshevEnums:: 00259 OutOfIntervalMode mode=ChebyshevEnums::CONSTANT, 00260 const T &defval=T(0)) : 00261 ChebyshevParamModeImpl<T>(min, max, mode, defval) {} 00262 00263 // create a fully specified Chebyshev polynomial. 00264 // coeffs holds the coefficients of the Chebyshev polynomial (see 00265 // setCoefficients() for details). 00266 // min is the minimum value of its canonical range, and 00267 // max is the maximum value. 00268 // mode sets the behavior of the function outside the Chebyshev interval 00269 // (see setOutOfIntervalMode() and OutOfIntervalMode enumeration 00270 // definition for details). 00271 // defval is the value returned when the function is evaluated outside 00272 // the canonical range and mode=CONSTANT. 00273 Chebyshev(const Vector<T> &coeffs, const T &min, const T &max, 00274 const typename ChebyshevEnums:: 00275 OutOfIntervalMode mode=ChebyshevEnums::CONSTANT, 00276 const T &defval=T(0)) : 00277 ChebyshevParamModeImpl<T>(coeffs, min, max, mode, defval) {} 00278 00279 // create a fully specified Chebyshev polynomial. 00280 // config is a record that contains the non-coefficient data 00281 // that configures this class. 00282 // The fields recognized by this class are those documented for the 00283 // <linkto class="ChebyshevParam">ChebyshevPara::setMode()</linkto> 00284 // function. 00285 // <group> 00286 Chebyshev(uInt order, const RecordInterface& mode) : 00287 ChebyshevParamModeImpl<T>(order, mode) { } 00288 Chebyshev(const Vector<T> &coeffs, const RecordInterface& mode) : 00289 ChebyshevParamModeImpl<T>(coeffs, mode) { } 00290 // </group> 00291 00292 // create a deep copy of another Chebyshev polynomial 00293 // <group> 00294 Chebyshev(const Chebyshev &other) : ChebyshevParamModeImpl<T>(other) {} 00295 // </group> 00296 00297 // make this instance a (deep) copy of another Chebyshev polynomial 00298 Chebyshev<T> &operator=(const Chebyshev<T> &other) { 00299 ChebyshevParam<T>::operator=(other); return *this; } 00300 00301 // Destructor 00302 virtual ~Chebyshev() {} 00303 00304 //# Operators 00305 // Evaluate the Chebyshev at <src>x</src>. 00306 virtual T eval(const typename FunctionTraits<T>::ArgType *x) const; 00307 00308 //# Member functions 00309 // Return the Chebyshev polynomial which is the derivative of this one 00310 // (with respect to the argument <src>x</src>). 00311 Chebyshev<T> derivative() const; 00312 00313 // Create a new copy of this object. The caller is responsible 00314 // for deleting the pointer. 00315 // <group> 00316 virtual Function<T> *clone() const { return new Chebyshev<T>(*this); } 00317 // </group> 00318 00319 }; 00320 00321 00322 } //# NAMESPACE CASA - END 00323 00324 #ifndef CASACORE_NO_AUTO_TEMPLATES 00325 #include <scimath/Functionals/Chebyshev.tcc> 00326 #endif //# CASACORE_NO_AUTO_TEMPLATES 00327 #endif