Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 255 lines (204 sloc) 8.119 kb
b9e84b0 Initial commit.
Zach Kost-Smith authored
1
2 (defpackage :cl-factoring
3 (:use :cl :iterate :cl-primality)
4aee661 Added the generic interface.
Zach Kost-Smith authored
4 (:export
5 #:factor))
b9e84b0 Initial commit.
Zach Kost-Smith authored
6
7 (in-package :cl-factoring)
8
9 ;; @\section{Introduction}
10
11 ;; This library presents a set of algorithms for computing integer
12 ;; factorizations. An interface is provided that takes an integer and will
13 ;; return a list of prime numbers such that, when multiplied together, will
14 ;; result in the original number.
15
16 ;; There is no magic sauce here or mathematical breakthroughs; the time
17 ;; complexities of each algorithm is exponential.
18
19 ;; @\section{Special Purpose Methods}
20
21 ;; In this section we present algorithms that perform integer factorization for
22 ;; composite numbers where we know some extra information about them. This
23 ;; contains several interesting problems, chief among them is when we know that
24 ;; the problem contains composites whose prime factors are all (or are all but
25 ;; one) small integers. This set of numbers contains most of the numbers that
26 ;; users encounter in everyday life with the notable exception of the numbers
27 ;; used in crypography.
28
29 ;; @\subsection{Trial Division}
30
31 ;; @The <<trial-division>> algorithm is given as a simple method of performing
32 ;; factorizations. This algorithm is O(sqrt(n)/2), and about the most naive
33 ;; method one can conceive of. It is still affective in many cases, though we
34 ;; find that its performance is superseded by the Monte Carlo methods introduced
35 ;; later.
36
37 (defun trial-division (n)
38 (cond ((primep n) (list n))
39 (t (apply #'append
40 (mapcar #'trial-division
41 (do ((i 2 (1+ i)))
42 ((or (integerp (/ n i))
43 (> i (isqrt n)) )
44 (list i (/ n i)) )))))))
45
46 ;; @\subsection{Pollard's Rho Method}
47
48 ;; @Although the complexity has not been proven, this method appears to work in
49 ;; some $O(n^{\frac 1 4} {\rm PolyLog}(n))$ making it assymptotically superior
50 ;; to trial division and much faster in practice (this should be really tested,
51 ;; particularly with a prime sieve in place).
52
870dcf9 Bug fix: handle squares properly
Zach Kost-Smith authored
53 (defun squarep (n)
54 (let ((sqrt (isqrt n)))
55 (if (= (* sqrt sqrt) n)
56 sqrt
57 nil)))
58
b9e84b0 Initial commit.
Zach Kost-Smith authored
59 (defun pollards-rho (n)
60 "Find the prime factorization of N."
61 (if (primep n)
62 (list n)
870dcf9 Bug fix: handle squares properly
Zach Kost-Smith authored
63 (sort (let ((factor
64 (or (squarep n)
65 (pollards-rho-find-factor n))))
66 (append (pollards-rho factor)
67 (pollards-rho (/ n factor))))
68 #'<)))
b9e84b0 Initial commit.
Zach Kost-Smith authored
69
70 (defun pollards-rho-find-factor (n)
71 (handler-case
870dcf9 Bug fix: handle squares properly
Zach Kost-Smith authored
72 (pollards-rho-attempt n)
b9e84b0 Initial commit.
Zach Kost-Smith authored
73 (factor-attempt-failed ()
74 (pollards-rho-find-factor n))))
75
76 (define-condition factor-attempt-failed () ())
77
78 ;; @We use the psuedorandom function that really isn't very random, but it seems
79 ;; to work in practice.
80
81 (defun pollards-rho-attempt (n)
82 (declare (optimize (speed 3))
83 (type integer n))
84 (let* ((c (1+ (random n)))
85 (f (lambda (x)
86 (declare (type integer x c))
87 (mod (+ (* x x) c) n))))
88 (iter
89 (declare (type integer x y d n))
90 (for x initially (funcall f 2) then (funcall f x))
91 (for y initially (funcall f (funcall f 2)) then (funcall f (funcall f y)))
92 (for d = (gcd (abs (- x y)) n))
93 (while (= d 1))
94 (finally (if (= d n)
95 (signal 'factor-attempt-failed)
96 (return d))))))
97
98 ;; @\subsection{Brent's Cycle Method}
99
100 ;; @Brent's cycle finding method is very similar to the pollard method but is
101 ;; reportedly a bit faster.
102
103 (defun brents-cycle (n)
104 "Find the prime factorization of N."
105 (if (primep n)
106 (list n)
870dcf9 Bug fix: handle squares properly
Zach Kost-Smith authored
107 (sort (let ((factor
108 (or (squarep n)
109 (pollards-rho-find-factor n))))
110 (append (pollards-rho factor)
111 (pollards-rho (/ n factor))))
112 #'<)))
b9e84b0 Initial commit.
Zach Kost-Smith authored
113
114 (defun brents-cycle-find-factor (n)
115 (handler-case
116 (brents-cycle-attempt n)
117 (factor-attempt-failed ()
118 (brents-cycle-find-factor n))))
119
120 ;; @This is a mess basically because the paper is a mess.
121
122 (defun brents-cycle-attempt (n)
123 (declare (optimize (debug 0) (safety 0) (speed 3)))
124 (let* ((x0 2)
125 (y x0)
126 (r 1)
127 (q 1)
128 x ys
129 (g 1)
130 k
131 (m 1)
132 (c (1+ (random n))))
133 (labels ((f (x) (mod (- (* x x) c) n)))
134 (iter
135 (setf x y)
136 (iter (for i from 1 to r)
137 (setf y (f y)))
138 (setf k 0)
139 (iter
140 (setf ys y)
141 (iter (for i from 1 to (min m (- r k)))
142 (setf y (f y)
143 q (mod (* q (abs (- x y))) n)))
144 (setf g (gcd q n)
145 k (+ k m))
146 (until (or (>= k r) (> g 1))))
147 (setf r (* 2 r))
148 (until (> g 1)))
149 (if (= g n)
150 (iter (setf ys (f ys)
151 g (gcd (abs (- x ys)) n))
152 (until (> g 1))))
153 (if (= g n)
154 (signal 'factor-attempt-failed)
155 g))))
156
157 ;; @While the paper that introduces Brent's method of factorization says that
158 ;; the method is faster than the Pollard method, my experiments with this
159 ;; implemetation place them in a dead heat.
160
161 ;; @\section{General Purpose Methods}
162
163 ;; These time complexity of these general methods are independent of the size of
164 ;; the prime factors of the numbers. The complexity is purely a function of the
165 ;; size of the argument that is to be factored.
166
167 ;; @\subsection{Shank's square forms factorization}
168
169 ;; O(n^(1/4))
170
658430d Added Shank's square form factoring method (O(N^(1/4)))
Zach Kost-Smith authored
171 ;; (defun shanks-square-forms (n)
172 ;; (let* ((k (1+ (random 100)))
173 ;; (p0 (isqrt (* k n)))
174 ;; (q0 1)
175 ;; (q1 (- (* k n) (* p0 p0))))
176 ;; (iter
177 ;; (for i from 1)
178 ;; (until (squarep qi))
179 ;; (for bi = (floor (/ (+ (isqrt (* k n)) pi-1)
180 ;; qi)))
181 ;; (for pi = (- (* bi qi) pi-1))
182 ;; (for qi+1 = (+ qi-1 (* bi (- pi-1 pi)))))
183 ;; (let* ((b0 (floor (/ (+ (isqrt (* k N)) pi-1) (sqrt qi))))
184 ;; (p0 (- (* b0 (sqrt qi)) pi-1))
185 ;; (q0 (sqrt qi))
186 ;; (q1 (/ (- (* k n) (* p0 p0)) q0)))
187 ;; (iter
188 ;; (until (= pi+1 pi))
189 ;; (for bi = (floor (/ (+ (isqrt (* k n)) pi-1)
190 ;; qi)))
191 ;; (for pi = (- (* bi qi) pi-1))
192 ;; (for qi+1 = (+ qi-1 (* bi (- pi-1 pi)))))
193 ;; (let ((gcd (gcd n pi)))
194 ;; (if (and (/= gcd 1) (/= gcd n))
195 ;; gcd
196 ;; (signal 'factor-attempt-failed))))))
197
198
199 ;; (defun shanks-square-forms (n)
200 ;; (let ((k (1+ (random 100))))
201 ;; (iter
202 ;; (squarep q)
203 ;; (for b initially 0 then (floor (/ (+ (isqrt (* k n)) pi-1) qi)))
204 ;; (for p initially (isqrt (* k n)) then (- (* bi qi) pi-1))
205 ;; (for q-next initially (- (* k n) (* p0 p0)) then (+ qi-1 (* bi (- pi-1 pi))))
206 ;; (for q previous q-next initially 1)
207
b9e84b0 Initial commit.
Zach Kost-Smith authored
208 ;; @\subsection{Dixon's factorization method}
209
210 ;; O(e^(2 sqrt(2) sqrt(log n log log n)))
211
212 ;; @\subsection{Continued fraction factorization}
213
214 ;; O(e^sqrt(2 log n log log n))
215
216 ;; @\subsection{Quadratic sieve}
217
218 ;; O(e^sqrt(log n log log n))
219
34e5de6 Added Hypercubic Polynomial Quadratic Sieve
Zach Kost-Smith authored
220 ;; +1@ulimy-hmpqs.lisp
221
b9e84b0 Initial commit.
Zach Kost-Smith authored
222 ;; Fastest known algorithm for numbers under 100 decimal digits
223
224 ;; @\subsection{General number field sieve}
225
226 ;; O(e^((c+o(1))(log n)^(1/3) (log log n)^(2/3))) (heuristically)
227
228 ;; Assymptotically fastest known algorithm
229
230
231 ;; @\section{Generic Interface}
232
4aee661 Added the generic interface.
Zach Kost-Smith authored
233 (defun factor (n)
234 "Return the prime factorization of N as a sorted \(smallest to largest) list. Factors that appear more than once are present mulitiple times in the output.
235
236 \(reduce '* (factor n)) = n"
c01caa4 Switch to Pollard Rho as a bug free implementation
Zach Kost-Smith authored
237 (pollards-rho n))
4aee661 Added the generic interface.
Zach Kost-Smith authored
238
b9e84b0 Initial commit.
Zach Kost-Smith authored
239 ;; Define some common name interfaces that hide the methods that are being used.
240
241 ;; If you would like to access a particular algorithm specifically, use the
242 ;; package <<cl-factoring-algorithms>>.
243
244 (defpackage :cl-factoring-algorithms
245 (:import-from :cl-factoring
246 #:trial-division
247 #:pollards-rho
77e2c15 Bug fix: exported symbols typo in cl-factoring-algorithms
Zach Kost-Smith authored
248 #:brents-cycle)
34e5de6 Added Hypercubic Polynomial Quadratic Sieve
Zach Kost-Smith authored
249 (:import-from :ulimy-hmpqs
250 #:hmpqs)
b9e84b0 Initial commit.
Zach Kost-Smith authored
251 (:export #:trial-division
252 #:pollards-rho
34e5de6 Added Hypercubic Polynomial Quadratic Sieve
Zach Kost-Smith authored
253 #:brents-cycle
254 #:hmpqs))
Something went wrong with that request. Please try again.