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



#include <Math.h>
#include <typeinfo>

#include "psychlops_m_function.h"

namespace Psychlops {



Wave::Wave() {
}
Wave::~Wave() {
}

Wave::WaveExpression_::WaveExpression_() : next_(0) {
}
Wave::WaveExpression_::~WaveExpression_() {
}
void Wave::WaveExpression_::add(Wave &target) {
}
void Wave::WaveExpression_::remove(Wave &target) {
}




namespace Waveform {

	////////	CONSTANT	////////
	CONSTANT::CONSTANT(double val) : value(val) {
	}
	double CONSTANT::operator ()(double x) const {
		return value;
	}
	double CONSTANT::operator ()(Angle a) const {
		return value;
	}

	ZERO::ZERO() {
	}
	double ZERO::operator ()(double x) const {
		return 0.0;
	}
	double ZERO::operator ()(Angle a) const {
		return 0.0;
	}

	ONE::ONE() {
	}
	double ONE::operator ()(double x) const {
		return 1.0;
	}
	double ONE::operator ()(Angle a) const {
		return 1.0;
	}


	////////	SIN	////////

	SIN::SIN() : amplitude(0), wavelength(0), phase(0)  {
	}
	SIN::SIN(const SIN &w) {
		*this = w;
	}
	SIN::SIN(double lngth, double amp, Angle phs) : amplitude(amp), wavelength(lngth), phase(phs) {
		if(wavelength<=0) throw(typeid(*this), "Range Error", "Wave length must be positive number.");
	}
	SIN & SIN::set(double lngth, double amp, Angle phs) {
		amplitude = amp;
		wavelength = lngth;
		phase = phs;
		if(wavelength<=0) throw(typeid(*this), "Range Error", "Wave length must be positive number.");
		return *this;
	}
	double SIN::operator ()(double x) const {
		return this->operator()((360*x/wavelength));
	}
	double SIN::operator ()(Angle a) const {
		Angle tmp = a+phase;
		return ::sin(tmp.at_radian()) * amplitude;
	}


	////////	COS, TAN	////////

	double COS::operator ()(double x) const {
		return this->operator()((360*x/wavelength));
	}
	double COS::operator ()(Angle a) const {
		Angle tmp = a+phase;
		return ::cos(tmp.at_radian()) * amplitude;
	}

	double TAN::operator ()(double x) const {
		return this->operator()((360*x/wavelength));
	}
	double TAN::operator ()(Angle a) const {
		Angle tmp = a+phase;
		return ::tan(tmp.at_radian()) * amplitude;
	}


	////////	PULSE	////////

	PULSE::PULSE(const PULSE &w) {
		*this = w;
	}
	PULSE::PULSE(double lngth, double amp, Angle phs, Angle step_boundary) : amplitude(amp), wavelength(lngth), phase(phs), step_boundary_(step_boundary) {
	}
	PULSE & PULSE::set(double lngth, double amp, Angle phs, Angle step_boundary) {
		amplitude = amp;
		wavelength = lngth;
		phase = phs;
		step_boundary_ = step_boundary;
		if(wavelength<=0) throw(typeid(*this), "Range Error", "Wave length must be positive number.");
		return *this;
	}
	double PULSE::operator ()(double x) const {
		return this->operator()((360*x/wavelength));
	}
	double PULSE::operator ()(Angle a) const {
		if(a.clip()<step_boundary_) {
			return 1.0;
		} else {
			return 0.0;
		}
	}

	MONOMIAL::MONOMIAL(const MONOMIAL &w) {
		*this = w;
	}
	MONOMIAL::MONOMIAL(int dgr, double fct) : degree(dgr), factor(fct) {
	}
	MONOMIAL & MONOMIAL::set(int dgr, double fct) {
		degree = dgr;
		factor = fct;
		return *this;
	}
	double MONOMIAL::operator ()(double x) const {
		return factor * pow(x, degree);
	}

	LINEAR::LINEAR(double fct) {
		degree = 1;
		factor = fct;
	}
	LINEAR & LINEAR::set(double fct) {
		factor = fct;
		return *this;
	}
	double LINEAR::operator ()(double x) const {
		return factor*x;
	}


}	/*	<- namespace Waveform 	*/
}	/*	<- namespace Psychlops 	*/
