Creating a function for the Generic Function package or inserting an existing function into the framework has low work overhead. Of course if the function is complicated and hard to write, this the framework does not make it easier! However there are only a small number of steps involved in creating a one- or multi-dimensional function and endowing it with parameters that control its shape. We present this procedure as a checklist:
AbsFunction
.
virtual unsigned int dimensionality() const;because the base class provides a default implementation which returns the value 1. Otherwise, if your function has two or more dimensions, you will need to override the method.
Parameter
data member for that
parameter, and initialize it with its default value and range in the
constructor. Also you will want a way of getting a reference to the
parameter-and actually you will want two methods, overloaded on const.
The purpose of having both methods is so that you will get back a
parameter that you can modify if the function itself is modifiable,
and a read-only parameter if the function is readonly. If overloading
on const is strange to you, you can read up on it in Meyers; or you
can just adapt both of these example lines:
Parameter & parm(); const Parameter & parm() const;which shows, for example how to retrieve a parameter called "parm" from a function. This is important and the compiler errors may appear very mysterious if you don't write your parameter accessors this way.
virtual double operator() (double) const; virtual double operator() (const Argument &) const;These operators are what your function "does" so how you go about doing this is your business. But typically, for one dimensional functions the second form of the function just calls the first; while for multidimensional functions the first form generates a run-time error and the second form checks the dimension of the argument before evaluating it.
operator()( const AbsFunction &)
is
overloaded in the base class and you don't want to hide it in the subclass,
so put the line using AbsFunction::operator()
in the header file
of your derived class.
virtual SubClass * clone() const;where
SubClass
is your new class. This construction uses the
covariant return type mechanism, since the function in the base class
returns an AbsFunction *
. The purpose of the routine is of course to
return a pointer to a newly allocated object. The easiest way of
implementing this function is to use the copy constructor that you
wrote (if you wrote one, otherwise you can take the default copy
constructor that the compiler wrote for you).
Derivative partial (unsigned int) const;
The function Sin
provides a good example of how to do this. Should you
choose to provide an analytic derivative, you should also then override the
method
bool hasAnalyticDerivative() constso that it returns true. Our preference is to put the implementation right in the header file since it provides useful information (``yes, this class has an analtyic derivative'') for users.