00001 //# Functionals.h: A module that represents various function-like classes. 00002 //# Copyright (C) 1995,1996,1998,1999,2001,2002 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 //# $Id$ 00027 00028 00029 #ifndef SCIMATH_FUNCTIONALS_H 00030 #define SCIMATH_FUNCTIONALS_H 00031 00032 //# Base classes 00033 #include <casacore/casa/aips.h> 00034 #include <casacore/casa/BasicMath/Functional.h> 00035 #include <casacore/scimath/Functionals/FunctionTraits.h> 00036 #include <casacore/scimath/Functionals/FunctionParam.h> 00037 #include <casacore/scimath/Functionals/Function.h> 00038 #include <casacore/scimath/Functionals/Function1D.h> 00039 00040 //# Combination methods 00041 #include <casacore/scimath/Functionals/FunctionWrapper.h> 00042 #include <casacore/scimath/Functionals/CombiFunction.h> 00043 #include <casacore/scimath/Functionals/CompoundFunction.h> 00044 00045 //# remainder will be removed 00046 #include <casacore/scimath/Functionals/SampledFunctional.h> 00047 00048 //# 1-D Functions 00049 #include <casacore/scimath/Functionals/Interpolate1D.h> 00050 #include <casacore/scimath/Functionals/ArraySampledFunctional.h> 00051 #include <casacore/scimath/Functionals/ScalarSampledFunctional.h> 00052 00053 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00054 00055 // <module> 00056 // 00057 // <summary>A module that represents various function-like classes.</summary> 00058 00059 // <reviewed reviewer="tcornwel" date="1996/02/13" demos=""></reviewed> 00060 00061 // <etymology> 00062 // The term <src>Functional</src> was chosen to roughly follow the usage in 00063 // Barton and Nackman's <em>Scientific and Engineering C++</em>. 00064 // Functional classes map a Domain object into a Range object, rather like a 00065 // mathematical <src>function</src>. They use <src>operator()</src>, 00066 // so they look much like single argument C++ <src>functions</src>. 00067 // </etymology> 00068 // 00069 // <synopsis> 00070 // <src>Functionals</src> and their derived classes map an input 00071 // <src>Domain</src> object into an output <src>Range</src> object using the 00072 // <src>operator()</src>. 00073 // Often the input and output types are numeric, but it can be of any type. 00074 // <srcblock> 00075 // class Offspring : public Functional<List<Parents>, List<Children> > { 00076 // public: 00077 // List<Children> operator()(List<Parents>); 00078 // }; 00079 // </srcblock> 00080 // would be a legal Functional. 00081 // 00082 // The <src>Functions</src> and their derived classes map, again using the 00083 // <src>operator()</src>, numeric value(s) into a numeric value. Since they are 00084 // numeric, the <src>Domain</src> and <src>Range</src> base type can be of type 00085 // <src>AutoDiff<T></src> (where <src>T</src> is numeric base type) or one 00086 // of its derivations, in which case the value and its derivatives will be 00087 // calculated. 00088 // 00089 // <note role=warning> In the current version the <src>Domain</src> and 00090 // <src>Range</src> are the same for Functions </note> 00091 // 00092 // The basic classes are: 00093 // <dl> 00094 // <dt> <linkto class=Functional><src>Functional<Domain, Range></src></linkto> 00095 // <dd> 00096 // A base class that maps a <src>Domain</src> object into a <src>Range</src> 00097 // object using the <src>Range operator(const Domain &)</src>. All 00098 // information necessary to convert the <src>Domain</src> into a 00099 // <src>Range</src> will be available in the class 00100 // or in the input information. No variable class state (<em>parameters</em>) 00101 // are available. 00102 // 00103 // <dt> <linkto class=FunctionParam><src>FunctionParam<T></src></linkto> 00104 // <dd> A helper base class that acts as a container for <em>parameters</em> 00105 // (<em>state</em>) used in <src>Function</src> classes. The class contains 00106 // a list of parameters, and a list of flags associated with the parameters. 00107 // Methods to set and obtain the parameters (using <src>operator[]</src>) 00108 // and their flags (using methods <src>mask()</src>) are available. The flags 00109 // can e.g. be used to indicate to <src>Fitting</src> routines if a certain 00110 // parameter has to be updated ('fitted') or not. 00111 // <note role=tip> 00112 // The FunctionParam class does not assume anything about the uses of the 00113 // class, but leaves that to the final users. This means that a lot of 00114 // copying between intermediate and final users is not necessary 00115 // (like between a Gaussian fitter with fixed parameters 00116 // and the Fitting routines: the Gaussian fitter just sets a flag to False, and 00117 // let the Fitting worry about what to do internally). 00118 // </note> 00119 // 00120 // <dt> <linkto class=Function><src>Function<T></src></linkto> 00121 // <dd> Base class for function objects with zero or more parameters (i.e. 00122 // Functionals with state). 00123 // All parameters should be of the same type <em>T</em> as the <src> 00124 // Function<T></src>. <src>Function</src> objects are specifically geared 00125 // towards use in the <linkto module=Fitting>Fitting</linkto> classes, but 00126 // can be used anywhere where the value (and/or derivatives) of functions 00127 // are needed. 00128 // 00129 // The <src>Function<T></src> class is derived from <src>Functional</src> 00130 // and contains a <src>FunctionParam<T></src> object. 00131 // The parameters act as state for the function 00132 // (e.g. a width for a Gaussian). A function object is called using the 00133 // <src>T operator(const T&)</src> (<em>ndim=1</em>), or the 00134 // <src>T operator(const Vector<T>&)</src> (all values of <em>ndim</em>), or 00135 // <src>T operator(const T&, const T&)</src> (for <em>ndim=2</em> only). 00136 // If the template argument is <src>AutoDiff<T></src>, the parameters and the 00137 // returned value will be <src>AutoDiff<T></src>; the arguments of the 00138 // <src>operator()</src> will be of type <src>T</src>. The returned value 00139 // of the function will be the function value at <em>x</em> (and the 00140 // derivatives w.r.t. the non-masked parameters) Using <src>AutoDiffA<T></src> 00141 // the derivatives can be calculated w.r.t. parameters and/or arguments, see 00142 // <linkto class=AutoDiff>AutoDiff</linkto> and <linkto class=FunctionTraits> 00143 // FunctionTraits</linkto> for details. 00144 // 00145 // <note role=tip> 00146 // A <src>Function1D</src> is provided for 1-dimensional function objects 00147 // </note> 00148 // </dl> 00149 // 00150 // Actual functional classes: 00151 // <dl> 00152 // <dt> e.g. <linkto 00153 // class=Gaussian1D><src>Gaussian1D<T></src></linkto> 00154 // <dd> An actual function object will be derived from 00155 // <src>Function<T></src>. The minimum functionality of a Function 00156 // object will be support for the <src>operator()</src> methods (through a 00157 // single, hidden, <src>eval()</src> method); for the manipulation of the 00158 // associated parameters (using <src>operator[index]</src> and 00159 // <src>mask(index)</src>) and some administrative aids (<src>ndim()</src>, 00160 // <src>nparameters()</src> and the like. 00161 // 00162 // In most cases it is advantageous to have a special parameter handling 00163 // class (e.g. <src>Gaussian1DParam</src>), to separate the (template 00164 // independent) parameter handling from the possible specialization of 00165 // the <src>eval()</src> method, and to more easily incorporate 00166 // special parameter handling (e.g. using <em>flux</em> rather than amplitude 00167 // of a Gaussian). All of this is transparent to the end-user. 00168 // </dl> 00169 // Combinatory Function objects are provided to easily combine and create 00170 // function objects: 00171 // <dl> 00172 // <dt> <linkto class=CompoundFunction>CompoundFunction</linkto> 00173 // <dd> creates 00174 // a new, compound, function object from one or more other function objects 00175 // (including compounds...). The new function will have the sum of the 00176 // parameters of the input functions as the new parameters (i.e the compound 00177 // function created from a 1-dimensional Gaussian (with 3 parameters) and a 00178 // third-order polynomial (with 4 parameters) will have 7 parameters). 00179 // <dt> <linkto class=CombiFunction>CombiFunction</linkto> 00180 // <dd> creates 00181 // a (linear) combination of a number of input functions. The number of 00182 // parameters of the newly created function will be equal to the number of 00183 // input functions (i.e. the combi 00184 // function created from a 1-dimensional Gaussian (with 3 parameters) and a 00185 // third-order polynomial (with 4 parameters) will have 2 parameters). The 00186 // function will be <src>param0*gauss(x) + param1*poly(x)</src> 00187 // <dt> <linkto class=FunctionWrapper>FunctionWrapper</linkto> 00188 // <dd> will take 00189 // a global function (or by the use of the <em>STL</em> function adapters 00190 // <src>mem_fun*</src> also member functions) of any dimension, and with 00191 // any number of parameters. The function is assumed to be called as 00192 // <src>f(x, p)</src>, and is wrapped like 00193 // <src>FunctionWrapper(&func, param&, ndim)</src> (see example). 00194 // 00195 // </dl> 00196 // 00197 // </synopsis> 00198 00199 // <example> 00200 // A function to find a bracketed root by bisection could be written 00201 // as follows: 00202 // <srcblock> 00203 // template <class Domain, class Range> 00204 // Domain findRoot(const Functional<Domain,Range> &func, Domain left, 00205 // Domain right, Domain tol) { 00206 // Range fr = func(right); 00207 // Range fl = func(left); 00208 // Range sign = fr > 0 ? 1 : -1 ; 00209 // AlwaysAssertExit(fl*fr < 0.0 && right > left); 00210 // while (right - left > tol) { 00211 // Domain mid = (left + right) / 2; 00212 // Range fmid = func(mid); 00213 // if (sign*fmid > 0.0) right = mid; 00214 // else left = mid; 00215 // }; 00216 // return (left + right)/2; 00217 // } 00218 // </srcblock> 00219 // Since Function1D is derived from Functional, the 00220 // above function will also work with classes derived from Function1D. To 00221 // behave sensibly, the Domain and Range types should be real, <em>i.e.</em>, 00222 // Float or Double. 00223 // 00224 // To calculate the value of a polynomial 00225 // <srcblock>2 + 4x<sup>2</sup> + 6x<sup>4</sup></srcblock> 00226 // at <src>x=5.1</src>: 00227 // <srcblock> 00228 // Polynomial<Double> pol(4); 00229 // pol[0] = 2; pol[2] = 4; pol[4] = 6; 00230 // cout << "Polynomial value at 5.1: " << pol(5.1) << endl; 00231 // </srcblock> 00232 // 00233 // Create a simple function (1-dimensional) with 2 parameters (A and B): 00234 // <srcblock> 00235 // Double myf(const Double x, const Vector<Double> p) { 00236 // return p[0]*sin(p[1]*x); } 00237 // </srcblock> 00238 // make it into a function object for initial parameters 2 and pi: 00239 // <srcblock> 00240 // Vector<Double> p(2); 00241 // p[0] = 2; p[1] = C::pi; 00242 // FunctionWrapper<Double> f0(myf, p, 2); 00243 // </srcblock> 00244 // Make the first parameter 3: 00245 // <srcblock> 00246 // f0[0] = 3; 00247 // </srcblock> 00248 // (for the global function you have to change <src>p[0]</src>). 00249 // Calculate the value of the function: 00250 // <srcblock> 00251 // cout << "The value " << f0(3) << " should be 1.5 times the value " << 00252 // myf(3) << endl; 00253 // </srcblock> 00254 // A function object could be created as: 00255 // <srcblock> 00256 // template<class T> class objf : public Function<T> { 00257 // public: 00258 // objf() : Function<T>(2) {}; // 2 parameters 00259 // objf(const objf<T> &other) : Function<T>(other) {}; 00260 // virtual ~objf() {}; 00261 // // The actual method called for the evaluation operator(): 00262 // virtual T eval(typename Function<T>::FunctionArg x) const { 00263 // return param_p[0] * sin(param_p[1] * x[0]); }; 00264 // // Return a copy of function (used for combination e.g.) 00265 // virtual Function<T> *clone() const { 00266 // return new objf<T>(*this); }; 00267 // }; 00268 // </srcblock> 00269 // Which can be called as: 00270 // <srcblock> 00271 // objf<Double> f1; 00272 // f1[0] = 2; f1[1] = C::pi; 00273 // cout << "The value " << myf(3) << " should be equal to the value " << 00274 // f1(3) << endl; 00275 // </srcblock> 00276 // </example> 00277 00278 // <motivation> 00279 // The immediate motivations for this module were: 00280 // <ol> 00281 // <li> To represent functions which are used in linear and non-linear least 00282 // squares fitting 00283 // </ol> 00284 // </motivation> 00285 00286 // <todo asof="2001/12/30"> 00287 // <li> It could be convenient to have a letter/envelope class, and to 00288 // define ``function arithmetic.'' 00289 // </todo> 00290 00291 // </module> 00292 00293 00294 } //# NAMESPACE CASACORE - END 00295 00296 #endif 00297