{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Modular (
Mod, Modulus,
unMod, toMod, toMod',
inv, type (/)(), ℤ,
modVal, SomeMod, someModVal
) where
import Control.Arrow (first)
import Data.Proxy (Proxy (..))
import Data.Ratio (denominator, numerator, (%))
import Text.Printf (printf)
#if MIN_VERSION_base(4,11,0)
import GHC.TypeLits hiding (Mod)
#else
import GHC.TypeLits
#endif
#if !MIN_VERSION_base(4,16,0)
import Data.Type.Equality ((:~:) (..))
import GHC.TypeLits.Compare ((%<=?), (:<=?) (LE, NLE))
import GHC.TypeLits.Witnesses (SNat (SNat))
#endif
newtype i `Mod` (n :: Nat) = Mod i deriving (Mod i n -> Mod i n -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall i (n :: Natural). Eq i => Mod i n -> Mod i n -> Bool
/= :: Mod i n -> Mod i n -> Bool
$c/= :: forall i (n :: Natural). Eq i => Mod i n -> Mod i n -> Bool
== :: Mod i n -> Mod i n -> Bool
$c== :: forall i (n :: Natural). Eq i => Mod i n -> Mod i n -> Bool
Eq, Mod i n -> Mod i n -> Bool
Mod i n -> Mod i n -> Ordering
Mod i n -> Mod i n -> Mod i n
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {i} {n :: Natural}. Ord i => Eq (Mod i n)
forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Bool
forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Ordering
forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Mod i n
min :: Mod i n -> Mod i n -> Mod i n
$cmin :: forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Mod i n
max :: Mod i n -> Mod i n -> Mod i n
$cmax :: forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Mod i n
>= :: Mod i n -> Mod i n -> Bool
$c>= :: forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Bool
> :: Mod i n -> Mod i n -> Bool
$c> :: forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Bool
<= :: Mod i n -> Mod i n -> Bool
$c<= :: forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Bool
< :: Mod i n -> Mod i n -> Bool
$c< :: forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Bool
compare :: Mod i n -> Mod i n -> Ordering
$ccompare :: forall i (n :: Natural). Ord i => Mod i n -> Mod i n -> Ordering
Ord)
unMod :: i `Mod` n -> i
unMod :: forall i (n :: Natural). Mod i n -> i
unMod (Mod i
i) = i
i
type (/) = Mod
type ℤ = Integer
type Modulus n = (KnownNat n, 1 <= n)
modulus :: forall n i. (Integral i, Modulus n) => i
modulus :: forall (n :: Natural) i. (Integral i, Modulus n) => i
modulus = forall a. Num a => Integer -> a
fromInteger forall a b. (a -> b) -> a -> b
$ forall (n :: Natural) (proxy :: Natural -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall {k} (t :: k). Proxy t
Proxy :: Proxy n)
toMod :: forall n i. (Integral i, Modulus n) => i -> i `Mod` n
toMod :: forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod i
i = forall i (n :: Natural). i -> Mod i n
Mod forall a b. (a -> b) -> a -> b
$ i
i forall a. Integral a => a -> a -> a
`mod` (forall (n :: Natural) i. (Integral i, Modulus n) => i
modulus @n)
modVal :: forall i proxy n. (Integral i, Modulus n)
=> i
-> proxy n
-> Mod i n
modVal :: forall i (proxy :: Natural -> *) (n :: Natural).
(Integral i, Modulus n) =>
i -> proxy n -> Mod i n
modVal i
i proxy n
_ = forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod i
i
toMod' :: forall n i j. (Integral i, Integral j, Modulus n)
=> i
-> j `Mod` n
toMod' :: forall (n :: Natural) i j.
(Integral i, Integral j, Modulus n) =>
i -> Mod j n
toMod' i
i = forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ i
i forall a. Integral a => a -> a -> a
`mod` (forall (n :: Natural) i. (Integral i, Modulus n) => i
modulus @n)
instance Show i => Show (i `Mod` n) where show :: Mod i n -> String
show (Mod i
i) = forall a. Show a => a -> String
show i
i
instance (Read i, Integral i, Modulus n) => Read (i `Mod` n)
where readsPrec :: Int -> ReadS (Mod i n)
readsPrec Int
prec = forall a b. (a -> b) -> [a] -> [b]
map (forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Read a => Int -> ReadS a
readsPrec Int
prec
instance (Integral i, Modulus n) => Num (i `Mod` n) where
fromInteger :: Integer -> Mod i n
fromInteger = forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => Integer -> a
fromInteger
Mod i
i₁ + :: Mod i n -> Mod i n -> Mod i n
+ Mod i
i₂ = forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod forall a b. (a -> b) -> a -> b
$ i
i₁ forall a. Num a => a -> a -> a
+ i
i₂
Mod i
i₁ * :: Mod i n -> Mod i n -> Mod i n
* Mod i
i₂ = forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod forall a b. (a -> b) -> a -> b
$ i
i₁ forall a. Num a => a -> a -> a
* i
i₂
abs :: Mod i n -> Mod i n
abs (Mod i
i) = forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
abs i
i
signum :: Mod i n -> Mod i n
signum (Mod i
i) = forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
signum i
i
negate :: Mod i n -> Mod i n
negate (Mod i
i) = forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
negate i
i
instance (Integral i, Modulus n) => Enum (i `Mod` n) where
toEnum :: Int -> Mod i n
toEnum = forall a b. (Integral a, Num b) => a -> b
fromIntegral
fromEnum :: Mod i n -> Int
fromEnum = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i (n :: Natural). Mod i n -> i
unMod
enumFrom :: Mod i n -> [Mod i n]
enumFrom Mod i n
x = forall a. Enum a => a -> a -> [a]
enumFromTo Mod i n
x forall a. Bounded a => a
maxBound
enumFromThen :: Mod i n -> Mod i n -> [Mod i n]
enumFromThen Mod i n
x Mod i n
y = forall a. Enum a => a -> a -> a -> [a]
enumFromThenTo Mod i n
x Mod i n
y Mod i n
bound
where
bound :: Mod i n
bound | forall a. Enum a => a -> Int
fromEnum Mod i n
y forall a. Ord a => a -> a -> Bool
>= forall a. Enum a => a -> Int
fromEnum Mod i n
x = forall a. Bounded a => a
maxBound
| Bool
otherwise = forall a. Bounded a => a
minBound
instance (Integral i, Modulus n) => Bounded (i `Mod` n) where
maxBound :: Mod i n
maxBound = forall i (n :: Natural). i -> Mod i n
Mod forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> a
pred (forall (n :: Natural) i. (Integral i, Modulus n) => i
modulus @n)
minBound :: Mod i n
minBound = Mod i n
0
instance (Integral i, Modulus n) => Real (i `Mod` n) where
toRational :: Mod i n -> Rational
toRational (Mod i
i) = forall a. Integral a => a -> Integer
toInteger i
i forall a. Integral a => a -> a -> Ratio a
% Integer
1
instance (Integral i, Modulus n) => Fractional (i `Mod` n) where
fromRational :: Rational -> Mod i n
fromRational Rational
r =
forall a. Num a => Integer -> a
fromInteger (forall a. Ratio a -> a
numerator Rational
r) forall a. Fractional a => a -> a -> a
/ forall a. Num a => Integer -> a
fromInteger (forall a. Ratio a -> a
denominator Rational
r)
recip :: Mod i n -> Mod i n
recip Mod i n
i = Maybe (Mod i n) -> Mod i n
unwrap forall a b. (a -> b) -> a -> b
$ forall (n :: Natural) i.
(Modulus n, Integral i) =>
(i / n) -> Maybe (i / n)
inv Mod i n
i
where
unwrap :: Maybe (Mod i n) -> Mod i n
unwrap (Just Mod i n
x) = Mod i n
x
unwrap Maybe (Mod i n)
Nothing =
let i' :: Integer
i' = forall a. Integral a => a -> Integer
toInteger forall a b. (a -> b) -> a -> b
$ forall i (n :: Natural). Mod i n -> i
unMod Mod i n
i
bound' :: Integer
bound' = forall (n :: Natural) i. (Integral i, Modulus n) => i
modulus @n @Integer
in forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$
forall r. PrintfType r => String -> r
printf String
"Cannot invert %d (mod %d): not coprime to modulus." Integer
i' Integer
bound'
inv :: forall n i. (Modulus n, Integral i) => (i/n) -> Maybe (i/n)
inv :: forall (n :: Natural) i.
(Modulus n, Integral i) =>
(i / n) -> Maybe (i / n)
inv (Mod i
k) = forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {b}. Integral b => b -> b -> Maybe (b, b)
inv' (forall (n :: Natural) i. (Integral i, Modulus n) => i
modulus @n) i
k
where
inv' :: b -> b -> Maybe (b, b)
inv' b
_ b
0 = forall a. Maybe a
Nothing
inv' b
_ b
1 = forall a. a -> Maybe a
Just (b
0, b
1)
inv' b
n b
x = do
let (b
q, b
r) = b
n forall a. Integral a => a -> a -> (a, a)
`quotRem` b
x
(b
q', b
r') <- b -> b -> Maybe (b, b)
inv' b
x b
r
forall (f :: * -> *) a. Applicative f => a -> f a
pure (b
r', b
q' forall a. Num a => a -> a -> a
- b
r' forall a. Num a => a -> a -> a
* b
q)
data SomeMod i where
SomeMod :: forall i (n :: Nat). Modulus n => Mod i n -> SomeMod i
instance Show i => Show (SomeMod i) where
showsPrec :: Int -> SomeMod i -> ShowS
showsPrec Int
p (SomeMod (i / n
x :: i/n)) = Bool -> ShowS -> ShowS
showParen (Int
p forall a. Ord a => a -> a -> Bool
> Int
10) forall a b. (a -> b) -> a -> b
$
String -> ShowS
showString forall a b. (a -> b) -> a -> b
$ forall r. PrintfType r => String -> r
printf String
"someModVal %s %d" (forall a. Show a => a -> String
show i / n
x) (forall (n :: Natural) i. (Integral i, Modulus n) => i
modulus @n @Integer)
someModVal :: Integral i
=> i
-> Integer
-> Maybe (SomeMod i)
someModVal :: forall i. Integral i => i -> Integer -> Maybe (SomeMod i)
someModVal i
i Integer
n = do
SomeNat (Proxy n
_ :: Proxy n) <- Integer -> Maybe SomeNat
someNatVal Integer
n
#if MIN_VERSION_base(4,16,0)
case forall {k} (t :: k). Proxy t
Proxy @1 forall (a :: Natural) (b :: Natural) (proxy1 :: Natural -> *)
(proxy2 :: Natural -> *).
(KnownNat a, KnownNat b) =>
proxy1 a -> proxy2 b -> OrderingI a b
`cmpNat` forall {k} (t :: k). Proxy t
Proxy @n of
OrderingI 1 n
LTI -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall i (n :: Natural). Modulus n => Mod i n -> SomeMod i
SomeMod forall a b. (a -> b) -> a -> b
$ forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod @n i
i
OrderingI 1 n
EQI -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall i (n :: Natural). Modulus n => Mod i n -> SomeMod i
SomeMod forall a b. (a -> b) -> a -> b
$ forall (n :: Natural) i. (Integral i, Modulus n) => i -> Mod i n
toMod @n i
i
OrderingI 1 n
GTI -> forall a. Maybe a
Nothing
#else
case SNat @1 %<=? SNat @n of
LE Refl -> pure $ SomeMod $ toMod @n i
NLE _ _ -> Nothing
#endif