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