/* Lecture code 15.2
*
* Code to generate a function's derivative using functors. This
* example illustrates using templates to pass functors as parameters,
* as well as type inference for functions.
*/
#include
#include // For sqrt
using namespace std;
const int kNumSteps = 20;
/* The TabulateValues function prints out twenty steps of the function between
* the start and stop point. Note that the function parameter is templatized over
* some type UnaryFunction. The name UnaryFunction is meaningless in this context
* and serves only to indicate to callers what type of objects to pass in. Passing
* an invalid argument will result in a compile-time error.
*/
template
void TabulateValues(double start, double stop, UnaryFunction function)
{
const double step = (stop - start) / (NUM_STEPS - 1);
for(int i = 0; i < kNumSteps; ++i)
{
const double value = start + step * i;
cout << "f(" << value << ") = " << function(value) << endl;
}
}
const double kEpsilon = 0.00001; // Epsilon for derivatives
/* Template class that wraps a unary function and produces a new unary
* function that is the derivative of the source function, to a certain
* precision.
*/
template
class Derivative
{
public:
/* Constructor stores the function of which to take the derivative. */
explicit Derivative(UnaryFunction fn): function(fn)
{
}
/* Functor operation returns the derivative at a point using the identity
* f(x + h) - f(x - h)
* f'(x) = -------------------
* lim (h->0) 2h
*
* Here, we substitute the value kEpsilon for the limit, which gives reasonable
* accuracy.
*/
double operator() (double input) const
{
return (function(input + kEpsilon) - function(input - kEpsilon)) / (2.0*kEpsilon);
}
private:
UnaryFunction function;
};
/* Because we have to explicitly provide template arguments to classes, it can be
* tricky to use the Derivative class. This helper function takes in a unary function
* and uses the template mechanism's type inference to construct and return a
* Derivative object of the appropriate type.
*/
template
Derivative takeDerivative(UnaryFunction fn)
{
return Derivative(fn);
}
int main()
{
/* Print out several values of the second derivative of the square root
* function. Feel free to experiment with this and see what you can
* come up with!
*/
TabulateValues(1.0, 2.0, takeDerivative(takeDerivative(sqrt)));
return 0;
}