<?php

class calc {
	
	const numregex = '[0-9]*\\.?[0-9]+';
	const grpregex = '\\([^()]*\\)';
	
	public function format($input) {
		return preg_replace('/[^\\/\\-0-9.+*()^=]+/','',$input);
	}
	
	public function evaluate($input, $format = true) {
		if($format) {			
			$input = $this->format($input);
		}
		
		//Remove double positive/negative identifiers.
		do{$input=str_replace(array('+-','-+'),'-',$input,$count);}while($count);
		do{$input=str_replace(array('++','--'),'+',$input,$count);}while($count);
		
		//Evaluate input between '(' and ')' operators
		while(preg_match('/'.self::grpregex.'/',$input,$match,PREG_OFFSET_CAPTURE)) {
			$input = 
				substr($input,0,$match[0][1])
				.$this->evaluate(substr($match[0][0],1,-1),false)
				.substr($input,$match[0][1]+strlen($match[0][0]));
		}
		
		//Calculate the Y'th power of X
		while(preg_match('/('.self::numregex.')\\^([+-]?'.self::numregex.')/',$input,$match,PREG_OFFSET_CAPTURE)) {
			$y = pow(floatval($match[1][0]),floatval($match[2][0]));
			$input = substr($input,0,$match[0][1]).$y.substr($input,$match[0][1]+strlen($match[0][0]));			
		}
		
		//Multiply and Divisions
		while(preg_match('/('.self::numregex.')([\\*\\/])([+-]?'.self::numregex.')/',$input,$match,PREG_OFFSET_CAPTURE)) {
			if($match[2][0]=='*') {
				$y = floatval($match[1][0])*floatval($match[3][0]);
			} elseif($match[2][0]=='/') {
				$y = floatval($match[1][0])/floatval($match[3][0]);
			}
			$input = substr($input,0,$match[0][1]).$y.substr($input,$match[0][1]+strlen($match[0][0]));					
		}
		
		//Add and Substract
		while(preg_match('/('.self::numregex.')([+-])([+-]?'.self::numregex.')/',$input,$match,PREG_OFFSET_CAPTURE)) {
			if($match[2][0]=='+') {
				$y = floatval($match[1][0])+floatval($match[3][0]);
			} elseif($match[2][0]=='-') {
				$y = floatval($match[1][0])-floatval($match[3][0]);
			}
			$input = substr($input,0,$match[0][1]).$y.substr($input,$match[0][1]+strlen($match[0][0]));					
		}
		
		if(preg_match('/([+-]?'.self::numregex.')=([+-]?'.self::numregex.')/',$input,$match)) {
			$input = (floatval($match[1][0])==floatval($match[2][0]));
		} else {
			$input = floatval($input);
		}
		
		return $input;
	}

	public static function ulate($input) {
		return calc::ulator()->evaluate($input);
	}
	
	public static function ulator() {
		if(!isset($GLOBALS['_calc'])) {
			$GLOBALS['_calc'] = new self;
		}		
		return $GLOBALS['_calc'];
	}
	
}

?>