HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulenumeric-prelude-0.4.4Haskell98

Algebra.PrincipalIdealDomain

  • 1 class
  • 24 values

Class

5 declarations
classclass (C a, C a) => C a where
#

A principal ideal domain is a ring in which every ideal (the set of multiples of some generating set of elements) is principal: That is, every element can be written as the multiple of some generating element. gcd a b gives a generator for the ideal generated by a and b. The algorithm above works whenever mod x y is smaller (in a suitable sense) than both x and y; otherwise the algorithm may run forever.

Laws:

  divides x (lcm x y)
  x `gcd` (y `gcd` z) == (x `gcd` y) `gcd` z
  gcd x y * z == gcd (x*z) (y*z)
  gcd x y * lcm x y == x * y

(etc: canonical)

Minimal definition: * nothing, if the standard Euclidean algorithm work * if extendedGCD is implemented customly, gcd and lcm make use of it

Instances11C, …
  • C IntegerDefined in numeric-prelude-0.4.4 · Algebra.PrincipalIdealDomain
  • C Int16Defined in numeric-prelude-0.4.4 · Algebra.PrincipalIdealDomain
  • C Int32Defined in numeric-prelude-0.4.4 · Algebra.PrincipalIdealDomain
  • C Int64Defined in numeric-prelude-0.4.4 · Algebra.PrincipalIdealDomain
  • C Int8Defined in numeric-prelude-0.4.4 · Algebra.PrincipalIdealDomain
  • C IntDefined in numeric-prelude-0.4.4 · Algebra.PrincipalIdealDomain
  • C TDefined in numeric-prelude-0.4.4 · Number.Peano
  • Integral a => C (T a)Defined in numeric-prelude-0.4.4 · MathObj.Wrapper.Haskell98
  • C a => C (T a)Defined in numeric-prelude-0.4.4 · MathObj.Wrapper.NumericPrelude
  • (Ord a, C a, C a) => C (T a)Defined in numeric-prelude-0.4.4 · Number.Complex
  • (C a, C a) => C (T a)Defined in numeric-prelude-0.4.4 · MathObj.Polynomial
methodextendedGCD :: a -> a -> (a, (a, a))
#

Compute the greatest common divisor and solve a respective Diophantine equation.

  (g,(a,b)) = extendedGCD x y ==>
       g==a*x+b*y   &&  g == gcd x y

TODO: This method is not appropriate for the PID class, because there are rings like the one of the multivariate polynomials, where for all x and y greatest common divisors of x and y exist, but they cannot be represented as a linear combination of x and y. TODO: The definition of extendedGCD does not return the canonical associate.

methodgcd :: a -> a -> a
#

The Greatest Common Divisor is defined by:

  gcd x y == gcd y x
  divides z x && divides z y ==> divides z (gcd x y)   (specification)
  divides (gcd x y) x
methodlcm :: a -> a -> a
#

Least common multiple

Standard implementations for instances

2 declarations
valueeuclid :: (C a, C a) => (a -> a -> a) -> a -> a -> a
#
valueextendedEuclid :: (C a, C a) => (a -> a -> (a, a)) -> a -> a -> (a, (a, a))
#

Algorithms

6 declarations
valueextendedGCDMulti :: C a => [a] -> (a, [a])
#

Compute the greatest common divisor for multiple numbers by repeated application of the two-operand-gcd.

valuediophantine :: C a => a -> a -> a -> Maybe (a, a)
#

A variant with small coefficients.

Just (a,b) = diophantine z x y means a*x+b*y = z. It is required that gcd(y,z) divides x.

valuediophantineMin :: C a => a -> a -> a -> Maybe (a, a)
#

Like diophantine, but a is minimal with respect to the measure function of the Euclidean algorithm.

valuechineseRemainder :: C a => (a, a) -> (a, a) -> Maybe (a, a)
#

Not efficient enough, because GCD/LCM is computed twice.

valuechineseRemainderMulti :: C a => [(a, a)] -> Maybe (a, a)
#

For Just (n,b) = chineseRemainderMulti [(m0,a0), (m1,a1), ..., (mk,ak)] and all x with x = b mod n, the congruences x=a0 mod m0, x=a1 mod m1, ..., x=ak mod mk are fulfilled. Also, n is the least common multiplier of all mi.

Example3 expressions
PID.chineseRemainderMulti [(100,21), (10000,2021::Integer)]Just (10000,2021)PID.chineseRemainderMulti [(97,90),(99,10),(100,0::Integer)]Just (960300,100000)PID.chineseRemainderMulti [(95,30),(97,27),(98,8),(99,1::Integer)]Just (89403930,1000000)
Property
QC.listOf genResidueClass /\ \xs -> case PID.chineseRemainderMulti xs of Nothing -> True; Just (n,b) -> abs n == abs (foldl lcm 1 (map fst xs)) && map snd xs == map (mod b . fst) xs
Property
\(QC.NonEmpty ms) b -> let xs = map (\(QC.NonZero m) -> (m, mod b m)) ms in case PID.chineseRemainderMulti xs of Nothing -> False; Just (n,c) -> abs n == abs (foldl lcm 1 (map QC.getNonZero ms)) && mod b n == (c::Integer)

Properties

15 declarations