

#include "misc.h"

#include <iostream>
#include <functional>

#include "compose.hpp"

using namespace std;
using namespace boost;


/*
Setting up Boost

Downloaded Boost from   http://www.boost.org/

Noticed that the main files were in
   boost_1_27_0/boost directory ie with *.hpp extensions,
   so pointed the compiler to find files here and compiled.
*/




void test01()
{
   // 3x+5

   cout << "beg" << endl;

   cout << compose_f_gx( 
      bind1st(plus<double>(),5), 
      bind1st(multiplies<double>(),3.0) )(2) << endl;

   cout << "***" << endl;

   //
   //  Comment : downside with above it that the function can't be
   //  locally stored without long type names.
   //  I have overcome this problem with functional objects - with
   //  a virtual function at the base.  See functionalobj.h
}

// <TODO>  Boost won't handle this, as what does
// it mean to have a zero operation?  - well this 
// is an example where its needed because a square root
// of a negative number will result otherwise
// with the concept of zero, and a binary operator 
// that knows what to do with it - eg ignore the calculation
// of the next function if the first returns zero under multiplication.
//
// [0,2)(Sqrt(2-x)) + [2,Infinity)(x-2)^2
//  
// Note: using Iverson's convention : 
//   [0,2) means 0<=x<2   [2,Infintiy) means x>=2


func(f1,x+3,x);
func(g1,x*x,x);

template<class X, class FX>
struct f2 : public unary_function<X,FX>
{
   FX operator()(X x) const { return x+3; }
};

/*
#define funcstl(nm,x,fx) \
template<class X, class FX> \
struct nm : public unary_function<X,FX>{ \
public: \
   FX _result; \
   FX operator()(X x) const { return (fx); } \
}
*/

funcstl(g2,x,x*x);


void test02()
{
// Using  compose_f_gx_hx

// error : boost explecting its own function - not a true functional object!
//   f1<double,double&,double> f;
//   g1<double,double&,double> g;

//   cout << compose_f_gx(f,g)(2.0) << endl;

   cout << f2<double,double>()(3.0) << endl;
   cout << g2<double,double>()(3.0) << endl;
   cout << compose_f_gx(
      f2<double,double>(), g2<double,double>() )(2.0) << endl;

   // Storing functions
   f2<double,double> f3;
   g2<double,double> g3;
   cout << f3(2.0) << endl;
   // Evaluating as a temporary object
   cout << compose_f_gx(f3,g3)(2.0) << endl;

   // Evaluating from a named variable
   compose_f_gx_t<f2<double,double>, g2<double,double> > fg(f3,g3);
   cout << fg(2.0) << endl;
   compose_f_gx_t<g2<double,double>, f2<double,double> > gf(g3,f3);
   cout << gf(2.0) << endl;
} 

   

   
   
   
   






int main()
{
   test02();

   return 0;
}

