{-
Copyright (C) 2011 Dr. Alistair Ward
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
-}
{- |
[@AUTHOR@] Dr. Alistair Ward
[@DESCRIPTION@]
* Describes a /Quotient Ring/; .
* This is a /ring/ composed from a residue-class resulting from /modular/ division.
-}
module Factory.Data.QuotientRing(
-- * Type-classes
QuotientRing(..),
-- * Functions
quot',
rem',
-- ** Predicates
areCongruentModulo,
isDivisibleBy
) where
import Factory.Data.Ring((=-=))
import qualified Factory.Data.Ring as Data.Ring
-- | Defines a sub-class of 'Data.Ring.Ring', in which division is implemented.
class Data.Ring.Ring q => QuotientRing q where
quotRem' :: q -> q -> (q, q) -- ^ Divides the first operand by the second, to yield a pair composed from the /quotient/ and the /remainder/.
-- | Returns the /quotient/, after division of the two specified 'QuotientRing's.
quot' :: QuotientRing q
=> q -- ^ Numerator.
-> q -- ^ Denominator.
-> q
quot' numerator = fst . quotRem' numerator
-- | Returns the /remainder/, after division of the two specified 'QuotientRing's.
rem' :: QuotientRing q
=> q -- ^ Numerator.
-> q -- ^ Denominator.
-> q
rem' numerator = snd . quotRem' numerator
{- |
* 'True' if the two specified 'QuotientRing's are /congruent/ in /modulo/-arithmetic, where the /modulus/ is a third 'QuotientRing'.
* .
-}
areCongruentModulo :: (Eq q, QuotientRing q)
=> q -- ^ LHS.
-> q -- ^ RHS.
-> q -- ^ Modulus.
-> Bool
areCongruentModulo l r modulus
| l == r = True --Only required for efficiency.
| otherwise = (l =-= r) `isDivisibleBy` modulus
-- | True if the second operand /divides/ the first.
isDivisibleBy :: (Eq q, QuotientRing q)
=> q -- ^ Numerator.
-> q -- ^ Denominator.
-> Bool
numerator `isDivisibleBy` denominator = rem' numerator denominator == Data.Ring.additiveIdentity