casacore
Loading...
Searching...
No Matches
Function.h
Go to the documentation of this file.
1// # Function.h: Numerical functional interface class
2// # Copyright (C) 2001,2002,2003,2004,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: casa-feedback@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#ifndef SCIMATH_FUNCTION_H
27#define SCIMATH_FUNCTION_H
28
29// # Includes
30#include <casacore/casa/aips.h>
31#include <casacore/casa/Arrays/Vector.h>
32#include <casacore/casa/BasicMath/Functional.h>
33#include <casacore/casa/Utilities/Assert.h>
34#include <casacore/scimath/Functionals/FunctionParam.h>
35#include <casacore/scimath/Functionals/FunctionTraits.h>
36
37// # Forward declarations
38#include <casacore/casa/iosfwd.h>
39
40namespace casacore { // # NAMESPACE CASACORE - BEGIN
41
42// # Forward declarations
43class String;
44class RecordInterface;
45
46// <summary> Numerical functional interface class
47// </summary>
48
49// <use visibility=export>
50
51// <reviewed reviewer="tcornwel" date="1996/02/22" tests="tGaussian2D"
52// demos="">
53// </reviewed>
54
55// <prerequisite>
56// <li> <linkto class="Functional">Functional</linkto>
57// <li> <linkto class="FunctionParam">FunctionParam</linkto>
58// </prerequisite>
59//
60// <synopsis>
61// A <src>Function</src> is used for classes which map a
62// scalar or n-dimensional Vector of type <src>T</src> into a <src>T</src>.
63// The object also has zero or more parameters which can be masked
64// if necessary, and be used in the <src>Fitting</src> module, and, implicitly,
65// in the <linkto class=AutoDiff>AutoDiff</linkto> differentiation module.
66//
67// The parameter interface is provided by the
68// <linkto class="FunctionParam"><src>FunctionParam</src></linkto> class.
69//
70// A Function can have a <src>name()</src> which can be used in generic
71// interfaces.
72//
73// The function calls implemented are:
74// <ul>
75// <li> <src>operator()()</src>
76// <li> <src>operator()(const T &x)</src>
77// <li> <src>operator()(const Vector<T> &x)</src>
78// <li> <src>operator()(Function::FunctionArg x)</src>
79// <li> <src>operator()(const T &x, const T &y)</src> (for 2D)
80// <li> <src>operator()(const T &x, const T &y, const T &z)</src> (for 3D)
81// </ul>
82// The <src>T</src> in the above is the <src>Function::ArgType</src>
83// as derived from the <linkto class="FunctionTraits">FunctionTraits</linkto>
84// class.
85// These calls are (in debug mode) tested for the correct number of arguments,
86// after which they call a <src>T eval(FunctionArg x) const = 0</src> to
87// be implemented in derived classes. The derived class should also implement
88// an <src>uInt ndim() const = 0</src>. The derived class can access the
89// nth parameter with the <src>[n]</src> operator, and the corresponding
90// mask with <src>mask(n)</src> method.
91// The variables are referenced with <src>x[i]</src>.
92//
93// </synopsis>
94
95// <example>
96// A complete implementation of say an <src>A.sin(2pi.f.x)</src> with
97// parameters amplitude(<em>A</em>) and frequency(<em>f</em>) and variable
98// time(<em>x</em>) could be:
99// <srcblock>
100// //# Sinusoid.h
101// #include <casacore/casa/aips.h>
102// #include <casacore/scimath/Functionals/Function.h>
103// #include <casacore/casa/BasicSL/Constants.h>
104// #include <casacore/casa/BasicMath/Math.h>
105// // The sinusoid class
106// template<class T> class Sinusoid : public Function<T> {
107// public:
108// // For easy reference of the parameters
109// enum { AMPL=0, FREQ };
110// // Constructors. Defaults are A=1, f=1
111// Sinusoid() : Function<T>(2) {
112// param_p[AMPL] = T(1.0); param_p[FREQ] = T(1.0); }
113// explicit Sinusoid(const T &ampl) : Function<T>(2) {
114// param_p[AMPL] = ampl; param_p[FREQ] = T(1.0); }
115// Sinusoid(const T &ampl, const T &freq) : Function<T>(2) {
116// param_p[AMPL] = ampl; param_p[FREQ] = freq; }
117// Sinusoid(const Sinusoid &other) : Function<T>(2) {
118// param_p[AMPL] = other.param_p[AMPL];
119// param_p[FREQ] = other.parameter[FREQ]; }
120// Sinusoid<T> &operator=(const Sinusoid<T> &other) {
121// if (this != &other) param_p = other.param_p;
122// return *this; }
123// virtual ~Sinusoid() {}
124// // Dimensionality
125// virtual uInt ndim() const { return 2; }
126// // Evaluate
127// virtual T eval(Function<T>::FunctionArg x) const {
128// return param_p[AMPL]*sin(T(C::_2pi)*param_p[FREQ]*x[0]); }
129// // Copy it
130// virtual Function<T> *clone() const { return new Sinusoid<T>(param_p); }
131// };
132// </srcblock>
133// The following will calculate the value and the derivative for
134// <src>A=2; f=3; x=0.1;</src>
135// <srcblock>
136// // The function objects for value, and for value + derivative
137// Sinusoid<Double> soid1(2.0, 3.0);
138// typedef AutoDiff<Double> Adif;
139// Sinusoid<Adif> soid2(Adif(2,2,0), Adif(3,2,1));
140// cout << "Value: " << soid1(0.1) << endl;
141// cout << "(val, deriv): " << soid2(Adif(0.1)) << endl;
142// </srcblock>
143//
144// A shorter version, where all parameter handling is done at user level
145// could be:
146// <srcblock>
147// //# Sinusoid.h
148// #include <casacore/casa/aips.h>
149// #include <casacore/scimath/Functionals/Function.h>
150// #include <casacore/casa/BasicSL/Constants.h>
151// #include <casacore/casa/BasicMath/Math.h>
152// template<class T> class Sinusoid : public Function<T> {
153// public:
154// enum { AMPL=0, FREQ };
155// Sinusoid() : Function<T>(2){param_p[AMPL] T(1);param_p[FREQ]=T(1);}
156// virtual ~Sinusoid() {}
157// virtual uInt ndim() const { return 2; }
158// virtual T eval(Function<T>::FunctionArg x) const {
159// return param_p[AMPL]*sin(T(C::_2pi)*param_p[FREQ]*x[0]); }
160// virtual Function<T> *clone() const { return new Sinusoid<T>param_p; }
161// };
162// </srcblock>
163// The following will calculate the value and the derivative for
164// <src>A=2; f=3; x=0.1;</src>
165// <srcblock>
166// // The function objects for value, and for value + derivative
167// typedef AutoDiff<Double> Adif;
168// typedef Function<Double> FD;
169// typedef Function<AutoDiff<Double> > FAdif
170// Sinusoid<Double> soid1;
171// Sinusoid<Adif> soid2;
172// soid1[FD::AMPL] = 2; soid1[FD::FREQ] = 3;
173// soid2[FAdif::AMPL] = Adif(2,2,0);
174// soid2[FAdif::FREQ] = Adif(3,2,1);
175// cout << "Value: " << soid1(0.1) << endl;
176// cout << "(val, deriv): " << soid2(Adif(0.1)) << endl;
177// </srcblock>
178// </example>
179
180// <motivation>
181// A function of more than one variable was required for a function which
182// represents the sky brightness. Adjustable parameters were required for
183// non-linear least squares fitting.
184// </motivation>
185//
186// <templating arg=T>
187// <li> Besides the requirements set by the
188// <linkto class="Functional">Functional</linkto> base class, it must be
189// possible to form a <src>Vector<T></src>.
190// </templating>
191//
192// <todo asof="2005/01/20">
193// <li> At some point, we may want to implement a letter-envelope class,
194// implement function arithmetic, etc.
195// <li> use maybe Poolstack for static Vector
196// </todo>
197
198template <class T, class U = T>
199class Function : public Functional<typename FunctionTraits<T>::ArgType, U>,
200 public Functional<Vector<typename FunctionTraits<T>::ArgType>, U> {
201 public:
202 // # Typedefs
204 typedef const ArgType *FunctionArg;
205
206 // # Constructors
207 // Constructors
208 // <group>
210 explicit Function(const uInt n) : param_p(n), arg_p(0), parset_p(False), locked_p(False) {}
211 explicit Function(const Vector<T> &in)
212 : param_p(in), arg_p(0), parset_p(False), locked_p(False) {}
214 : param_p(other), arg_p(0), parset_p(False), locked_p(False) {}
215 template <class W, class X>
217 : param_p(other.parameters()), arg_p(0), parset_p(other.parsetp()), locked_p(False) {}
218 // </group>
219
220 // Destructor
221 virtual ~Function() {}
222
223 // Returns the number of dimensions of function
224 virtual uInt ndim() const = 0;
225 // Returns the number of parameters
226 uInt nparameters() const { return param_p.nelements(); }
227
228 // Evaluate the function object
229 virtual U eval(FunctionArg x) const = 0;
230
231 // # Operators
232 // Manipulate the nth parameter (0-based) with no index check
233 // <group>
234 T &operator[](const uInt n) {
235 parset_p |= !locked_p;
236 return param_p[n];
237 }
238 const T &operator[](const uInt n) const { return param_p[n]; }
239 // </group>
240 // Evaluate this function object at <src>x</src>or at <src>x, y</src>.
241 // The length of <src>x</src> must be greater than or equal to
242 // <src>ndim()</src>.
243 // <group>
244 virtual U operator()() const {
245 DebugAssert(ndim() == 0, AipsError);
246 return eval(FunctionArg(0));
247 }
248 virtual U operator()(const ArgType &x) const {
249 DebugAssert(ndim() <= 1, AipsError);
250 return eval(&x);
251 }
252 virtual U operator()(const Vector<ArgType> &x) const;
253 virtual U operator()(FunctionArg x) const { return eval(x); }
254 virtual U operator()(const ArgType &x, const ArgType &y) const;
255 virtual U operator()(const ArgType &x, const ArgType &y, const ArgType &z) const;
256 // </group>
257
258 // # Member functions
259 // Specify the name associated with the function (default will be
260 // <src>unknown</src>)
261 virtual const String &name() const;
262 // Manipulate the mask associated with the nth parameter
263 // (e.g. to indicate whether the parameter is adjustable or
264 // nonadjustable).
265 // Note: no index check.
266 // <group>
267 Bool &mask(const uInt n) {
268 parset_p |= !locked_p;
269 return param_p.mask(n);
270 }
271 const Bool &mask(const uInt n) const { return param_p.mask(n); }
272 // </group>
273 // Return the parameter interface
274 // <group>
275 const FunctionParam<T> &parameters() const { return param_p; }
277 parset_p = True;
278 return param_p;
279 }
280 // </group>
281 // Get <src>arg_p</src> and <src>parset_p</src>. Necessary for reasons
282 // of protection in the copying of non-conforming Functions.
283 // <group>
284 const Vector<ArgType> &argp() const { return arg_p; }
285 Bool parsetp() const { return parset_p; }
286 // </group>
287 // Compiler cannot always find the correct 'const' version of parameter
288 // access. In cases where this would lead to excessive overheads in
289 // moving parameters around (like in <src>CompoundFunction</src>) the
290 // parameter changing can be set to be locked, and no changes are
291 // assumed.
292 // <group>
293 void lockParam() { locked_p = True; }
295 // </group>
296
297 // get/set the function mode. These provide an interface to
298 // function-specific configuration or state that controls how the
299 // function calculates its values but otherwise does not qualify as
300 // a parameter. Some part of the state, for example, might have a
301 // type different from that of T. The state is passed as fields of a
302 // record, mode--the names, types and values of which are specific to
303 // the implementing function and should be documented in the implementing
304 // class. It is recommended that all possible inputs passed to this
305 // function via setMode() be considered optional such that if the
306 // record omits a legal field, that part of the state is left unchanged.
307 // Fields not recognized by the implementing class should be ignored.
308 // An exception should be thrown if a recognized field contains illegal
309 // data. The default implementations for both getMode() and setMode()
310 // ignore the input record.
311 // <group>
312 virtual void setMode(const RecordInterface &mode);
313 virtual void getMode(RecordInterface &mode) const;
314 // </group>
315
316 // return True if the implementing function supports a mode. The default
317 // implementation returns False.
318 virtual Bool hasMode() const;
319
320 // Print the function (i.e. the parameters)
321 ostream &print(ostream &os) const { return param_p.print(os); }
322 // Return a copy of this object from the heap. The caller is responsible
323 // for deleting this pointer. The <src>cloneAD</src> will return a clone
324 // with an <src>AutoDef<T></src>; the <src>cloneNonAD</src> a clone
325 // with <src><T></src>. An <src>AipsError</src> will be thrown if the
326 // <src>cloneAD()</src> or <src>cloneNonAD()</src> is not implemented
327 // for a specific function.
328 // <group>
329 virtual Function<T, U> *clone() const = 0;
332 // </group>
333
334 protected:
335 // # Data
336 // The parameters and masks
338 // Aid for non-contiguous argument storage
340 // Indicate parameter written
341 mutable Bool parset_p;
342 // Indicate that parameters are expected to be locked from changing
343 mutable Bool locked_p;
344};
345
346// # Global functions
347// <summary> Global functions </summary>
348// <group name=Output>
349// Output declaration
350template <class T, class U>
351ostream &operator<<(ostream &os, const Function<T, U> &fun);
352// </group>
354// # Inlines
355template <class T, class U>
356inline ostream &operator<<(ostream &os, const Function<T, U> &fun) {
357 return fun.print(os);
358}
359
360} // namespace casacore
361
362#ifndef CASACORE_NO_AUTO_TEMPLATES
363#include <casacore/scimath/Functionals/Function.tcc>
364#endif // # CASACORE_NO_AUTO_TEMPLATES
365#endif
#define DebugAssert(expr, exception)
Definition Assert.h:161
T ArgType
Type for arguments.
FunctionParam< T > param_p
The parameters and masks.
Definition Function.h:337
FunctionTraits< T >::ArgType ArgType
Definition Function.h:203
virtual void setMode(const RecordInterface &mode)
get/set the function mode.
const T & operator[](const uInt n) const
Definition Function.h:238
virtual U operator()(const ArgType &x, const ArgType &y) const
Function(const Vector< T > &in)
Definition Function.h:211
virtual U operator()(const ArgType &x) const
Definition Function.h:248
FunctionParam< T > & parameters()
Definition Function.h:276
virtual Function< T, U > * clone() const =0
Return a copy of this object from the heap.
Function()
Constructors.
Definition Function.h:209
virtual void getMode(RecordInterface &mode) const
virtual U operator()() const
Evaluate this function object at xor at x, y.
Definition Function.h:244
virtual Function< typename FunctionTraits< T >::BaseType > * cloneNonAD() const
Bool & mask(const uInt n)
Manipulate the mask associated with the nth parameter (e.g.
Definition Function.h:267
const Bool & mask(const uInt n) const
Definition Function.h:271
virtual U operator()(FunctionArg x) const
Definition Function.h:253
const FunctionParam< T > & parameters() const
Return the parameter interface.
Definition Function.h:275
void lockParam()
Compiler cannot always find the correct 'const' version of parameter access.
Definition Function.h:293
Function(const Function< W, X > &other)
Definition Function.h:216
T & operator[](const uInt n)
Manipulate the nth parameter (0-based) with no index check.
Definition Function.h:234
virtual uInt ndim() const =0
Returns the number of dimensions of function.
virtual Bool hasMode() const
return True if the implementing function supports a mode.
virtual ~Function()
Destructor.
Definition Function.h:221
virtual const String & name() const
Specify the name associated with the function (default will be unknown).
virtual U operator()(const ArgType &x, const ArgType &y, const ArgType &z) const
Function(const uInt n)
Definition Function.h:210
Vector< ArgType > arg_p
Aid for non-contiguous argument storage.
Definition Function.h:339
ostream & print(ostream &os) const
Print the function (i.e.
Definition Function.h:321
virtual U operator()(const Vector< ArgType > &x) const
const Vector< ArgType > & argp() const
Get arg_p and parset_p.
Definition Function.h:284
Bool parset_p
Indicate parameter written.
Definition Function.h:341
Function(const FunctionParam< T > &other)
Definition Function.h:213
virtual U eval(FunctionArg x) const =0
Evaluate the function object.
uInt nparameters() const
Returns the number of parameters.
Definition Function.h:226
Bool locked_p
Indicate that parameters are expected to be locked from changing.
Definition Function.h:343
const ArgType * FunctionArg
Definition Function.h:204
Bool parsetp() const
Definition Function.h:285
virtual Function< typename FunctionTraits< T >::DiffType > * cloneAD() const
String: the storage and methods of handling collections of characters.
Definition String.h:355
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
const Bool False
Definition aipstype.h:42
ostream & operator<<(ostream &os, const IComplex &)
Show on ostream.
unsigned int uInt
Definition aipstype.h:49
RecordInterface()
The default constructor creates an empty record with a variable structure.
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
const Bool True
Definition aipstype.h:41
ostream & operator<<(ostream &os, const Function< T, U > &fun)
Output declaration.