algebra-4.3.1: src/Numeric/Domain/Euclidean.hs
module Numeric.Domain.Euclidean (Euclidean(..), euclid, prs, chineseRemainder) where
import Numeric.Additive.Group
import Numeric.Algebra.Class
import Numeric.Algebra.Unital
import Numeric.Decidable.Zero
import Numeric.Domain.Internal
import Prelude (otherwise)
import qualified Prelude as P
prs :: Euclidean r => r -> r -> [(r, r, r)]
prs f g = step [(g, zero, one), (f, one, zero)]
where
step acc@((r',s',t'):(r,s,t):_)
| isZero r' = P.tail acc
| otherwise =
let q = r `quot` r'
s'' = (s - q * s')
t'' = (t - q * t')
in step ((r - q * r', s'', t'') : acc)
step _ = P.error "cannot happen!"
chineseRemainder :: Euclidean r
=> [(r, r)] -- ^ List of @(m_i, v_i)@
-> r -- ^ @f@ with @f@ = @v_i@ (mod @v_i@)
chineseRemainder mvs =
let (ms, _) = P.unzip mvs
m = product ms
in sum [((vi*s) `rem` mi)*n | (mi, vi) <- mvs
, let n = m `quot` mi
, let (_, s, _) : _ = euclid n mi
]