@@ -61,11 +61,9 @@ import Math.NumberTheory.Curves.Montgomery
61
61
import Math.NumberTheory.Euclidean.Coprimes (splitIntoCoprimes , unCoprimes )
62
62
import Math.NumberTheory.Roots.General (highestPower , largePFPower )
63
63
import Math.NumberTheory.Roots.Squares (integerSquareRoot' )
64
- import Math.NumberTheory.Primes.Sieve.Eratosthenes (PrimeSieve (.. ), psieveFrom )
65
- import Math.NumberTheory.Primes.Sieve.Indexing (toPrim )
64
+ import Math.NumberTheory.Primes.Sieve.Atkin
66
65
import Math.NumberTheory.Primes.Small
67
66
import Math.NumberTheory.Primes.Testing.Probabilistic
68
- import Math.NumberTheory.Unsafe
69
67
import Math.NumberTheory.Utils
70
68
71
69
-- | @'factorise' n@ produces the prime factorisation of @n@. @'factorise' 0@ is
@@ -160,36 +158,36 @@ curveFactorisation primeBound primeTest prng seed mbdigs n
160
158
fact :: Integer -> Int -> State g [(Integer , Word )]
161
159
fact 1 _ = return mempty
162
160
fact m digs = do
163
- let (b1, b2, ct) = findParms digs
161
+ let (b1, b1Sieve, b2, ct) = findParms digs
164
162
-- All factors (both @pfs@ and @cfs@), are pairwise coprime. This is
165
163
-- because 'repFact' returns either a single factor, or output of 'workFact'.
166
164
-- In its turn, 'workFact' returns either a single factor,
167
165
-- or concats 'repFact's over coprime integers. Induction completes the proof.
168
- Factors pfs cfs <- repFact m b1 b2 ct
166
+ Factors pfs cfs <- repFact m b1 b1Sieve b2 ct
169
167
case cfs of
170
168
[] -> return pfs
171
169
_ -> do
172
170
nfs <- forM cfs $ \ (k, j) ->
173
171
map (second (* j)) <$> fact k (if null pfs then digs + 5 else digs)
174
172
return $ mconcat (pfs : nfs)
175
173
176
- repFact :: Integer -> Word -> Word -> Word -> State g Factors
177
- repFact 1 _ _ _ = return mempty
178
- repFact m b1 b2 count =
174
+ repFact :: Integer -> Word -> PrimeSieve -> Word -> Word -> State g Factors
175
+ repFact 1 _ _ _ _ = return mempty
176
+ repFact m b1 b1Sieve b2 count =
179
177
case perfPw m of
180
- (_, 1 ) -> workFact m b1 b2 count
178
+ (_, 1 ) -> workFact m b1 b1Sieve b2 count
181
179
(b, e)
182
180
| ptest b -> return $ singlePrimeFactor b e
183
- | otherwise -> modifyPowers (* e) <$> workFact b b1 b2 count
181
+ | otherwise -> modifyPowers (* e) <$> workFact b b1 b1Sieve b2 count
184
182
185
- workFact :: Integer -> Word -> Word -> Word -> State g Factors
186
- workFact 1 _ _ _ = return mempty
187
- workFact m _ _ 0 = return $ singleCompositeFactor m 1
188
- workFact m b1 b2 count = do
183
+ workFact :: Integer -> Word -> PrimeSieve -> Word -> Word -> State g Factors
184
+ workFact 1 _ _ _ _ = return mempty
185
+ workFact m _ _ _ 0 = return $ singleCompositeFactor m 1
186
+ workFact m b1 b1Sieve b2 count = do
189
187
s <- rndR m
190
188
case someNatVal (fromInteger m) of
191
- SomeNat (_ :: Proxy t ) -> case montgomeryFactorisation b1 b2 (fromInteger s :: Mod t ) of
192
- Nothing -> workFact m b1 b2 (count - 1 )
189
+ SomeNat (_ :: Proxy t ) -> case montgomeryFactorisation b1 b1Sieve b2 (fromInteger s :: Mod t ) of
190
+ Nothing -> workFact m b1 b1Sieve b2 (count - 1 )
193
191
Just d -> do
194
192
let cs = unCoprimes $ splitIntoCoprimes [(d, 1 ), (m `quot` d, 1 )]
195
193
-- Since all @cs@ are coprime, we can factor each of
@@ -198,7 +196,7 @@ curveFactorisation primeBound primeTest prng seed mbdigs n
198
196
fmap mconcat $ flip mapM cs $
199
197
\ (x, xm) -> if ptest x
200
198
then pure $ singlePrimeFactor x xm
201
- else repFact x b1 b2 (count - 1 )
199
+ else repFact x b1 b1Sieve b2 (count - 1 )
202
200
203
201
data Factors = Factors
204
202
{ _primeFactors :: [(Integer , Word )]
@@ -240,8 +238,8 @@ modifyPowers f (Factors pfs cfs)
240
238
-- It is assumed that @n@ has no small prime factors.
241
239
--
242
240
-- The result is maybe a nontrivial divisor of @n@.
243
- montgomeryFactorisation :: KnownNat n => Word -> Word -> Mod n -> Maybe Integer
244
- montgomeryFactorisation b1 b2 s = case newPoint (toInteger (unMod s)) n of
241
+ montgomeryFactorisation :: KnownNat n => Word -> PrimeSieve -> Word -> Mod n -> Maybe Integer
242
+ montgomeryFactorisation b1 b1Sieve b2 s = case newPoint (toInteger (unMod s)) n of
245
243
Nothing -> Nothing
246
244
Just (SomePoint p0) -> do
247
245
-- Small step: for each prime p <= b1
@@ -257,9 +255,7 @@ montgomeryFactorisation b1 b2 s = case newPoint (toInteger (unMod s)) n of
257
255
g -> Just g
258
256
where
259
257
n = toInteger (natVal s)
260
- smallPowers
261
- = map findPower
262
- $ takeWhile (<= b1) (2 : 3 : 5 : list primeStore)
258
+ smallPowers = map (findPower . fromIntegral ) (atkinPrimeList b1Sieve)
263
259
findPower p = go p
264
260
where
265
261
go acc
@@ -282,7 +278,7 @@ bigStep q b1 b2 = rs
282
278
us * (pointZ p * pointX pq - pointX p * pointZ pq) `rem` n
283
279
) ts qks) 1 qs
284
280
285
- wheel :: Word
281
+ wheel :: Num a => a
286
282
wheel = 210
287
283
288
284
wheelCoprimes :: [Word ]
@@ -307,15 +303,6 @@ enumAndMultiplyFromThenTo p from thn to = zip [from, thn .. to] progression
307
303
308
304
progression = pFrom : pThen : zipWith (\ x0 x1 -> add x0 pStep x1) progression (tail progression)
309
305
310
- -- primes, compactly stored as a bit sieve
311
- primeStore :: [PrimeSieve ]
312
- primeStore = psieveFrom 7
313
-
314
- -- generate list of primes from arrays
315
- list :: [PrimeSieve ] -> [Word ]
316
- list sieves = concat [[off + toPrim i | i <- [0 .. li], unsafeAt bs i]
317
- | PS vO bs <- sieves, let { (_,li) = bounds bs; off = fromInteger vO; }]
318
-
319
306
-- | @'smallFactors' n@ finds all prime divisors of @n > 1@ up to 2^16 by trial division and returns the
320
307
-- list of these together with their multiplicities, and a possible remaining factor which may be composite.
321
308
smallFactors :: Integer -> ([(Integer , Word )], Maybe Integer )
@@ -339,8 +326,10 @@ smallFactors n = case shiftToOddCount n of
339
326
-- ("tier") return parameters B1, B2 and the number of curves to try
340
327
-- before next "tier".
341
328
-- Roughly based on http://www.mersennewiki.org/index.php/Elliptic_Curve_Method#Choosing_the_best_parameters_for_ECM
342
- testParms :: IntMap (Word , Word , Word )
343
- testParms = IM. fromList
329
+ testParms :: IntMap (Word , PrimeSieve , Word , Word )
330
+ testParms
331
+ = IM. fromList
332
+ $ map (\ (k, (b1, b2, ct)) -> (k, (b1, atkinSieve 0 (fromIntegral b1), b2, ct)))
344
333
[ (12 , ( 400 , 40000 , 10 ))
345
334
, (15 , ( 2000 , 200000 , 25 ))
346
335
, (20 , ( 11000 , 1100000 , 90 ))
@@ -356,5 +345,7 @@ testParms = IM.fromList
356
345
, (70 , (2900000000 , 290000000000 , 340000 ))
357
346
]
358
347
359
- findParms :: Int -> (Word , Word , Word )
360
- findParms digs = maybe (wheel, 1000 , 7 ) snd (IM. lookupLT digs testParms)
348
+ findParms :: Int -> (Word , PrimeSieve , Word , Word )
349
+ findParms digs
350
+ = maybe (wheel, atkinSieve 0 wheel, 1000 , 7 ) snd
351
+ $ IM. lookupLT digs testParms
0 commit comments