Dixon graceful error handling
This commit is contained in:
@@ -42,7 +42,11 @@ dixonUI = do
|
|||||||
n <- askNumber "Enter an integer n > 1:"
|
n <- askNumber "Enter an integer n > 1:"
|
||||||
b <- askNumber "Enter the bound B:"
|
b <- askNumber "Enter the bound B:"
|
||||||
x <- askNumber "Enter the max random integer x:"
|
x <- askNumber "Enter the max random integer x:"
|
||||||
let (p, q) = dixon n b x
|
|
||||||
putStrLn ("n = " ++ show n)
|
case dixon n b x of
|
||||||
putStrLn ("p = " ++ show p)
|
Left err -> do
|
||||||
putStrLn ("q = " ++ show q)
|
putStrLn ("Error: " ++ err)
|
||||||
|
Right (p, q) -> do
|
||||||
|
putStrLn ("n = " ++ show n)
|
||||||
|
putStrLn ("p = " ++ show p)
|
||||||
|
putStrLn ("q = " ++ show q)
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ factorOverBase primes a = go primes a []
|
|||||||
in go ps num' (e : acc)
|
in go ps num' (e : acc)
|
||||||
|
|
||||||
|
|
||||||
dixon :: Integer -> Integer -> Integer -> (Integer, Integer)
|
dixon :: Integer -> Integer -> Integer -> Either String (Integer, Integer)
|
||||||
dixon n b maxX
|
dixon n b maxX
|
||||||
| n <= 3 = error "n must be greater than 3"
|
| n <= 3 = Left "n must be greater than 3"
|
||||||
| even n = (2, n `div` 2)
|
| even n = Right (2, n `div` 2)
|
||||||
| otherwise =
|
| otherwise =
|
||||||
let base = erathosteneSieve b
|
let base = erathosteneSieve b
|
||||||
numCols = length base
|
numCols = length base
|
||||||
@@ -33,21 +33,21 @@ dixon n b maxX
|
|||||||
Just exps <- [factorOverBase base a]]
|
Just exps <- [factorOverBase base a]]
|
||||||
numCollected = length pairs
|
numCollected = length pairs
|
||||||
in if numCollected <= numCols
|
in if numCollected <= numCols
|
||||||
then error $ "Not enough smooth squares found up to " ++ show maxX
|
then Left $ "Not enough smooth squares found up to " ++ show maxX
|
||||||
else let xs = map fst pairs
|
else let xs = map fst pairs
|
||||||
allExps = map snd pairs
|
allExps = map snd pairs
|
||||||
bitvecs = map (fromBools . map (\e -> e `mod` 2 == 1)) allExps
|
bitvecs = map (fromBools . map (\e -> e `mod` 2 == 1)) allExps
|
||||||
in case gaussianEliminationMask numCols bitvecs of
|
in case gaussianEliminationMask numCols bitvecs of
|
||||||
Nothing -> error "No linear dependency found"
|
Nothing -> Left "No linear dependency found"
|
||||||
Just mask ->
|
Just mask ->
|
||||||
let indices = maskToIndicesInt mask
|
let indices = maskToIndicesInt mask
|
||||||
in if null indices
|
in if null indices
|
||||||
then error "Empty dependency"
|
then Left "Empty dependency"
|
||||||
else let productX = foldl (\acc idx -> modMul acc (xs !! idx) n) 1 indices
|
else let productX = foldl (\acc idx -> modMul acc (xs !! idx) n) 1 indices
|
||||||
fs = [ sum [ (allExps !! idx !! j) | idx <- indices ] `div` 2 | j <- [0 .. numCols - 1] ]
|
fs = [ sum [ (allExps !! idx !! j) | idx <- indices ] `div` 2 | j <- [0 .. numCols - 1] ]
|
||||||
z = foldl (\acc (p, f) -> if f == 0 then acc else modMul (modExp p f n) acc n) 1 (zip base fs)
|
z = foldl (\acc (p, f) -> if f == 0 then acc else modMul (modExp p f n) acc n) 1 (zip base fs)
|
||||||
diff = productX - z
|
diff = productX - z
|
||||||
g = gcd (abs diff) n
|
g = gcd (abs diff) n
|
||||||
in if g == 1 || g == n
|
in if g == 1 || g == n
|
||||||
then error "non trivial factors not found, try larger b or maximum x"
|
then Left "non trivial factors not found, try larger b or maximum x"
|
||||||
else (g, n `div` g)
|
else Right (g, n `div` g)
|
||||||
|
|||||||
Reference in New Issue
Block a user