module Graphics.Rasterific.QuadraticFormula( QuadraticFormula( .. )
                                           , discriminant
                                           , formulaRoots
                                           ) where

-- | Represent an equation `a * x^2 + b * x + c = 0`
data QuadraticFormula a = QuadraticFormula
    { _coeffA :: !a -- ^ Coefficient for the square part (x^2)
    , _coeffB :: !a -- ^ Coefficient the linear part (x)
    , _coeffC :: !a -- ^ Constant
    }

instance Functor QuadraticFormula where
    {-# INLINE fmap #-}
    fmap f (QuadraticFormula a b c) =
        QuadraticFormula (f a) (f b) (f c)

instance Applicative QuadraticFormula where
  pure a = QuadraticFormula a a a
  {-# INLINE pure #-}

  QuadraticFormula a b c <*> QuadraticFormula d e f =
      QuadraticFormula (a d) (b e) (c f)
  {-# INLINE (<*>) #-}

-- | Discriminant equation, if the result is:
--
--  * Below 0, then the formula doesn't have any solution
--
--  * Equal to 0, then the formula has an unique root.
--
--  * Above 0, the formula has two solutions
--
discriminant :: Num a => QuadraticFormula a -> a
discriminant (QuadraticFormula a b c) = b * b - 4 * a *c

-- | Extract all the roots of the formula ie. where the
-- unknown gives a result of 0
formulaRoots :: (Ord a, Floating a) => QuadraticFormula a -> [a]
formulaRoots formula@(QuadraticFormula a b _)
  | disc < 0 = []
  | disc == 0 = [positiveResult]
  | otherwise = [positiveResult, negativeResult]
  where
    disc = discriminant formula
    squarePart = sqrt disc
    positiveResult = (negate b + squarePart) / (2 * a)
    negativeResult = (negate b - squarePart) / (2 * a)