Exception: ghc-6.2.1: internal error: scavenge_mutable_list: strange
object? 55456
Michael Spencer Leeming
msle763 at cse.unsw.EDU.AU
Thu Sep 2 06:29:30 EDT 2004
Hi everyone,
First let me say thanks for maintaining my favourite programming language.
I managed to crash ghci-6.2.1 for the first time tonight, with the
attached module, and the following command:
qsFactor 1000 10000 ((nextPrime 4938203842901)*(nextPrime 4389273982791)) 4
*** Exception: ghc-6.2.1: internal error: scavenge_mutable_list: strange
object? 55456
Please report this as a bug to glasgow-haskell-bugs at haskell.org,
or http://www.sourceforge.net/projects/ghc/
Cheers,
Michael
-------------- next part --------------
module Numtheory where
import List
import Maybe
import GHC.Real
import GHC.Arr
import Bits
import Array
modA :: Integral a => a -> a -> a
modA a n
| r < (div n 2) = r
| otherwise = r-n
where
r = a `mod` n
mulPair (a,b) (c,d) = (a*c,b*d)
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
| x <= y = x:(merge xs (y:ys))
| otherwise = y:(merge (x:xs) ys)
plusMod2 x y
| even x == even y = 0
| otherwise = 1
iSqrt n = head $ dropWhile (\x -> x*x /= n) (iterate approx n)
where
approx x = (x + (n `div` x)) `div` 2
-- returns the coefficients (a,b) such that a*x + b*y = gcd x y
egcd :: Integer -> Integer -> (Integer, Integer)
egcd x y
| y == 0 = (signum x, 0)
| otherwise = (b, a - b*(div x y))
where
(a, b) = egcd y (x `mod` y)
-- inverse: returns an _invertible_ k such that kx `mod` n == gcd x n
inverse :: Integer -> Integer -> Integer
inverse x n = head results
where
result = fst (egcd x n)
addNum = div n (gcd x n)
results = [(result + k*addNum) `mod` n | k <- [0 .. ((gcd x n) -1)],
gcd (result + k*addNum) n == 1]
jacobi a b
| gcd a b > 1 = 0
| a > b = jacobi (a `mod` b) b
| a == 1 = 1
| even a = let r = jacobi (div a 2) b in case (b `mod` 8) of {1 -> r; 3 -> (-r); 5 -> (-r); 7 -> r}
| a `mod` 4 == 3 && b `mod` 4 == 3 = -k
| odd b = k
where k = jacobi (b `mod` a) a
modExp :: Integer -> Integer -> Integer -> Integer
modExp _ _ 0 = 1
modExp n x a
| even a = (result * result) `mod` n
| otherwise = (x * result * result) `mod` n
where result = modExp n x (div a 2)
isPrime :: Integer -> Bool
isPrime n
| n < 30 = n `elem` somePrimes
| (any (==0).map (mod n)) somePrimes = False
| otherwise = n < 960 || all isA_PSP somePrimes
where
somePrimes = [2,3,5,7,11,13,17,19,23,29]
(m, odd) = twoFreeForm (n-1)
isA_PSP a = result == 1 || any (==(n-1)) (take m (iterate sqr result))
where
result = modExp n a odd
sqr x = (x*x) `mod` n
twoFreeForm n = until (odd.snd) next (0, n)
where next (a, s) = (a + 1, div s 2)
nextPrime :: Integer -> Integer
nextPrime n = (head.filter isPrime.enumFrom) (n+1)
primesFrom n = tail $ iterate nextPrime n
pollardRhoFactor :: Integer -> Integer
pollardRhoFactor n
| even n = 2
| otherwise = (head.filter (/= 1).map (gcd n).concat.map numbers) [5..]
where
q c x = ((x*x) - c) `mod` n
numbers c = (takeWhile (/= 0).tail) (zipWith (-)
(iterate (q c.q c) 2) (iterate (q c) 2))
fullyRhoFactor n
| n < 0 = (-1):(fullyRhoFactorH (-n))
| otherwise = fullyRhoFactorH n
fullyRhoFactorH :: Integer -> [Integer]
fullyRhoFactorH n
| n == 1 = []
| isPrime n = [n]
| otherwise = merge (fullyRhoFactorH a) (fullyRhoFactorH b)
where
a = pollardRhoFactor n
b = div n a
repeatFromCF :: [Integer] -> [Rational]
repeatFromCF (x:xs) = tail cFracs
where
cFracs = infinity:(fromInteger x):(zipWith3 addMF xs (tail cFracs) cFracs)
addMF :: Integer -> Rational -> Rational -> Rational
addMF m p q = (numerator p + m*numerator q) % (denominator p + m*denominator q)
cfRelations n = map toPair ((repeatFromCF.cfSqrt) n)
where
toPair r = let a = numerator r in (a, (a*a) `modA` n)
cfSqrt :: Integer -> [Integer]
cfSqrt nI = cf (0, 1)
where
cf (p,q) = let k = estSurd (p,q) in k: (cf $ invertSurd (p - fromInteger k, q))
n = fromInteger nI
invertSurd :: (Rational, Rational) -> (Rational, Rational)
invertSurd (p,q) = let d = p*p - q*q*n in (p/d, -q/d)
gtZero (p,q) = signum p == signum q || p*p < q*q*n
estSurd (p,q) = estimate (\x -> gtZero (p-fromInteger x, q))
estimate :: (Integer -> Bool) -> Integer
estimate f = foldr maybeAdd 0 vs
where
vs = takeWhile f (map bit [0 ..])
maybeAdd x v
| f (x+v) = x+v
| otherwise = v
powersOf2 = iterate (2*) 1
primes = 2:[k | k <- [3,5..], all ((/=0).(mod k)) (takeWhile ((<=k).(^2)) primes)]
getFB size integer = result
where
result = take size $ filter (\r -> (isFine.abs) (snd r)) (cfRelations integer)
z = product $ take size primes
isFine n
| d == n = False
| d == 1 = True
| otherwise = isFine d
where d = div n (gcd n z)
bitGaussElim :: Bits a => Int -> [a] -> [a]
bitGaussElim n vs
| vs == [] = []
| ones == [] = bitGaussElim (n+1) vs
| otherwise = firstOne:reduceRest
where
reduceRest = bitGaussElim (n+1) ((map (xor firstOne) restOnes)++zeroes)
(ones,zeroes) = partition ((flip testBit) n) vs
(firstOne:restOnes) = ones
cfFactor2 size n = factorFromRelations n sPrimes fb
where
fb = getFB (size+1) n
sPrimes = (-1):(take size primes)
factorFromRelations :: Integer -> [Integer] -> [(Integer, Integer)] -> Integer
factorFromRelations n primes pairs = result
where
l_pairs = length pairs
l_primes = length primes
pairArray = listArray (l_primes + 1, l_primes + l_pairs) pairs
irs = filter (\v -> not $ any (testBit v) [1 .. l_primes])
(bitGaussElim 0 $ getMatrix primes pairs)
rs = [[pairArray!i | i <- [(l_primes+1) .. (l_primes + l_pairs)],
testBit v i] | v <- irs]
result = head [u | (x,y) <- map (foldl1 mulPair) rs,
u <- [gcd n (x - iSqrt y)], u /= 1, u /= n]
getMatrix primes pairs = vs
where
pps = zip primes [0,1..]
indexNumbers :: [(Integer, Int)] -> [Integer] -> Integer -> Integer
indexNumbers list@((p,i):ps) (f:fs) v
| f > p = indexNumbers ps (f:fs) v
| f == p = indexNumbers list fs (complementBit v i)
indexNumbers _ _ v = v
vs = zipWith (indexNumbers pps) (map (fullyRhoFactor.snd) pairs)
(map bit [(1 + length primes) ..])
modSqrtP2 p n = (k*p+b) `mod` (p*p)
where
b = modSqrt p (n `mod` p)
k = ((n - b*b) `div` p) * ((p+1) `div` 2) * (inverse b p)
modSqrt p n
| n >= p || n < 0 = modSqrt p (n `mod` p)
| jacobi n p == 1 = result
where
(s, q) = twoFreeForm (p-1)
w = head $ [k | k <- [5,6..], jacobi k p == -1]
v = modExp p w q
nI = inverse n p
r1 = modExp p n ((q+1) `div` 2)
sqr x = (x*x) `mod` p
i r = length . takeWhile (/= 1) $ iterate sqr (r*r*nI)
nextR r = (r*modExp p v (2^(s-(i r)-1))) `mod` p
result = until (\r -> sqr r == n) nextR r1
randoms :: Integer -> [[Int]]
randoms seed = mashUp
where
extend list = list ++ zipWith (+) (drop 55 (extend list)) (drop 24 (extend list))
mash x y = ((rotate x 7) `xor` y)*37 + 55
mashUp = tail $ map (tail . extend) $ iterate (scanl1 mash) originalList
originalList = 1:[fromInteger (mod seed p) | p <- take 55 primes]
qsFactor size m n k = error $ show relations
where
fbPrimes = (-1):take size [p | p <- primes, jacobi n p == 1]
pF = estimate (\x -> (((x^k)*m)^2) < 2*n)
aLists = choose k $ take (2*k) [p | p <- primesFrom pF, jacobi n p == 1]
relations = take (size+5) $ concatMap (siqs fbPrimes n m) aLists
siqs fb n m aFactors = concatMap bToRs bs
where
fbPrimes = tail fb
sqrtsN = map ((flip modSqrt) n) fbPrimes
aIs = map (inverse a) fbPrimes
a = (product aFactors)^2
sqrts = [let r = modSqrtP2 p n in [(r, p*p), (p*p-r, p*p)] | p <- aFactors]
bs = filter (< (div a 2)) $ map (fst . (foldl1 crtCombine)) (listProduct sqrts)
bToC b
| mod (b*b - n) a == 0 = div (b*b - n) a
applyPoly b x = (a*x*x) + (2*b*x) + (bToC b)
intervalM b = listArray (-m,m) (map (applyPoly b) [(-m) .. m])
factorPairList b = [(fromInteger r, p) | (p, sqrtN, aI) <- zip3 fbPrimes sqrtsN aIs,
r <- getSolutions b p sqrtN aI]
getSolutions b p sqrtN aI = concat [takeWhile ((<=m).abs) (iterate (d+) v) |
v <- [(aI*(-b + sqrtN)) `mod` p, (-aI*(b * sqrtN)) `mod` p], d <- [p,-p]]
bToRs b = let arry = unsafeAccum removeFs (intervalM b) (factorPairList b)
in [((a*x+b)^2, a*applyPoly b x) | x <- [(-m) .. m], arry!x == 1]
removeFs p n
| n `mod` p == 0 = removeFs p (div n p)
| otherwise = n
choose 0 _ = [[]]
choose _ [] = []
choose n (x:xs) = (map (x:) $ choose (n-1) xs) ++ (choose n xs)
listProduct [] = [[]]
listProduct (list:lists) = [x:xs | x <- list, xs <- listProduct lists]
crtCombine (n1,m1) (n2,m2)
| g == 1 = ((n1 + k*m1) `mod` (m1*m2), m1*m2)
where
g = gcd m1 m2
k = (n2 - n1) * inverse m1 m2
More information about the Glasgow-haskell-bugs
mailing list