CLI interface + restructuration + precision fixes Fermat Factorization
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
|
||||
## running project from CLI
|
||||
```
|
||||
$ ghci -i./src
|
||||
ghci> :load HaskellMath.hs
|
||||
$ cabal update
|
||||
$ cabal build
|
||||
$ cabal run
|
||||
```
|
||||
|
||||
## algorithms
|
||||
|
||||
36
app/FactorizationUI.hs
Normal file
36
app/FactorizationUI.hs
Normal file
@@ -0,0 +1,36 @@
|
||||
module FactorizationUI (run) where
|
||||
|
||||
import Utils (askChoice, askNumber)
|
||||
import Factorization (fermatFactorization, pollardPminus1)
|
||||
|
||||
run :: IO ()
|
||||
run = do
|
||||
putStrLn "Factorization"
|
||||
putStrLn "1) Fermat factorization"
|
||||
putStrLn "2) Pollard p-1"
|
||||
|
||||
choice <- askChoice 2
|
||||
|
||||
case choice of
|
||||
1 -> fermatUI
|
||||
2 -> pollardUI
|
||||
_ -> 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)."
|
||||
16
app/Main.hs
16
app/Main.hs
@@ -1,7 +1,19 @@
|
||||
module Main where
|
||||
|
||||
import qualified Primes ()
|
||||
import Utils (askChoice)
|
||||
import qualified FactorizationUI
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
putStrLn "unimplemented"
|
||||
putStrLn "Haskell Math Toolkit"
|
||||
putStrLn "1) Factorization"
|
||||
putStrLn "2) Modular square root (not yet implemented)"
|
||||
putStrLn "3) Primality test (not yet implemented)"
|
||||
|
||||
choice <- askChoice 3
|
||||
|
||||
case choice of
|
||||
1 -> FactorizationUI.run
|
||||
2 -> putStrLn "Modular square root: not implemented yet."
|
||||
3 -> putStrLn "Primality test: not implemented yet."
|
||||
_ -> error "Impossible"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module Utils (askNumber) where
|
||||
module Utils (askNumber, askChoice) where
|
||||
|
||||
import Text.Read (readMaybe)
|
||||
import System.Exit (exitSuccess)
|
||||
@@ -13,3 +13,13 @@ askNumber s = do
|
||||
_ -> do
|
||||
putStrLn "Not a valid integer"
|
||||
exitSuccess
|
||||
|
||||
askChoice :: Int -> IO Int
|
||||
askChoice maxChoice = do
|
||||
putStrLn "Enter your choice:"
|
||||
input <- getLine
|
||||
case readMaybe input of
|
||||
Just n | n >= 1 && n <= maxChoice -> return n
|
||||
_ -> do
|
||||
putStrLn "Invalid choice"
|
||||
exitSuccess
|
||||
@@ -20,10 +20,16 @@ library
|
||||
import: warnings
|
||||
exposed-modules:
|
||||
Primes
|
||||
Factorization
|
||||
ModularSquareRoot
|
||||
ModularArithmeticUtils
|
||||
other-modules:
|
||||
Primes.FermatPrimeTest
|
||||
Primes.MillerRabin
|
||||
Primes.SolovayStrassen
|
||||
ModularArithmeticUtils
|
||||
Factorization.FermatFactorization
|
||||
Factorization.PollardPminus1
|
||||
ModularSquareRoot.TonelliShanks
|
||||
build-depends:
|
||||
base ^>=4.18.2.1,
|
||||
random ^>=1.2
|
||||
@@ -33,6 +39,9 @@ library
|
||||
executable haskell-math
|
||||
import: warnings
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
FactorizationUI
|
||||
Utils
|
||||
build-depends:
|
||||
base ^>=4.18.2.1,
|
||||
haskell-math
|
||||
|
||||
4
src/Factorization.hs
Normal file
4
src/Factorization.hs
Normal file
@@ -0,0 +1,4 @@
|
||||
module Factorization ( fermatFactorization, pollardPminus1) where
|
||||
|
||||
import Factorization.FermatFactorization
|
||||
import Factorization.PollardPminus1
|
||||
31
src/Factorization/FermatFactorization.hs
Normal file
31
src/Factorization/FermatFactorization.hs
Normal file
@@ -0,0 +1,31 @@
|
||||
module Factorization.FermatFactorization (fermatFactorization) where
|
||||
|
||||
fermatFactorization :: Integer -> (Integer, Integer)
|
||||
fermatFactorization n
|
||||
| n <= 0 = error "n must be positive"
|
||||
| even n = (2, n `div` 2)
|
||||
| otherwise = (p, q)
|
||||
where
|
||||
(d, root) = findIntegerSqrt n
|
||||
p = root + d
|
||||
q = root - d
|
||||
|
||||
-- Find the smallest integer d >= 0 such that sqrt(n + d^2) is an integer
|
||||
findIntegerSqrt :: Integer -> (Integer, Integer)
|
||||
findIntegerSqrt n = go 0
|
||||
where
|
||||
go d =
|
||||
let val = n + d*d
|
||||
root = isqrt val
|
||||
in if root * root == val
|
||||
then (d, root)
|
||||
else go (d + 1)
|
||||
|
||||
isqrt :: Integer -> Integer
|
||||
isqrt 0 = 0
|
||||
isqrt 1 = 1
|
||||
isqrt n = iterateSqrt n
|
||||
where
|
||||
iterateSqrt x =
|
||||
let y = (x + n `div` x) `div` 2
|
||||
in if y >= x then x else iterateSqrt y
|
||||
@@ -1,25 +1,10 @@
|
||||
import Text.Read (readMaybe)
|
||||
import System.Exit (exitSuccess)
|
||||
import Utils (askNumber)
|
||||
module Factorization.PollardPminus1 (pollardPminus1) where
|
||||
|
||||
import ModularArithmeticUtils (modExp)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
n <- askNumber "Enter an integer n>1 to factor:"
|
||||
b <- askNumber "Enter the bound B:"
|
||||
putStrLn ("n = " ++ show n)
|
||||
|
||||
case pollardP1 n b of
|
||||
Just factor -> do
|
||||
putStrLn ("Found factor: " ++ show factor)
|
||||
let otherFactor = n `div` factor
|
||||
putStrLn ("Other factor: " ++ show otherFactor)
|
||||
Nothing -> do
|
||||
putStrLn "Failed to find a factor using Pollard p-1 method. n could be prime or different parameters needed."
|
||||
|
||||
-- Pollard p-1 factorization algorithm
|
||||
pollardP1 :: Integer -> Integer -> Maybe Integer
|
||||
pollardP1 n b = tryBases [2..5]
|
||||
pollardPminus1 :: Integer -> Integer -> Maybe Integer
|
||||
pollardPminus1 n b = tryBases [2..5]
|
||||
where
|
||||
tryBases [] = Nothing
|
||||
tryBases (a:as) =
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import Text.Read (readMaybe)
|
||||
import System.Exit (exitSuccess)
|
||||
import Utils (askNumber)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
n <- askNumber "Enter an integer:"
|
||||
let (d, root) = findIntegerSqrt n
|
||||
q = (root - d)
|
||||
p = (root + d)
|
||||
putStrLn ("n = " ++ show n)
|
||||
putStrLn ("Found d = " ++ show d ++ ", sqrt(n + d^2) = " ++ show root)
|
||||
putStrLn ("q = " ++ show q ++ ", p = " ++ show p)
|
||||
|
||||
-- Find the smallest integer d >= 0 such that sqrt(n + d^2) is an integer
|
||||
findIntegerSqrt :: Integer -> (Integer, Integer)
|
||||
findIntegerSqrt n = go 0
|
||||
where
|
||||
go d =
|
||||
let val = n + d*d
|
||||
root = floor (sqrt (fromIntegral val))
|
||||
in if root * root == val
|
||||
then (d, root)
|
||||
else go (d + 1)
|
||||
3
src/ModularSquareRoot.hs
Normal file
3
src/ModularSquareRoot.hs
Normal file
@@ -0,0 +1,3 @@
|
||||
module ModularSquareRoot (tonelliShanks) where
|
||||
|
||||
import ModularSquareRoot.TonelliShanks
|
||||
@@ -1,4 +1,4 @@
|
||||
module TonelliShanks (tonelliShanks) where
|
||||
module ModularSquareRoot.TonelliShanks (tonelliShanks) where
|
||||
|
||||
import ModularArithmeticUtils (modExp, modMul, legendre, factorOutTwos)
|
||||
|
||||
Reference in New Issue
Block a user