Dixon graceful error handling

This commit is contained in:
2026-01-21 10:11:11 +01:00
parent 76caeec9e4
commit 2c1528075c
2 changed files with 16 additions and 12 deletions

View File

@@ -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)

View File

@@ -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)