-- | -- Module : Math.Diophantine -- Copyright : Joe Jevnik 2013 -- -- License : GPL-2 -- Maintainer : joejev@gmail.org -- Stability : stable -- Portability : GHC -- -- A module for solving quadratic diophantine equations. module Math.Diophantine ( -- * Data Equation(GeneralEquation) -- instances: Show , Solution(..) -- instances: Eq, Show , Z , SolveError(..) -- instances: Show , ParseError(..) -- instances: Show -- * Utilities , readEquation -- :: String -> Either ParseError Equation , specializeEquation -- :: Equation -> Equation , toMaybeList -- :: Solution -> Maybe [(Integer,Integer)] , mergeSolutions -- :: Solution -> Solution -> Solution -- * Equation Solving , solve -- :: Equation -> Either SolveError Solution , solveString -- :: String -> Either SolveError Solution ) where import Math.Diophantine.Internal ( Equation(..) , Solution(..) , Z(..) , mergeSolutions , specializeEquation , solveLinear , solveSimpleHyperbolic , solveEliptical , solveParabolic ) import Math.Diophantine.Parser ( ParseError(..) , readEquation ) -- -------------------------------------------------------------------------- -- -- Data types. -- | A way to report an error in solving. data SolveError = SolveError ParseError -- ^ Represents a read error when -- reading the equation from a string. | HyperbolicError -- ^ The error when you try to solve a -- hyperbolic equation. deriving (Show) -- -------------------------------------------------------------------------- -- -- Exported functions. -- | Extracts the list of solution pairs from a 'Solution'. toMaybeList :: Solution -> Maybe [(Z,Z)] toMaybeList (SolutionSet ns) = Just ns toMaybeList _ = Nothing -- | Determines what type of equation to solve for, and then calls the -- appropriate solve function. Example: -- -- >>> solve (GeneralEquation 1 2 3 3 5 0) -- [(-3,0),(-2,-1),(0,0),(1,-1)] solve :: Equation -> Either SolveError Solution solve e = case specializeEquation e of e@(LinearEquation{}) -> Right $ solveLinear e e@(SimpleHyperbolicEquation{}) -> Right $ solveSimpleHyperbolic e e@(ElipticalEquation{}) -> Right $ solveEliptical e e@(ParabolicEquation{}) -> Right $ solveParabolic e e@(HyperbolicEquation{}) -> Left HyperbolicError -- | Read an 'Equation' out of a 'String', and then solve it. -- This can fail because the string is not a valid equation. solveString :: String -> Either SolveError Solution solveString e = case readEquation e of Right eq -> solve eq Left er -> Left $ SolveError er