module Numeric.Rig.Characteristic ( Characteristic(..) , charInt , charWord , frobenius ) where import Data.Int import Data.Word import Data.Proxy import Numeric.Rig.Class import Numeric.Ring.Endomorphism import Numeric.Natural.Internal import Numeric.Monoid.Multiplicative import Prelude hiding ((^)) class Rig r => Characteristic r where char :: Proxy r -> Natural -- the frobenius ring endomorphism (assuming the characteristic is prime) frobenius :: Characteristic r => End r frobenius = End $ \r -> r `pow` char (ofRing r) ofRing :: r -> Proxy r ofRing _ = Proxy charInt :: (Integral s, Bounded s) => Proxy s -> Natural charInt p = 2 * fromIntegral (maxBound `asProxyTypeOf` p) + 2 charWord :: (Whole s, Bounded s) => Proxy s -> Natural charWord p = toNatural (maxBound `asProxyTypeOf` p) + 1 -- | NB: we're using the boolean semiring, not the boolean ring instance Characteristic Bool where char _ = 0 instance Characteristic Integer where char _ = 0 instance Characteristic Natural where char _ = 0 instance Characteristic Int where char = charInt instance Characteristic Int8 where char = charInt instance Characteristic Int16 where char = charInt instance Characteristic Int32 where char = charInt instance Characteristic Int64 where char = charInt instance Characteristic Word where char = charWord instance Characteristic Word8 where char = charWord instance Characteristic Word16 where char = charWord instance Characteristic Word32 where char = charWord instance Characteristic Word64 where char = charWord instance Characteristic () where char _ = 1 instance (Characteristic a, Characteristic b) => Characteristic (a,b) where char p = char (a p) `lcm` char (b p) where a :: Proxy (a,b) -> Proxy a a _ = Proxy b :: Proxy (a,b) -> Proxy b b _ = Proxy instance (Characteristic a, Characteristic b, Characteristic c) => Characteristic (a,b,c) where char p = char (a p) `lcm` char (b p) `lcm` char (c p) where a :: Proxy (a,b,c) -> Proxy a a _ = Proxy b :: Proxy (a,b,c) -> Proxy b b _ = Proxy c :: Proxy (a,b,c) -> Proxy c c _ = Proxy instance (Characteristic a, Characteristic b, Characteristic c, Characteristic d) => Characteristic (a,b,c,d) where char p = char (a p) `lcm` char (b p) `lcm` char (c p) `lcm` char (d p) where a :: Proxy (a,b,c,d) -> Proxy a a _ = Proxy b :: Proxy (a,b,c,d) -> Proxy b b _ = Proxy c :: Proxy (a,b,c,d) -> Proxy c c _ = Proxy d :: Proxy (a,b,c,d) -> Proxy d d _ = Proxy instance (Characteristic a, Characteristic b, Characteristic c, Characteristic d, Characteristic e) => Characteristic (a,b,c,d,e) where char p = char (a p) `lcm` char (b p) `lcm` char (c p) `lcm` char (d p) `lcm` char (e p) where a :: Proxy (a,b,c,d,e) -> Proxy a a _ = Proxy b :: Proxy (a,b,c,d,e) -> Proxy b b _ = Proxy c :: Proxy (a,b,c,d,e) -> Proxy c c _ = Proxy d :: Proxy (a,b,c,d,e) -> Proxy d d _ = Proxy e :: Proxy (a,b,c,d,e) -> Proxy e e _ = Proxy