<commit_before>{-# LANGUAGE DataKinds, FlexibleContexts, FlexibleInstances          #-}
{-# LANGUAGE MultiParamTypeClasses, PolyKinds, RankNTypes            #-}
{-# LANGUAGE ScopedTypeVariables, TypeFamilies, UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Algebra.Field.Finite (F(), naturalRepr, reifyPrimeField, withPrimeField,
                             modNat, modNat', modRat, modRat', FiniteField(..), order) where
import Algebra.Algorithms.PrimeTest
import Algebra.Ring.Polynomial.Class (PrettyCoeff (..))
import Algebra.Wrapped

import           Control.Monad.Random                  (uniform)
import           Control.Monad.Random                  (runRand)
import           Control.Monad.Random                  (Random (..))
import           Data.Maybe                            (fromMaybe)
import           Data.Proxy
import qualified Data.Ratio                            as R
import           Data.Reflection
import qualified Data.Type.Natural                     as TN
import           GHC.TypeLits                          (KnownNat)
import           Numeric.Algebra                       (Field)
import           Numeric.Algebra                       (char)
import           Numeric.Algebra                       (Natural)
import qualified Numeric.Algebra                       as NA
import           Numeric.Algebra.Unital.UnitNormalForm
import           Numeric.Decidable.Associates
import           Numeric.Decidable.Units
import           Numeric.Decidable.Zero
import           Numeric.Domain.Euclidean              (Euclidean, euclid)
import           Numeric.Domain.GCD                    (GCDDomain)
import           Numeric.Domain.Integral
import           Numeric.Domain.PID
import           Numeric.Domain.UFD
import           Numeric.Field.Fraction                (Fraction)
import           Numeric.Field.Fraction                (denominator)
import           Numeric.Field.Fraction                (numerator)
import           Numeric.Rig.Characteristic            (Characteristic)
import           Numeric.Semiring.ZeroProduct          (ZeroProductSemiring)

-- | Prime field of characteristic @p@.
--   @p@ should be prime, and not statically checked.
newtype F (p :: k) = F { runF :: Integer }

naturalRepr :: F p -> Integer
naturalRepr = runF

instance Reifies (p :: k) Integer => Show (F p) where
  showsPrec d n@(F p) = showsPrec d (p `mod` reflect n)

instance Reifies (p :: k) Integer => PrettyCoeff (F p)

modNat :: Reifies (p :: k) Integer => Integer -> F p
modNat = modNat' Proxy
{-# INLINE modNat #-}

modNat' :: forall proxy (p :: k). Reifies p Integer =>  proxy (F p) -> Integer -> F p
modNat' _ i =
  let p = reflect (Proxy :: Proxy p)
  in F (i `mod` p)
{-# INLINE modNat' #-}

reifyPrimeField :: Integer -> (forall p. KnownNat p => Proxy (F p) -> a) -> a
reifyPrimeField p f = reifyNat p (\pxy -> f (proxyF pxy))

withPrimeField :: Integer -> (forall p. KnownNat p => F p) -> Integer
withPrimeField p f = reifyPrimeField p $ runF . asProxyTypeOf f

proxyF :: Proxy (a :: k) -> Proxy (F a)
proxyF Proxy = Proxy

-- instance Reifies p Int => Noetherian (F p)
<commit_msg>Made pretty printing for Prime fields more prettier<commit_after>{-# LANGUAGE DataKinds, FlexibleContexts, FlexibleInstances          #-}
{-# LANGUAGE MultiParamTypeClasses, PolyKinds, RankNTypes            #-}
{-# LANGUAGE ScopedTypeVariables, TypeFamilies, UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Algebra.Field.Finite (F(), naturalRepr, reifyPrimeField, withPrimeField,
                             modNat, modNat', modRat, modRat', FiniteField(..), order) where
import Algebra.Algorithms.PrimeTest
import Algebra.Ring.Polynomial.Class (PrettyCoeff (..), ShowSCoeff (..))
import Algebra.Wrapped

import           Control.Monad.Random                  (uniform)
import           Control.Monad.Random                  (runRand)
import           Control.Monad.Random                  (Random (..))
import           Data.Maybe                            (fromMaybe)
import           Data.Proxy
import qualified Data.Ratio                            as R
import           Data.Reflection
import qualified Data.Type.Natural                     as TN
import           GHC.TypeLits                          (KnownNat)
import           Numeric.Algebra                       (Field)
import           Numeric.Algebra                       (char)
import           Numeric.Algebra                       (Natural)
import qualified Numeric.Algebra                       as NA
import           Numeric.Algebra.Unital.UnitNormalForm
import           Numeric.Decidable.Associates
import           Numeric.Decidable.Units
import           Numeric.Decidable.Zero
import           Numeric.Domain.Euclidean              (Euclidean, euclid)
import           Numeric.Domain.GCD                    (GCDDomain)
import           Numeric.Domain.Integral
import           Numeric.Domain.PID
import           Numeric.Domain.UFD
import           Numeric.Field.Fraction                (Fraction)
import           Numeric.Field.Fraction                (denominator)
import           Numeric.Field.Fraction                (numerator)
import           Numeric.Rig.Characteristic            (Characteristic)
import           Numeric.Semiring.ZeroProduct          (ZeroProductSemiring)

-- | Prime field of characteristic @p@.
--   @p@ should be prime, and not statically checked.
newtype F (p :: k) = F { runF :: Integer }

naturalRepr :: F p -> Integer
naturalRepr = runF

instance Reifies (p :: k) Integer => Show (F p) where
  showsPrec d n@(F p) = showsPrec d (p `mod` reflect n)

instance Reifies (p :: k) Integer => PrettyCoeff (F p) where
  showsCoeff d (F p) =
    if p == 0
    then Vanished
    else if p == 1
         then OneCoeff
         else Positive $ showsPrec d p

modNat :: Reifies (p :: k) Integer => Integer -> F p
modNat = modNat' Proxy
{-# INLINE modNat #-}

modNat' :: forall proxy (p :: k). Reifies p Integer =>  proxy (F p) -> Integer -> F p
modNat' _ i =
  let p = reflect (Proxy :: Proxy p)
  in F (i `mod` p)
{-# INLINE modNat' #-}

reifyPrimeField :: Integer -> (forall p. KnownNat p => Proxy (F p) -> a) -> a
reifyPrimeField p f = reifyNat p (\pxy -> f (proxyF pxy))

withPrimeField :: Integer -> (forall p. KnownNat p => F p) -> Integer
withPrimeField p f = reifyPrimeField p $ runF . asProxyTypeOf f

proxyF :: Proxy (a :: k) -> Proxy (F a)
proxyF Proxy = Proxy

-- instance Reifies p Int => Noetherian (F p)

{'fraction_non_alphanumeric': 0.09646550393579256, 'fraction_numerical': 0.0003086896125945362, 'mean_word_length': 1.9361123697326688, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '884890', 'n_tokens_mistral': 1979, 'n_tokens_neox': 1846, 'n_words': 555}