{-# OPTIONS_GHC -Wall #-}
module NumHask.Algebra.Integral
( Integral(..)
, ToInteger(..)
, FromInteger(..)
, fromIntegral
, even
, odd
, (^)
, (^^)
) where
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Word (Word, Word8, Word16, Word32, Word64)
import GHC.Natural (Natural(..))
import NumHask.Algebra.Ring
import NumHask.Algebra.Additive
import NumHask.Algebra.Multiplicative
import qualified Prelude as P
import Prelude (Double, Float, Int, Integer, (.), fst, snd)
class (Semiring a) =>
Integral a where
infixl 7 `div`, `mod`
div :: a -> a -> a
div a1 a2 = fst (divMod a1 a2)
mod :: a -> a -> a
mod a1 a2 = snd (divMod a1 a2)
divMod :: a -> a -> (a, a)
quot :: a -> a -> a
quot a1 a2 = fst (quotRem a1 a2)
rem :: a -> a -> a
rem a1 a2 = snd (quotRem a1 a2)
quotRem :: a -> a -> (a, a)
instance Integral Int where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Integer where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Natural where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Int8 where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Int16 where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Int32 where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Int64 where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Word where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Word8 where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Word16 where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Word32 where
divMod = P.divMod
quotRem = P.quotRem
instance Integral Word64 where
divMod = P.divMod
quotRem = P.quotRem
class ToInteger a where
toInteger :: a -> Integer
instance ToInteger Int where
toInteger = P.toInteger
instance ToInteger Integer where
toInteger = P.toInteger
instance ToInteger Natural where
toInteger = P.toInteger
instance ToInteger Int8 where
toInteger = P.toInteger
instance ToInteger Int16 where
toInteger = P.toInteger
instance ToInteger Int32 where
toInteger = P.toInteger
instance ToInteger Int64 where
toInteger = P.toInteger
instance ToInteger Word where
toInteger = P.toInteger
instance ToInteger Word8 where
toInteger = P.toInteger
instance ToInteger Word16 where
toInteger = P.toInteger
instance ToInteger Word32 where
toInteger = P.toInteger
instance ToInteger Word64 where
toInteger = P.toInteger
class FromInteger a where
fromInteger :: Integer -> a
fromIntegral :: (ToInteger a, FromInteger b) => a -> b
fromIntegral = fromInteger . toInteger
instance FromInteger Double where
fromInteger = P.fromInteger
instance FromInteger Float where
fromInteger = P.fromInteger
instance FromInteger Int where
fromInteger = P.fromInteger
instance FromInteger Integer where
fromInteger = P.fromInteger
instance FromInteger Natural where
fromInteger = P.fromInteger
instance FromInteger Int8 where
fromInteger = P.fromInteger
instance FromInteger Int16 where
fromInteger = P.fromInteger
instance FromInteger Int32 where
fromInteger = P.fromInteger
instance FromInteger Int64 where
fromInteger = P.fromInteger
instance FromInteger Word where
fromInteger = P.fromInteger
instance FromInteger Word8 where
fromInteger = P.fromInteger
instance FromInteger Word16 where
fromInteger = P.fromInteger
instance FromInteger Word32 where
fromInteger = P.fromInteger
instance FromInteger Word64 where
fromInteger = P.fromInteger
even :: (P.Eq a, Integral a) => a -> P.Bool
even n = n `rem` (one + one) P.== zero
odd :: (P.Eq a, Integral a) => a -> P.Bool
odd = P.not . even
(^) :: (P.Ord b, Integral b, Multiplicative a) => a -> b -> a
x0 ^ y0 | y0 P.< zero = P.undefined
| y0 P.== zero = one
| P.otherwise = f x0 y0
where
two = one+one
f x y | even y = f (x * x) (y `quot` two)
| y P.== one = x
| P.otherwise = g (x * x) (y `quot` two) x
g x y z | even y = g (x * x) (y `quot` two) z
| y P.== one = x * z
| P.otherwise = g (x * x) (y `quot` two) (x * z)
(^^) :: (MultiplicativeGroup a) => a -> Integer -> a
(^^) x n = if n P.>= zero then x^n else recip (x ^ negate n)