Click here to Skip to main content
15,891,529 members
Articles / Programming Languages / C++

A powerful function parser

Rate me:
Please Sign up or sign in to vote.
4.40/5 (21 votes)
22 Feb 2000 141.3K   2.2K   60  
A simple yet powerful function parser that parses and evaluates standard mathematical functions
#ifndef __FUNCTIONPARSER_H
#define __FUNCTIONPARSER_H

#include "stdafx.h"

// Klassen in diesem Header-File (Forward-Deklarationen)
/*
template <class T>  class CFunction;
	template <class T>  class CNullFunction;
	template <class T>  class CIdentityFunction;
	template <class T>  class CPolynom1Function;
	template <class T>  class CPolynom2Function;
	template <class T>  class CPolynom3Function;
	template <class T>  class CPolynom4Function;
	template <class T>  class CExp1Function;
	template <class T>  class CSin1Function;
	template <class T>  class CCos1Function;
	template <class T>  class CTan1Function;
	template <class T>  class CCot1Function;
	template <class T>  class CAsin1Function;
	template <class T>  class CAcos1Function;
	template <class T>  class CAtan1Function;
	template <class T>  class CSinh1Function;
	template <class T>  class CCosh1Function;
	template <class T>  class CTanh1Function;
	template <class T>  class CCoth1Function;
	template <class T>  class CSign1Function;
	template <class T>  class CAbs1Function;
	template <class T>  class CCeil1Function;
	template <class T>  class CFloor1Function;
	template <class T>  class CLog101Function;
	template <class T>  class CLog1Function;
	template <class T>  class CLogarithmus1Function;
	template <class T>  class CSqrt1Function;
	template <class T>  class CSqr1Function;
	template <class T>  class CGamma1Function;
	template <class T>  class CConstFunction;

	template <class T>  class CFunction1;
		template <class T>  class CExpFunction;
		template <class T>  class CSinFunction;
		template <class T>  class CCosFunction;
		template <class T>  class CTanFunction;
		template <class T>  class CCotFunction;
		template <class T>  class CAsinFunction;
		template <class T>  class CAcosFunction;
		template <class T>  class CAtanFunction;
		template <class T>  class CSinhFunction;
		template <class T>  class CCoshFunction;
		template <class T>  class CTanhFunction;
		template <class T>  class CCothFunction;
		template <class T>  class CSignFunction;
		template <class T>  class CAbsFunction;
		template <class T>  class CCeilFunction;
		template <class T>  class CFloorFunction;
		template <class T>  class CLog10Function;
		template <class T>  class CLogFunction;
		template <class T>  class CLogarithmusFunction;
		template <class T>  class CSqrFunction;
		template <class T>  class CSqrtFunction;
		template <class T>  class CGammaFunction;
		template <class T>  class CNegFunction;
		template <class T>  class CAdd0Function;
		template <class T>  class CSubR0Function;
		template <class T>  class CSubL0Function;
		template <class T>  class CMul0Function;
		template <class T>  class CDivL0Function;
		template <class T>  class CDivR0Function;
		template <class T>  class CPowerL0Function;
		template <class T>  class CPowerR0Function;

	template <class T>  class CFunction2;
		template <class T>  class CAddFunction;
		template <class T>  class CSubFunction;
		template <class T>  class CMulFunction;
		template <class T>  class CDivFunction;
		template <class T>  class CPowerFunction;
		template <class T>  class CComponenteFunction;
*/

// Um symbolisches Ableiten zu beschleunigen:
// Kann besser gemacht werden, indem erst die Bausteine der Ableitung berechnet werden und dann nochmal geguckt wird
#define DERIVATE_TEST if (IsConstantFunction()) return new CNullFunction<T>();

// Basisklasse, abstrakt
template <class T>
class CFunction : public CObject
{
public:
	// Konstruktor, Destruktor
	CFunction() {};
	virtual ~CFunction() {};

	// Abstrakte Prototypen
	virtual CString GetName() const = 0;            // abstrakte Funktion, mu� �berschrieben werden
	virtual CString GetTeX() const = 0;             // abstrakte Funktion, mu� �berschrieben werden
	virtual CFunction<T>* GetDerivate() const = 0;  // abstrakte Funktion, mu� �berschrieben werden
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const = 0; // abstrakte Funktion, mu� �berschrieben werden
	virtual T Execute(T x) const = 0;               // abstrakte Funktion, mu� �berschrieben werden

	virtual bool IsConstantFunction() const     {return false;}  // Sollte �berschrieben werden, um symbolische Operationen zu beschleunigen und Ausdr�cke zu vereinfachen
	virtual bool IsNullFunction() const         {return false;}  // Sollte �berschrieben werden, um symbolische Operationen zu beschleunigen und Ausdr�cke zu vereinfachen

	// Ableitung, Nullstellenbestimmung, Integrale (numerisch)
	virtual T Derivate(T x, int grad = 1, double h = 1E-6) const;
	virtual T Nullstelle_Newton(T StartWert, double tol = 1E-6) const;
	virtual T Integral_Trapezregel(T x1, T x2, long nIntervals, double tol = 1E-6) const;
	virtual T Integral_Mittelpunktregel(T x1, T x2, long nIntervals, double tol = 1E-6) const;
	virtual T Integral_Simpsonregel(T x1, T x2, long nIntervals, double tol = 1E-6) const;

	// Funktions-Parser und Hilfsfunktionen
	static CFunction<T>* Parse(CString& str, const char* Var = _T("X"));
	static CFunction<T>* Parse1(const char* str, const char* Var = _T("X"));
	static bool IsFunction(CString& str, const char* Token); // Pr�ft, ob Ausdruck Funktion ist
	static bool IsConstFunction(CString& str, const char* Token); // Pr�ft, ob Ausdruck Funktion ist und ob das Argument die Identit�t ist
	static bool IsPureFunction(CString& str, const char* Token, const char* Var = _T("X")); // Pr�ft, ob Ausdruck Funktion ist und ob das Argument die Identit�t ist
	static bool IsConst(const char* str); // strtod anwendbar?
	static T Value(const char* str);      // liefert Ergebnis der Funktion strtod
	static bool IsIdentity(const char* str, const char* Var = _T("X"));
};

// Funktion mit einer eingebetteten Funktion, immer noch abstrakt!
template <class T>
class CFunction1 : public CFunction<T>
{
public:
	CFunction1(CFunction<T>* _f1) : f1(_f1) {};
	virtual ~CFunction1()                 {delete f1;};

	virtual CString GetConcName(const char* basisfkt) const;
protected:
	CFunction<T>* f1;
};

// Funktion mit zwei eingebetteten Funktionen, immer noch abstrakt!
template <class T>
class CFunction2 : public CFunction<T>
{
public:
	CFunction2(CFunction<T>* _f1, CFunction<T>* _f2) : f1(_f1), f2(_f2) {};
	virtual ~CFunction2()                 {delete f1; delete f2;};

	virtual CString GetConcName(const char* basisfkt) const;
protected:
	CFunction<T>* f1;
	CFunction<T>* f2;
};

// Nullfunktion
template <class T>
class CNullFunction : public CFunction<T>
{
public:
	CNullFunction()                       {};
	virtual T Execute(T /*x*/) const            {return 0;};

	virtual bool IsConstantFunction() const     {return true;}
	virtual bool IsNullFunction() const         {return true;}
	
	virtual CString GetName() const             {return _T("0");};
	virtual CString GetTeX() const              {return _T("0");};
	virtual CFunction<T>* GetDerivate() const   {return new CNullFunction<T>;};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

// Identit�t
template <class T>
class CIdentityFunction : public CFunction<T>
{
public:
	CIdentityFunction()                   {};
	virtual T Execute(T x) const                {return x;};

	virtual CString GetName() const             {return _T("x");};
	virtual CString GetTeX() const              {return _T("x");};
	virtual CFunction<T>* GetDerivate() const   {return new CConstFunction<T>(1);};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CIdentityFunction<T>;};
};

// Polynome
template <class T>
class CPolynom1Function : public CFunction<T>
{
public:
	CPolynom1Function(T _a0, T _a1) : a0(_a0), a1(_a1) {};
	virtual T Execute(T x) const                {return a0+x*a1;};

	virtual bool IsConstantFunction() const     {return a1==0.0;}
	virtual bool IsNullFunction() const         {return a1==0.0 && a0==0.0;}

	virtual CString GetName() const;
	virtual CString GetTeX() const;
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CConstFunction<T>(a1);};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T a0;
	T a1; 
};

template <class T>
class CPolynom2Function : public CFunction<T>
{
public:
	CPolynom2Function(T _a0, T _a1, T _a2) : a0(_a0), a1(_a1), a2(_a2) {};
	virtual T Execute(T x) const                {return a0+x*(a1+x*a2);};

	virtual bool IsConstantFunction() const     {return a2==0.0 && a1==0.0;}
	virtual bool IsNullFunction() const         {return a2==0.0 && a1==0.0 && a0==0.0;}

	virtual CString GetName() const;
	virtual CString GetTeX() const;
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CPolynom1Function<T>(a1,2*a2);};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T a0;
	T a1; 
	T a2;
};

template <class T>
class CPolynom3Function : public CFunction<T>
{
public:
	CPolynom3Function(T _a0, T _a1, T _a2, T _a3) : a0(_a0), a1(_a1), a2(_a2), a3(_a3) {};
	virtual T Execute(T x) const                {return a0+x*(a1+x*(a2+x*a3));};

	virtual bool IsConstantFunction() const     {return a3==0.0 && a2==0.0 && a1==0.0;}
	virtual bool IsNullFunction() const         {return a3==0.0 && a2==0.0 && a1==0.0 && a0==0.0;}

	virtual CString GetName() const;
	virtual CString GetTeX() const;
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CPolynom2Function<T>(a1,2*a2,3*a3);};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T a0;
	T a1; 
	T a2;
	T a3;
};

template <class T>
class CPolynom4Function : public CFunction<T>
{
public:
	CPolynom4Function(T _a0, T _a1, T _a2, T _a3, T _a4) : a0(_a0), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {};
	virtual T Execute(T x) const                {return a0+x*(a1+x*(a2+x*(a3+x*a4)));};

