/*
 *  psychlops_math_range.h
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2005/07/04 by Kenchi HOSOKAWA
 *  (C) 2005 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
 */

#ifndef HEADER_PSYCHLOPS_MATH_RANGE
#define HEADER_PSYCHLOPS_MATH_RANGE

#include <iostream>

#include "../ApplicationInterfaces/psychlops_code.h"

namespace Psychlops {

	class Interval;
	class Interval_acc;
	typedef Interval Range;

	class Interval {
		public:
		enum TYPES { NaN, NORMAL, INF, NINF };
		enum OPERATOR { CLOSE, OPEN };
		struct INTERVAL_ {
			private:
			public:
			TYPES type;
			OPERATOR op;
			double value;
			INTERVAL_() : type(INF), op(CLOSE), value(0.0) {}
			INTERVAL_(TYPES val) : type(val), op(CLOSE), value(0.0) {}
			INTERVAL_(double val) : type(NORMAL), op(CLOSE), value(val) {}
			INTERVAL_(double val, OPERATOR op) : type(NORMAL), op(op), value(val) {}
			INTERVAL_& set(TYPES mm, OPERATOR cop) { type=mm; op=cop; value=0.0; return *this; }
			INTERVAL_& set(double value_, OPERATOR cop) { type=NORMAL; op=cop; value=value_; return *this; }
			operator double() { if(type==NORMAL){return value;} else {throw type;return 0.0;} }
		};
		INTERVAL_ begin, end;

		public:
		Interval();
		Interval(double floor_val, double ceil_val);
		Interval(double floor_val, OPERATOR floor_op, double ceil_val, OPERATOR ceil_op);
		virtual ~Interval();
		Interval& operator <(double value);
		Interval& operator <=(double value);
		Interval& operator >(double value);
		Interval& operator >=(double value);
		Interval& operator <(TYPES value);
		Interval& operator <=(TYPES value);
		Interval& operator >(TYPES value);
		Interval& operator >=(TYPES value);
		int int_floor() const;
		int int_floor(int minval) const;
		int int_ceil() const;
		int int_ceil(int maxval) const;
		bool includes(double val) const;
		bool bounded() const;


		friend class Interval_acc;
		friend Interval_acc operator <(double val, Interval &rng);
		friend Interval_acc operator <=(double val, Interval &rng);
		friend Interval_acc operator >(double val, Interval &rng);
		friend Interval_acc operator >=(double val, Interval &rng);
		friend Interval_acc operator <(TYPES val, Interval &rng);
		friend Interval_acc operator <=(TYPES val, Interval &rng);
		friend Interval_acc operator >(TYPES val, Interval &rng);
		friend Interval_acc operator >=(TYPES val, Interval &rng);
	};


	class Interval_acc : public Interval {
		private:
		Interval &_range;
		public:
		Interval_acc(Interval &rng);
		~Interval_acc();
		Interval& operator <(double value);
		Interval& operator <=(double value);
		Interval& operator >(double value);
		Interval& operator >=(double value);
		Interval& operator <(TYPES value);
		Interval& operator <=(TYPES value);
		Interval& operator >(TYPES value);
		Interval& operator >=(TYPES value);
	};

	Interval_acc operator <(double val, Interval &rng);
	Interval_acc operator <=(double val, Interval &rng);
	Interval_acc operator >(double val, Interval &rng);
	Interval_acc operator >=(double val, Interval &rng);
	Interval_acc operator <(Interval::TYPES val, Interval &rng);
	Interval_acc operator <=(Interval::TYPES val, Interval &rng);
	Interval_acc operator >(Interval::TYPES val, Interval &rng);
	Interval_acc operator >=(Interval::TYPES val, Interval &rng);


}	/*	<- namespace Psycholops 	*/

#endif

