// A class that implements the QE interface.
// Barry Cornelius, 28th February 2000
public class QEImpl implements QE
{
   private static final double tCloseToZero = 1.0E-8;
   private double iA;
   private double iB;
   private double iC;
   private double iRoot1;
   private double iRoot2;
   private boolean iRootsAreOutOfDate = true;
   private void iSolve()
   {
      final double tDiscriminant = iB*iB - 4.0*iA*iC;
      final double tSqrtPart = Math.sqrt(tDiscriminant);
      iRoot1 = (-iB + tSqrtPart)/(2.0*iA);
      iRoot2 = (-iB - tSqrtPart)/(2.0*iA);
      iRootsAreOutOfDate = false;
   }
   public QEImpl(final double pA, final double pB, final double pC)
   {
      iA = pA;
      iB = pB;
      iC = pC;
      iRootsAreOutOfDate = true;
   }
   public double getA()
   {
      return iA;
   }
   public double getB()
   {
      return iB;
   }
   public double getC()
   {
      return iC;
   }
   public void setA(final double pA)
   {
      iA = pA;
      iRootsAreOutOfDate = true;
   }
   public void setB(final double pB)
   {
      iB = pB;
      iRootsAreOutOfDate = true;
   }
   public void setC(final double pC)
   {
      iC = pC;
      iRootsAreOutOfDate = true;
   }
   public boolean equals(final Object pObject)
   {
      if (pObject instanceof QEImpl)
      {
         final QEImpl tQEImpl = (QEImpl)pObject;
         return iA==tQEImpl.iA && iB==tQEImpl.iB && iC==tQEImpl.iC;
      }
      return false;
   }
   public int hashCode()
   {
      return (int)iA + (int)iB + (int)iC;
   }
   public String toString()
   {
      return iA + "@" + iB + "@" + iC;
   }
   public boolean isReal()
   {
      final double tDiscriminant = iB*iB - 4.0*iA*iC;
      return Math.abs(iA)>=tCloseToZero && tDiscriminant>=0.0;
   }
   public double getRoot1()
   {
      if (iRootsAreOutOfDate)
      {
         iSolve();
      }
      return iRoot1;
   }
   public double getRoot2()
   {
      if (iRootsAreOutOfDate)
      {
         iSolve();
      }
      return iRoot2;
   }
}
