www.pudn.com > 1.rar > FktParser.h


#ifndef __FUNCTIONPARSER_H 
#define __FUNCTIONPARSER_H 
   
//#include "stdafx.h" 
 
// Klassen in diesem Header-File (Forward-Deklarationen) 
/* 
template   class CFunction; 
	template   class CNullFunction; 
	template   class CIdentityFunction; 
	template   class CPolynom1Function; 
	template   class CPolynom2Function; 
	template   class CPolynom3Function; 
	template   class CPolynom4Function; 
	template   class CExp1Function; 
	template   class CSin1Function; 
	template   class CCos1Function; 
	template   class CTan1Function; 
	template   class CCot1Function; 
	template   class CAsin1Function; 
	template   class CAcos1Function; 
	template   class CAtan1Function; 
	template   class CSinh1Function; 
	template   class CCosh1Function; 
	template   class CTanh1Function; 
	template   class CCoth1Function; 
	template   class CSign1Function; 
	template   class CAbs1Function; 
	template   class CCeil1Function; 
	template   class CFloor1Function; 
	template   class CLog101Function; 
	template   class CLog1Function; 
	template   class CLogarithmus1Function; 
	template   class CSqrt1Function; 
	template   class CSqr1Function; 
	template   class CGamma1Function; 
	template   class CConstFunction; 
 
	template   class CFunction1; 
		template   class CExpFunction; 
		template   class CSinFunction; 
		template   class CCosFunction; 
		template   class CTanFunction; 
		template   class CCotFunction; 
		template   class CAsinFunction; 
		template   class CAcosFunction; 
		template   class CAtanFunction; 
		template   class CSinhFunction; 
		template   class CCoshFunction; 
		template   class CTanhFunction; 
		template   class CCothFunction; 
		template   class CSignFunction; 
		template   class CAbsFunction; 
		template   class CCeilFunction; 
		template   class CFloorFunction; 
		template   class CLog10Function; 
		template   class CLogFunction; 
		template   class CLogarithmusFunction; 
		template   class CSqrFunction; 
		template   class CSqrtFunction; 
		template   class CGammaFunction; 
		template   class CNegFunction; 
		template   class CAdd0Function; 
		template   class CSubR0Function; 
		template   class CSubL0Function; 
		template   class CMul0Function; 
		template   class CDivL0Function; 
		template   class CDivR0Function; 
		template   class CPowerL0Function; 
		template   class CPowerR0Function; 
 
	template   class CFunction2; 
		template   class CAddFunction; 
		template   class CSubFunction; 
		template   class CMulFunction; 
		template   class CDivFunction; 
		template   class CPowerFunction; 
		template   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(); 
 
// Basisklasse, abstrakt 
template  
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* GetDerivate() const = 0;  // abstrakte Funktion, muß überschrieben werden 
	virtual CFunction* 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* Parse(CString& str, const char* Var = _T("X")); 
	static CFunction* 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 CFunction1 : public CFunction 
{ 
public: 
	CFunction1(CFunction* _f1) : f1(_f1) {}; 
	virtual ~CFunction1()                 {delete f1;}; 
 
	virtual CString GetConcName(const char* basisfkt) const; 
protected: 
	CFunction* f1; 
}; 
 
// Funktion mit zwei eingebetteten Funktionen, immer noch abstrakt! 
template  
class CFunction2 : public CFunction 
{ 
public: 
	CFunction2(CFunction* _f1, CFunction* _f2) : f1(_f1), f2(_f2) {}; 
	virtual ~CFunction2()                 {delete f1; delete f2;}; 
 
	virtual CString GetConcName(const char* basisfkt) const; 
protected: 
	CFunction* f1; 
	CFunction* f2; 
}; 
 
// Nullfunktion 
template  
class CNullFunction : public CFunction 
{ 
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* GetDerivate() const   {return new CNullFunction;}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
// Identität 
template  
class CIdentityFunction : public CFunction 
{ 
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* GetDerivate() const   {return new CConstFunction(1);}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CIdentityFunction;}; 
}; 
 
// Polynome 
template  
class CPolynom1Function : public CFunction 
{ 
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* GetDerivate() const   {DERIVATE_TEST; return new CConstFunction(a1);}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T a0; 
	T a1;  
}; 
 
template  
class CPolynom2Function : public CFunction 
{ 
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* GetDerivate() const   {DERIVATE_TEST; return new CPolynom1Function(a1,2*a2);}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T a0; 
	T a1;  
	T a2; 
}; 
 
template  
class CPolynom3Function : public CFunction 
{ 
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* GetDerivate() const   {DERIVATE_TEST; return new CPolynom2Function(a1,2*a2,3*a3);}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T a0; 
	T a1;  
	T a2; 
	T a3; 
}; 
 
template  
class CPolynom4Function : public CFunction 
{ 
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* GetDerivate() const   {DERIVATE_TEST; return new CPolynom3Function(a1,2*a2,3*a3,4*a4);}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T a0; 
	T a1;  
	T a2; 
	T a3; 
	T a4; 
}; 
 
// Exponentialfunktion 
template  
class CExpFunction : public CFunction1 
{ 
public: 
	CExpFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CExpFunction(f1->GetDuplicate()), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CExp1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CExp1Function;}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CExp1Function;}; 
}; 
 
// Trigonometrische Funktionen 
template  
class CSinFunction : public CFunction1 
{ 
public: 
	CSinFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CCosFunction(f1->GetDuplicate()), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CCosFunction : public CFunction1 
{ 
public: 
	CCosFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction(new CMulFunction(new CSinFunction(f1->GetDuplicate()), f1->GetDerivate()));}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CTanFunction : public CFunction1 
{ 
public: 
	CTanFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CAdd0Function(new CMulFunction(new CTanFunction(f1->GetDuplicate()), new CTanFunction(f1->GetDuplicate())), 1), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CCotFunction : public CFunction1 
{ 
public: 
	CCotFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction(new CMulFunction(new CAdd0Function(new CMulFunction(new CCotFunction(f1->GetDuplicate()), new CCotFunction(f1->GetDuplicate())), 1), f1->GetDerivate()));}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CAsinFunction : public CFunction1 
{ 
public: 
	CAsinFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CDivL0Function(1, new CSqrtFunction(new CPolynom2Function(1, 0, -1))), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CAcosFunction : public CFunction1 
{ 
public: 
	CAcosFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CDivL0Function(-1, new CSqrtFunction(new CPolynom2Function(1, 0, -1))), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CAtanFunction : public CFunction1 
{ 
public: 
	CAtanFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CDivL0Function(1, new CPolynom2Function(1, 0, 1)), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CAcotFunction : public CFunction1 
{ 
public: 
	CAcotFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CDivL0Function(-1, new CPolynom2Function(1, 0, 1))), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CSin1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CCos1Function;}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CSin1Function;}; 
}; 
 
template  
class CCos1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CNegFunction(new CSin1Function);}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CCos1Function;}; 
}; 
 
template  
class CTan1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CAdd0Function(new CMulFunction(new CTan1Function, new CTan1Function), 1);}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CTan1Function;}; 
}; 
 
template  
class CCot1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CNegFunction(new CAdd0Function(new CMulFunction(new CCot1Function, new CCot1Function), 1));}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CCot1Function;}; 
}; 
 
template  
class CAsin1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(1, new CSqrtFunction(new CPolynom2Function(1,0,-1)));}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CAsin1Function;}; 
}; 
 
template  
class CAcos1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(-1, new CSqrtFunction(new CPolynom2Function(1,0,-1)));}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CAcos1Function;}; 
}; 
 
template  
class CAtan1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(1, new CPolynom2Function(1, 0, 1));}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CAtan1Function;}; 
}; 
 
template  
class CAcot1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(-1, new CPolynom2Function(1, 0, 1));}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const  {return new CAcot1Function;}; 
}; 
 
// Hyperbolische Funktionen 
template  
class CSinhFunction : public CFunction1 
{ 
public: 
	CSinhFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CCoshFunction(f1->GetDuplicate()), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CCoshFunction : public CFunction1 
{ 
public: 
	CCoshFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CSinhFunction(f1->GetDuplicate()), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CTanhFunction : public CFunction1 
{ 
public: 
	CTanhFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CDivL0Function(1, new CMulFunction(new CCoshFunction(f1->GetDuplicate()), new CCoshFunction(f1->GetDuplicate()))), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CCothFunction : public CFunction1 
{ 
public: 
	CCothFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CDivL0Function(-1, new CMulFunction(new CSinhFunction(f1->GetDuplicate()), new CSinhFunction(f1->GetDuplicate()))), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CSinh1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CCosh1Function;}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CSinh1Function;}; 
}; 
 
template  
class CCosh1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CSinh1Function;}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CCosh1Function;}; 
}; 
 
template  
class CTanh1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(1, new CMulFunction(new CCosh1Function, new CCosh1Function));}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CTanh1Function;}; 
}; 
 
template  
class CCoth1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(-1, new CMulFunction(new CSinh1Function, new CSinh1Function));}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CCoth1Function;}; 
}; 
 
// Vorzeichen-Funktion 
template  
class CSignFunction : public CFunction1 
{ 
public: 
	CSignFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CNullFunction;}; // !! eigentlich nicht korrekt, aber das überhaupt etwas definiert ist! 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CSign1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CNullFunction;}; // !! eigentlich nicht korrekt, aber das überhaupt etwas definiert ist! 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CSign1Function;}; 
}; 
 
// Absoluter Betrag 
template  
class CAbsFunction : public CFunction1 
{ 
public: 
	CAbsFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMulFunction(new CSignFunction(f1->GetDuplicate()), f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CAbs1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CSign1Function;}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CAbs1Function;}; 
}; 
 
// ceil 
template  
class CCeilFunction : public CFunction1 
{ 
public: 
	CCeilFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CNullFunction;}; // eigentlich nicht korrekt 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CCeil1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CNullFunction;}; // eigentlich nicht korrekt 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CCeil1Function;}; 
}; 
 
// floor 
template  
class CFloorFunction : public CFunction1 
{ 
public: 
	CFloorFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CNullFunction;}; // eigentlich nicht korrekt 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CFloor1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CNullFunction;}; // eigentlich nicht korrekt 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CFloor1Function;}; 
}; 
 
// Logarithmus 
template  
class CLog10Function : public CFunction1 
{ 
public: 
	CLog10Function(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction(f1->GetDerivate(), new CMul0Function(f1->GetDuplicate(), logl(10)));}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CLogFunction : public CFunction1 
{ 
public: 
	CLogFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction(f1->GetDerivate(), f1->GetDuplicate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CLogarithmusFunction : public CFunction1 
{ 
public: 
	CLogarithmusFunction(T _b, CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction(f1->GetDerivate(), new CMulFunction(logl(b), f1->GetDuplicate()));}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T b; 
}; 
 
template  
class CLog101Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(1/logl(10), new CIdentityFunction);}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CLog101Function;}; 
}; 
 
template  
class CLog1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(1, new CIdentityFunction);}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CLog1Function;}; 
}; 
 
template  
class CLogarithmus1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(1/logl(b), new CIdentityFunction);}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const  {return new CLogarithmusFunction(b);}; 
private: 
	T b; 
}; 
 
// Wurzel 
template  
class CSqrtFunction : public CFunction1 
{ 
public: 
	CSqrtFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction(f1->GetDerivate(), new CMul0Function(new CSqrtFunction(f1->GetDuplicate()), 2));}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CSqrt1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CDivL0Function(1/2, new CSqrt1Function);}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CSqrt1Function;}; 
}; 
 
// Wurzel 
template  
class CSqrFunction : public CFunction1 
{ 
public: 
	CSqrFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMul0Function(f1->GetDuplicate(), 2);}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CSqr1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CPolynom1Function(0, 2.0);}; 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CSqr1Function;}; 
}; 
 
// Gamma-Funktion 
template  
class CGammaFunction : public CFunction1 
{ 
public: 
	CGammaFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CNullFunction;}; // not implemented 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
template  
class CGamma1Function : public CFunction 
{ 
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* GetDerivate() const   {return new CNullFunction;}; // not implemented 
	virtual CFunction* GetDuplicate(bool /*simplify*/ = true) const  {return new CGamma1Function;}; 
}; 
 
