CLI interface + restructuration + precision fixes Fermat Factorization
This commit is contained in:
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
## running project from CLI
|
## running project from CLI
|
||||||
```
|
```
|
||||||
$ ghci -i./src
|
$ cabal update
|
||||||
ghci> :load HaskellMath.hs
|
$ cabal build
|
||||||
|
$ cabal run
|
||||||
```
|
```
|
||||||
|
|
||||||
## algorithms
|
## 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
|
module Main where
|
||||||
|
|
||||||
import qualified Primes ()
|
import Utils (askChoice)
|
||||||
|
import qualified FactorizationUI
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
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 Text.Read (readMaybe)
|
||||||
import System.Exit (exitSuccess)
|
import System.Exit (exitSuccess)
|
||||||
@@ -13,3 +13,13 @@ askNumber s = do
|
|||||||
_ -> do
|
_ -> do
|
||||||
putStrLn "Not a valid integer"
|
putStrLn "Not a valid integer"
|
||||||
exitSuccess
|
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
|
import: warnings
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
Primes
|
Primes
|
||||||
|
Factorization
|
||||||
|
ModularSquareRoot
|
||||||
|
ModularArithmeticUtils
|
||||||
other-modules:
|
other-modules:
|
||||||
|
Primes.FermatPrimeTest
|
||||||
Primes.MillerRabin
|
Primes.MillerRabin
|
||||||
Primes.SolovayStrassen
|
Primes.SolovayStrassen
|
||||||
ModularArithmeticUtils
|
Factorization.FermatFactorization
|
||||||
|
Factorization.PollardPminus1
|
||||||
|
ModularSquareRoot.TonelliShanks
|
||||||
build-depends:
|
build-depends:
|
||||||
base ^>=4.18.2.1,
|
base ^>=4.18.2.1,
|
||||||
random ^>=1.2
|
random ^>=1.2
|
||||||
@@ -33,6 +39,9 @@ library
|
|||||||
executable haskell-math
|
executable haskell-math
|
||||||
import: warnings
|
import: warnings
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
|
other-modules:
|
||||||
|
FactorizationUI
|
||||||
|
Utils
|
||||||
build-depends:
|
build-depends:
|
||||||
base ^>=4.18.2.1,
|
base ^>=4.18.2.1,
|
||||||
haskell-math
|
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)
|
module Factorization.PollardPminus1 (pollardPminus1) where
|
||||||
import System.Exit (exitSuccess)
|
|
||||||
import Utils (askNumber)
|
|
||||||
import ModularArithmeticUtils (modExp)
|
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
|
-- Pollard p-1 factorization algorithm
|
||||||
pollardP1 :: Integer -> Integer -> Maybe Integer
|
pollardPminus1 :: Integer -> Integer -> Maybe Integer
|
||||||
pollardP1 n b = tryBases [2..5]
|
pollardPminus1 n b = tryBases [2..5]
|
||||||
where
|
where
|
||||||
tryBases [] = Nothing
|
tryBases [] = Nothing
|
||||||
tryBases (a:as) =
|
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)
|
import ModularArithmeticUtils (modExp, modMul, legendre, factorOutTwos)
|
||||||
|
|
||||||
Reference in New Issue
Block a user