// Example demonstrating use of Bus & Dekker solver
//
// (C) Alan Bain 2005
#include <iostream>
#include <iomanip>

#include "bd.h"


using namespace NumericalLib;
using namespace std;


// This is a demonstration class only ; this is not a sensible
// implementation of a quadratic solver!
class quadratic {
	public:
		quadratic(double a,double b, double c) : a(a), b(b), c(c) {};
		double operator()(double x) const {
			return (a*x*x+b*x+c);
		}
private:
	// a*x^2 + bx + c =0
	double a,b,c;
};

// now suppose we are interested in quadratics and their first deriv
class quadraticWithDeriv { 
	public:
		quadraticWithDeriv(double a,double b, double c) : a(a), b(b), c(c) {};
		
		class evalf { 
		public: 
			public: 
				evalf(quadraticWithDeriv* obj) : ptr(obj) {}
			double operator()(double x) const {
				return (ptr->a*x*x+ptr->b*x+ptr->c);
			}

			private:
			quadraticWithDeriv *ptr;
		};

		class evalfdash {
			public: 
				evalfdash(quadraticWithDeriv* obj) : ptr(obj) {}
			double operator()(double x) const {
				return (2*ptr->a*x+ptr->b);
			}
		private:
			quadraticWithDeriv *ptr;
		};

		template <class T> T make () {
			return T(this);
		}
		
	private:
	// a*x^2 + bx + c =0
	double a,b,c;
};



int main(int,char**) {
	double b=-1.0; // LH endpoint
	double c=10.0; // RH endpoint

	relativeTol rt;

	// Simple case of functor class
	// x^2 -2 =0 has root x=1.414.... (sqrt(2))
	quadratic function(1.0,0.0,-2.0);
	cout << setprecision(17) << BDsolve(b,c,function,rt) << endl;


	// This demonstrates the usual method of invocation for a nested
	// class functor
	quadraticWithDeriv quad(1.0,0.0,-2.0);
	cout << setprecision(17) << BDsolve(b,c,quad.make<quadraticWithDeriv::evalf>(),rt) << endl;
	
	
	cout << setprecision(17) << BDsolve(b,c,quadraticWithDeriv::evalf(&quad),rt) << endl;

	return 0;
}