Up

 

Function Object (Functor) and Template

 

When a function has some parameters, it is appropriate to use a function object (functor).

For example, a logistic function

has two parameters, a and s. Hence, this function can be prepared as a method, i.e., operator ( ) overrided as follows:

 

class CLogistic {

public:

        double a, s;

        double operator()(double x){

                return 1.0 / (1.0 + exp(-(x - a) / s));

        }

};

 

In this case, by the following code

CLogistic f;

f(1.0);

the body of the overrided operator ( )

{

        return 1.0 / (1.0 + exp(-(x - a) / s));

}

is called with x = 1.0;

 

When using a functor as a parameter in another function, template is useful.

For example, if various functors may be used in bisection algorithm, the template would be as follows:

 

template <class TF> void TBisection(TF & f,     // Functor(double x)

        double s,                               // s > 0 or s < 0 if f is increasing or decreasing, respectively.

        double c,                               // c = f(Root)

        double L_b, double U_b,                 // Set so that f(L_b) < c < f(U_b)  

        double & Root,                          // The required value so that f(Root) = c

        double acc)                             // Accuracy

{

        if ((f(L_b) - c) * (f(U_b) - c) > 0.0){

                throw  "Value error of L_b or U_b.";

        }

        do {

                double m = 0.5 * (L_b + U_b);

                double v = f(m);

                if (s * (v - c) > 0.0) {

                        U_b = m;

                }

                else {

                        L_b = m;

                }

        } while ((abs(U_b - L_b) >= acc * abs(U_b))

                &&

                ((abs(U_b) + abs(L_b)) >= 1.0e-14)

                );

        Root = 0.5 * (L_b + U_b);

}

 

Using this template, a program, which calculates the values the 1st, 2nd, and 3rd quantiles, i.e., Q1, Med, and Q3, respectively, is written as follows;

 

#include <iostream>

#include <iomanip>

#include <cmath>

#include <exception>

 

using namespace std;

 

 

class CLogistic {

public:

        double a, s;

        double operator()(double x){

                return 1.0 / (1.0 + exp(-(x - a) / s));

        }

};

 

template <class TF> void TBisection(TF & f,     // Functor(double x)

        double s,                               // s > 0 or s < 0 if f is increasing or decreasing, respectively.

        double c,                               // c = f(Root)

        double L_b, double U_b,                 // Set so that f(L_b) < c < f(U_b)  

        double & Root,                          // The required value so that f(Root) = c

        double acc)                             // Accuracy

{

        if ((f(L_b) - c) * (f(U_b) - c) > 0.0){

                throw  "Value error of L_b or U_b.";

        }

        do {

                double m = 0.5 * (L_b + U_b);

                double v = f(m);

                if (s * (v - c) > 0.0) {

                        U_b = m;

                }

                else {

                        L_b = m;

                }

        } while ((abs(U_b - L_b) >= acc * abs(U_b))

                &&

                ((abs(U_b) + abs(L_b)) >= 1.0e-14)

                );

        Root = 0.5 * (L_b + U_b);

}

 

 

int main(){

        CLogistic f;

        cout << "a = ";

        cin >> f.a;

        cout << "s (> 0) = ";

        cin >> f.s;

        double U_v = 10.0;

        while (f(U_v) <= 0.75) U_v += 10.0;

        double L_v = -10.0;

        while (f(L_v) >= 0.25) L_v -= 10.0;

        double FQ1, FMed, FQ3;

        TBisection(f, 1.0, 0.25, L_v, U_v, FQ1, 1.0e-12);

        TBisection<CLogistic>(f, 1.0, 0.5, L_v, U_v, FMed, 1.0e-12);

        TBisection(f, 1.0, 0.75, L_v, U_v, FQ3, 1.0e-12);

        cout << "Q1 = " << setprecision(9) << fixed << FQ1

                << "   Med = " << FMed

                << "   Q3 = " << FQ3 << endl;

       

        return 0;

}

 

If you run this program, you would get a picture like Figure 1.

Figure 1

 

The program is packed as main.cpp.zip, which can be downloaded and extended to open by a editor.

 

 

Up