smithzvk/cl-factoring

Subversion checkout URL

You can clone with
or
.
 b9e84b0 Initial commit. Zach Kost-Smith authored Jun 3, 2012 1 2 (defpackage :cl-factoring 3 (:use :cl :iterate :cl-primality) 4aee661 Added the generic interface. Zach Kost-Smith authored Jun 3, 2012 4 (:export 5 #:factor)) b9e84b0 Initial commit. Zach Kost-Smith authored Jun 3, 2012 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 <> 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 Jun 3, 2012 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 Jun 3, 2012 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 Jun 3, 2012 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 Jun 3, 2012 69 70 (defun pollards-rho-find-factor (n) 71 (handler-case 870dcf9 Bug fix: handle squares properly Zach Kost-Smith authored Jun 3, 2012 72 (pollards-rho-attempt n) b9e84b0 Initial commit. Zach Kost-Smith authored Jun 3, 2012 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 Jun 3, 2012 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 Jun 3, 2012 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 Jun 13, 2012 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 Jun 3, 2012 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 Jun 13, 2012 220 ;; +1@ulimy-hmpqs.lisp 221 b9e84b0 Initial commit. Zach Kost-Smith authored Jun 3, 2012 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 Jun 3, 2012 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 Mar 9, 2015 237 (pollards-rho n)) 4aee661 Added the generic interface. Zach Kost-Smith authored Jun 3, 2012 238 b9e84b0 Initial commit. Zach Kost-Smith authored Jun 3, 2012 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 <>. 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 Jun 3, 2012 248 #:brents-cycle) 34e5de6 Added Hypercubic Polynomial Quadratic Sieve Zach Kost-Smith authored Jun 13, 2012 249 (:import-from :ulimy-hmpqs 250 #:hmpqs) b9e84b0 Initial commit. Zach Kost-Smith authored Jun 3, 2012 251 (:export #:trial-division 252 #:pollards-rho 34e5de6 Added Hypercubic Polynomial Quadratic Sieve Zach Kost-Smith authored Jun 13, 2012 253 #:brents-cycle 254 #:hmpqs))