// Konstante Funtion 
template  
class CConstFunction : public CFunction 
{ 
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* GetDerivate() const   {return new CNullFunction;}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T c; 
}; 
 
// Negation 
template  
class CNegFunction : public CFunction1 
{ 
public: 
	CNegFunction(CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction(f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
// Addition 
template  
class CAdd0Function : public CFunction1 
{ 
public: 
	CAdd0Function(CFunction* _f1, T _c) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return f1->GetDerivate();}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T c; 
}; 
 
// Subtraktion 
template  
class CSubR0Function : public CFunction1 
{ 
public: 
	CSubR0Function(CFunction* _f1, T _c) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return f1->GetDerivate();}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T c; 
}; 
 
template  
class CSubL0Function : public CFunction1 
{ 
public: 
	CSubL0Function(T _c, CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction(f1->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T c; 
}; 
 
// Multiplikation 
template  
class CMul0Function : public CFunction1 
{ 
public: 
	CMul0Function(CFunction* _f1, T _c) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CMul0Function(f1->GetDerivate(), c);}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T c; 
}; 
 
// Division 
template  
class CDivL0Function : public CFunction1 
{ 
public: 
	CDivL0Function(T _c, CFunction* _f1) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CNegFunction(new CDivFunction(f1->GetDerivate(), new CMulFunction(f1->GetDuplicate(), f1->GetDuplicate())));}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T c; 
}; 
 
template  
class CDivR0Function : public CFunction1 
{ 
public: 
	CDivR0Function(CFunction* _f1, T _c) : CFunction1(_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* GetDerivate() const   {DERIVATE_TEST; return new CDivR0Function(f1->GetDerivate(), c);}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T c; 
}; 
 
// Addition 
template  
class CAddFunction : public CFunction2 
{ 
public: 
	CAddFunction(CFunction* _f1, CFunction* _f2) : CFunction2(_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* GetDerivate() const   {DERIVATE_TEST; return new CAddFunction(f1->GetDerivate(), f2->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
// Subtraktion 
template  
class CSubFunction : public CFunction2 
{ 
public: 
	CSubFunction(CFunction* _f1, CFunction* _f2) : CFunction2(_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* GetDerivate() const   {DERIVATE_TEST; return new CSubFunction(f1->GetDerivate(), f2->GetDerivate());}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
// Multiplikation 
template  
class CMulFunction : public CFunction2 
{ 
public: 
	CMulFunction(CFunction* _f1, CFunction* _f2) : CFunction2(_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* GetDerivate() const   {DERIVATE_TEST; return new CAddFunction(new CMulFunction(f1->GetDuplicate(), f2->GetDerivate()), new CMulFunction(f1->GetDerivate(), f2->GetDuplicate()));}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
// Division 
template  
class CDivFunction : public CFunction2 
{ 
public: 
	CDivFunction(CFunction* _f1, CFunction* _f2) : CFunction2(_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* GetDerivate() const   {DERIVATE_TEST; return new CDivFunction(new CSubFunction(new CMulFunction(f1->GetDerivate(), f2->GetDuplicate()), new CMulFunction(f1->GetDuplicate(), f2->GetDerivate())), new CMulFunction(f2->GetDuplicate(), f2->GetDuplicate()));}; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
// Potenzieren 
template  
class CPowerFunction : public CFunction2 
{ 
public: 
	CPowerFunction(CFunction* _f1, CFunction* _f2) : CFunction2(_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* GetDerivate() const; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
}; 
 
// c ^ f1(x) 
template  
class CPowerL0Function : public CFunction1 
{ 
public: 
	CPowerL0Function(T _c, CFunction* _f1) : c(_c), CFunction1(_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* GetDerivate() const; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T c; 
}; 
 
// f1(x) ^ c 
template  
class CPowerR0Function : public CFunction1 
{ 
public: 
	CPowerR0Function(CFunction* _f1, T _c) : c(_c), CFunction1(_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* GetDerivate() const; 
	virtual CFunction* GetDuplicate(bool simplify = true) const; 
private: 
	T c; 
}; 
 
// noch nicht verwendet 
template  
class CComponenteFunction : public CFunction 
{ 
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* GetDerivate() const   {return new CNullFunction;}; // not implemented 
	virtual CFunction* GetDuplicate(bool simplify = true) const  {return new CComponenteFunction(index);}; 
private: 
	int index; 
}; 
 
template  
T CFunction::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  
T CFunction::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  
T CFunction::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 
T CFunction::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 
T CFunction::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 
bool CFunction::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::IsConst(str.Mid(strlen(Token)))) return false; 
	str = str1; 
	// Alle Tests überstanden -> true zurückgeben 
	return true; 
}; 
 
template  
bool CFunction::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::IsIdentity(str.Mid(strlen(Token)), Var)) return false; 
	// Alle Tests überstanden -> true zurückgeben 
	return true; 
}; 
 
template  
bool CFunction::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 
bool CFunction::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  
T CFunction::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  
bool CFunction::IsIdentity(const char* str, const char* Var) 
{ 
	int i; 
	int Level = 0; 
	CString str1 = str; 
	// Einschließende Klammern beseitigen 
	for (i=0; i 
CFunction* CFunction::Parse1(const char* str, const char* Var) 
{ 
	CString str1 = str; 
	return CFunction::Parse(str1, Var); 
}; 
 
template  
CFunction* CFunction::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* f2 = CFunction::Parse1(str.Mid(1), Var); 
		return new CNegFunction(f2); 
	}*/ 
	// Zerlegen des Ausdrucks, Suche nach Operatoren 
	Level=0; 
	//for (i=0; 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(CFunction::Value(str.Left(i)) + CFunction::Value(str.Mid(i+1))); 
		} 
		if (str[i]=='+' && Level==0 && i>0 && IsConst(str.Left(i))) 
		{ 
			CFunction* f2 = CFunction::Parse1(str.Mid(i+1), Var); 
			CFunction* f3 = new CAdd0Function(f2, CFunction::Value(str.Left(i))); 
			if (f3->IsNullFunction()) 
			{ 
				delete f3; 
				return new CNullFunction(); 
			} 
			if (f3->IsConstantFunction()) 
			{ 
				T value1 = f3->Execute(0.0); 
				delete f3; 
				return new CConstFunction(value1); 
			} 
			return f3; 
		} 
		if (str[i]=='+' && Level==0 && i>0 && IsConst(str.Mid(i+1))) 
		{ 
			CFunction* f1 = CFunction::Parse1(str.Left(i), Var); 
			CFunction* f3 = new CAdd0Function(f1, CFunction::Value(str.Mid(i+1))); 
			if (f3->IsNullFunction()) 
			{ 
				delete f3; 
				return new CNullFunction(); 
			} 
			if (f3->IsConstantFunction()) 
			{ 
				T value1 = f3->Execute(0.0); 
				delete f3; 
				return new CConstFunction(value1); 
			} 
			return f3; 
		} 
		if (str[i]=='+' && Level==0 && i>0) 
		{ 
			CFunction* f1 = CFunction::Parse1(str.Left(i), Var); 
			if (str.Left(i) == str.Mid(i+1)) 
			{ 
				return new CMul0Function(f1, 2); 
			} 
			CFunction* f2 = CFunction::Parse1(str.Mid(i+1), Var); 
			CFunction* f3 = new CAddFunction(f1, f2); 
			if (f3->IsNullFunction()) 
			{ 
				delete f3; 
				return new CNullFunction(); 
			} 
			if (f3->IsConstantFunction()) 
			{ 
				T value1 = f3->Execute(0.0); 
				delete f3; 
				return new CConstFunction(value1); 
			} 
			return f3; 
		} 
		if (str[i]=='-' && Level==0 && i==0 && IsConst(str.Mid(i+1))) 
		{ 
			return new CConstFunction(CFunction::Value(str)); 
		} 
		if (str[i]=='-' && Level==0 && i==0) 
		{ 
			CFunction* f1 = CFunction::Parse1(str.Mid(i+1), Var); 
			if (f1->IsNullFunction()) 
			{ 
				delete f1; 
				return new CNullFunction(); 
			} 
			if (f1->IsConstantFunction()) 
			{ 
				T value1 = f1->Execute(0.0); 
				delete f1; 
				return new CConstFunction(-value1); 
			} 
			return new CNegFunction(f1); 
		} 
		if (str[i]=='-' && Level==0 && i>0 && IsConst(str.Left(i)) && IsConst(str.Mid(i+1))) 
		{ 
			return new CConstFunction(CFunction::Value(str.Left(i)) - CFunction::Value(str.Mid(i+1))); 
		} 
		if (str[i]=='-' && Level==0 && i>0 && IsConst(str.Left(i))) 
		{ 
			CFunction* f2 = CFunction::Parse1(str.Mid(i+1), Var); 
			CFunction* f3 = new CSubL0Function(CFunction::Value(str.Left(i)), f2); 
			if (f3->IsNullFunction()) 
			{ 
				delete f3; 
				return new CNullFunction(); 
			} 
			if (f3->IsConstantFunction()) 
			{ 
				T value1 = f3->Execute(0.0); 
				delete f3; 
				return new CConstFunction(value1); 
			} 
			return f3; 
		} 
		if (str[i]=='-' && Level==0 && i>0 && IsConst(str.Mid(i+1))) 
		{ 
			CFunction* f1 = CFunction::Parse1(str.Left(i), Var); 
			CFunction* f3 = new CSubR0Function(f1, CFunction::Value(str.Mid(i+1))); 
			if (f3->IsNullFunction()) 
			{ 
				delete f3; 
				return new CNullFunction(); 
			} 
			if (f3->IsConstantFunction()) 
			{ 
				T value1 = f3->Execute(0.0); 
				delete f3; 
				return new CConstFunction(value1); 
			} 
			return f3; 
		} 
		if (str[i]=='-' && Level==0 && i>0) 
		{ 
			if (str.Left(i) == str.Mid(i+1)) 
			{ 
				return new CNullFunction; 
			} 
			CFunction* f1 = CFunction::Parse1(str.Left(i), Var); 
			CFunction* f2 = CFunction::Parse1(str.Mid(i+1), Var); 
			CFunction* f3 = new CSubFunction(f1, f2); 
			if (f3->IsNullFunction()) 
			{ 
				delete f3; 
				return new CNullFunction(); 
			} 
			if (f3->IsConstantFunction()) 
			{ 
				T value1 = f3->Execute(0.0); 
				delete f3; 
				return new CConstFunction(value1); 
			} 
			return f3; 
		} 
	} 
	Level=0; 
	//for (i=0; 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::Value(str1) * CFunction::Value(str2); 
				if (value == 0.0) 
					return new CNullFunction(); 
				return new CConstFunction(value); 
			} 
			if (IsConst(str1) && !IsConst(str2)) 
			{ 
				T value = CFunction::Value(str1); 
				if (value == 0.0) 
					return new CNullFunction(); 
				CFunction* f1 = CFunction::Parse1(str2, Var); 
				CFunction* f3 = new CMul0Function(f1, value); 
				if (f3->IsNullFunction()) 
				{ 
					delete f3; 
					return new CNullFunction(); 
				} 
				if (f3->IsConstantFunction()) 
				{ 
					T value1 = f3->Execute(0.0); 
					delete f3; 
					return new CConstFunction(value1); 
				} 
				return f3; 
			} 
			if (!IsConst(str1) && IsConst(str2)) 
			{ 
				T value = CFunction::Value(str2); 
				if (value == 0.0) 
					return new CNullFunction(); 
				CFunction* f1 = CFunction::Parse1(str1, Var); 
				CFunction* f3 = new CMul0Function(f1, value); 
				if (f3->IsNullFunction()) 
				{ 
					delete f3; 
					return new CNullFunction(); 
				} 
				if (f3->IsConstantFunction()) 
				{ 
					T value1 = f3->Execute(0.0); 
					delete f3; 
					return new CConstFunction(value1); 
				} 
				return f3; 
			} 
			if (!IsConst(str1) && !IsConst(str2)) 
			{ 
				CFunction* f1 = CFunction::Parse1(str.Left(i), Var); 
				if (str1 == str2 && str1 == Var) 
				{ 
					return new CSqr1Function; 
				} 
				if (str1 == str2 && str1 != Var) 
				{ 
					return new CSqrFunction(f1); 
				} 
				CFunction* f2 = CFunction::Parse1(str.Mid(i+1), Var); 
				CFunction* f3 = new CMulFunction(f1, f2); 
				if (f3->IsNullFunction()) 
				{ 
					delete f3; 
					return new CNullFunction(); 
				} 
				if (f3->IsConstantFunction()) 
				{ 
					T value1 = f3->Execute(0.0); 
					delete f3; 
					return new CConstFunction(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(CFunction::Value(str1) / CFunction::Value(str2)); 
			} 
			if (IsConst(str1) && !IsConst(str2)) 
			{ 
				T value = CFunction::Value(str1); 
				if (value == 0.0) 
					return new CNullFunction(); 
				CFunction* f1 = CFunction::Parse1(str2, Var); 
				CFunction* f3 = new CDivL0Function(value, f1); 
				if (f3->IsNullFunction()) 
				{ 
					delete f3; 
					return new CNullFunction(); 
				} 
				if (f3->IsConstantFunction()) 
				{ 
					T value1 = f3->Execute(0.0); 
					delete f3; 
					return new CConstFunction(value1); 
				} 
				return f3; 
			} 
			if (!IsConst(str1) && IsConst(str2)) 
			{ 
				T value = CFunction::Value(str2); 
				if (value == 0.0) 
					return new CNullFunction(); 
				CFunction* f1 = CFunction::Parse1(str1, Var); 
				CFunction* f3 = new CDivR0Function(f1, value); 
				if (f3->IsNullFunction()) 
				{ 
					delete f3; 
					return new CNullFunction(); 
				} 
				if (f3->IsConstantFunction()) 
				{ 
					T value1 = f3->Execute(0.0); 
					delete f3; 
					return new CConstFunction(value1); 
				} 
				return f3; 
			} 
			if (!IsConst(str1) && !IsConst(str2)) 
			{ 
				if (str1 == str2) 
				{ 
					return new CConstFunction(1.0); 
				} 
				CFunction* f1 = CFunction::Parse1(str.Left(i), Var); 
				CFunction* f2 = CFunction::Parse1(str.Mid(i+1), Var); 
				CFunction* f3 = new CDivFunction(f1, f2); 
				if (f3->IsNullFunction()) 
				{ 
					delete f3; 
					return new CNullFunction(); 
				} 
				if (f3->IsConstantFunction()) 
				{ 
					T value = f3->Execute(0.0); 
					delete f3; 
					return new CConstFunction(value); 
				} 
				return f3; 
			} 
		} 
	} 
	Level=0; 
	//for (i=0; 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(powl(CFunction::Value(str1), CFunction::Value(str2))); 
			} 
			if (IsConst(str1) && !IsConst(str2)) 
			{ 
				CFunction* f1 = CFunction::Parse1(str2, Var); 
				return new CPowerL0Function(CFunction::Value(str1), f1); 
			} 
			if (!IsConst(str1) && IsConst(str2)) 
			{ 
				CFunction* f1 = CFunction::Parse1(str1, Var); 
				return new CPowerR0Function(f1, CFunction::Value(str2)); 
			} 
			if (!IsConst(str1) && !IsConst(str2)) 
			{ 
				CFunction* f1 = CFunction::Parse1(str.Left(i), Var); 
				CFunction* f2 = CFunction::Parse1(str.Mid(i+1), Var); 
				return new CPowerFunction(f1, f2); 
			} 
		} 
	} 
	// Suche nach Funktionen 
	if (IsConstFunction(str, _T("EXP")))  
	{ 
		T value = CFunction::Value(str); 
		return new CConstFunction(expl(value)); 
	} 
	if (IsConstFunction(str, _T("SIN")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(sinl(value)); 
	} 
	if (IsConstFunction(str, _T("COS")))  
	{ 
		T value = CFunction::Value(str); 
		return new CConstFunction(cosl(value)); 
	} 
	if (IsConstFunction(str, _T("TAN")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(tanl(value)); 
	} 
	if (IsConstFunction(str, _T("COT")))  
	{ 
		T value = CFunction::Value(str); 
		return new CConstFunction(cosl(value)/sinl(value)); 
	} 
	if (IsConstFunction(str, _T("SINH")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(sinhl(value)); 
	} 
	if (IsConstFunction(str, _T("COSH")))  
	{ 
		T value = CFunction::Value(str); 
		return new CConstFunction(coshl(value)); 
	} 
	if (IsConstFunction(str, _T("TANH")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(tanhl(value)); 
	} 
	if (IsConstFunction(str, _T("ABS")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(fabsl(value)); 
	} 
	if (IsConstFunction(str, _T("CEIL")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(ceill(value)); 
	} 
	if (IsConstFunction(str, _T("FLOOR")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(floorl(value)); 
	} 
	if (IsConstFunction(str, _T("LG")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 1.0) 
			return new CNullFunction(); 
		return new CConstFunction(log10l(value)); 
	} 
	if (IsConstFunction(str, _T("LN")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 1.0) 
			return new CNullFunction(); 
		return new CConstFunction(logl(value)); 
	} 
	if (IsConstFunction(str, _T("SQRT")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(sqrtl(value)); 
	} 
	if (IsConstFunction(str, _T("ASIN")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(asinl(value)); 
	} 
	if (IsConstFunction(str, _T("ACOS")))  
	{ 
		T value = CFunction::Value(str); 
		return new CConstFunction(acosl(value)); 
	} 
	if (IsConstFunction(str, _T("ATAN")))  
	{ 
		T value = CFunction::Value(str); 
		if (value == 0.0) 
			return new CNullFunction(); 
		return new CConstFunction(atanl(value)); 
	} 
	if (IsConstFunction(str, _T("GAMMA")))  
	{ 
		T value = CFunction::Value(str); 
		return new CConstFunction(FGammal(value)); 
	} 
 
	if (IsPureFunction(str, _T("EXP"), Var))  
		return new CExp1Function; 
	if (IsPureFunction(str, _T("SIN"), Var))  
		return new CSin1Function; 
	if (IsPureFunction(str, _T("COS"), Var))  
		return new CCos1Function; 
	if (IsPureFunction(str, _T("TAN"), Var))  
		return new CTan1Function; 
	if (IsPureFunction(str, _T("COT"), Var))  
		return new CCot1Function; 
	if (IsPureFunction(str, _T("SINH"), Var))  
		return new CSinh1Function; 
	if (IsPureFunction(str, _T("COSH"), Var))  
		return new CCosh1Function; 
	if (IsPureFunction(str, _T("TANH"), Var))  
		return new CTanh1Function; 
	if (IsPureFunction(str, _T("COTH"), Var))  
		return new CCoth1Function; 
	if (IsPureFunction(str, _T("ABS"), Var))  
		return new CAbs1Function; 
	if (IsPureFunction(str, _T("CEIL"), Var))  
		return new CCeil1Function; 
	if (IsPureFunction(str, _T("FLOOR"), Var))  
		return new CFloor1Function; 
	if (IsPureFunction(str, _T("LG"), Var))  
		return new CLog101Function; 
	if (IsPureFunction(str, _T("LN"), Var))  
		return new CLog1Function; 
	if (IsPureFunction(str, _T("SQRT"), Var))  
		return new CSqrt1Function; 
	if (IsPureFunction(str, _T("ASIN"), Var))  
		return new CAsin1Function; 
	if (IsPureFunction(str, _T("ACOS"), Var))  
		return new CAcos1Function; 
	if (IsPureFunction(str, _T("ATAN"), Var))  
		return new CAtan1Function; 
	if (IsPureFunction(str, _T("GAMMA"), Var))  
		return new CGamma1Function; 
 
	if (IsFunction(str, _T("EXP")))  
		return new CExpFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("SIN")))  
		return new CSinFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("COS")))  
		return new CCosFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("TAN")))  
		return new CTanFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("COT")))  
		return new CCotFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("SINH")))  
		return new CSinhFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("COSH")))  
		return new CCoshFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("TANH")))  
		return new CTanhFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("COTH")))  
		return new CCothFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("ABS")))  
		return new CAbsFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("CEIL")))  
		return new CCeilFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("FLOOR")))  
		return new CFloorFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("LG")))  
		return new CLog10Function(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("LN")))  
		return new CLogFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("SQRT")))  
		return new CSqrtFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("ASIN")))  
		return new CAsinFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("ACOS")))  
		return new CAcosFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("ATAN")))  
		return new CAtanFunction(CFunction::Parse(str, Var)); 
	if (IsFunction(str, _T("GAMMA")))  
		return new CGammaFunction(CFunction::Parse(str, Var)); 
	// x ? 
	if (stricmp(str, Var)==0)  
		return new CIdentityFunction; 
	if (str[0]=='-') // Ist diese Position besser? 
	{ 
		CFunction* f2 = CFunction::Parse1(str.Mid(1), Var); 
		if (f2->IsNullFunction()) 
		{ 
			delete f2; 
			return new CNullFunction(); 
		} 
		if (f2->IsConstantFunction()) 
		{ 
			T value = f2->Execute(0.0); 
			delete f2; 
			return new CConstFunction(-value); 
		} 
		return new CNegFunction(f2); 
	} 
