<?php
/**
*
* @package com.cisneiros.math
* @version 1.0
* @copyright 2009 - 2010 (C) by Cisneiros
*/

/**
* Quadratic equation to be solved by Bhaskara's method, like "ax^2 + bx + c = 0".
*
* @package com.cisneiros.math
* @version 1.0
* @property float \$a The "a" value of the equation. Cannot be zero.
* @property float \$b The "b" value of the equation.
* @property float \$c The "c" value of the equation.
* @property int \$precision The number of decimal places of the roots.
* @property float \$delta The discriminant of the equation, calculated based on a, b and c.
* @property array \$roots The array containing the equation's roots.
*/
{
private \$a;
private \$b;
private \$c;
private \$precision;
private \$delta;
private \$roots;

/**
* Constructs the class, optionally setting \$a, \$b, \$c and \$precision.
*
* @version 1.0
* @since 1.0
* @param float \$a The "a" value of the equation.
* @param float \$b The "b" value of the equation.
* @param float \$c The "c" value of the equation.
* @param int \$precision The number of decimal places of the roots.
*/
public function __construct (\$a = NULL, \$b = NULL, \$c = NULL, \$precision = NULL)
{
if (\$a)
{
\$this->setA(\$a);
\$this->setB(\$b);
\$this->setC(\$c);
}
if (\$precision)
{
\$this->setPrecision(\$precision);
}
}

/**
* Return the root(s) as a string. CANNOT BE USED if the equation is unsolvable!
*
* @version 1.0
* @since 1.0
* @return string Root(s)
* @throws Exception On unsolvable equation (delta < 0).
*/
public function __toString()
{
\$roots = \$this->getRoots();
\$string = "{\$roots[0]}";

if (isset(\$roots[1]))
{
\$string .= "; {\$roots[1]}";
}

return \$string;
}

/**
* Returns the value of "a".
*
* @version 1.0
* @since 1.0
* @return float Value of "a".
*/
public function getA()
{
return \$this->a;
}

/**
* Returns the value of "b".
*
* @version 1.0
* @since 1.0
* @return float Value of "b".
*/
public function getB()
{
return \$this->b;
}

/**
* Returns the value of "c".
*
* @version 1.0
* @since 1.0
* @return float Value of "c".
*/
public function getC()
{
return \$this->c;
}

/**
* Returns the precision.
*
* @version 1.0
* @since 1.0
* @return int Precision.
*/
public function getPrecision()
{
if (!isset(\$this->precision))
{
\$this->setPrecision(2);
}

return \$this->precision;
}

/**
* Returns the discriminant (delta).
*
* @version 1.0
* @since 1.0
* @return float Discriminant (delta).
*/
public function getDelta()
{
if (!isset(\$this->delta))
{
\$this->delta = pow(\$this->getB(), 2) - (4 * \$this->getA() * \$this->getC());
}

return \$this->delta;
}

/**
* Calculates the roots and returns them as an array.
*
* @version 1.0
* @since 1.0
* @return array Roots.
* @throws Exception On unsolvable equation (delta < 0).
*/
public function getRoots()
{
if (!isset(\$this->roots))
{
if (\$this->getDelta() < 0)
{
throw new Exception ('This equation has no real roots.');
}
elseif (\$this->getDelta() == 0)
{
\$x = (0 - \$this->getB()) / 2;
\$this->roots = array(round(\$x, \$this->getPrecision()));
}
else
{
\$x1 = (0 - \$this->getB() + sqrt(\$this->getDelta())) / (2 * \$this->getA());
\$x2 = (0 - \$this->getB() - sqrt(\$this->getDelta())) / (2 * \$this->getA());

\$this->roots = array(round(\$x1, \$this->getPrecision()), round(\$x2, \$this->getPrecision()));
}
}

return \$this->roots;
}

/**
* Sets the value of "a". Also unsets the delta and the roots for recalculation.
*
* @version 1.0
* @since 1.0
* @throws Exception On setting a "zero" value.
*/
public function setA(\$a)
{
if (\$a == 0)
{
throw new Exception('The value of "a" cannot be zero.');
}
else
{
\$this->a = (float) \$a;
unset(\$this->delta);
unset(\$this->roots);
}
}

/**
* Sets the value of "b". Also unsets the delta and the roots for recalculation.
*
* @version 1.0
* @since 1.0
*/
public function setB(\$b)
{
\$this->b = (float) \$b;
unset(\$this->delta);
unset(\$this->roots);
}

/**
* Sets the value of "c". Also unsets the delta and the roots for recalculation.
*
* @version 1.0
* @since 1.0
*/
public function setC(\$c)
{
\$this->c = (float) \$c;
unset(\$this->delta);
unset(\$this->roots);
}

/**
* Sets the precision. Also unsets the roots for rerouding.
*
* @version 1.0
* @since 1.0
* @throws Exception On precision smaller than zero.
*/
public function setPrecision(\$precision)
{
if (\$precision < 0)
{
throw new Exception('The number of decimal places may not be smaller then zero.');
}
else
{
\$this->precision = (int) \$precision;
unset(\$this->roots);
}
}
}