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

#include <Math.h>
#include "../ApplicationInterfaces/psychlops_code.h"
#include "psychlops_m_interval.h"

namespace Psychlops {


	Interval::Interval() : begin(NINF), end(INF) {}
	Interval::Interval(double floor_val, double ceil_val) : begin(floor_val, OPEN), end(ceil_val, OPEN) {}
	Interval::Interval(double floor_val, OPERATOR floor_op, double ceil_val, OPERATOR ceil_op) : begin(floor_val, floor_op), end(ceil_val, ceil_op) {}
	Interval::~Interval() {}

	Interval& Interval::operator <(double value) { end.set(value,OPEN); begin.set(NINF,CLOSE); return *this; }
	Interval& Interval::operator <=(double value) { end.set(value,CLOSE); begin.set(NINF,CLOSE); return *this; }
	Interval& Interval::operator >(double value) { begin.set(value,OPEN); end.set(INF,CLOSE); return *this; }
	Interval& Interval::operator >=(double value) { begin.set(value,CLOSE); end.set(INF,CLOSE); return *this; }
	Interval& Interval::operator <(TYPES value) { end.set(value,OPEN); begin.set(NINF,CLOSE); return *this; }
	Interval& Interval::operator <=(TYPES value) { end.set(value,CLOSE); begin.set(NINF,CLOSE); return *this; }
	Interval& Interval::operator >(TYPES value) { begin.set(value,OPEN); end.set(INF,CLOSE); return *this; }
	Interval& Interval::operator >=(TYPES value) { begin.set(value,CLOSE); end.set(INF,CLOSE); return *this; }


	Interval_acc::Interval_acc(Interval &rng) : _range(rng) { begin=rng.begin; end=rng.end; }
	Interval_acc::~Interval_acc() {}

	Interval& Interval_acc::operator <(double value) { _range.end.set(value, OPEN); return _range; }
	Interval& Interval_acc::operator <=(double value) { _range.end.set(value, CLOSE); return _range; }
	Interval& Interval_acc::operator >(double value) { _range.begin.set(value, OPEN); return _range; }
	Interval& Interval_acc::operator >=(double value) { _range.begin.set(value, CLOSE); return _range; }
	Interval& Interval_acc::operator <(TYPES value) { _range.end.set(value, OPEN); return _range; }
	Interval& Interval_acc::operator <=(TYPES value) { _range.end.set(value, CLOSE); return _range; }
	Interval& Interval_acc::operator >(TYPES value) { _range.begin.set(value, OPEN); return _range; }
	Interval& Interval_acc::operator >=(TYPES value) { _range.begin.set(value, CLOSE); return _range; }

	int Interval::int_floor() const {
		if(begin.type!=NORMAL) throw begin.type;
		double v = ceil(begin.value);
		if(begin.op==OPEN && v==begin.value) { return (int)v+1; }
		else return int(v);
	}
	int Interval::int_floor(int minval) const {
		if(begin.type==NaN) throw end.type;
		if(begin.type==NINF || begin.value<minval) return minval;
		double v = ceil(begin.value);
		if(begin.op==OPEN && v==begin.value) { return (int)v+1; }
		else return int(v);
	}
	int Interval::int_ceil() const {
		if(begin.type!=NORMAL) throw end.type;
		double v = floor(end.value);
		if(end.op==OPEN && v==end.value) { return (int)v-1; }
		else return int(v);
	}
	int Interval::int_ceil(int maxval) const {
		if(begin.type==NaN) throw end.type;
		if(end.type==INF || end.value>maxval) return maxval;
		double v = floor(end.value);
		if(end.op==OPEN && v==end.value) { return (int)v-1; }
		else return int(v);
	}

	bool Interval::includes(double value_) const {
		if(begin.type==NaN || end.type==NaN) throw end.type;
		if(begin.type!=NINF) if((begin.op==CLOSE && begin.value>value_) || (begin.op==OPEN && begin.value>=value_)) return false;
		if(end.type!=INF) if((end.op==CLOSE && end.value<value_) || (end.op==OPEN && end.value<=value_)) return false;
		return true;
	}
	bool Interval::bounded() const {
		return (begin.type==NORMAL && end.type==NORMAL);
	}

	Interval_acc operator <(double value, Interval &rng) { rng.begin.set(value, Interval::OPEN); rng.end.set(Interval::INF,Interval::CLOSE); return Interval_acc(rng); }
	Interval_acc operator <=(double value, Interval &rng) { rng.begin.set(value, Interval::CLOSE); rng.end.set(Interval::INF,Interval::CLOSE); return Interval_acc(rng); }
	Interval_acc operator >(double value, Interval &rng) { rng.end.set(value, Interval::OPEN); rng.begin.set(Interval::NINF,Interval::CLOSE); return Interval_acc(rng); }
	Interval_acc operator >=(double value, Interval &rng) { rng.end.set(value, Interval::CLOSE); rng.begin.set(Interval::NINF,Interval::CLOSE); return Interval_acc(rng); }
	Interval_acc operator <(Interval::TYPES value, Interval &rng) { rng.begin.set(value, Interval::OPEN); rng.end.set(Interval::INF,Interval::CLOSE); return Interval_acc(rng); }
	Interval_acc operator <=(Interval::TYPES value, Interval &rng) { rng.begin.set(value, Interval::CLOSE); rng.end.set(Interval::INF,Interval::CLOSE); return Interval_acc(rng); }
	Interval_acc operator >(Interval::TYPES value, Interval &rng) { rng.end.set(value, Interval::OPEN); rng.begin.set(Interval::NINF,Interval::CLOSE); return Interval_acc(rng); }
	Interval_acc operator >=(Interval::TYPES value, Interval &rng) { rng.end.set(value, Interval::CLOSE); rng.begin.set(Interval::NINF,Interval::CLOSE); return Interval_acc(rng); }


}	/*	<- namespace Psycholops 	*/
