-- |-- Module: Math.NumberTheory.Moduli.Multiplicative-- Copyright: (c) 2017 Andrew Lelechenko-- Licence: MIT-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>---- Multiplicative groups of integers modulo m.--{-# LANGUAGE ScopedTypeVariables #-}{-# LANGUAGE ViewPatterns #-}moduleMath.NumberTheory.Moduli.Multiplicative(-- * Multiplicative groupMultMod ,multElement ,isMultElement ,invertGroup -- * Primitive roots,PrimitiveRoot ,unPrimitiveRoot ,isPrimitiveRoot ,discreteLogarithm )whereimportControl.MonadimportData.ConstraintimportData.ModimportData.SemigroupimportGHC.TypeNats(KnownNat,natVal)importNumeric.NaturalimportMath.NumberTheory.Moduli.Internal importMath.NumberTheory.Moduli.Singleton importMath.NumberTheory.Primes -- | This type represents elements of the multiplicative group mod m, i.e.-- those elements which are coprime to m. Use @isMultElement@ to construct.newtypeMultMod m =MultMod {forall (m :: Nat). MultMod m -> Mod m
multElement ::Modm -- ^ Unwrap a residue.}deriving(MultMod m -> MultMod m -> Bool
(MultMod m -> MultMod m -> Bool)
-> (MultMod m -> MultMod m -> Bool) -> Eq (MultMod m)
forall (m :: Nat). MultMod m -> MultMod m -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall (m :: Nat). MultMod m -> MultMod m -> Bool
== :: MultMod m -> MultMod m -> Bool
$c/= :: forall (m :: Nat). MultMod m -> MultMod m -> Bool
/= :: MultMod m -> MultMod m -> Bool
Eq,Eq (MultMod m)
Eq (MultMod m) =>
(MultMod m -> MultMod m -> Ordering)
-> (MultMod m -> MultMod m -> Bool)
-> (MultMod m -> MultMod m -> Bool)
-> (MultMod m -> MultMod m -> Bool)
-> (MultMod m -> MultMod m -> Bool)
-> (MultMod m -> MultMod m -> MultMod m)
-> (MultMod m -> MultMod m -> MultMod m)
-> Ord (MultMod m)
MultMod m -> MultMod m -> Bool
MultMod m -> MultMod m -> Ordering
MultMod m -> MultMod m -> MultMod m
forall (m :: Nat). Eq (MultMod m)
forall (m :: Nat). MultMod m -> MultMod m -> Bool
forall (m :: Nat). MultMod m -> MultMod m -> Ordering
forall (m :: Nat). MultMod m -> MultMod m -> MultMod m
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
$ccompare :: forall (m :: Nat). MultMod m -> MultMod m -> Ordering
compare :: MultMod m -> MultMod m -> Ordering
$c< :: forall (m :: Nat). MultMod m -> MultMod m -> Bool
< :: MultMod m -> MultMod m -> Bool
$c<= :: forall (m :: Nat). MultMod m -> MultMod m -> Bool
<= :: MultMod m -> MultMod m -> Bool
$c> :: forall (m :: Nat). MultMod m -> MultMod m -> Bool
> :: MultMod m -> MultMod m -> Bool
$c>= :: forall (m :: Nat). MultMod m -> MultMod m -> Bool
>= :: MultMod m -> MultMod m -> Bool
$cmax :: forall (m :: Nat). MultMod m -> MultMod m -> MultMod m
max :: MultMod m -> MultMod m -> MultMod m
$cmin :: forall (m :: Nat). MultMod m -> MultMod m -> MultMod m
min :: MultMod m -> MultMod m -> MultMod m
Ord,Int -> MultMod m -> ShowS
[MultMod m] -> ShowS
MultMod m -> String
(Int -> MultMod m -> ShowS)
-> (MultMod m -> String)
-> ([MultMod m] -> ShowS)
-> Show (MultMod m)
forall (m :: Nat). Int -> MultMod m -> ShowS
forall (m :: Nat). [MultMod m] -> ShowS
forall (m :: Nat). MultMod m -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall (m :: Nat). Int -> MultMod m -> ShowS
showsPrec :: Int -> MultMod m -> ShowS
$cshow :: forall (m :: Nat). MultMod m -> String
show :: MultMod m -> String
$cshowList :: forall (m :: Nat). [MultMod m] -> ShowS
showList :: [MultMod m] -> ShowS
Show)instanceKnownNatm =>Semigroup(MultMod m )whereMultMod Mod m
a <> :: MultMod m -> MultMod m -> MultMod m
<>MultMod Mod m
b =Mod m -> MultMod m
forall (m :: Nat). Mod m -> MultMod m
MultMod (Mod m
a Mod m -> Mod m -> Mod m
forall a. Num a => a -> a -> a
*Mod m
b )stimes :: forall b. Integral b => b -> MultMod m -> MultMod m
stimes b
k a :: MultMod m
a @(MultMod Mod m
a' )|b
k b -> b -> Bool
forall a. Ord a => a -> a -> Bool
>=b
0=Mod m -> MultMod m
forall (m :: Nat). Mod m -> MultMod m
MultMod (Mod m
a' Mod m -> b -> Mod m
forall (m :: Nat) a.
(KnownNat m, Integral a) =>
Mod m -> a -> Mod m
^%b
k )|Bool
otherwise=MultMod m -> MultMod m
forall (m :: Nat). KnownNat m => MultMod m -> MultMod m
invertGroup (MultMod m -> MultMod m) -> MultMod m -> MultMod m
forall a b. (a -> b) -> a -> b
$b -> MultMod m -> MultMod m
forall b. Integral b => b -> MultMod m -> MultMod m
forall a b. (Semigroup a, Integral b) => b -> a -> a
stimes(-b
k )MultMod m
a -- ^ This Semigroup is in fact a group, so @stimes@ can be called with a negative first argument.instanceKnownNatm =>Monoid(MultMod m )wheremempty :: MultMod m
mempty=Mod m -> MultMod m
forall (m :: Nat). Mod m -> MultMod m
MultMod Mod m
1instanceKnownNatm =>Bounded(MultMod m )whereminBound :: MultMod m
minBound =Mod m -> MultMod m
forall (m :: Nat). Mod m -> MultMod m
MultMod Mod m
1maxBound :: MultMod m
maxBound =Mod m -> MultMod m
forall (m :: Nat). Mod m -> MultMod m
MultMod (-Mod m
1)-- | Attempt to construct a multiplicative group element.isMultElement ::KnownNatm =>Modm ->Maybe(MultMod m )isMultElement :: forall (m :: Nat). KnownNat m => Mod m -> Maybe (MultMod m)
isMultElement Mod m
a =ifMod m -> Nat
forall (m :: Nat). Mod m -> Nat
unModMod m
a Nat -> Nat -> Nat
forall a. Integral a => a -> a -> a
`gcd`Mod m -> Nat
forall (n :: Nat) (proxy :: Nat -> *). KnownNat n => proxy n -> Nat
natValMod m
a Nat -> Nat -> Bool
forall a. Eq a => a -> a -> Bool
==Nat
1thenMultMod m -> Maybe (MultMod m)
forall a. a -> Maybe a
Just(MultMod m -> Maybe (MultMod m)) -> MultMod m -> Maybe (MultMod m)
forall a b. (a -> b) -> a -> b
$Mod m -> MultMod m
forall (m :: Nat). Mod m -> MultMod m
MultMod Mod m
a elseMaybe (MultMod m)
forall a. Maybe a
Nothing-- | For elements of the multiplicative group, we can safely perform the inverse-- without needing to worry about failure.invertGroup ::KnownNatm =>MultMod m ->MultMod m invertGroup :: forall (m :: Nat). KnownNat m => MultMod m -> MultMod m
invertGroup (MultMod Mod m
a )=caseMod m -> Maybe (Mod m)
forall (m :: Nat). KnownNat m => Mod m -> Maybe (Mod m)
invertModMod m
a ofJustMod m
b ->Mod m -> MultMod m
forall (m :: Nat). Mod m -> MultMod m
MultMod Mod m
b Maybe (Mod m)
Nothing->String -> MultMod m
forall a. HasCallStack => String -> a
errorString
"Math.NumberTheory.Moduli.invertGroup: failed to invert element"-- | 'PrimitiveRoot' m is a type which is only inhabited-- by <https://en.wikipedia.org/wiki/Primitive_root_modulo_n primitive roots> of m.newtypePrimitiveRoot m =PrimitiveRoot {forall (m :: Nat). PrimitiveRoot m -> MultMod m
unPrimitiveRoot ::MultMod m -- ^ Extract primitive root value.}deriving(PrimitiveRoot m -> PrimitiveRoot m -> Bool
(PrimitiveRoot m -> PrimitiveRoot m -> Bool)
-> (PrimitiveRoot m -> PrimitiveRoot m -> Bool)
-> Eq (PrimitiveRoot m)
forall (m :: Nat). PrimitiveRoot m -> PrimitiveRoot m -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall (m :: Nat). PrimitiveRoot m -> PrimitiveRoot m -> Bool
== :: PrimitiveRoot m -> PrimitiveRoot m -> Bool
$c/= :: forall (m :: Nat). PrimitiveRoot m -> PrimitiveRoot m -> Bool
/= :: PrimitiveRoot m -> PrimitiveRoot m -> Bool
Eq,Int -> PrimitiveRoot m -> ShowS
[PrimitiveRoot m] -> ShowS
PrimitiveRoot m -> String
(Int -> PrimitiveRoot m -> ShowS)
-> (PrimitiveRoot m -> String)
-> ([PrimitiveRoot m] -> ShowS)
-> Show (PrimitiveRoot m)
forall (m :: Nat). Int -> PrimitiveRoot m -> ShowS
forall (m :: Nat). [PrimitiveRoot m] -> ShowS
forall (m :: Nat). PrimitiveRoot m -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall (m :: Nat). Int -> PrimitiveRoot m -> ShowS
showsPrec :: Int -> PrimitiveRoot m -> ShowS
$cshow :: forall (m :: Nat). PrimitiveRoot m -> String
show :: PrimitiveRoot m -> String
$cshowList :: forall (m :: Nat). [PrimitiveRoot m] -> ShowS
showList :: [PrimitiveRoot m] -> ShowS
Show)-- | Check whether a given modular residue is-- a <https://en.wikipedia.org/wiki/Primitive_root_modulo_n primitive root>.---- >>> :set -XDataKinds-- >>> import Data.Maybe-- >>> isPrimitiveRoot (fromJust cyclicGroup) (1 :: Mod 13)-- Nothing-- >>> isPrimitiveRoot (fromJust cyclicGroup) (2 :: Mod 13)-- Just (PrimitiveRoot {unPrimitiveRoot = MultMod {multElement = (2 `modulo` 13)}})isPrimitiveRoot ::(Integrala ,UniqueFactorisation a )=>CyclicGroup a m ->Modm ->Maybe(PrimitiveRoot m )isPrimitiveRoot :: forall a (m :: Nat).
(Integral a, UniqueFactorisation a) =>
CyclicGroup a m -> Mod m -> Maybe (PrimitiveRoot m)
isPrimitiveRoot CyclicGroup a m
cg Mod m
r =caseCyclicGroup a m -> (() :: Constraint) :- KnownNat m
forall a (m :: Nat).
Integral a =>
CyclicGroup a m -> (() :: Constraint) :- KnownNat m
proofFromCyclicGroup CyclicGroup a m
cg ofSubDict (KnownNat m)
(() :: Constraint) => Dict (KnownNat m)
Dict->doMultMod m
r' <-Mod m -> Maybe (MultMod m)
forall (m :: Nat). KnownNat m => Mod m -> Maybe (MultMod m)
isMultElement Mod m
r Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard(Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$CyclicGroup a m -> a -> Bool
forall a (m :: Nat).
(Integral a, UniqueFactorisation a) =>
CyclicGroup a m -> a -> Bool
isPrimitiveRoot' CyclicGroup a m
cg (Nat -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral(Mod m -> Nat
forall (m :: Nat). Mod m -> Nat
unModMod m
r ))PrimitiveRoot m -> Maybe (PrimitiveRoot m)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return(PrimitiveRoot m -> Maybe (PrimitiveRoot m))
-> PrimitiveRoot m -> Maybe (PrimitiveRoot m)
forall a b. (a -> b) -> a -> b
$MultMod m -> PrimitiveRoot m
forall (m :: Nat). MultMod m -> PrimitiveRoot m
PrimitiveRoot MultMod m
r' -- | Computes the discrete logarithm. Currently uses a combination of the baby-step-- giant-step method and Pollard's rho algorithm, with Bach reduction.---- >>> :set -XDataKinds-- >>> import Data.Maybe-- >>> let cg = fromJust cyclicGroup :: CyclicGroup Integer 13-- >>> let rt = fromJust (isPrimitiveRoot cg 2)-- >>> let x = fromJust (isMultElement 11)-- >>> discreteLogarithm cg rt x-- 7discreteLogarithm ::CyclicGroup Integerm ->PrimitiveRoot m ->MultMod m ->NaturaldiscreteLogarithm :: forall (m :: Nat).
CyclicGroup Integer m -> PrimitiveRoot m -> MultMod m -> Nat
discreteLogarithm CyclicGroup Integer m
cg (MultMod m -> Mod m
forall (m :: Nat). MultMod m -> Mod m
multElement (MultMod m -> Mod m)
-> (PrimitiveRoot m -> MultMod m) -> PrimitiveRoot m -> Mod m
forall b c a. (b -> c) -> (a -> b) -> a -> c
.PrimitiveRoot m -> MultMod m
forall (m :: Nat). PrimitiveRoot m -> MultMod m
unPrimitiveRoot ->Mod m
a )(MultMod m -> Mod m
forall (m :: Nat). MultMod m -> Mod m
multElement ->Mod m
b )=caseCyclicGroup Integer m
cg ofCyclicGroup Integer m
CG2 ->Nat
0-- the only valid input was a=1, b=1CyclicGroup Integer m
CG4 ->ifMod m -> Nat
forall (m :: Nat). Mod m -> Nat
unModMod m
b Nat -> Nat -> Bool
forall a. Eq a => a -> a -> Bool
==Nat
1thenNat
0elseNat
1-- the only possible input here is a=3 with b = 1 or 3CGOddPrimePower (Prime Integer -> Integer
forall a. Prime a -> a
unPrime ->Integer
p )Word
k ->Integer -> Word -> Integer -> Integer -> Nat
discreteLogarithmPP Integer
p Word
k (Nat -> Integer
forall a. Integral a => a -> Integer
toInteger(Mod m -> Nat
forall (m :: Nat). Mod m -> Nat
unModMod m
a ))(Nat -> Integer
forall a. Integral a => a -> Integer
toInteger(Mod m -> Nat
forall (m :: Nat). Mod m -> Nat
unModMod m
b ))CGDoubleOddPrimePower (Prime Integer -> Integer
forall a. Prime a -> a
unPrime ->Integer
p )Word
k ->Integer -> Word -> Integer -> Integer -> Nat
discreteLogarithmPP Integer
p Word
k (Nat -> Integer
forall a. Integral a => a -> Integer
toInteger(Mod m -> Nat
forall (m :: Nat). Mod m -> Nat
unModMod m
a )Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`rem`Integer
p Integer -> Word -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^Word
k )(Nat -> Integer
forall a. Integral a => a -> Integer
toInteger(Mod m -> Nat
forall (m :: Nat). Mod m -> Nat
unModMod m
b )Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`rem`Integer
p Integer -> Word -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^Word
k )-- we have the isomorphism t -> t `rem` p^k from (Z/2p^kZ)* -> (Z/p^kZ)*

AltStyle によって変換されたページ (->オリジナル) /