121 lines
4.1 KiB
Haskell
121 lines
4.1 KiB
Haskell
module FactorizationUI (run) where
|
|
|
|
import System.Exit (exitSuccess)
|
|
import Utils (askChoice, askNumber)
|
|
import Factorization
|
|
( fermatFactorization, pollardPminus1, dixon, dixonDefaultParams
|
|
, 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
|
|
putStrLn "Dixon"
|
|
putStrLn "Factors a composite n (not a prime, a perfect square or a prime power)."
|
|
putStrLn "Practical for n up to roughly 22 digits; 24 digits already takes about a minute."
|
|
n <- askNumber "Enter an integer n > 1:"
|
|
|
|
putStrLn "Parameters:"
|
|
putStrLn "1) Automatic (recommended)"
|
|
putStrLn "2) Custom"
|
|
mode <- askChoice 2
|
|
|
|
let (autoB, autoX) = dixonDefaultParams n
|
|
(b, x) <- case mode of
|
|
1 -> return (autoB, autoX)
|
|
_ -> do
|
|
putStrLn ("Automatic values for this n: bound B = " ++ show autoB
|
|
++ ", max x = " ++ show autoX)
|
|
b' <- askNumber "Enter the bound B:"
|
|
x' <- askNumber "Enter the max integer x (the search starts at floor(sqrt n) + 1):"
|
|
return (b', x')
|
|
|
|
putStrLn "Running Dixon (this may take a while)..."
|
|
case dixon n b x of
|
|
Left err -> do
|
|
putStrLn ("Error: " ++ err)
|
|
if mode == 1
|
|
then putStrLn "Check that n is composite and not a perfect square or a prime power."
|
|
else return ()
|
|
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)
|