#pragma warning ( disable : 4244 ) 
	return new CConstFunction(CFunction::Value(str)); 
#pragma warning ( default : 4244 ) 
}; 
 
template  
CString CFunction1::GetConcName(const char* basisfkt) const 
{ 
	CString str = basisfkt; 
	str += _T("("); 
	str += f1->GetName(); 
	str += _T(")"); 
	return str; 
}; 
 
template  
CString CFunction2::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  
CString CPolynom1Function::GetName() const 
{ 
	CString str; 
	str += CMathString(a1); 
	str += _T("*x+"); 
	str += CMathString(a0); 
	return str; 
}; 
 
template  
CString CPolynom1Function::GetTeX() const 
{ 
	CString str; 
	str += CMathString(a1); 
	str += _T("x+"); 
	str += CMathString(a0); 
	return str; 
}; 
 
template  
CString CPolynom2Function::GetName() const 
{ 
	CString str; 
	str += CMathString(a2); 
	str += _T("*x^2+"); 
	str += CMathString(a1); 
	str += _T("*x+"); 
	str += CMathString(a0); 
	return str; 
}; 
 
template  
CString CPolynom2Function::GetTeX() const 
{ 
	CString str; 
	str += CMathString(a2); 
	str += _T("x^2+"); 
	str += CMathString(a1); 
	str += _T("x+"); 
	str += CMathString(a0); 
	return str; 
}; 
 
template  
CString CPolynom3Function::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  
CString CPolynom3Function::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  
CString CPolynom4Function::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  
CString CPolynom4Function::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  
CFunction* CPowerFunction::GetDerivate() const 
{ 
	DERIVATE_TEST; 
	return new CMulFunction(GetDuplicate(), new CAddFunction(new CMulFunction(f2->GetDerivate(), new CLogFunction(f1->GetDuplicate())), 
										  new CDivFunction(new CMulFunction(f1->GetDerivate(), f2->GetDuplicate()), f1->GetDuplicate()))); 
}; 
 
// c ^ f1(x) 
template  
CFunction* CPowerL0Function::GetDerivate() const 
{ 
	DERIVATE_TEST; 
	return new CMulFunction(GetDuplicate(), new CMul0Function(f1->GetDerivate(), logl(c))); 
}; 
 
// f1(x) ^ c 
template  
CFunction* CPowerR0Function::GetDerivate() const 
{ 
	DERIVATE_TEST; 
	if (c==0) 
		return new CNullFunction; 
	if (c==1) 
		return f1->GetDerivate(); 
	return new CMul0Function(new CMulFunction(new CPowerR0Function(f1->GetDuplicate(), c-1), f1->GetDerivate()), c); 
}; 
 
template  
CFunction* CNullFunction::GetDuplicate(bool /*simplify*/ /*= true*/) const   
{ 
	return new CNullFunction; 
}; 
 
template  
CFunction* CPolynom1Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	if (simplify) 
	{ 
		if (a1==0.0 && a0==0.0) 
			return new CNullFunction(); 
		if (a1==0.0) 
			return new CConstFunction(a0); 
	} 
	return new CPolynom1Function(a0,a1); 
}; 
 
template  
CFunction* CPolynom2Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	if (simplify) 
	{ 
		if (a2==0.0 && a1==0.0 && a0==0.0) 
			return new CNullFunction(); 
		if (a2==0.0 && a1==0.0) 
			return new CConstFunction(a0); 
		if (a2==0.0) 
			return new CPolynom1Function(a0, a1); 
	} 
	return new CPolynom2Function(a0,a1,a2); 
}; 
 
template  
CFunction* CPolynom3Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	if (simplify) 
	{ 
		if (a3==0.0 && a2==0.0 && a1==0.0 && a0==0.0) 
			return new CNullFunction(); 
		if (a3==0.0 && a2==0.0 && a1==0.0) 
			return new CConstFunction(a0); 
		if (a3==0.0 && a2==0.0) 
			return new CPolynom1Function(a0, a1); 
		if (a3==0.0) 
			return new CPolynom2Function(a0, a1, a2); 
	} 
	return new CPolynom3Function(a0,a1,a2,a3); 
}; 
 
template  
CFunction* CPolynom4Function::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(); 
		if (a4==0.0 && a3==0.0 && a2==0.0 && a1==0.0) 
			return new CConstFunction(a0); 
		if (a4==0.0 && a3==0.0 && a2==0.0) 
			return new CPolynom1Function(a0, a1); 
		if (a4==0.0 && a3==0.0) 
			return new CPolynom2Function(a0, a1, a2); 
		if (a4==0.0) 
			return new CPolynom3Function(a0, a1, a2, a3); 
	} 
	return new CPolynom4Function(a0,a1,a2,a3,a4); 
}; 
 
template  
CFunction* CExpFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CExpFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CSinFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CSinFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CCosFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CCosFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CTanFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CTanFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CCotFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CCotFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CAsinFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CAsinFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CAcosFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CAcosFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CAtanFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CAtanFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CAcotFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CAcotFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CSinhFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CSinhFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CCoshFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CCoshFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CTanhFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CTanhFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CCothFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CCothFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CSignFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CSignFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CAbsFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CAbsFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CCeilFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CCeilFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CFloorFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CFloorFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CLog10Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CLog10Function(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CLogFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CLogFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CLogarithmusFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CLogarithmusFunction(f1->GetDuplicate(simplify), b); 
}; 
 
template  
CFunction* CSqrFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CSqrFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CSqrtFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CSqrtFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CGammaFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CGammaFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CConstFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	if (simplify && c==0.0) 
		return new CNullFunction(); 
	return new CConstFunction(c); 
}; 
 
template  
CFunction* CNegFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CNegFunction(f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CAdd0Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsNullFunction()) 
		{ 
			delete df1; 
			return new CConstFunction(c); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value = df1->Execute(0.0); 
			delete df1; 
			return new CConstFunction(c+value); 
		} 
	} 
	return new CAdd0Function(df1, c); 
}; 
 
template  
CFunction* CSubR0Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsNullFunction()) 
		{ 
			delete df1; 
			return new CConstFunction(-c); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value = df1->Execute(0.0); 
			delete df1; 
			return new CConstFunction(value-c); 
		} 
	} 
	return new CSubR0Function(df1, c); 
}; 
 
template  
CFunction* CSubL0Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsNullFunction()) 
		{ 
			delete df1; 
			return new CConstFunction(c); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value = df1->Execute(0.0); 
			delete df1; 
			return new CConstFunction(c-value); 
		} 
	} 
	return new CSubL0Function(c, df1); 
}; 
 
template  
CFunction* CMul0Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsNullFunction()) 
		{ 
			delete df1; 
			return new CNullFunction(); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value = df1->Execute(0.0); 
			delete df1; 
			return new CConstFunction(c*value); 
		} 
	} 
	return new CMul0Function(df1, c); 
}; 
 
template  
CFunction* CDivL0Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsConstantFunction()) 
		{ 
			T value = df1->Execute(0.0); 
			delete df1; 
			return new CConstFunction(c/value); 
		} 
	} 
	return new CDivL0Function(c, df1); 
}; 
 
template  
CFunction* CDivR0Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsNullFunction()) 
		{ 
			delete df1; 
			return new CNullFunction(); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value = df1->Execute(0.0); 
			delete df1; 
			return new CConstFunction(value/c); 
		} 
	} 
	return new CDivR0Function(df1, c); 
}; 
 
template  
CFunction* CAddFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	CFunction* df2 = f2->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsNullFunction() && df2->IsNullFunction()) 
		{ 
			delete df1; 
			delete df2; 
			return new CNullFunction(); 
		} 
		if (df1->IsConstantFunction() && df2->IsConstantFunction()) 
		{ 
			T value1 = df1->Execute(0.0); 
			T value2 = df2->Execute(0.0); 
			delete df1; 
			delete df2; 
			return new CConstFunction(value1 + value2); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value1 = df1->Execute(0.0); 
			delete df1; 
			return new CAdd0Function(df2, value1); 
		} 
		if (df2->IsConstantFunction()) 
		{ 
			T value2 = df2->Execute(0.0); 
			delete df2; 
			return new CAdd0Function(df1, value2); 
		} 
	} 
	return new CAddFunction(df1, df2); 
}; 
 
template  
CFunction* CSubFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	CFunction* df2 = f2->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsNullFunction() && df2->IsNullFunction()) 
		{ 
			delete df1; 
			delete df2; 
			return new CNullFunction(); 
		} 
		if (df1->IsConstantFunction() && df2->IsConstantFunction()) 
		{ 
			T value1 = df1->Execute(0.0); 
			T value2 = df2->Execute(0.0); 
			delete df1; 
			delete df2; 
			return new CConstFunction(value1 - value2); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value1 = df1->Execute(0.0); 
			delete df1; 
			return new CSubL0Function(value1, df2); 
		} 
		if (df2->IsConstantFunction()) 
		{ 
			T value2 = df2->Execute(0.0); 
			delete df2; 
			return new CSubR0Function(df1, value2); 
		} 
	} 
	return new CSubFunction(df1, df2); 
}; 
 
template  
CFunction* CMulFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	CFunction* df2 = f2->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsNullFunction() || df2->IsNullFunction()) 
		{ 
			delete df1; 
			delete df2; 
			return new CNullFunction(); 
		} 
		if (df1->IsConstantFunction() && df2->IsConstantFunction()) 
		{ 
			T value1 = df1->Execute(0.0); 
			T value2 = df2->Execute(0.0); 
			delete df1; 
			delete df2; 
			return new CConstFunction(value1 * value2); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value1 = df1->Execute(0.0); 
			delete df1; 
			return new CMul0Function(df2, value1); 
		} 
		if (df2->IsConstantFunction()) 
		{ 
			T value2 = df2->Execute(0.0); 
			delete df2; 
			return new CMul0Function(df1, value2); 
		} 
	} 
	return new CMulFunction(df1, df2); 
}; 
 
template  
CFunction* CDivFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	CFunction* df2 = f2->GetDuplicate(simplify); 
	if (simplify) 
	{ 
		if (df1->IsNullFunction()) 
		{ 
			delete df1; 
			delete df2; 
			return new CNullFunction(); 
		} 
		if (df1->IsConstantFunction() && df2->IsConstantFunction()) 
		{ 
			T value1 = df1->Execute(0.0); 
			T value2 = df2->Execute(0.0); 
			delete df1; 
			delete df2; 
			return new CConstFunction(value1 / value2); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value1 = df1->Execute(0.0); 
			delete df1; 
			return new CDivL0Function(value1, df2); 
		} 
		if (df2->IsConstantFunction()) 
		{ 
			T value2 = df2->Execute(0.0); 
			delete df2; 
			return new CDivR0Function(df1, value2); 
		} 
	} 
	return new CDivFunction(df1, df2); 
}; 
 
template  
CFunction* CPowerFunction::GetDuplicate(bool simplify /*= true*/) const 
{ 
	CFunction* df1 = f1->GetDuplicate(simplify); 
	CFunction* 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(powl(value1, value2)); 
		} 
		if (df1->IsConstantFunction()) 
		{ 
			T value1 = df1->Execute(0.0); 
			delete df1; 
			return new CPowerL0Function(value1, df2); 
		} 
		if (df2->IsConstantFunction()) 
		{ 
			T value2 = df2->Execute(0.0); 
			delete df2; 
			return new CPowerR0Function(df1, value2); 
		} 
 	} 
	return new CPowerFunction(df1, df2); 
}; 
 
template  
CFunction* CPowerL0Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CPowerL0Function(c, f1->GetDuplicate(simplify)); 
}; 
 
template  
CFunction* CPowerR0Function::GetDuplicate(bool simplify /*= true*/) const 
{ 
	return new CPowerR0Function(f1->GetDuplicate(simplify), c); 
}; 
 
#else 
#error already included 
#endif