module FactorizationUI (run) where import System.Exit (exitSuccess) import Utils (askChoice, askNumber) import Factorization ( fermatFactorization, pollardPminus1, dixon , gnfsWith, GNFSParams(..), defaultParams ) run :: IO () run = do putStrLn "Factorization" putStrLn "1) Fermat factorization" putStrLn "2) Pollard p-1" putStrLn "3) Dixon" putStrLn "4) General Number Field Sieve (GNFS)" choice <- askChoice 4 case choice of 1 -> fermatUI 2 -> pollardUI 3 -> dixonUI 4 -> gnfsUI _ -> error "Impossible" fermatUI :: IO () fermatUI = do n <- askNumber "Enter an integer n > 1:" let (p, q) = fermatFactorization n putStrLn ("n = " ++ show n) putStrLn ("p = " ++ show p) putStrLn ("q = " ++ show q) pollardUI :: IO () pollardUI = do n <- askNumber "Enter an integer n > 1:" b <- askNumber "Enter the bound B:" case pollardPminus1 n b of Just factor -> do putStrLn ("Found factor: " ++ show factor) putStrLn ("Other factor: " ++ show (n `div` factor)) Nothing -> putStrLn "Failed to find a factor (try a different B or method)." dixonUI :: IO () dixonUI = do n <- askNumber "Enter an integer n > 1:" b <- askNumber "Enter the bound B:" x <- askNumber "Enter the max random integer x:" case dixon n b x of Left err -> do putStrLn ("Error: " ++ err) Right (p, q) -> do putStrLn ("n = " ++ show n) putStrLn ("p = " ++ show p) putStrLn ("q = " ++ show q) gnfsUI :: IO () gnfsUI = do putStrLn "General Number Field Sieve" putStrLn "Factors a composite n (not a prime or a prime power) into two non-trivial factors." putStrLn "Practical for n up to roughly 30 digits; the running time grows quickly beyond that." n <- askNumber "Enter an integer n > 1:" putStrLn "Parameters:" putStrLn "1) Automatic (recommended)" putStrLn "2) Custom" mode <- askChoice 2 let auto = defaultParams n params <- case mode of 1 -> return auto _ -> do putStrLn ("Automatic values for this n: degree = " ++ show (paramDegree auto) ++ ", bound B = " ++ show (paramRatBound auto) ++ ", sieve half-width = " ++ show (paramHalfWidth auto)) d <- askNumber "Enter the polynomial degree d (odd, 3 or 5):" if d /= 3 && d /= 5 then do putStrLn "The degree must be 3 or 5." exitSuccess else return () b <- askNumber "Enter the factor base bound B (used for both bases):" w <- askNumber "Enter the sieve half-width (a ranges over [-w, w]):" return auto { paramDegree = fromInteger d , paramRatBound = b , paramAlgBound = b , paramHalfWidth = fromInteger w } putStrLn "Running GNFS (this may take a while)..." case gnfsWith params n of Left err -> putStrLn ("Error: " ++ err) Right (p, q) -> do putStrLn ("n = " ++ show n) putStrLn ("p = " ++ show p) putStrLn ("q = " ++ show q)