CLI interface + restructuration + precision fixes Fermat Factorization

This commit is contained in:
2026-01-11 17:58:36 +01:00
parent ada11a25d2
commit 6689ff8ae2
11 changed files with 117 additions and 50 deletions

View File

@@ -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
View 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)."

View File

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

View File

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

View File

@@ -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
View File

@@ -0,0 +1,4 @@
module Factorization ( fermatFactorization, pollardPminus1) where
import Factorization.FermatFactorization
import Factorization.PollardPminus1

View 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

View File

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

View File

@@ -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
View File

@@ -0,0 +1,3 @@
module ModularSquareRoot (tonelliShanks) where
import ModularSquareRoot.TonelliShanks

View File

@@ -1,4 +1,4 @@
module TonelliShanks (tonelliShanks) where
module ModularSquareRoot.TonelliShanks (tonelliShanks) where
import ModularArithmeticUtils (modExp, modMul, legendre, factorOutTwos)