	virtual bool IsConstantFunction() const     {return a4==0.0 && a3==0.0 && a2==0.0 && a1==0.0;}
	virtual bool IsNullFunction() const         {return a4==0.0 && a3==0.0 && a2==0.0 && a1==0.0 && a0==0.0;}

	virtual CString GetName() const;
	virtual CString GetTeX() const;
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CPolynom3Function<T>(a1,2*a2,3*a3,4*a4);};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T a0;
	T a1; 
	T a2;
	T a3;
	T a4;
};

// Exponentialfunktion
template <class T>
class CExpFunction : public CFunction1<T>
{
public:
	CExpFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return expl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("exp"));};
	virtual CString GetTeX() const              {CString str = _T("e^{"); str += f1->GetTeX(); str += _T("}"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CExpFunction<T>(f1->GetDuplicate()), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CExp1Function : public CFunction<T>
{
public:
	CExp1Function()                       {};
	virtual T Execute(T x) const                {return expl(x);};

	virtual CString GetName() const             {return _T("exp(x)");};
	virtual CString GetTeX() const              {return _T("e^x");};
	virtual CFunction<T>* GetDerivate() const   {return new CExp1Function<T>;};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CExp1Function<T>;};
};

// Trigonometrische Funktionen
template <class T>
class CSinFunction : public CFunction1<T>
{
public:
	CSinFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return sinl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("sin"));};
	virtual CString GetTeX() const              {CString str = _T("\\sin\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CCosFunction<T>(f1->GetDuplicate()), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CCosFunction : public CFunction1<T>
{
public:
	CCosFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return cosl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}

	virtual CString GetName() const             {return GetConcName(_T("cos"));};
	virtual CString GetTeX() const              {CString str = _T("\\cos\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction<T>(new CMulFunction<T>(new CSinFunction<T>(f1->GetDuplicate()), f1->GetDerivate()));};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CTanFunction : public CFunction1<T>
{
public:
	CTanFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return tanl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("tan"));};
	virtual CString GetTeX() const              {CString str = _T("\\tan\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CAdd0Function<T>(new CMulFunction<T>(new CTanFunction<T>(f1->GetDuplicate()), new CTanFunction<T>(f1->GetDuplicate())), 1), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CCotFunction : public CFunction1<T>
{
public:
	CCotFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return cosl(f1->Execute(x))/sinl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}

	virtual CString GetName() const             {return GetConcName(_T("cot"));};
	virtual CString GetTeX() const              {CString str = _T("\\cot\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction<T>(new CMulFunction<T>(new CAdd0Function<T>(new CMulFunction<T>(new CCotFunction<T>(f1->GetDuplicate()), new CCotFunction<T>(f1->GetDuplicate())), 1), f1->GetDerivate()));};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CAsinFunction : public CFunction1<T>
{
public:
	CAsinFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return asinl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("Asin"));};
	virtual CString GetTeX() const              {CString str = _T("\\arcsin\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CDivL0Function<T>(1, new CSqrtFunction<T>(new CPolynom2Function<T>(1, 0, -1))), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CAcosFunction : public CFunction1<T>
{
public:
	CAcosFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return acosl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}

	virtual CString GetName() const             {return GetConcName(_T("Acos"));};
	virtual CString GetTeX() const              {CString str = _T("\\arccos\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CDivL0Function<T>(-1, new CSqrtFunction<T>(new CPolynom2Function<T>(1, 0, -1))), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CAtanFunction : public CFunction1<T>
{
public:
	CAtanFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return atanl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("Atan"));};
	virtual CString GetTeX() const              {CString str = _T("\\arctan\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CDivL0Function<T>(1, new CPolynom2Function<T>(1, 0, 1)), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CAcotFunction : public CFunction1<T>
{
public:
	CAcotFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return acotl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}

	virtual CString GetName() const             {return GetConcName(_T("Acot"));};
	virtual CString GetTeX() const              {CString str = _T("\\mathop{\\rm arccot}\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CDivL0Function<T>(-1, new CPolynom2Function<T>(1, 0, 1))), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CSin1Function : public CFunction<T>
{
public:
	CSin1Function()                       {};
	virtual T Execute(T x) const                {return sinl(x);};

	virtual CString GetName() const             {return _T("sin(x)");};
	virtual CString GetTeX() const              {return _T("\\sin(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CCos1Function<T>;};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CSin1Function<T>;};
};

template <class T>
class CCos1Function : public CFunction<T>
{
public:
	CCos1Function()                       {};
	virtual T Execute(T x) const                {return cosl(x);};

	virtual CString GetName() const             {return _T("cos(x)");};
	virtual CString GetTeX() const              {return _T("\\cos(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CNegFunction<T>(new CSin1Function<T>);};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CCos1Function<T>;};
};

template <class T>
class CTan1Function : public CFunction<T>
{
public:
	CTan1Function()                       {};
	virtual T Execute(T x) const                {return tanl(x);};

	virtual CString GetName() const             {return _T("tan(x)");};
	virtual CString GetTeX() const              {return _T("\\tan(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CAdd0Function<T>(new CMulFunction<T>(new CTan1Function<T>, new CTan1Function<T>), 1);};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CTan1Function<T>;};
};

template <class T>
class CCot1Function : public CFunction<T>
{
public:
	CCot1Function()                       {};
	virtual T Execute(T x) const                {return cosl(x)/sinl(x);};

	virtual CString GetName() const             {return _T("cot(x)");};
	virtual CString GetTeX() const              {return _T("\\cot(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CNegFunction<T>(new CAdd0Function<T>(new CMulFunction<T>(new CCot1Function<T>, new CCot1Function<T>), 1));};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CCot1Function<T>;};
};

template <class T>
class CAsin1Function : public CFunction<T>
{
public:
	CAsin1Function()                      {};
	virtual T Execute(T x) const                {return asinl(x);};

	virtual CString GetName() const             {return _T("Asin(x)");};
	virtual CString GetTeX() const              {return _T("\\arcsin(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(1, new CSqrtFunction<T>(new CPolynom2Function<T>(1,0,-1)));};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CAsin1Function<T>;};
};

template <class T>
class CAcos1Function : public CFunction<T>
{
public:
	CAcos1Function()                      {};
	virtual T Execute(T x) const                {return acosl(x);};

	virtual CString GetName() const             {return _T("Acos(x)");};
	virtual CString GetTeX() const              {return _T("\\arccos(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(-1, new CSqrtFunction<T>(new CPolynom2Function<T>(1,0,-1)));};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CAcos1Function<T>;};
};

template <class T>
class CAtan1Function : public CFunction<T>
{
public:
	CAtan1Function()                      {};
	virtual T Execute(T x) const                {return atanl(x);};

	virtual CString GetName() const             {return _T("Atan(x)");};
	virtual CString GetTeX() const              {return _T("\\arctan(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(1, new CPolynom2Function<T>(1, 0, 1));};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CAtan1Function<T>;};
};

template <class T>
class CAcot1Function : public CFunction<T>
{
public:
	CAcot1Function()                      {};
	virtual T Execute(T x) const                {return acotl(x);};

	virtual CString GetName() const             {return _T("Acot(x)");};
	virtual CString GetTeX() const              {return _T("\\mathop{\\rm arccot}(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(-1, new CPolynom2Function<T>(1, 0, 1));};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const  {return new CAcot1Function<T>;};
};

// Hyperbolische Funktionen
template <class T>
class CSinhFunction : public CFunction1<T>
{
public:
	CSinhFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return sinhl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("sinh"));};
	virtual CString GetTeX() const              {CString str = _T("\\sinh\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CCoshFunction<T>(f1->GetDuplicate()), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CCoshFunction : public CFunction1<T>
{
public:
	CCoshFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return coshl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}

	virtual CString GetName() const             {return GetConcName(_T("cosh"));};
	virtual CString GetTeX() const              {CString str = _T("\\cosh\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CSinhFunction<T>(f1->GetDuplicate()), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CTanhFunction : public CFunction1<T>
{
public:
	CTanhFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return tanhl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("tanh"));};
	virtual CString GetTeX() const              {CString str = _T("\\tanh\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CDivL0Function<T>(1, new CMulFunction<T>(new CCoshFunction<T>(f1->GetDuplicate()), new CCoshFunction<T>(f1->GetDuplicate()))), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CCothFunction : public CFunction1<T>
{
public:
	CCothFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return coshl(f1->Execute(x)) / sinhl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}

	virtual CString GetName() const             {return GetConcName(_T("coth"));};
	virtual CString GetTeX() const              {CString str = _T("\\coth\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CDivL0Function<T>(-1, new CMulFunction<T>(new CSinhFunction<T>(f1->GetDuplicate()), new CSinhFunction<T>(f1->GetDuplicate()))), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CSinh1Function : public CFunction<T>
{
public:
	CSinh1Function()                            {};
	virtual T Execute(T x) const                {return sinhl(x);};

	virtual CString GetName() const             {return _T("sinh(x)");};
	virtual CString GetTeX() const              {return _T("\\sinh(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CCosh1Function<T>;};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CSinh1Function<T>;};
};

template <class T>
class CCosh1Function : public CFunction<T>
{
public:
	CCosh1Function()                            {};
	virtual T Execute(T x) const                {return coshl(x);};

	virtual CString GetName() const             {return _T("cosh(x)");};
	virtual CString GetTeX() const              {return _T("\\cosh(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CSinh1Function<T>;};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CCosh1Function<T>;};
};

template <class T>
class CTanh1Function : public CFunction<T>
{
public:
	CTanh1Function()                            {};
	virtual T Execute(T x) const                {return tanhl(x);};

	virtual CString GetName() const             {return _T("tanh(x)");};
	virtual CString GetTeX() const              {return _T("\\tanh(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(1, new CMulFunction<T>(new CCosh1Function<T>, new CCosh1Function<T>));};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CTanh1Function<T>;};
};

template <class T>
class CCoth1Function : public CFunction<T>
{
public:
	CCoth1Function()                            {};
	virtual T Execute(T x) const                {return coshl(x)/sinhl(x);};

	virtual CString GetName() const             {return _T("coth(x)");};
	virtual CString GetTeX() const              {return _T("\\coth(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(-1, new CMulFunction<T>(new CSinh1Function<T>, new CSinh1Function<T>));};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CCoth1Function<T>;};
};

// Vorzeichen-Funktion
template <class T>
class CSignFunction : public CFunction1<T>
{
public:
	CSignFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return signl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("sign"));};
	virtual CString GetTeX() const              {CString str = _T("\\mathop{\\rm sign}\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CNullFunction<T>;}; // !! eigentlich nicht korrekt, aber das �berhaupt etwas definiert ist!
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CSign1Function : public CFunction<T>
{
public:
	CSign1Function()                            {};
	virtual T Execute(T x) const                {return signl(x);};

	virtual CString GetName() const             {return _T("sing(x)");};
	virtual CString GetTeX() const              {return _T("\\mathop{\\rm sign}(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CNullFunction<T>;}; // !! eigentlich nicht korrekt, aber das �berhaupt etwas definiert ist!
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CSign1Function<T>;};
};

// Absoluter Betrag
template <class T>
class CAbsFunction : public CFunction1<T>
{
public:
	CAbsFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return fabsl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("abs"));};
	virtual CString GetTeX() const              {CString str = _T("\\left\\|"); str += f1->GetTeX(); str += _T("\\right\\|"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction<T>(new CSignFunction<T>(f1->GetDuplicate()), f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CAbs1Function : public CFunction<T>
{
public:
	CAbs1Function()                       {};
	virtual T Execute(T x) const                {return fabsl(x);};

	virtual CString GetName() const             {return _T("abs(x)");};
	virtual CString GetTeX() const              {return _T("\\left\\|x\\right\\|");};
	virtual CFunction<T>* GetDerivate() const   {return new CSign1Function<T>;};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CAbs1Function<T>;};
};

// ceil
template <class T>
class CCeilFunction : public CFunction1<T>
{
public:
	CCeilFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return ceill(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("ceil"));};
	virtual CString GetTeX() const              {CString str = _T("\\mathop{\\rm ceil}\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CNullFunction<T>;}; // eigentlich nicht korrekt
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CCeil1Function : public CFunction<T>
{
public:
	CCeil1Function()                            {};
	virtual T Execute(T x) const                {return ceill(x);};

	virtual CString GetName() const             {return _T("ceil(x)");};
	virtual CString GetTeX() const              {return _T("\\mathop{\\rm ceil}(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CNullFunction<T>;}; // eigentlich nicht korrekt
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CCeil1Function<T>;};
};

// floor
template <class T>
class CFloorFunction : public CFunction1<T>
{
public:
	CFloorFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return floorl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("floor"));};
	virtual CString GetTeX() const              {CString str = _T("\\mathop{\\rm floor}\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CNullFunction<T>;}; // eigentlich nicht korrekt
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CFloor1Function : public CFunction<T>
{
public:
	CFloor1Function()                           {};
	virtual T Execute(T x) const                {return floorl(x);};

	virtual CString GetName() const             {return _T("floor(x)");};
	virtual CString GetTeX() const              {return _T("\\mathop{\\rm floor}(x)");};
	virtual CFunction<T>* GetDerivate() const   {return new CNullFunction<T>;}; // eigentlich nicht korrekt
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CFloor1Function<T>;};
};

// Logarithmus
template <class T>
class CLog10Function : public CFunction1<T>
{
public:
	CLog10Function(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return log10l(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsConstantFunction() && f1->Execute(0.0)==1.0;}

	virtual CString GetName() const             {return GetConcName(_T("lg"));};
	virtual CString GetTeX() const              {CString str = _T("\\lg\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction<T>(f1->GetDerivate(), new CMul0Function<T>(f1->GetDuplicate(), logl(10)));};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CLogFunction : public CFunction1<T>
{
public:
	CLogFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return logl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsConstantFunction() && f1->Execute(0.0)==1.0;}

	virtual CString GetName() const             {return GetConcName(_T("log"));};
	virtual CString GetTeX() const              {CString str = _T("\\ln\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction<T>(f1->GetDerivate(), f1->GetDuplicate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CLogarithmusFunction : public CFunction1<T>
{
public:
	CLogarithmusFunction(T _b, CFunction<T>* _f1) : CFunction1<T>(_f1), b(_b) {};
	virtual T Execute(T x) const                {return log(f1->Execute(x))/log(b);};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsConstantFunction() && f1->Execute(0.0)==1.0;}

	virtual CString GetName() const             {CString str = _T("log_"); str += CMathString(b); return GetConcName(str);};
	virtual CString GetTeX() const              {CString str = _T("\\log_"); str += CMathString(b); str += _T("\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction<T>(f1->GetDerivate(), new CMulFunction<T>(logl(b), f1->GetDuplicate()));};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T b;
};

template <class T>
class CLog101Function : public CFunction<T>
{
public:
	CLog101Function()                           {};
	virtual T Execute(T x) const                {return log10l(x);};

	virtual CString GetName() const             {return _T("lg(x)");};
	virtual CString GetTeX() const              {return _T("\\lg\\left(x\\right)");};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(1/logl(10), new CIdentityFunction<T>);};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CLog101Function<T>;};
};

template <class T>
class CLog1Function : public CFunction<T>
{
public:
	CLog1Function()                             {};
	virtual T Execute(T x) const                {return logl(x);};

	virtual CString GetName() const             {return _T("log(x)");};
	virtual CString GetTeX() const              {return _T("\\ln\\left(x\\right)");};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(1, new CIdentityFunction<T>);};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CLog1Function<T>;};
};

template <class T>
class CLogarithmus1Function : public CFunction<T>
{
public:
	CLogarithmus1Function(T _b) : b(_b)         {};
	virtual T Execute(T x) const                {return log(x)/log(b);};

	virtual CString GetName() const             {CString str = _T("log_"); str += CMathString(b); str += _T("(x)"); return str;};
	virtual CString GetTeX() const              {CString str = _T("\\log_"); str += CMathString(b); str += _T("\\left(x\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(1/logl(b), new CIdentityFunction<T>);};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const  {return new CLogarithmusFunction<T>(b);};
private:
	T b;
};

// Wurzel
template <class T>
class CSqrtFunction : public CFunction1<T>
{
public:
	CSqrtFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return sqrtl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("sqrt"));};
	virtual CString GetTeX() const              {CString str = _T("\\sqrt\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction<T>(f1->GetDerivate(), new CMul0Function<T>(new CSqrtFunction<T>(f1->GetDuplicate()), 2));};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CSqrt1Function : public CFunction<T>
{
public:
	CSqrt1Function()                            {};
	virtual T Execute(T x) const                {return sqrtl(x);};

	virtual CString GetName() const             {return _T("sqrt(x)");};
	virtual CString GetTeX() const              {return _T("\\sqrt\\left(x\\right)");};
	virtual CFunction<T>* GetDerivate() const   {return new CDivL0Function<T>(1/2, new CSqrt1Function<T>);};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CSqrt1Function<T>;};
};

// Wurzel
template <class T>
class CSqrFunction : public CFunction1<T>
{
public:
	CSqrFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return sqrl(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("sqr"));};
	virtual CString GetTeX() const              {CString str = _T("\\sqr\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMul0Function<T>(f1->GetDuplicate(), 2);};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CSqr1Function : public CFunction<T>
{
public:
	CSqr1Function()                             {};
	virtual T Execute(T x) const                {return sqrl(x);};

	virtual CString GetName() const             {return _T("x^2");};
	virtual CString GetTeX() const              {return _T("x^2");};
	virtual CFunction<T>* GetDerivate() const   {return new CPolynom1Function<T>(0, 2.0);};
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CSqr1Function<T>;};
};

// Gamma-Funktion
template <class T>
class CGammaFunction : public CFunction1<T>
{
public:
	CGammaFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return FGammal(f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}

	virtual CString GetName() const             {return GetConcName(_T("Gamma"));};
	virtual CString GetTeX() const              {CString str = _T("\\Gamma\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CNullFunction<T>;}; // not implemented
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

template <class T>
class CGamma1Function : public CFunction<T>
{
public:
	CGamma1Function()                           {};
	virtual T Execute(T x) const                {return FGammal(x);};

	virtual CString GetName() const             {return _T("Gamma(x)");};
	virtual CString GetTeX() const              {return _T("\\Gamma\\left(x\\right)");};
	virtual CFunction<T>* GetDerivate() const   {return new CNullFunction<T>;}; // not implemented
	virtual CFunction<T>* GetDuplicate(bool /*simplify*/ = true) const  {return new CGamma1Function<T>;};
};

// Konstante Funtion
template <class T>
class CConstFunction : public CFunction<T>
{
public:
	CConstFunction(T _c) : c(_c)                {};
	virtual T Execute(T /*x*/) const            {return c;};

	virtual bool IsConstantFunction() const     {return true;}
	virtual bool IsNullFunction() const         {return c==0.0;}

	virtual CString GetName() const             {return CMathString(c);};
	virtual CString GetTeX() const              {return CMathString(c);};
	virtual CFunction<T>* GetDerivate() const   {return new CNullFunction<T>;};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T c;
};

// Negation
template <class T>
class CNegFunction : public CFunction1<T>
{
public:
	CNegFunction(CFunction<T>* _f1) : CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return -f1->Execute(x);};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {CString str = _T("-"); str += f1->GetName(); return str;};
	virtual CString GetTeX() const              {CString str = _T("-"); str += f1->GetTeX(); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction<T>(f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

// Addition
template <class T>
class CAdd0Function : public CFunction1<T>
{
public:
	CAdd0Function(CFunction<T>* _f1, T _c) : CFunction1<T>(_f1), c(_c) {};
	virtual T Execute(T x) const                {return f1->Execute(x) + c;};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsConstantFunction() && f1->Execute(0.0)==-c;}

	virtual CString GetName() const             {CString str = f1->GetName(); str += _T("+"); str += CMathString(c); return str;};
	virtual CString GetTeX() const              {CString str = f1->GetTeX(); str += _T("+"); str += CMathString(c); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return f1->GetDerivate();};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T c;
};

// Subtraktion
template <class T>
class CSubR0Function : public CFunction1<T>
{
public:
	CSubR0Function(CFunction<T>* _f1, T _c) : CFunction1<T>(_f1), c(_c) {};
	virtual T Execute(T x) const                {return f1->Execute(x) - c;};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsConstantFunction() && f1->Execute(0.0)==c;}

	virtual CString GetName() const             {CString str = f1->GetName(); str += _T("-"); str += CMathString(c); return str;};
	virtual CString GetTeX() const              {CString str = f1->GetTeX(); str += _T("-"); str += CMathString(c); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return f1->GetDerivate();};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T c;
};

template <class T>
class CSubL0Function : public CFunction1<T>
{
public:
	CSubL0Function(T _c, CFunction<T>* _f1) : CFunction1<T>(_f1), c(_c) {};
	virtual T Execute(T x) const                {return c - f1->Execute(x);};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsConstantFunction() && f1->Execute(0.0)==c;}

	virtual CString GetName() const             {CString str = CMathString(c);  str += _T("-"); str += f1->GetName(); return str;};
	virtual CString GetTeX() const              {CString str = CMathString(c);  str += _T("-"); str += f1->GetTeX(); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction<T>(f1->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T c;
};

// Multiplikation
template <class T>
class CMul0Function : public CFunction1<T>
{
public:
	CMul0Function(CFunction<T>* _f1, T _c) : CFunction1<T>(_f1), c(_c) {};
	virtual T Execute(T x) const                {return f1->Execute(x) * c;};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction() || c==0.0;}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction() || c==0.0;}

	virtual CString GetName() const             {CString str = CMathString(c);  str += _T("*("); str += f1->GetName(); str += _T(")"); return str;};
	virtual CString GetTeX() const              {CString str = CMathString(c);  str += _T("\\left("); str += f1->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CMul0Function<T>(f1->GetDerivate(), c);};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T c;
};

// Division
template <class T>
class CDivL0Function : public CFunction1<T>
{
public:
	CDivL0Function(T _c, CFunction<T>* _f1) : CFunction1<T>(_f1), c(_c) {};
	virtual T Execute(T x) const                {return c / f1->Execute(x);};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction() || c==0.0;}
	virtual bool IsNullFunction() const         {return c==0.0;}

	virtual CString GetName() const             {CString str = CMathString(c);  str += _T("/("); str += f1->GetName(); str += _T(")"); return str;};
	virtual CString GetTeX() const              {CString str = _T("\\frac{"); str += CMathString(c);  str += _T("}{"); str += f1->GetTeX(); str += _T("}"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction<T>(new CDivFunction<T>(f1->GetDerivate(), new CMulFunction<T>(f1->GetDuplicate(), f1->GetDuplicate())));};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T c;
};

template <class T>
class CDivR0Function : public CFunction1<T>
{
public:
	CDivR0Function(CFunction<T>* _f1, T _c) : CFunction1<T>(_f1), c(_c) {};
	virtual T Execute(T x) const                {return f1->Execute(x) / c;};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {CString str = _T("("); str += f1->GetName(); str += _T(")/"); str += CMathString(c); return str;};
	virtual CString GetTeX() const              {CString str = _T("\\frac{"); str += f1->GetTeX(); str += _T("}{"); str += CMathString(c); str += _T("}"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CDivR0Function<T>(f1->GetDerivate(), c);};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T c;
};

// Addition
template <class T>
class CAddFunction : public CFunction2<T>
{
public:
	CAddFunction(CFunction<T>* _f1, CFunction<T>* _f2) : CFunction2<T>(_f1, _f2) {};
	virtual T Execute(T x) const                {return f1->Execute(x) + f2->Execute(x);};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction() && f2->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return (f1->IsNullFunction() && f2->IsNullFunction()) || (f1->IsConstantFunction() && f2->IsConstantFunction() && f1->Execute(0.0)==-f2->Execute(0.0));}

	virtual CString GetName() const             {CString str = f1->GetName(); str += _T("+"); str += f2->GetName(); return str;};
	virtual CString GetTeX() const              {CString str = f1->GetTeX(); str += _T("+"); str += f2->GetTeX(); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CAddFunction<T>(f1->GetDerivate(), f2->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

// Subtraktion
template <class T>
class CSubFunction : public CFunction2<T>
{
public:
	CSubFunction(CFunction<T>* _f1, CFunction<T>* _f2) : CFunction2<T>(_f1, _f2) {};
	virtual T Execute(T x) const                {return f1->Execute(x) - f2->Execute(x);};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction() && f2->IsConstantFunction();}
	virtual bool IsNullFunction() const         {return (f1->IsNullFunction() && f2->IsNullFunction()) || (f1->IsConstantFunction() && f2->IsConstantFunction() && f1->Execute(0.0)==f2->Execute(0.0));}

	//virtual CString GetName() const             {CString str = _T("("); str += f1->GetName(); str += _T(")-("); str += f2->GetName(); str += _T(")"); return str;};
	virtual CString GetName() const             {return GetConcName(_T("-"));};
	virtual CString GetTeX() const              {CString str = f1->GetTeX(); str += _T("-"); str += f2->GetTeX(); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CSubFunction<T>(f1->GetDerivate(), f2->GetDerivate());};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

// Multiplikation
template <class T>
class CMulFunction : public CFunction2<T>
{
public:
	CMulFunction(CFunction<T>* _f1, CFunction<T>* _f2) : CFunction2<T>(_f1, _f2) {};
	virtual T Execute(T x) const                {return f1->Execute(x) * f2->Execute(x);};

	virtual bool IsConstantFunction() const     {return (f1->IsConstantFunction() && f2->IsConstantFunction()) || f1->IsNullFunction() || f2->IsNullFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction() || f2->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("*"));};
	virtual CString GetTeX() const              {CString str = _T("\\left("); str += f1->GetTeX(); str += _T("\\right)\\left("); str += f2->GetTeX(); str += _T("\\right)"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CAddFunction<T>(new CMulFunction<T>(f1->GetDuplicate(), f2->GetDerivate()), new CMulFunction<T>(f1->GetDerivate(), f2->GetDuplicate()));};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

// Division
template <class T>
class CDivFunction : public CFunction2<T>
{
public:
	CDivFunction(CFunction<T>* _f1, CFunction<T>* _f2) : CFunction2<T>(_f1, _f2) {};
	virtual T Execute(T x) const                {return f1->Execute(x) / f2->Execute(x);};

	virtual bool IsConstantFunction() const     {return (f1->IsConstantFunction() && f2->IsConstantFunction()) || f1->IsNullFunction();}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {return GetConcName(_T("/"));};
	virtual CString GetTeX() const              {CString str = _T("\\frac{"); str += f1->GetTeX(); str += _T("}{"); str += f2->GetTeX(); str += _T("}"); return str;};
	virtual CFunction<T>* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction<T>(new CSubFunction<T>(new CMulFunction<T>(f1->GetDerivate(), f2->GetDuplicate()), new CMulFunction<T>(f1->GetDuplicate(), f2->GetDerivate())), new CMulFunction<T>(f2->GetDuplicate(), f2->GetDuplicate()));};
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

// Potenzieren
template <class T>
class CPowerFunction : public CFunction2<T>
{
public:
	CPowerFunction(CFunction<T>* _f1, CFunction<T>* _f2) : CFunction2<T>(_f1, _f2) {};
	virtual T Execute(T x) const                {return powl(f1->Execute(x), f2->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsNullFunction() || f2->IsNullFunction() || (f1->IsConstantFunction() && f2->IsConstantFunction());}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	//virtual CString GetName() const             {CString str = _T("("); str += f1->GetName(); str += _T(")^("); str += f2->GetName(); str += _T(")"); return str;};
	virtual CString GetName() const             {return GetConcName(_T("^"));};
	virtual CString GetTeX() const              {CString str = _T("{"); str += f1->GetTeX(); str += _T("}^{"); str += f2->GetTeX(); str += _T("}"); return str;};
	virtual CFunction<T>* GetDerivate() const;
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
};

// c ^ f1(x)
template <class T>
class CPowerL0Function : public CFunction1<T>
{
public:
	CPowerL0Function(T _c, CFunction<T>* _f1) : c(_c), CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return powl(c, f1->Execute(x));};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction() && c==0.0;}
	virtual bool IsNullFunction() const         {return c==0.0;}

	virtual CString GetName() const             {CMathString str(c); str += _T("^("); str += f1->GetName(); str += _T(")"); return str;};
	virtual CString GetTeX() const              {CMathString str(c); str += _T("^{"); str += f1->GetName(); str += _T("}"); return str;};
	virtual CFunction<T>* GetDerivate() const;
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T c;
};

// f1(x) ^ c
template <class T>
class CPowerR0Function : public CFunction1<T>
{
public:
	CPowerR0Function(CFunction<T>* _f1, T _c) : c(_c), CFunction1<T>(_f1) {};
	virtual T Execute(T x) const                {return powl(f1->Execute(x), c);};

	virtual bool IsConstantFunction() const     {return f1->IsConstantFunction() || c==0.0;}
	virtual bool IsNullFunction() const         {return f1->IsNullFunction();}

	virtual CString GetName() const             {CString str = f1->GetName(); str += _T("^"); str += CMathString(c); return str;};
	virtual CString GetTeX() const              {CString str = f1->GetName(); str += _T("^"); str += CMathString(c); return str;};
	virtual CFunction<T>* GetDerivate() const;
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const;
private:
	T c;
};

// noch nicht verwendet
template <class T>
class CComponenteFunction : public CFunction<T>
{
public:
	CComponenteFunction(int _index) : index(_index)   {};
	virtual T Execute(T x) const                {return x[index];};

	virtual CString GetName() const             {CString str; str.Format(_T("x[%d]"), index); return str;};
	virtual CString GetTeX() const              {CString str; str.Format(_T("x_{%d}"), index); return str;};
	virtual CFunction<T>* GetDerivate() const   {return new CNullFunction<T>;}; // not implemented
	virtual CFunction<T>* GetDuplicate(bool simplify = true) const  {return new CComponenteFunction<T>(index);};
private:
	int index;
};

template <class T>
T CFunction<T>::Derivate(T x, int grad, double h) const
{
	switch (grad)
	{
	case 0:
	{
		return Execute(x);
	}
	case 1:
	{
		T y1 = Execute(x);
		T y2 = Execute(x+h);
		return (y2-y1)/h;
	}
	case 2:
	{
		T y1 = Execute(x-h);
		T y2 = Execute(x);
		T y3 = Execute(x+h);
		return (2*y2-y1-y3)/(2*h*h);
	}
	default:
	{
		T y1 = Derivate(x+h, grad-1, h);
		T y2 = Derivate(x, grad-1, h);
		return (y2-y1)/h;
	}
	}
};

template <class T>
T CFunction<T>::Nullstelle_Newton(T x/*StartWert*/, double tol) const
{
	T y = Execute(x);
	while (fabsl(y)>tol)
	{
		T z = Derivate(x);
		x -= y/z;
		y = Execute(x);
	}
	return x;
};

template <class T>
T CFunction<T>::Integral_Trapezregel(T x1, T x2, long nIntervals, double /*tol*/) const
{
	T summe = 0;
	T delta = (x2-x1) / nIntervals;
	T u = x1;
	summe += delta/2 * Execute(u);
	u += delta;
	for (int i=1; i<nIntervals; i++)
	{
		summe += delta * Execute(u);
		u += delta;
	}
	summe += delta/2 * Execute(u);
	return summe;
};

template <class T>
T CFunction<T>::Integral_Mittelpunktregel(T x1, T x2, long nIntervals, double /*tol*/) const
{
	T summe = 0;
	T delta = (x2-x1) / nIntervals;
	T u = x1;
	for (int i=0; i<nIntervals; i++)
	{
		summe += delta * Execute(u+delta/2);
		u += delta;
	}
	return summe;
};

template <class T>
T CFunction<T>::Integral_Simpsonregel(T x1, T x2, long nIntervals, double /*tol*/) const
{
	T summe = 0;
	// nIntervals mu� gerade sein, Intervall-Punkte: 0 bis 2m
	if (nIntervals%2)
		nIntervals++;
	T delta = (x2-x1) / nIntervals;
	T u = x1;
	summe += delta/3 * Execute(u);        // 0
	u += delta;
	summe += 4*delta/3 * Execute(u);      // 1
	u += delta;
	for (long i=1; i<nIntervals/2; i++)
	{
		summe += 4*delta/3 * Execute(u);  // 2j,   von 2 bis 2m-2
		u += delta;
		summe += 2*delta/3 * Execute(u);  // 2j+1, von 3 bis 2m-1
		u += delta;
	}
	summe += delta/3 * Execute(u);        // 2m
	return summe;
};

template <class T>
bool CFunction<T>::IsConstFunction(CString& str, const char* Token)
{
	// Token OK ?
	if (strnicmp(str, Token, strlen(Token)) != 0) return false;
	// Nach Token Klammer auf oder leer ?
	if (str.GetAt(strlen(Token))!='(' && str.GetAt(strlen(Token))!=' ') return false;
	// Verbliebener Ausdruck Identit�t ?
	CString str1 = str.Mid(strlen(Token)+1);
	str1 = str1.Left(str1.GetLength()-1);
	if (!CFunction<T>::IsConst(str.Mid(strlen(Token)))) return false;
	str = str1;
	// Alle Tests �berstanden -> true zur�ckgeben
	return true;
};

template <class T>
bool CFunction<T>::IsPureFunction(CString& str, const char* Token, const char* Var)
{
	// Token OK ?
	if (strnicmp(str, Token, strlen(Token)) != 0) return false;
	// Nach Token Klammer auf oder leer ?
	if (str.GetAt(strlen(Token))!='(' && str.GetAt(strlen(Token))!=' ') return false;
	// Verbliebener Ausdruck Identit�t ?
	if (!CFunction<T>::IsIdentity(str.Mid(strlen(Token)), Var)) return false;
	// Alle Tests �berstanden -> true zur�ckgeben
	return true;
};

template <class T>
bool CFunction<T>::IsFunction(CString& str, const char* Token)
{
	if (strnicmp(str, Token, strlen(Token)) != 0) return false;
	if (str.GetAt(strlen(Token))!='(' && str.GetAt(strlen(Token))!=' ') return false;
	int Level = 0;
	for (int i=strlen(Token); i<str.GetLength(); i++)
	{
		switch (str[i])
		{
		case '(': Level++; break;
		case ')': Level--; break;
		}
		if (Level==0 && i<str.GetLength()-1) return false;
	}
	if (Level!=0) return false;
	str = str.Mid(strlen(Token));
	return true;
};

template <class T>
bool CFunction<T>::IsConst(const char* str)
{
	// Konstanten abfragen
	CString str1(str);
	str1.TrimLeft();
	str1.TrimRight();
	if (stricmp(str1, _T("M_E"))==0)        return true;
	if (stricmp(str1, _T("M_LOG2E"))==0)    return true;
	if (stricmp(str1, _T("M_LOG10E"))==0)   return true;
	if (stricmp(str1, _T("M_LN2"))==0)      return true;
	if (stricmp(str1, _T("M_LN10"))==0)     return true;
	if (stricmp(str1, _T("M_PI_2"))==0)     return true;
	if (stricmp(str1, _T("M_PI_4"))==0)     return true;
	if (stricmp(str1, _T("M_PI"))==0)       return true;
	if (stricmp(str1, _T("M_1_PI"))==0)     return true;
	if (stricmp(str1, _T("M_2_PI"))==0)     return true;
	if (stricmp(str1, _T("M_1_SQRTPI"))==0) return true;
	if (stricmp(str1, _T("M_2_SQRTPI"))==0) return true;
	if (stricmp(str1, _T("M_SQRT2"))==0)    return true;
	if (stricmp(str1, _T("M_SQRT_2"))==0)   return true;
	if (stricmp(str1, _T("PI"))==0)         return true;
	char* stopstring;
	T x;
	x = strtod(str, &stopstring);
	return (stopstring==NULL || strlen(stopstring)==0) ? true : false;
};

template <class T>
T CFunction<T>::Value(const char* str)
{
	CString str1(str);
	str1.TrimLeft();
	str1.TrimRight();
	if (stricmp(str1, _T("M_E"))==0)        return 2.71828182845904523536;
	if (stricmp(str1, _T("M_LOG2E"))==0)    return 1.44269504088896340736;
	if (stricmp(str1, _T("M_LOG10E"))==0)   return 0.434294481903251827651;
	if (stricmp(str1, _T("M_LN2"))==0)      return 0.693147180559945309417;
	if (stricmp(str1, _T("M_LN10"))==0)     return 2.30258509299404568402;
	if (stricmp(str1, _T("M_PI_2"))==0)     return 1.57079632679489661923;
	if (stricmp(str1, _T("M_PI_4"))==0)     return 0.785398163397448309616;
	if (stricmp(str1, _T("M_PI"))==0)       return 3.14159265358979323846;
	if (stricmp(str1, _T("M_1_PI"))==0)     return 0.318309886183790671538;
	if (stricmp(str1, _T("M_2_PI"))==0)     return 0.636619772367581343076;
	if (stricmp(str1, _T("M_1_SQRTPI"))==0) return 0.564189583547756286948;
	if (stricmp(str1, _T("M_2_SQRTPI"))==0) return 1.12837916709551257390;
	if (stricmp(str1, _T("M_SQRT2"))==0)    return 1.41421356237309504880;
	if (stricmp(str1, _T("M_SQRT_2"))==0)   return 0.707106781186547524401;
	if (stricmp(str1, _T("PI"))==0)         return 3.14159265358979323846;
	char* stopstring;
	T x;
	x = strtod(str, &stopstring);
	return x;
};

template <class T>
bool CFunction<T>::IsIdentity(const char* str, const char* Var)
{
	int i;
	int Level = 0;
	CString str1 = str;
	// Einschlie�ende Klammern beseitigen
	for (i=0; i<str1.GetLength(); i++)
	{
		switch (str1[i])
		{
		case '(': Level++; continue;
		case ')': Level--; continue;
		}
		if (Level==0 && i<str1.GetLength()-1)
		{
			Level = -1; // Markierung
			break;
		}
	}
	if (Level!=-1)
	{
		while (str1[0]=='(' && str1[str1.GetLength()-1]==')')
		{
			str1 = str1.Mid(1, str1.GetLength()-2);
		}
	}
	// F�hrende Leerzeichen und positive Vorzeichen entfernen
	while (str1[0]=='+' || str1[0]==' ') 
	{
		str1 = str1.Mid(1);
	}
	return (stricmp(str1, Var)==0) ? true : false;
};

template <class T>
CFunction<T>* CFunction<T>::Parse1(const char* str, const char* Var)
{
	CString str1 = str;
	return CFunction<T>::Parse(str1, Var);
};

template <class T>
CFunction<T>* CFunction<T>::Parse(CString& str, const char* Var)
{
	int i;
	int Level = 0;
	CMathString str1;
	CMathString str2;
	// Punkte durch Kommas ersetzen, alles runde Klammern
	CMathString::Replace_All(str, _T("."), _T(","));
	CMathString::Replace_All(str, _T("["), _T("("));
	CMathString::Replace_All(str, _T("]"), _T(")"));
	CMathString::Replace_All(str, _T("{"), _T("("));
	CMathString::Replace_All(str, _T("}"), _T(")"));
	// Einschlie�ende Klammern beseitigen
	for (i=0; i<str.GetLength(); i++)
	{
		switch (str[i])
		{
		case '(': Level++; continue;
		case ')': Level--; continue;
		}
		if (Level==0 && i<str.GetLength()-1)
		{
			Level = -1; // Markierung
			break;
		}
	}
	if (Level!=-1)
	{
		while (str[0]=='(' && str[str.GetLength()-1]==')')
		{
			str = str.Mid(1, str.GetLength()-2);
		}
	}
	// F�hrende und abschlie�ende Leerzeichen und positive Vorzeichen entfernen
	while (str[0]=='+' || str[0]==' ') 
	{
		str = str.Mid(1);
	}
	str.TrimRight();
/*	if (str[0]=='-')
	{
		CFunction<T>* f2 = CFunction<T>::Parse1(str.Mid(1), Var);
		return new CNegFunction<T>(f2);
	}*/
	// Zerlegen des Ausdrucks, Suche nach Operatoren
	Level=0;
	//for (i=0; i<str.GetLength(); i++)
	for (i=str.GetLength()-1; i>=0; i--)
	{
		// Verarbeitung von Klammern
		switch (str[i])
		{
		case '(': Level--; continue;
		case ')': Level++; continue;
		}
		// Weiterarbeiten nur, wenn in �u�erer Ebene
		if (Level>0) continue;
		// Operatoren des niedrigsten Ranges
		if (str[i]=='+' && Level==0 && i>0 && IsConst(str.Left(i)) && IsConst(str.Mid(i+1)))
		{
			return new CConstFunction<T>(CFunction<T>::Value(str.Left(i)) + CFunction<T>::Value(str.Mid(i+1)));
		}
		if (str[i]=='+' && Level==0 && i>0 && IsConst(str.Left(i)))
		{
			CFunction<T>* f2 = CFunction<T>::Parse1(str.Mid(i+1), Var);
			CFunction<T>* f3 = new CAdd0Function<T>(f2, CFunction<T>::Value(str.Left(i)));
			if (f3->IsNullFunction())
			{
				delete f3;
				return new CNullFunction<T>();
			}
			if (f3->IsConstantFunction())
			{
				T value1 = f3->Execute(0.0);
				delete f3;
				return new CConstFunction<T>(value1);
			}
			return f3;
		}
		if (str[i]=='+' && Level==0 && i>0 && IsConst(str.Mid(i+1)))
		{
			CFunction<T>* f1 = CFunction<T>::Parse1(str.Left(i), Var);
			CFunction<T>* f3 = new CAdd0Function<T>(f1, CFunction<T>::Value(str.Mid(i+1)));
			if (f3->IsNullFunction())
			{
				delete f3;
				return new CNullFunction<T>();
			}
			if (f3->IsConstantFunction())
			{
				T value1 = f3->Execute(0.0);
				delete f3;
				return new CConstFunction<T>(value1);
			}
			return f3;
		}
		if (str[i]=='+' && Level==0 && i>0)
		{
			CFunction<T>* f1 = CFunction<T>::Parse1(str.Left(i), Var);
			if (str.Left(i) == str.Mid(i+1))
			{
				return new CMul0Function<T>(f1, 2);
			}
			CFunction<T>* f2 = CFunction<T>::Parse1(str.Mid(i+1), Var);
			CFunction<T>* f3 = new CAddFunction<T>(f1, f2);
			if (f3->IsNullFunction())
			{
				delete f3;
				return new CNullFunction<T>();
			}
			if (f3->IsConstantFunction())
			{
				T value1 = f3->Execute(0.0);
				delete f3;
				return new CConstFunction<T>(value1);
			}
			return f3;
		}
		if (str[i]=='-' && Level==0 && i==0 && IsConst(str.Mid(i+1)))
		{
			return new CConstFunction<T>(CFunction<T>::Value(str));
		}
		if (str[i]=='-' && Level==0 && i==0)
		{
			CFunction<T>* f1 = CFunction<T>::Parse1(str.Mid(i+1), Var);
			if (f1->IsNullFunction())
			{
				delete f1;
				return new CNullFunction<T>();
			}
			if (f1->IsConstantFunction())
			{
				T value1 = f1->Execute(0.0);
				delete f1;
				return new CConstFunction<T>(-value1);
			}
			return new CNegFunction<T>(f1);
		}
		if (str[i]=='-' && Level==0 && i>0 && IsConst(str.Left(i)) && IsConst(str.Mid(i+1)))
		{
			return new CConstFunction<T>(CFunction<T>::Value(str.Left(i)) - CFunction<T>::Value(str.Mid(i+1)));
		}
		if (str[i]=='-' && Level==0 && i>0 && IsConst(str.Left(i)))
		{
			CFunction<T>* f2 = CFunction<T>::Parse1(str.Mid(i+1), Var);
			CFunction<T>* f3 = new CSubL0Function<T>(CFunction<T>::Value(str.Left(i)), f2);
			if (f3->IsNullFunction())
			{
				delete f3;
				return new CNullFunction<T>();
			}
			if (f3->IsConstantFunction())
			{
				T value1 = f3->Execute(0.0);
				delete f3;
				return new CConstFunction<T>(value1);
			}
			return f3;
		}
		if (str[i]=='-' && Level==0 && i>0 && IsConst(str.Mid(i+1)))
		{
			CFunction<T>* f1 = CFunction<T>::Parse1(str.Left(i), Var);
			CFunction<T>* f3 = new CSubR0Function<T>(f1, CFunction<T>::Value(str.Mid(i+1)));
			if (f3->IsNullFunction())
			{
				delete f3;
				return new CNullFunction<T>();
			}
			if (f3->IsConstantFunction())
			{
				T value1 = f3->Execute(0.0);
				delete f3;
				return new CConstFunction<T>(value1);
			}
			return f3;
		}
		if (str[i]=='-' && Level==0 && i>0)
		{
			if (str.Left(i) == str.Mid(i+1))
			{
				return new CNullFunction<T>;
			}
			CFunction<T>* f1 = CFunction<T>::Parse1(str.Left(i), Var);
			CFunction<T>* f2 = CFunction<T>::Parse1(str.Mid(i+1), Var);
			CFunction<T>* f3 = new CSubFunction<T>(f1, f2);
			if (f3->IsNullFunction())
			{
				delete f3;
				return new CNullFunction<T>();
			}
			if (f3->IsConstantFunction())
			{
				T value1 = f3->Execute(0.0);
				delete f3;
				return new CConstFunction<T>(value1);
			}
			return f3;
		}
	}
	Level=0;
	//for (i=0; i<str.GetLength(); i++)
	for (i=str.GetLength()-1; i>=0; i--)
	{
		// Verarbeitung von Klammern
		switch (str[i])
		{
		case '(': Level--; continue;
		case ')': Level++; continue;
		}
		if (str[i]=='*' && Level==0 && i>0)
		{
			str1 = str.Left(i);
			str2 = str.Mid(i+1);
			if (IsConst(str1) && IsConst(str2))
			{
				T value = CFunction<T>::Value(str1) * CFunction<T>::Value(str2);
				if (value == 0.0)
					return new CNullFunction<T>();
				return new CConstFunction<T>(value);
			}
			if (IsConst(str1) && !IsConst(str2))
			{
				T value = CFunction<T>::Value(str1);
				if (value == 0.0)
					return new CNullFunction<T>();
				CFunction<T>* f1 = CFunction<T>::Parse1(str2, Var);
				CFunction<T>* f3 = new CMul0Function<T>(f1, value);
				if (f3->IsNullFunction())
				{
					delete f3;
					return new CNullFunction<T>();
				}
				if (f3->IsConstantFunction())
				{
					T value1 = f3->Execute(0.0);
					delete f3;
					return new CConstFunction<T>(value1);
				}
				return f3;
			}
			if (!IsConst(str1) && IsConst(str2))
			{
				T value = CFunction<T>::Value(str2);
				if (value == 0.0)
					return new CNullFunction<T>();
				CFunction<T>* f1 = CFunction<T>::Parse1(str1, Var);
				CFunction<T>* f3 = new CMul0Function<T>(f1, value);
				if (f3->IsNullFunction())
				{
					delete f3;
					return new CNullFunction<T>();
				}
				if (f3->IsConstantFunction())
				{
					T value1 = f3->Execute(0.0);
					delete f3;
					return new CConstFunction<T>(value1);
				}
				return f3;
			}
			if (!IsConst(str1) && !IsConst(str2))
			{
				CFunction<T>* f1 = CFunction<T>::Parse1(str.Left(i), Var);
				if (str1 == str2 && str1 == Var)
				{
					return new CSqr1Function<T>;
				}
				if (str1 == str2 && str1 != Var)
				{
					return new CSqrFunction<T>(f1);
				}
				CFunction<T>* f2 = CFunction<T>::Parse1(str.Mid(i+1), Var);
				CFunction<T>* f3 = new CMulFunction<T>(f1, f2);
				if (f3->IsNullFunction())
				{
					delete f3;
					return new CNullFunction<T>();
				}
				if (f3->IsConstantFunction())
				{
					T value1 = f3->Execute(0.0);
					delete f3;
					return new CConstFunction<T>(value1);
				}
				return f3;
			}
		}
		if (str[i]=='/' && Level==0 && i>0)
		{
			str1 = str.Left(i);
			str2 = str.Mid(i+1);
			if (IsConst(str1) && IsConst(str2))
			{
				return new CConstFunction<T>(CFunction<T>::Value(str1) / CFunction<T>::Value(str2));
			}
			if (IsConst(str1) && !IsConst(str2))
			{
				T value = CFunction<T>::Value(str1);
				if (value == 0.0)
					return new CNullFunction<T>();
				CFunction<T>* f1 = CFunction<T>::Parse1(str2, Var);
				CFunction<T>* f3 = new CDivL0Function<T>(value, f1);
				if (f3->IsNullFunction())
				{
					delete f3;
					return new CNullFunction<T>();
				}
				if (f3->IsConstantFunction())
				{
					T value1 = f3->Execute(0.0);
					delete f3;
					return new CConstFunction<T>(value1);
				}
				return f3;
			}
			if (!IsConst(str1) && IsConst(str2))
			{
				T value = CFunction<T>::Value(str2);
				if (value == 0.0)
					return new CNullFunction<T>();
				CFunction<T>* f1 = CFunction<T>::Parse1(str1, Var);
				CFunction<T>* f3 = new CDivR0Function<T>(f1, value);
				if (f3->IsNullFunction())
				{
					delete f3;
					return new CNullFunction<T>();
				}
				if (f3->IsConstantFunction())
				{
					T value1 = f3->Execute(0.0);
					delete f3;
					return new CConstFunction<T>(value1);
				}
				return f3;
			}
			if (!IsConst(str1) && !IsConst(str2))
			{
				if (str1 == str2)
				{
					return new CConstFunction<T>(1.0);
				}
				CFunction<T>* f1 = CFunction<T>::Parse1(str.Left(i), Var);
				CFunction<T>* f2 = CFunction<T>::Parse1(str.Mid(i+1), Var);
				CFunction<T>* f3 = new CDivFunction<T>(f1, f2);
				if (f3->IsNullFunction())
				{
					delete f3;
					return new CNullFunction<T>();
				}
				if (f3->IsConstantFunction())
				{
					T value = f3->Execute(0.0);
					delete f3;
					return new CConstFunction<T>(value);
				}
				return f3;
			}
		}
	}
	Level=0;
	//for (i=0; i<str.GetLength(); i++)
	for (i=str.GetLength()-1; i>=0; i--)
	{
		// Verarbeitung von Klammern
		switch (str[i])
		{
		case '(': Level--; continue;
		case ')': Level++; continue;
		}
		if (str[i]=='^' && Level==0 && i>0)
		{
			str1 = str.Left(i);
			str2 = str.Mid(i+1);
			if (IsConst(str1) && IsConst(str2))
			{
				return new CConstFunction<T>(powl(CFunction<T>::Value(str1), CFunction<T>::Value(str2)));
			}
			if (IsConst(str1) && !IsConst(str2))
			{
				CFunction<T>* f1 = CFunction<T>::Parse1(str2, Var);
				return new CPowerL0Function<T>(CFunction<T>::Value(str1), f1);
			}
			if (!IsConst(str1) && IsConst(str2))
			{
				CFunction<T>* f1 = CFunction<T>::Parse1(str1, Var);
				return new CPowerR0Function<T>(f1, CFunction<T>::Value(str2));
			}
			if (!IsConst(str1) && !IsConst(str2))
			{
				CFunction<T>* f1 = CFunction<T>::Parse1(str.Left(i), Var);
				CFunction<T>* f2 = CFunction<T>::Parse1(str.Mid(i+1), Var);
				return new CPowerFunction<T>(f1, f2);
			}
		}
	}
	// Suche nach Funktionen
	if (IsConstFunction(str, _T("EXP"))) 
	{
		T value = CFunction<T>::Value(str);
		return new CConstFunction<T>(expl(value));
	}
	if (IsConstFunction(str, _T("SIN"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(sinl(value));
	}
	if (IsConstFunction(str, _T("COS"))) 
	{
		T value = CFunction<T>::Value(str);
		return new CConstFunction<T>(cosl(value));
	}
	if (IsConstFunction(str, _T("TAN"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(tanl(value));
	}
	if (IsConstFunction(str, _T("COT"))) 
	{
		T value = CFunction<T>::Value(str);
		return new CConstFunction<T>(cosl(value)/sinl(value));
	}
	if (IsConstFunction(str, _T("SINH"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(sinhl(value));
	}
	if (IsConstFunction(str, _T("COSH"))) 
	{
		T value = CFunction<T>::Value(str);
		return new CConstFunction<T>(coshl(value));
	}
	if (IsConstFunction(str, _T("TANH"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(tanhl(value));
	}
	if (IsConstFunction(str, _T("ABS"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(fabsl(value));
	}
	if (IsConstFunction(str, _T("CEIL"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(ceill(value));
	}
	if (IsConstFunction(str, _T("FLOOR"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(floorl(value));
	}
	if (IsConstFunction(str, _T("LG"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 1.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(log10l(value));
	}
	if (IsConstFunction(str, _T("LN"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 1.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(logl(value));
	}
	if (IsConstFunction(str, _T("SQRT"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(sqrtl(value));
	}
	if (IsConstFunction(str, _T("ASIN"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(asinl(value));
	}
	if (IsConstFunction(str, _T("ACOS"))) 
	{
		T value = CFunction<T>::Value(str);
		return new CConstFunction<T>(acosl(value));
	}
	if (IsConstFunction(str, _T("ATAN"))) 
	{
		T value = CFunction<T>::Value(str);
		if (value == 0.0)
			return new CNullFunction<T>();
		return new CConstFunction<T>(atanl(value));
	}
	if (IsConstFunction(str, _T("GAMMA"))) 
	{
		T value = CFunction<T>::Value(str);
		return new CConstFunction<T>(FGammal(value));
	}

	if (IsPureFunction(str, _T("EXP"), Var)) 
		return new CExp1Function<T>;
	if (IsPureFunction(str, _T("SIN"), Var)) 
		return new CSin1Function<T>;
	if (IsPureFunction(str, _T("COS"), Var)) 
		return new CCos1Function<T>;
	if (IsPureFunction(str, _T("TAN"), Var)) 
		return new CTan1Function<T>;
	if (IsPureFunction(str, _T("COT"), Var)) 
		return new CCot1Function<T>;
	if (IsPureFunction(str, _T("SINH"), Var)) 
		return new CSinh1Function<T>;
	if (IsPureFunction(str, _T("COSH"), Var)) 
		return new CCosh1Function<T>;
	if (IsPureFunction(str, _T("TANH"), Var)) 
		return new CTanh1Function<T>;
	if (IsPureFunction(str, _T("COTH"), Var)) 
		return new CCoth1Function<T>;
	if (IsPureFunction(str, _T("ABS"), Var)) 
		return new CAbs1Function<T>;
	if (IsPureFunction(str, _T("CEIL"), Var)) 
		return new CCeil1Function<T>;
	if (IsPureFunction(str, _T("FLOOR"), Var)) 
		return new CFloor1Function<T>;
	if (IsPureFunction(str, _T("LG"), Var)) 
		return new CLog101Function<T>;
	if (IsPureFunction(str, _T("LN"), Var)) 
		return new CLog1Function<T>;
	if (IsPureFunction(str, _T("SQRT"), Var)) 
		return new CSqrt1Function<T>;
	if (IsPureFunction(str, _T("ASIN"), Var)) 
		return new CAsin1Function<T>;
	if (IsPureFunction(str, _T("ACOS"), Var)) 
		return new CAcos1Function<T>;
	if (IsPureFunction(str, _T("ATAN"), Var)) 
		return new CAtan1Function<T>;
	if (IsPureFunction(str, _T("GAMMA"), Var)) 
		return new CGamma1Function<T>;

	if (IsFunction(str, _T("EXP"))) 
		return new CExpFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("SIN"))) 
		return new CSinFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("COS"))) 
		return new CCosFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("TAN"))) 
		return new CTanFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("COT"))) 
		return new CCotFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("SINH"))) 
		return new CSinhFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("COSH"))) 
		return new CCoshFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("TANH"))) 
		return new CTanhFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("COTH"))) 
		return new CCothFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("ABS"))) 
		return new CAbsFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("CEIL"))) 
		return new CCeilFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("FLOOR"))) 
		return new CFloorFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("LG"))) 
		return new CLog10Function<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("LN"))) 
		return new CLogFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("SQRT"))) 
		return new CSqrtFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("ASIN"))) 
		return new CAsinFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("ACOS"))) 
		return new CAcosFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("ATAN"))) 
		return new CAtanFunction<T>(CFunction<T>::Parse(str, Var));
	if (IsFunction(str, _T("GAMMA"))) 
		return new CGammaFunction<T>(CFunction<T>::Parse(str, Var));
	// x ?
	if (stricmp(str, Var)==0) 
		return new CIdentityFunction<T>;
	if (str[0]=='-') // Ist diese Position besser?
	{
		CFunction<T>* f2 = CFunction<T>::Parse1(str.Mid(1), Var);
		if (f2->IsNullFunction())
		{
			delete f2;
			return new CNullFunction<T>();
		}
		if (f2->IsConstantFunction())
		{
			T value = f2->Execute(0.0);
			delete f2;
			return new CConstFunction<T>(-value);
		}
		return new CNegFunction<T>(f2);
	}
#pragma warning ( disable : 4244 )
	return new CConstFunction<T>(CFunction<T>::Value(str));
#pragma warning ( default : 4244 )
};

template <class T>
CString CFunction1<T>::GetConcName(const char* basisfkt) const
{
	CString str = basisfkt;
	str += _T("(");
	str += f1->GetName();
	str += _T(")");
	return str;
};

template <class T>
CString CFunction2<T>::GetConcName(const char* basisfkt) const
{
	CString str = _T("(");
	str += f1->GetName();
	str += _T(")");
	str += basisfkt;
	str += _T("(");
	str += f2->GetName();
	str += _T(")");
	return str;
};

template <class T>
CString CPolynom1Function<T>::GetName() const
{
	CString str;
	str += CMathString(a1);
	str += _T("*x+");
	str += CMathString(a0);
	return str;
};

template <class T>
CString CPolynom1Function<T>::GetTeX() const
{
	CString str;
	str += CMathString(a1);
	str += _T("x+");
	str += CMathString(a0);
	return str;
};

template <class T>
CString CPolynom2Function<T>::GetName() const
{
	CString str;
	str += CMathString(a2);
	str += _T("*x^2+");
	str += CMathString(a1);
	str += _T("*x+");
	str += CMathString(a0);
	return str;
};

template <class T>
CString CPolynom2Function<T>::GetTeX() const
{
	CString str;
	str += CMathString(a2);
	str += _T("x^2+");
	str += CMathString(a1);
	str += _T("x+");
	str += CMathString(a0);
	return str;
};

template <class T>
CString CPolynom3Function<T>::GetName() const
{
	CString str;
	str += CMathString(a3);
	str += _T("*x^3+");
	str += CMathString(a2);
	str += _T("*x^2+");
	str += CMathString(a1);
	str += _T("*x+");
	str += CMathString(a0);
	return str;
};

template <class T>
CString CPolynom3Function<T>::GetTeX() const
{
	CString str;
	str += CMathString(a3);
	str += _T("x^3+");
	str += CMathString(a2);
	str += _T("x^2+");
	str += CMathString(a1);
	str += _T("x+");
	str += CMathString(a0);
	return str;
};

template <class T>
CString CPolynom4Function<T>::GetName() const
{
	CString str;
	str += CMathString(a4);
	str += _T("*x^4+");
	str += CMathString(a3);
	str += _T("*x^3+");
	str += CMathString(a2);
	str += _T("*x^2+");
	str += CMathString(a1);
	str += _T("*x+");
	str += CMathString(a0);
	return str;
};

template <class T>
CString CPolynom4Function<T>::GetTeX() const
{
	CString str;
	str += CMathString(a4);
	str += _T("x^4+");
	str += CMathString(a3);
	str += _T("x^3+");
	str += CMathString(a2);
	str += _T("x^2+");
	str += CMathString(a1);
	str += _T("x+");
	str += CMathString(a0);
	return str;
};

// f1(x) ^ f2(x)
template <class T>
CFunction<T>* CPowerFunction<T>::GetDerivate() const
{
	DERIVATE_TEST;
	return new CMulFunction<T>(GetDuplicate(), new CAddFunction<T>(new CMulFunction<T>(f2->GetDerivate(), new CLogFunction<T>(f1->GetDuplicate())),
										  new CDivFunction<T>(new CMulFunction<T>(f1->GetDerivate(), f2->GetDuplicate()), f1->GetDuplicate())));
};

// c ^ f1(x)
template <class T>
CFunction<T>* CPowerL0Function<T>::GetDerivate() const
{
	DERIVATE_TEST;
	return new CMulFunction<T>(GetDuplicate(), new CMul0Function<T>(f1->GetDerivate(), logl(c)));
};

// f1(x) ^ c
template <class T>
CFunction<T>* CPowerR0Function<T>::GetDerivate() const
{
	DERIVATE_TEST;
	if (c==0)
		return new CNullFunction<T>;
	if (c==1)
		return f1->GetDerivate();
	return new CMul0Function<T>(new CMulFunction<T>(new CPowerR0Function<T>(f1->GetDuplicate(), c-1), f1->GetDerivate()), c);
};

template <class T>
CFunction<T>* CNullFunction<T>::GetDuplicate(bool /*simplify*/ /*= true*/) const  
{
	return new CNullFunction<T>;
};

template <class T>
CFunction<T>* CPolynom1Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	if (simplify)
	{
		if (a1==0.0 && a0==0.0)
			return new CNullFunction<T>();
		if (a1==0.0)
			return new CConstFunction<T>(a0);
	}
	return new CPolynom1Function<T>(a0,a1);
};

template <class T>
CFunction<T>* CPolynom2Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	if (simplify)
	{
		if (a2==0.0 && a1==0.0 && a0==0.0)
			return new CNullFunction<T>();
		if (a2==0.0 && a1==0.0)
			return new CConstFunction<T>(a0);
		if (a2==0.0)
			return new CPolynom1Function<T>(a0, a1);
	}
	return new CPolynom2Function<T>(a0,a1,a2);
};

template <class T>
CFunction<T>* CPolynom3Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	if (simplify)
	{
		if (a3==0.0 && a2==0.0 && a1==0.0 && a0==0.0)
			return new CNullFunction<T>();
		if (a3==0.0 && a2==0.0 && a1==0.0)
			return new CConstFunction<T>(a0);
		if (a3==0.0 && a2==0.0)
			return new CPolynom1Function<T>(a0, a1);
		if (a3==0.0)
			return new CPolynom2Function<T>(a0, a1, a2);
	}
	return new CPolynom3Function<T>(a0,a1,a2,a3);
};

template <class T>
CFunction<T>* CPolynom4Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	if (simplify)
	{
		if (a4==0.0 && a3==0.0 && a2==0.0 && a1==0.0 && a0==0.0)
			return new CNullFunction<T>();
		if (a4==0.0 && a3==0.0 && a2==0.0 && a1==0.0)
			return new CConstFunction<T>(a0);
		if (a4==0.0 && a3==0.0 && a2==0.0)
			return new CPolynom1Function<T>(a0, a1);
		if (a4==0.0 && a3==0.0)
			return new CPolynom2Function<T>(a0, a1, a2);
		if (a4==0.0)
			return new CPolynom3Function<T>(a0, a1, a2, a3);
	}
	return new CPolynom4Function<T>(a0,a1,a2,a3,a4);
};

template <class T>
CFunction<T>* CExpFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CExpFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CSinFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CSinFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CCosFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CCosFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CTanFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CTanFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CCotFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CCotFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CAsinFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CAsinFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CAcosFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CAcosFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CAtanFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CAtanFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CAcotFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CAcotFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CSinhFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CSinhFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CCoshFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CCoshFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CTanhFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CTanhFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CCothFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CCothFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CSignFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CSignFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CAbsFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CAbsFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CCeilFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CCeilFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CFloorFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CFloorFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CLog10Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CLog10Function<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CLogFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CLogFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CLogarithmusFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CLogarithmusFunction<T>(f1->GetDuplicate(simplify), b);
};

template <class T>
CFunction<T>* CSqrFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CSqrFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CSqrtFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CSqrtFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CGammaFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CGammaFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CConstFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	if (simplify && c==0.0)
		return new CNullFunction<T>();
	return new CConstFunction<T>(c);
};

template <class T>
CFunction<T>* CNegFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CNegFunction<T>(f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CAdd0Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsNullFunction())
		{
			delete df1;
			return new CConstFunction<T>(c);
		}
		if (df1->IsConstantFunction())
		{
			T value = df1->Execute(0.0);
			delete df1;
			return new CConstFunction<T>(c+value);
		}
	}
	return new CAdd0Function<T>(df1, c);
};

template <class T>
CFunction<T>* CSubR0Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsNullFunction())
		{
			delete df1;
			return new CConstFunction<T>(-c);
		}
		if (df1->IsConstantFunction())
		{
			T value = df1->Execute(0.0);
			delete df1;
			return new CConstFunction<T>(value-c);
		}
	}
	return new CSubR0Function<T>(df1, c);
};

template <class T>
CFunction<T>* CSubL0Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsNullFunction())
		{
			delete df1;
			return new CConstFunction<T>(c);
		}
		if (df1->IsConstantFunction())
		{
			T value = df1->Execute(0.0);
			delete df1;
			return new CConstFunction<T>(c-value);
		}
	}
	return new CSubL0Function<T>(c, df1);
};

template <class T>
CFunction<T>* CMul0Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsNullFunction())
		{
			delete df1;
			return new CNullFunction<T>();
		}
		if (df1->IsConstantFunction())
		{
			T value = df1->Execute(0.0);
			delete df1;
			return new CConstFunction<T>(c*value);
		}
	}
	return new CMul0Function<T>(df1, c);
};

template <class T>
CFunction<T>* CDivL0Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsConstantFunction())
		{
			T value = df1->Execute(0.0);
			delete df1;
			return new CConstFunction<T>(c/value);
		}
	}
	return new CDivL0Function<T>(c, df1);
};

template <class T>
CFunction<T>* CDivR0Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsNullFunction())
		{
			delete df1;
			return new CNullFunction<T>();
		}
		if (df1->IsConstantFunction())
		{
			T value = df1->Execute(0.0);
			delete df1;
			return new CConstFunction<T>(value/c);
		}
	}
	return new CDivR0Function<T>(df1, c);
};

template <class T>
CFunction<T>* CAddFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	CFunction<T>* df2 = f2->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsNullFunction() && df2->IsNullFunction())
		{
			delete df1;
			delete df2;
			return new CNullFunction<T>();
		}
		if (df1->IsConstantFunction() && df2->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			T value2 = df2->Execute(0.0);
			delete df1;
			delete df2;
			return new CConstFunction<T>(value1 + value2);
		}
		if (df1->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			delete df1;
			return new CAdd0Function<T>(df2, value1);
		}
		if (df2->IsConstantFunction())
		{
			T value2 = df2->Execute(0.0);
			delete df2;
			return new CAdd0Function<T>(df1, value2);
		}
	}
	return new CAddFunction<T>(df1, df2);
};

template <class T>
CFunction<T>* CSubFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	CFunction<T>* df2 = f2->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsNullFunction() && df2->IsNullFunction())
		{
			delete df1;
			delete df2;
			return new CNullFunction<T>();
		}
		if (df1->IsConstantFunction() && df2->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			T value2 = df2->Execute(0.0);
			delete df1;
			delete df2;
			return new CConstFunction<T>(value1 - value2);
		}
		if (df1->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			delete df1;
			return new CSubL0Function<T>(value1, df2);
		}
		if (df2->IsConstantFunction())
		{
			T value2 = df2->Execute(0.0);
			delete df2;
			return new CSubR0Function<T>(df1, value2);
		}
	}
	return new CSubFunction<T>(df1, df2);
};

template <class T>
CFunction<T>* CMulFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	CFunction<T>* df2 = f2->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsNullFunction() || df2->IsNullFunction())
		{
			delete df1;
			delete df2;
			return new CNullFunction<T>();
		}
		if (df1->IsConstantFunction() && df2->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			T value2 = df2->Execute(0.0);
			delete df1;
			delete df2;
			return new CConstFunction<T>(value1 * value2);
		}
		if (df1->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			delete df1;
			return new CMul0Function<T>(df2, value1);
		}
		if (df2->IsConstantFunction())
		{
			T value2 = df2->Execute(0.0);
			delete df2;
			return new CMul0Function<T>(df1, value2);
		}
	}
	return new CMulFunction<T>(df1, df2);
};

template <class T>
CFunction<T>* CDivFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	CFunction<T>* df2 = f2->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsNullFunction())
		{
			delete df1;
			delete df2;
			return new CNullFunction<T>();
		}
		if (df1->IsConstantFunction() && df2->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			T value2 = df2->Execute(0.0);
			delete df1;
			delete df2;
			return new CConstFunction<T>(value1 / value2);
		}
		if (df1->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			delete df1;
			return new CDivL0Function<T>(value1, df2);
		}
		if (df2->IsConstantFunction())
		{
			T value2 = df2->Execute(0.0);
			delete df2;
			return new CDivR0Function<T>(df1, value2);
		}
	}
	return new CDivFunction<T>(df1, df2);
};

template <class T>
CFunction<T>* CPowerFunction<T>::GetDuplicate(bool simplify /*= true*/) const
{
	CFunction<T>* df1 = f1->GetDuplicate(simplify);
	CFunction<T>* df2 = f2->GetDuplicate(simplify);
	if (simplify)
	{
		if (df1->IsConstantFunction() && df2->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			T value2 = df2->Execute(0.0);
			delete df1;
			delete df2;
			return new CConstFunction<T>(powl(value1, value2));
		}
		if (df1->IsConstantFunction())
		{
			T value1 = df1->Execute(0.0);
			delete df1;
			return new CPowerL0Function<T>(value1, df2);
		}
		if (df2->IsConstantFunction())
		{
			T value2 = df2->Execute(0.0);
			delete df2;
			return new CPowerR0Function<T>(df1, value2);
		}
 	}
	return new CPowerFunction<T>(df1, df2);
};

template <class T>
CFunction<T>* CPowerL0Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CPowerL0Function<T>(c, f1->GetDuplicate(simplify));
};

template <class T>
CFunction<T>* CPowerR0Function<T>::GetDuplicate(bool simplify /*= true*/) const
{
	return new CPowerR0Function<T>(f1->GetDuplicate(simplify), c);
};

#else
#error already included
#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions