/*
 *  psychlops_math_function.h
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2005/10/13 by Kenchi HOSOKAWA
 *  (C) 2005 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
 */

#ifndef HEADER_PSYCHLOPS_MATH_FUNCTION
#define HEADER_PSYCHLOPS_MATH_FUNCTION


#include "psychlops_m_util.h"
#include "../graphic/psychlops_g_fundamental.h"

namespace Psychlops {


	class Wave {
		private:
		class WaveExpression_ {
			public:
			enum OP_ { ADD, SUB, MUL, DIV };
			Wave *next_;
			OP_ op_;

			WaveExpression_();
			~WaveExpression_();
			void add(Wave &target);
			void remove(Wave &target);
		};
//		WaveExpression_ next_;

		public:
		enum BASIC_WAVE_FORM { sin, cos, tan, rect, triangle, saw };
		Wave();
		Wave(const Wave& w);
		virtual ~Wave();

		virtual double operator ()(double x) const = 0;

	};


	////////	Standard Classes	////////

	namespace Waveform {

		class CONSTANT : public Wave {
			public:
			double value;

			public:
			CONSTANT(double val = 0.0);
			virtual double operator ()(double x) const;
			virtual double operator ()(Angle a) const;
		};
		class ZERO : public Wave {
			public:
			ZERO();
			virtual double operator ()(double x) const;
			virtual double operator ()(Angle a) const;
		};
		class ONE : public Wave {
			public:
			ONE();
			virtual double operator ()(double x) const;
			virtual double operator ()(Angle a) const;
		};

		class SIN : public Wave {
			public:
			double amplitude;
			double wavelength;
			Angle phase;

			public:
			SIN();
			SIN(const SIN &w);
			SIN(double lngth, double amp=1.0, Angle phs=0.0);
			SIN & set(double lngth, double amp=1.0, Angle phs=0.0);
			virtual double operator ()(double x) const;
			virtual double operator ()(Angle a) const;
		};

		class COS : public SIN {
			virtual double operator ()(double x) const;
			virtual double operator ()(Angle a) const;
		};

		class TAN : public SIN {
			virtual double operator ()(double x) const;
			virtual double operator ()(Angle a) const;
		};

		class PULSE : public Wave {
			public:
			double amplitude;
			double wavelength;
			Angle phase;
			Angle step_boundary_;

			public:
			PULSE(const PULSE &w);
			PULSE(double lngth, double amp=1.0, Angle phs=0.0, Angle step_boundary=180.0);
			PULSE & set(double lngth, double amp=1.0, Angle phs=0.0, Angle step_boundary=180.0);
			virtual double operator ()(double x) const;
			virtual double operator ()(Angle a) const;
		};

		class MONOMIAL : public Wave {
			public:
			int degree;
			double factor;

			public:
			MONOMIAL(const MONOMIAL &w);
			MONOMIAL(int dgr=1, double fct=1.0);
			MONOMIAL & set(int dgr=1, double fct=1.0);
			virtual double operator ()(double x) const;
		};

		class LINEAR : public MONOMIAL {
			public:
			LINEAR(double fct=1.0);
			LINEAR & set(double fct=1.0);
			virtual double operator ()(double x) const;
		};

/*		template <double (*X)(double)> class FUNCTION : public Wave {
			public:
			FUNCTION() {
			}
			virtual double operator ()(double x) const {
				return X(x);
			}
		};
*/
//		typedef FUNCTION<exp> EXP;
//		typedef FUNCTION<log> LOG;
	}


}	/*	<- namespace Psycholops 	*/


#endif
