Remove single use function, revise comment, fix inlining failure
[sbcl.git] / src / code / bignum.lisp
blob722fea6d899971b9c4c5d14ca80af26278d27eba
1 ;;;; code to implement bignum support
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB!BIGNUM")
14 ;;;; notes
16 ;;; comments from CMU CL:
17 ;;; These symbols define the interface to the number code:
18 ;;; add-bignums multiply-bignums negate-bignum subtract-bignum
19 ;;; multiply-bignum-and-fixnum multiply-fixnums
20 ;;; bignum-ashift-right bignum-ashift-left bignum-gcd
21 ;;; bignum-to-float bignum-integer-length
22 ;;; bignum-logical-and bignum-logical-ior bignum-logical-xor
23 ;;; bignum-logical-not bignum-load-byte
24 ;;; bignum-truncate bignum-plus-p bignum-compare make-small-bignum
25 ;;; bignum-logbitp bignum-logcount
26 ;;; These symbols define the interface to the compiler:
27 ;;; bignum-element-type bignum-index %allocate-bignum
28 ;;; %bignum-length %bignum-set-length %bignum-ref %bignum-set
29 ;;; %digit-0-or-plusp %add-with-carry %subtract-with-borrow
30 ;;; %multiply-and-add %multiply %lognot %logand %logior %logxor
31 ;;; %fixnum-to-digit %bigfloor %fixnum-digit-with-correct-sign %ashl
32 ;;; %ashr %digit-logical-shift-right))
34 ;;; The following interfaces will either be assembler routines or code
35 ;;; sequences expanded into the code as basic bignum operations:
36 ;;; General:
37 ;;; %BIGNUM-LENGTH
38 ;;; %ALLOCATE-BIGNUM
39 ;;; %BIGNUM-REF
40 ;;; %NORMALIZE-BIGNUM
41 ;;; %BIGNUM-SET-LENGTH
42 ;;; %FIXNUM-DIGIT-WITH-CORRECT-SIGN
43 ;;; %SIGN-DIGIT
44 ;;; %ASHR
45 ;;; %ASHL
46 ;;; %BIGNUM-0-OR-PLUSP
47 ;;; %DIGIT-LOGICAL-SHIFT-RIGHT
48 ;;; General (May not exist when done due to sole use in %-routines.)
49 ;;; %DIGIT-0-OR-PLUSP
50 ;;; Addition:
51 ;;; %ADD-WITH-CARRY
52 ;;; Subtraction:
53 ;;; %SUBTRACT-WITH-BORROW
54 ;;; Multiplication
55 ;;; %MULTIPLY
56 ;;; Negation
57 ;;; %LOGNOT
58 ;;; Shifting (in place)
59 ;;; %NORMALIZE-BIGNUM-BUFFER
60 ;;; Relational operators:
61 ;;; %LOGAND
62 ;;; %LOGIOR
63 ;;; %LOGXOR
64 ;;; LDB
65 ;;; %FIXNUM-TO-DIGIT
66 ;;; TRUNCATE
67 ;;; %BIGFLOOR
68 ;;;
69 ;;; Note: The floating routines know about the float representation.
70 ;;;
71 ;;; PROBLEM 1:
72 ;;; There might be a problem with various LET's and parameters that take a
73 ;;; digit value. We need to write these so those things stay in machine
74 ;;; registers and number stack slots. I bind locals to these values, and I
75 ;;; use function on them -- ZEROP, ASH, etc.
76 ;;;
77 ;;; PROBLEM 2:
78 ;;; In shifting and byte operations, I use masks and logical operations that
79 ;;; could result in intermediate bignums. This is hidden by the current system,
80 ;;; but I may need to write these in a way that keeps these masks and logical
81 ;;; operations from diving into the Lisp level bignum code.
82 ;;;
83 ;;; To do:
84 ;;; fixnums
85 ;;; logior, logxor, logand
86 ;;; depending on relationals, < (twice) and <= (twice)
87 ;;; or write compare thing (twice).
88 ;;; LDB on fixnum with bignum result.
89 ;;; DPB on fixnum with bignum result.
90 ;;; TRUNCATE returns zero or one as one value and fixnum or minus fixnum
91 ;;; for the other value when given (truncate fixnum bignum).
92 ;;; Returns (truncate bignum fixnum) otherwise.
93 ;;; addition
94 ;;; subtraction (twice)
95 ;;; multiply
96 ;;; GCD
97 ;;; Write MASK-FIELD and DEPOSIT-FIELD in terms of logical operations.
98 ;;; DIVIDE
99 ;;; IF (/ x y) with bignums:
100 ;;; do the truncate, and if rem is 0, return quotient.
101 ;;; if rem is non-0
102 ;;; gcd of x and y.
103 ;;; "truncate" each by gcd, ignoring remainder 0.
104 ;;; form ratio of each result, bottom is positive.
106 ;;;; What's a bignum?
108 (defconstant digit-size sb!vm:n-word-bits)
110 (defconstant all-ones-digit (1- (ash 1 sb!vm:n-word-bits)))
112 ;;;; internal inline routines
114 ;;; %ALLOCATE-BIGNUM must zero all elements.
115 (defun %allocate-bignum (length)
116 (declare (type bignum-length length))
117 (%allocate-bignum length))
119 ;;; Extract the length of the bignum.
120 (defun %bignum-length (bignum)
121 (declare (type bignum bignum))
122 (%bignum-length bignum))
124 ;;; %BIGNUM-REF needs to access bignums as obviously as possible, and it needs
125 ;;; to be able to return the digit somewhere no one looks for real objects.
126 (defun %bignum-ref (bignum i)
127 (declare (type bignum bignum)
128 (type bignum-index i))
129 (%bignum-ref bignum i))
130 (defun %bignum-set (bignum i value)
131 (declare (type bignum bignum)
132 (type bignum-index i)
133 (type bignum-element-type value))
134 (%bignum-set bignum i value))
136 ;;; Return T if digit is positive, or NIL if negative.
137 (defun %digit-0-or-plusp (digit)
138 (declare (type bignum-element-type digit))
139 (not (logbitp (1- digit-size) digit)))
141 #!-sb-fluid (declaim (inline %bignum-0-or-plusp))
142 (defun %bignum-0-or-plusp (bignum len)
143 (declare (type bignum bignum)
144 (type bignum-length len))
145 (%digit-0-or-plusp (%bignum-ref bignum (1- len))))
147 ;;; This should be in assembler, and should not cons intermediate
148 ;;; results. It returns a bignum digit and a carry resulting from adding
149 ;;; together a, b, and an incoming carry.
150 (defun %add-with-carry (a b carry)
151 (declare (type bignum-element-type a b)
152 (type (mod 2) carry))
153 (%add-with-carry a b carry))
155 ;;; This should be in assembler, and should not cons intermediate
156 ;;; results. It returns a bignum digit and a borrow resulting from
157 ;;; subtracting b from a, and subtracting a possible incoming borrow.
159 ;;; We really do: a - b - 1 + borrow, where borrow is either 0 or 1.
160 (defun %subtract-with-borrow (a b borrow)
161 (declare (type bignum-element-type a b)
162 (type (mod 2) borrow))
163 (%subtract-with-borrow a b borrow))
165 ;;; Multiply two digit-size numbers, returning a 2*digit-size result
166 ;;; split into two digit-size quantities.
167 (defun %multiply (x y)
168 (declare (type bignum-element-type x y))
169 (%multiply x y))
171 ;;; This multiplies x-digit and y-digit, producing high and low digits
172 ;;; manifesting the result. Then it adds the low digit, res-digit, and
173 ;;; carry-in-digit. Any carries (note, you still have to add two digits
174 ;;; at a time possibly producing two carries) from adding these three
175 ;;; digits get added to the high digit from the multiply, producing the
176 ;;; next carry digit. Res-digit is optional since two uses of this
177 ;;; primitive multiplies a single digit bignum by a multiple digit
178 ;;; bignum, and in this situation there is no need for a result buffer
179 ;;; accumulating partial results which is where the res-digit comes
180 ;;; from.
181 (defun %multiply-and-add (x-digit y-digit carry-in-digit
182 &optional (res-digit 0))
183 (declare (type bignum-element-type x-digit y-digit res-digit carry-in-digit))
184 (%multiply-and-add x-digit y-digit carry-in-digit res-digit))
186 (defun %lognot (digit)
187 (declare (type bignum-element-type digit))
188 (%lognot digit))
190 ;;; Each of these does the digit-size unsigned op.
191 (declaim (inline %logand %logior %logxor))
192 (defun %logand (a b)
193 (declare (type bignum-element-type a b))
194 (logand a b))
195 (defun %logior (a b)
196 (declare (type bignum-element-type a b))
197 (logior a b))
198 (defun %logxor (a b)
199 (declare (type bignum-element-type a b))
200 (logxor a b))
202 ;;; This takes a fixnum and sets it up as an unsigned digit-size
203 ;;; quantity.
204 (defun %fixnum-to-digit (x)
205 (declare (fixnum x))
206 (logand x (1- (ash 1 digit-size))))
208 #!-32x16-divide
209 ;;; This takes three digits and returns the FLOOR'ed result of
210 ;;; dividing the first two as a 2*digit-size integer by the third.
212 ;;; Do weird LET and SETQ stuff to bamboozle the compiler into allowing
213 ;;; the %BIGFLOOR transform to expand into pseudo-assembler for which the
214 ;;; compiler can later correctly allocate registers.
215 (defun %bigfloor (a b c)
216 (let ((a a) (b b) (c c))
217 (declare (type bignum-element-type a b c))
218 (setq a a b b c c)
219 (%bigfloor a b c)))
221 ;;; Convert the digit to a regular integer assuming that the digit is signed.
222 (defun %fixnum-digit-with-correct-sign (digit)
223 (declare (type bignum-element-type digit))
224 (if (logbitp (1- digit-size) digit)
225 (logior digit (ash -1 digit-size))
226 digit))
228 ;;; Do an arithmetic shift right of data even though bignum-element-type is
229 ;;; unsigned.
230 (defun %ashr (data count)
231 (declare (type bignum-element-type data)
232 (type (mod #.sb!vm:n-word-bits) count))
233 (%ashr data count))
235 ;;; This takes a digit-size quantity and shifts it to the left,
236 ;;; returning a digit-size quantity.
237 (defun %ashl (data count)
238 (declare (type bignum-element-type data)
239 (type (mod #.sb!vm:n-word-bits) count))
240 (%ashl data count))
242 ;;; Do an unsigned (logical) right shift of a digit by Count.
243 (defun %digit-logical-shift-right (data count)
244 (declare (type bignum-element-type data)
245 (type (mod #.sb!vm:n-word-bits) count))
246 (%digit-logical-shift-right data count))
248 ;;; Change the length of bignum to be newlen. Newlen must be the same or
249 ;;; smaller than the old length, and any elements beyond newlen must be zeroed.
250 (defun %bignum-set-length (bignum newlen)
251 (declare (type bignum bignum)
252 (type bignum-length newlen))
253 (%bignum-set-length bignum newlen))
255 ;;; This returns 0 or "-1" depending on whether the bignum is positive. This
256 ;;; is suitable for infinite sign extension to complete additions,
257 ;;; subtractions, negations, etc. This cannot return a -1 represented as
258 ;;; a negative fixnum since it would then have to low zeros.
259 #!-sb-fluid (declaim (inline %sign-digit))
260 (defun %sign-digit (bignum len)
261 (declare (type bignum bignum)
262 (type bignum-length len))
263 (%ashr (%bignum-ref bignum (1- len)) (1- digit-size)))
265 (declaim (inline bignum-plus-p))
266 (defun bignum-plus-p (bignum)
267 (declare (type bignum bignum))
268 (%bignum-0-or-plusp bignum (%bignum-length bignum)))
270 (declaim (optimize (speed 3) (safety 0)))
272 ;;;; addition
274 (defun add-bignums (a b)
275 (declare (type bignum a b))
276 (declare (muffle-conditions compiler-note)) ; returns lispobj, so what.
277 (let ((len-a (%bignum-length a))
278 (len-b (%bignum-length b)))
279 (multiple-value-bind (a len-a b len-b)
280 (if (> len-a len-b)
281 (values a len-a b len-b)
282 (values b len-b a len-a))
283 (declare (type bignum a b)
284 (type bignum-length len-a len-b))
285 (let* ((len-res (1+ len-a))
286 (res (%allocate-bignum len-res))
287 (carry 0))
288 (declare (type bignum-length len-res)
289 (type bignum res)
290 (type (mod 2) carry))
291 (dotimes (i len-b)
292 (declare (type bignum-index i))
293 (multiple-value-bind (v k)
294 (%add-with-carry (%bignum-ref a i) (%bignum-ref b i) carry)
295 (declare (type bignum-element-type v)
296 (type (mod 2) k))
297 (setf (%bignum-ref res i) v)
298 (setf carry k)))
299 (if (/= len-a len-b)
300 (finish-add a res carry (%sign-digit b len-b) len-b len-a)
301 (setf (%bignum-ref res len-a)
302 (%add-with-carry (%sign-digit a len-a)
303 (%sign-digit b len-b)
304 carry)))
305 (%normalize-bignum res len-res)))))
307 ;;; This takes the longer of two bignums and propagates the carry through its
308 ;;; remaining high order digits.
309 (defun finish-add (a res carry sign-digit-b start end)
310 (declare (type bignum a res)
311 (type (mod 2) carry)
312 (type bignum-element-type sign-digit-b)
313 (type bignum-index start)
314 (type bignum-length end))
315 (do ((i start (1+ i)))
316 ((= i end)
317 (setf (%bignum-ref res end)
318 (%add-with-carry (%sign-digit a end) sign-digit-b carry)))
319 (declare (type bignum-index i))
320 (multiple-value-bind (v k)
321 (%add-with-carry (%bignum-ref a i) sign-digit-b carry)
322 (setf (%bignum-ref res i) v)
323 (setf carry k)))
324 (values))
326 ;;;; subtraction
328 (eval-when (:compile-toplevel :execute)
330 ;;; This subtracts b from a plugging result into res. Return-fun is the
331 ;;; function to call that fixes up the result returning any useful values, such
332 ;;; as the result. This macro may evaluate its arguments more than once.
333 (sb!xc:defmacro subtract-bignum-loop (a len-a b len-b res len-res return-fun)
334 (with-unique-names (borrow a-digit a-sign b-digit b-sign i v k)
335 `(let* ((,borrow 1)
336 (,a-sign (%sign-digit ,a ,len-a))
337 (,b-sign (%sign-digit ,b ,len-b)))
338 (declare (type bignum-element-type ,a-sign ,b-sign))
339 (dotimes (,i ,len-res)
340 (declare (type bignum-index ,i))
341 (let ((,a-digit (if (< ,i ,len-a) (%bignum-ref ,a ,i) ,a-sign))
342 (,b-digit (if (< ,i ,len-b) (%bignum-ref ,b ,i) ,b-sign)))
343 (declare (type bignum-element-type ,a-digit ,b-digit))
344 (multiple-value-bind (,v ,k)
345 (%subtract-with-borrow ,a-digit ,b-digit ,borrow)
346 (setf (%bignum-ref ,res ,i) ,v)
347 (setf ,borrow ,k))))
348 (,return-fun ,res ,len-res))))
350 ) ;EVAL-WHEN
352 (defun subtract-bignum (a b)
353 (declare (type bignum a b))
354 (let* ((len-a (%bignum-length a))
355 (len-b (%bignum-length b))
356 (len-res (1+ (max len-a len-b)))
357 (res (%allocate-bignum len-res)))
358 (declare (type bignum-length len-a len-b len-res)) ;Test len-res for bounds?
359 (subtract-bignum-loop a len-a b len-b res len-res %normalize-bignum)))
361 ;;; Operations requiring a subtraction without the overhead of intermediate
362 ;;; results, such as GCD, use this. It assumes Result is big enough for the
363 ;;; result.
364 (defun subtract-bignum-buffers-with-len (a len-a b len-b result len-res)
365 (declare (type bignum a b result)
366 (type bignum-length len-a len-b len-res))
367 (subtract-bignum-loop a len-a b len-b result len-res
368 %normalize-bignum-buffer))
370 (defun subtract-bignum-buffers (a len-a b len-b result)
371 (declare (type bignum a b result)
372 (type bignum-length len-a len-b))
373 (subtract-bignum-loop a len-a b len-b result (max len-a len-b)
374 %normalize-bignum-buffer))
376 ;;;; multiplication
378 (defun multiply-bignums (a b)
379 (declare (type bignum a b))
380 (let* ((a-plusp (bignum-plus-p a))
381 (b-plusp (bignum-plus-p b))
382 (a (if a-plusp a (negate-bignum a)))
383 (b (if b-plusp b (negate-bignum b)))
384 (len-a (%bignum-length a))
385 (len-b (%bignum-length b))
386 (len-res (+ len-a len-b))
387 (res (%allocate-bignum len-res))
388 (negate-res (not (eq a-plusp b-plusp))))
389 (declare (type bignum-length len-a len-b len-res))
390 (dotimes (i len-a)
391 (declare (type bignum-index i))
392 (let ((carry-digit 0)
393 (x (%bignum-ref a i))
394 (k i))
395 (declare (type bignum-index k)
396 (type bignum-element-type carry-digit x))
397 (dotimes (j len-b)
398 (multiple-value-bind (big-carry res-digit)
399 (%multiply-and-add x
400 (%bignum-ref b j)
401 (%bignum-ref res k)
402 carry-digit)
403 (declare (type bignum-element-type big-carry res-digit))
404 (setf (%bignum-ref res k) res-digit)
405 (setf carry-digit big-carry)
406 (incf k)))
407 (setf (%bignum-ref res k) carry-digit)))
408 (when negate-res (negate-bignum-in-place res))
409 (%normalize-bignum res len-res)))
411 (defun multiply-bignum-and-fixnum (bignum fixnum)
412 (declare (type bignum bignum) (type fixnum fixnum))
413 (let* ((bignum-plus-p (bignum-plus-p bignum))
414 (fixnum-plus-p (not (minusp fixnum)))
415 (bignum (if bignum-plus-p bignum (negate-bignum bignum)))
416 (bignum-len (%bignum-length bignum))
417 (fixnum (if fixnum-plus-p fixnum (- fixnum)))
418 (result (%allocate-bignum (1+ bignum-len)))
419 (carry-digit 0))
420 (declare (type bignum bignum result)
421 (type bignum-element-type fixnum carry-digit))
422 (dotimes (index bignum-len)
423 (declare (type bignum-index index))
424 (multiple-value-bind (next-digit low)
425 (%multiply-and-add (%bignum-ref bignum index) fixnum carry-digit)
426 (declare (type bignum-element-type next-digit low))
427 (setf carry-digit next-digit)
428 (setf (%bignum-ref result index) low)))
429 (setf (%bignum-ref result bignum-len) carry-digit)
430 (unless (eq bignum-plus-p fixnum-plus-p)
431 (negate-bignum-in-place result))
432 (%normalize-bignum result (1+ bignum-len))))
434 (defun multiply-fixnums (a b)
435 (declare (fixnum a b))
436 (declare (muffle-conditions compiler-note)) ; returns lispobj, so what.
437 (let* ((a-minusp (minusp a))
438 (b-minusp (minusp b)))
439 (multiple-value-bind (high low)
440 (%multiply (if a-minusp (- a) a)
441 (if b-minusp (- b) b))
442 (declare (type bignum-element-type high low))
443 (if (and (zerop high)
444 (%digit-0-or-plusp low))
445 (let ((low (truly-the (unsigned-byte #.(1- sb!vm:n-word-bits))
446 (%fixnum-digit-with-correct-sign low))))
447 (if (eq a-minusp b-minusp)
449 (- low)))
450 (let ((res (%allocate-bignum 2)))
451 (%bignum-set res 0 low)
452 (%bignum-set res 1 high)
453 (unless (eq a-minusp b-minusp) (negate-bignum-in-place res))
454 (%normalize-bignum res 2))))))
456 ;;;; BIGNUM-REPLACE and WITH-BIGNUM-BUFFERS
458 (eval-when (:compile-toplevel :execute)
460 (sb!xc:defmacro bignum-replace (dest
462 &key
463 (start1 '0)
464 end1
465 (start2 '0)
466 end2
467 from-end)
468 (sb!int:once-only ((n-dest dest)
469 (n-src src))
470 (with-unique-names (n-start1 n-end1 n-start2 n-end2 i1 i2)
471 (let ((end1 (or end1 `(%bignum-length ,n-dest)))
472 (end2 (or end2 `(%bignum-length ,n-src))))
473 (if from-end
474 `(let ((,n-start1 ,start1)
475 (,n-start2 ,start2))
476 (do ((,i1 (1- ,end1) (1- ,i1))
477 (,i2 (1- ,end2) (1- ,i2)))
478 ((or (< ,i1 ,n-start1) (< ,i2 ,n-start2)))
479 (declare (fixnum ,i1 ,i2))
480 (%bignum-set ,n-dest ,i1 (%bignum-ref ,n-src ,i2))))
481 (if (eql start1 start2)
482 `(let ((,n-end1 (min ,end1 ,end2)))
483 (do ((,i1 ,start1 (1+ ,i1)))
484 ((>= ,i1 ,n-end1))
485 (declare (type bignum-index ,i1))
486 (%bignum-set ,n-dest ,i1 (%bignum-ref ,n-src ,i1))))
487 `(let ((,n-end1 ,end1)
488 (,n-end2 ,end2))
489 (do ((,i1 ,start1 (1+ ,i1))
490 (,i2 ,start2 (1+ ,i2)))
491 ((or (>= ,i1 ,n-end1) (>= ,i2 ,n-end2)))
492 (declare (type bignum-index ,i1 ,i2))
493 (%bignum-set ,n-dest ,i1 (%bignum-ref ,n-src ,i2))))))))))
495 (sb!xc:defmacro with-bignum-buffers (specs &body body)
496 "WITH-BIGNUM-BUFFERS ({(var size [init])}*) Form*"
497 (sb!int:collect ((binds)
498 (inits))
499 (dolist (spec specs)
500 (let ((name (first spec))
501 (size (second spec)))
502 (binds `(,name (%allocate-bignum ,size)))
503 (let ((init (third spec)))
504 (when init
505 (inits `(bignum-replace ,name ,init))))))
506 `(let* ,(binds)
507 ,@(inits)
508 ,@body)))
510 ) ;EVAL-WHEN
512 ;;;; GCD
514 (eval-when (:compile-toplevel :load-toplevel :execute)
515 ;; The asserts in the GCD implementation are way too expensive to
516 ;; check in normal use, and are disabled here.
517 (sb!xc:defmacro gcd-assert (&rest args)
518 (declare (ignore args))
519 #+sb-bignum-assertions `(assert ,@args))
520 ;; We'll be doing a lot of modular arithmetic.
521 (sb!xc:defmacro modularly (form)
522 `(logand all-ones-digit ,form)))
524 ;;; I'm not sure why I need this FTYPE declaration. Compiled by the
525 ;;; target compiler, it can deduce the return type fine, but without
526 ;;; it, we pay a heavy price in BIGNUM-GCD when compiled by the
527 ;;; cross-compiler. -- CSR, 2004-07-19
528 (declaim (ftype (sfunction (bignum bignum-length bignum bignum-length)
529 (and unsigned-byte fixnum))
530 bignum-factors-of-two))
531 (defun bignum-factors-of-two (a len-a b len-b)
532 (declare (type bignum-length len-a len-b) (type bignum a b))
533 (do ((i 0 (1+ i))
534 (end (min len-a len-b)))
535 ((= i end) (error "Unexpected zero bignums?"))
536 (declare (type bignum-index i)
537 (type bignum-length end))
538 (let ((or-digits (%logior (%bignum-ref a i) (%bignum-ref b i))))
539 (unless (zerop or-digits)
540 (return (do ((j 0 (1+ j))
541 (or-digits or-digits (%ashr or-digits 1)))
542 ((oddp or-digits) (+ (* i digit-size) j))
543 (declare (type (mod #.sb!vm:n-word-bits) j))))))))
545 ;;; Multiply a bignum buffer with a fixnum or a digit, storing the
546 ;;; result in another bignum buffer, and without using any
547 ;;; temporaries. Inlined to avoid boxing smallnum if it's actually a
548 ;;; digit. Needed by GCD, should possibly OAOO with
549 ;;; MULTIPLY-BIGNUM-AND-FIXNUM.
550 (declaim (inline multiply-bignum-buffer-and-smallnum-to-buffer))
551 (defun multiply-bignum-buffer-and-smallnum-to-buffer (bignum bignum-len
552 smallnum res)
553 (declare (type bignum bignum))
554 (let* ((bignum-plus-p (%bignum-0-or-plusp bignum bignum-len))
555 (smallnum-plus-p (not (minusp smallnum)))
556 (smallnum (if smallnum-plus-p smallnum (- smallnum)))
557 (carry-digit 0))
558 (declare (type bignum bignum res)
559 (type bignum-length bignum-len)
560 (type bignum-element-type smallnum carry-digit))
561 (unless bignum-plus-p
562 (negate-bignum-buffer-in-place bignum bignum-len))
563 (dotimes (index bignum-len)
564 (declare (type bignum-index index))
565 (multiple-value-bind (next-digit low)
566 (%multiply-and-add (%bignum-ref bignum index)
567 smallnum
568 carry-digit)
569 (declare (type bignum-element-type next-digit low))
570 (setf carry-digit next-digit)
571 (setf (%bignum-ref res index) low)))
572 (setf (%bignum-ref res bignum-len) carry-digit)
573 (unless bignum-plus-p
574 (negate-bignum-buffer-in-place bignum bignum-len))
575 (let ((res-len (%normalize-bignum-buffer res (1+ bignum-len))))
576 (unless (eq bignum-plus-p smallnum-plus-p)
577 (negate-bignum-buffer-in-place res res-len))
578 res-len)))
580 ;;; Given U and V, return U / V mod 2^32. Implements the algorithm in the
581 ;;; paper, but uses some clever bit-twiddling nicked from Nickle to do it.
582 (declaim (inline bmod))
583 (defun bmod (u v)
584 (declare (muffle-conditions compiler-note)) ; returns lispobj, so what.
585 (let ((ud (%bignum-ref u 0))
586 (vd (%bignum-ref v 0))
587 (umask 0)
588 (imask 1)
589 (m 0))
590 (declare (type (unsigned-byte #.sb!vm:n-word-bits) ud vd umask imask m))
591 (dotimes (i digit-size)
592 (setf umask (logior umask imask))
593 (when (logtest ud umask)
594 (setf ud (modularly (- ud vd)))
595 (setf m (modularly (logior m imask))))
596 (setf imask (modularly (ash imask 1)))
597 (setf vd (modularly (ash vd 1))))
600 (defun dmod (u u-len v v-len tmp1)
601 (loop while (> (bignum-buffer-integer-length u u-len)
602 (+ (bignum-buffer-integer-length v v-len)
603 digit-size))
605 (unless (zerop (%bignum-ref u 0))
606 (let* ((bmod (bmod u v))
607 (tmp1-len (multiply-bignum-buffer-and-smallnum-to-buffer v v-len
608 bmod
609 tmp1)))
610 (setf u-len (subtract-bignum-buffers u u-len
611 tmp1 tmp1-len
613 (bignum-abs-buffer u u-len)))
614 (gcd-assert (zerop (%bignum-ref u 0)))
615 (setf u-len (bignum-buffer-ashift-right u u-len digit-size)))
616 (let* ((d (+ 1 (- (bignum-buffer-integer-length u u-len)
617 (bignum-buffer-integer-length v v-len))))
618 (n (1- (ash 1 d))))
619 (declare (type (unsigned-byte #.(integer-length #.sb!vm:n-word-bits)) d)
620 (type (unsigned-byte #.sb!vm:n-word-bits) n))
621 (gcd-assert (>= d 0))
622 (when (logtest (%bignum-ref u 0) n)
623 (let ((tmp1-len
624 (multiply-bignum-buffer-and-smallnum-to-buffer v v-len
625 (logand n (bmod u
627 tmp1)))
628 (setf u-len (subtract-bignum-buffers u u-len
629 tmp1 tmp1-len
631 (bignum-abs-buffer u u-len)))
632 u-len))
634 (defconstant lower-ones-digit (1- (ash 1 (truncate sb!vm:n-word-bits 2))))
636 ;;; Find D and N such that (LOGAND ALL-ONES-DIGIT (- (* D X) (* N Y))) is 0,
637 ;;; (< 0 N LOWER-ONES-DIGIT) and (< 0 (ABS D) LOWER-ONES-DIGIT).
638 (defun reduced-ratio-mod (x y)
639 (let* ((c (bmod x y))
640 (n1 c)
641 (d1 1)
642 (n2 (modularly (1+ (modularly (lognot n1)))))
643 (d2 (modularly -1)))
644 (declare (type (unsigned-byte #.sb!vm:n-word-bits) n1 d1 n2 d2))
645 (loop while (> n2 (expt 2 (truncate digit-size 2))) do
646 (loop for i of-type (mod #.sb!vm:n-word-bits)
647 downfrom (- (integer-length n1) (integer-length n2))
648 while (>= n1 n2) do
649 (when (>= n1 (modularly (ash n2 i)))
650 (psetf n1 (modularly (- n1 (modularly (ash n2 i))))
651 d1 (modularly (- d1 (modularly (ash d2 i)))))))
652 (psetf n1 n2
653 d1 d2
654 n2 n1
655 d2 d1))
656 (values n2 (if (>= d2 (expt 2 (1- digit-size)))
657 (lognot (logand most-positive-fixnum (lognot d2)))
658 (logand lower-ones-digit d2)))))
661 (defun copy-bignum (a &optional (len (%bignum-length a)))
662 (let ((b (%allocate-bignum len)))
663 (bignum-replace b a)
664 (%bignum-set-length b len)
667 ;;; Allocate a single word bignum that holds fixnum. This is useful when
668 ;;; we are trying to mix fixnum and bignum operands.
669 #!-sb-fluid (declaim (inline make-small-bignum))
670 (defun make-small-bignum (fixnum)
671 (let ((res (%allocate-bignum 1)))
672 (setf (%bignum-ref res 0) (%fixnum-to-digit fixnum))
673 res))
675 ;; When the larger number is less than this many bignum digits long, revert
676 ;; to old algorithm.
677 (defparameter *accelerated-gcd-cutoff* 3)
679 ;;; Alternate between k-ary reduction with the help of
680 ;;; REDUCED-RATIO-MOD and digit modulus reduction via DMOD. Once the
681 ;;; arguments get small enough, drop through to BIGNUM-MOD-GCD (since
682 ;;; k-ary reduction can introduce spurious factors, which need to be
683 ;;; filtered out). Reference: Kenneth Weber, "The accelerated integer
684 ;;; GCD algorithm", ACM Transactions on Mathematical Software, volume
685 ;;; 21, number 1, March 1995, epp. 111-122.
686 (defun bignum-gcd (u0 v0)
687 (declare (type bignum u0 v0))
688 (let* ((u1 (if (bignum-plus-p u0)
690 (negate-bignum u0 nil)))
691 (v1 (if (bignum-plus-p v0)
693 (negate-bignum v0 nil))))
694 (if (zerop v1)
695 (return-from bignum-gcd u1))
696 (when (> u1 v1)
697 (rotatef u1 v1))
698 (let ((n (mod v1 u1)))
699 (setf v1 (if (fixnump n)
700 (make-small-bignum n)
701 n)))
702 (if (and (= 1 (%bignum-length v1))
703 (zerop (%bignum-ref v1 0)))
704 (return-from bignum-gcd (%normalize-bignum u1
705 (%bignum-length u1))))
706 (let* ((buffer-len (+ 2 (%bignum-length u1)))
707 (u (%allocate-bignum buffer-len))
708 (u-len (%bignum-length u1))
709 (v (%allocate-bignum buffer-len))
710 (v-len (%bignum-length v1))
711 (tmp1 (%allocate-bignum buffer-len))
712 (tmp1-len 0)
713 (tmp2 (%allocate-bignum buffer-len))
714 (tmp2-len 0)
715 (factors-of-two
716 (bignum-factors-of-two u1 (%bignum-length u1)
717 v1 (%bignum-length v1))))
718 (declare (type (or null bignum-length)
719 buffer-len u-len v-len tmp1-len tmp2-len))
720 (bignum-replace u u1)
721 (bignum-replace v v1)
722 (setf u-len
723 (make-gcd-bignum-odd u
724 (bignum-buffer-ashift-right u u-len
725 factors-of-two)))
726 (setf v-len
727 (make-gcd-bignum-odd v
728 (bignum-buffer-ashift-right v v-len
729 factors-of-two)))
730 (loop until (or (< u-len *accelerated-gcd-cutoff*)
731 (not v-len)
732 (zerop v-len)
733 (and (= 1 v-len)
734 (zerop (%bignum-ref v 0))))
736 (gcd-assert (= buffer-len (%bignum-length u)
737 (%bignum-length v)
738 (%bignum-length tmp1)
739 (%bignum-length tmp2)))
740 (if (> (bignum-buffer-integer-length u u-len)
741 (+ #.(truncate sb!vm:n-word-bits 4)
742 (bignum-buffer-integer-length v v-len)))
743 (setf u-len (dmod u u-len
744 v v-len
745 tmp1))
746 (multiple-value-bind (n d) (reduced-ratio-mod u v)
747 (setf tmp1-len
748 (multiply-bignum-buffer-and-smallnum-to-buffer v v-len
749 n tmp1))
750 (setf tmp2-len
751 (multiply-bignum-buffer-and-smallnum-to-buffer u u-len
752 d tmp2))
753 (gcd-assert (= (copy-bignum tmp2 tmp2-len)
754 (* (copy-bignum u u-len) d)))
755 (gcd-assert (= (copy-bignum tmp1 tmp1-len)
756 (* (copy-bignum v v-len) n)))
757 (setf u-len
758 (subtract-bignum-buffers-with-len tmp1 tmp1-len
759 tmp2 tmp2-len
761 (1+ (max tmp1-len
762 tmp2-len))))
763 (gcd-assert (or (zerop (- (copy-bignum tmp1 tmp1-len)
764 (copy-bignum tmp2 tmp2-len)))
765 (= (copy-bignum u u-len)
766 (- (copy-bignum tmp1 tmp1-len)
767 (copy-bignum tmp2 tmp2-len)))))
768 (bignum-abs-buffer u u-len)
769 (gcd-assert (zerop (modularly u)))))
770 (setf u-len (make-gcd-bignum-odd u u-len))
771 (rotatef u v)
772 (rotatef u-len v-len))
773 (bignum-abs-buffer u u-len)
774 (setf u (copy-bignum u u-len))
775 (let ((n (bignum-mod-gcd v1 u)))
776 (ash (bignum-mod-gcd u1 (if (fixnump n)
777 (make-small-bignum n)
779 factors-of-two)))))
781 (defun bignum-mod-gcd (a b)
782 (declare (type bignum a b))
783 (when (< a b)
784 (rotatef a b))
785 ;; While the length difference of A and B is sufficiently large,
786 ;; reduce using MOD (slowish, but it should equalize the sizes of
787 ;; A and B pretty quickly). After that, use the binary GCD
788 ;; algorithm to handle the rest.
789 (loop until (and (= (%bignum-length b) 1) (zerop (%bignum-ref b 0))) do
790 (when (<= (%bignum-length a) (1+ (%bignum-length b)))
791 (return-from bignum-mod-gcd (bignum-binary-gcd a b)))
792 (let ((rem (mod a b)))
793 (if (fixnump rem)
794 (setf a (make-small-bignum rem))
795 (setf a rem))
796 (rotatef a b)))
797 (if (= (%bignum-length a) 1)
798 (%normalize-bignum a 1)
801 (defun bignum-binary-gcd (a b)
802 (declare (type bignum a b))
803 (let* ((len-a (%bignum-length a))
804 (len-b (%bignum-length b)))
805 (with-bignum-buffers ((a-buffer len-a a)
806 (b-buffer len-b b)
807 (res-buffer (max len-a len-b)))
808 (let* ((factors-of-two
809 (bignum-factors-of-two a-buffer len-a
810 b-buffer len-b))
811 (len-a (make-gcd-bignum-odd
812 a-buffer
813 (bignum-buffer-ashift-right a-buffer len-a
814 factors-of-two)))
815 (len-b (make-gcd-bignum-odd
816 b-buffer
817 (bignum-buffer-ashift-right b-buffer len-b
818 factors-of-two))))
819 (declare (type bignum-length len-a len-b))
820 (let ((x a-buffer)
821 (len-x len-a)
822 (y b-buffer)
823 (len-y len-b)
824 (z res-buffer))
825 (loop
826 (multiple-value-bind (u v len-v r len-r)
827 (bignum-gcd-order-and-subtract x len-x y len-y z)
828 (declare (type bignum-length len-v len-r))
829 (when (and (= len-r 1) (zerop (%bignum-ref r 0)))
830 (if (zerop factors-of-two)
831 (let ((ret (%allocate-bignum len-v)))
832 (dotimes (i len-v)
833 (setf (%bignum-ref ret i) (%bignum-ref v i)))
834 (return (%normalize-bignum ret len-v)))
835 (return (bignum-ashift-left v factors-of-two len-v))))
836 (setf x v len-x len-v)
837 (setf y r len-y (make-gcd-bignum-odd r len-r))
838 (setf z u))))))))
840 (defun bignum-gcd-order-and-subtract (a len-a b len-b res)
841 (declare (type bignum-length len-a len-b) (type bignum a b))
842 (cond ((= len-a len-b)
843 (do ((i (1- len-a) (1- i)))
844 ((= i -1)
845 (setf (%bignum-ref res 0) 0)
846 (values a b len-b res 1))
847 (let ((a-digit (%bignum-ref a i))
848 (b-digit (%bignum-ref b i)))
849 (cond ((= a-digit b-digit))
850 ((> a-digit b-digit)
851 (return
852 (values a b len-b res
853 (subtract-bignum-buffers a len-a b len-b
854 res))))
856 (return
857 (values b a len-a res
858 (subtract-bignum-buffers b len-b
859 a len-a
860 res))))))))
861 ((> len-a len-b)
862 (values a b len-b res
863 (subtract-bignum-buffers a len-a b len-b res)))
865 (values b a len-a res
866 (subtract-bignum-buffers b len-b a len-a res)))))
868 (defun make-gcd-bignum-odd (a len-a)
869 (declare (type bignum a) (type bignum-length len-a))
870 (dotimes (index len-a)
871 (declare (type bignum-index index))
872 (do ((digit (%bignum-ref a index) (%ashr digit 1))
873 (increment 0 (1+ increment)))
874 ((zerop digit))
875 (declare (type (mod #.sb!vm:n-word-bits) increment))
876 (when (oddp digit)
877 (return-from make-gcd-bignum-odd
878 (bignum-buffer-ashift-right a len-a
879 (+ (* index digit-size)
880 increment)))))))
883 ;;;; negation
885 (eval-when (:compile-toplevel :execute)
887 ;;; This negates bignum-len digits of bignum, storing the resulting digits into
888 ;;; result (possibly EQ to bignum) and returning whatever end-carry there is.
889 (sb!xc:defmacro bignum-negate-loop
890 (bignum bignum-len &optional (result nil resultp))
891 (with-unique-names (carry end value last)
892 `(let* (,@(if (not resultp) `(,last))
893 (,carry
894 (multiple-value-bind (,value ,carry)
895 (%add-with-carry (%lognot (%bignum-ref ,bignum 0)) 1 0)
896 ,(if resultp
897 `(setf (%bignum-ref ,result 0) ,value)
898 `(setf ,last ,value))
899 ,carry))
900 (i 1)
901 (,end ,bignum-len))
902 (declare (type bit ,carry)
903 (type bignum-index i)
904 (type bignum-length ,end))
905 (loop
906 (when (= i ,end) (return))
907 (multiple-value-bind (,value temp)
908 (%add-with-carry (%lognot (%bignum-ref ,bignum i)) 0 ,carry)
909 ,(if resultp
910 `(setf (%bignum-ref ,result i) ,value)
911 `(setf ,last ,value))
912 (setf ,carry temp))
913 (incf i))
914 ,(if resultp carry `(values ,carry ,last)))))
916 ) ; EVAL-WHEN
918 ;;; Fully-normalize is an internal optional. It cause this to always return
919 ;;; a bignum, without any extraneous digits, and it never returns a fixnum.
920 (defun negate-bignum (x &optional (fully-normalize t))
921 (declare (type bignum x))
922 (let* ((len-x (%bignum-length x))
923 (len-res (1+ len-x))
924 (res (%allocate-bignum len-res)))
925 (declare (type bignum-length len-x len-res)) ;Test len-res for range?
926 (let ((carry (bignum-negate-loop x len-x res)))
927 (setf (%bignum-ref res len-x)
928 (%add-with-carry (%lognot (%sign-digit x len-x)) 0 carry)))
929 (if fully-normalize
930 (%normalize-bignum res len-res)
931 (%mostly-normalize-bignum res len-res))))
933 ;;; This assumes bignum is positive; that is, the result of negating it will
934 ;;; stay in the provided allocated bignum.
935 (declaim (maybe-inline negate-bignum-buffer-in-place))
936 (defun negate-bignum-buffer-in-place (bignum bignum-len)
937 (bignum-negate-loop bignum bignum-len bignum)
938 bignum)
940 (defun negate-bignum-in-place (bignum)
941 (declare (inline negate-bignum-buffer-in-place))
942 (negate-bignum-buffer-in-place bignum (%bignum-length bignum)))
944 (defun bignum-abs-buffer (bignum len)
945 (unless (%bignum-0-or-plusp bignum len)
946 (negate-bignum-buffer-in-place bignum len)))
948 ;;;; shifting
950 (eval-when (:compile-toplevel :execute)
952 ;;; This macro is used by BIGNUM-ASHIFT-RIGHT, BIGNUM-BUFFER-ASHIFT-RIGHT, and
953 ;;; BIGNUM-LDB-BIGNUM-RES. They supply a termination form that references
954 ;;; locals established by this form. Source is the source bignum. Start-digit
955 ;;; is the first digit in source from which we pull bits. Start-pos is the
956 ;;; first bit we want. Res-len-form is the form that computes the length of
957 ;;; the resulting bignum. Termination is a DO termination form with a test and
958 ;;; body. When result is supplied, it is the variable to which this binds a
959 ;;; newly allocated bignum.
961 ;;; Given start-pos, 1-31 inclusively, of shift, we form the j'th resulting
962 ;;; digit from high bits of the i'th source digit and the start-pos number of
963 ;;; bits from the i+1'th source digit.
964 (sb!xc:defmacro shift-right-unaligned (source
965 start-digit
966 start-pos
967 res-len-form
968 termination
969 &optional result)
970 `(let* ((high-bits-in-first-digit (- digit-size ,start-pos))
971 (res-len ,res-len-form)
972 (res-len-1 (1- res-len))
973 ,@(if result `((,result (%allocate-bignum res-len)))))
974 (declare (type bignum-length res-len res-len-1))
975 (do ((i ,start-digit (1+ i))
976 (j 0 (1+ j)))
977 ,termination
978 (declare (type bignum-index i j))
979 (setf (%bignum-ref ,(if result result source) j)
980 (%logior (%digit-logical-shift-right (%bignum-ref ,source i)
981 ,start-pos)
982 (%ashl (%bignum-ref ,source (1+ i))
983 high-bits-in-first-digit))))))
985 ) ; EVAL-WHEN
987 ;;; First compute the number of whole digits to shift, shifting them by
988 ;;; skipping them when we start to pick up bits, and the number of bits to
989 ;;; shift the remaining digits into place. If the number of digits is greater
990 ;;; than the length of the bignum, then the result is either 0 or -1. If we
991 ;;; shift on a digit boundary (that is, n-bits is zero), then we just copy
992 ;;; digits. The last branch handles the general case which uses a macro that a
993 ;;; couple other routines use. The fifth argument to the macro references
994 ;;; locals established by the macro.
995 (defun bignum-ashift-right (bignum count)
996 (declare (type bignum bignum)
997 (type unsigned-byte count))
998 (let ((bignum-len (%bignum-length bignum)))
999 (cond ((fixnump count)
1000 (multiple-value-bind (digits n-bits) (truncate count digit-size)
1001 (declare (type bignum-length digits))
1002 (cond
1003 ((>= digits bignum-len)
1004 (if (%bignum-0-or-plusp bignum bignum-len) 0 -1))
1005 ((zerop n-bits)
1006 (bignum-ashift-right-digits bignum digits))
1008 (shift-right-unaligned bignum digits n-bits (- bignum-len digits)
1009 ((= j res-len-1)
1010 (setf (%bignum-ref res j)
1011 (%ashr (%bignum-ref bignum i) n-bits))
1012 (%normalize-bignum res res-len))
1013 res)))))
1014 ((> count bignum-len)
1015 (if (%bignum-0-or-plusp bignum bignum-len) 0 -1))
1016 ;; Since a FIXNUM should be big enough to address anything in
1017 ;; memory, including arrays of bits, and since arrays of bits
1018 ;; take up about the same space as corresponding fixnums, there
1019 ;; should be no way that we fall through to this case: any shift
1020 ;; right by a bignum should give zero. But let's check anyway:
1021 (t (error "bignum overflow: can't shift right by ~S" count)))))
1023 (defun bignum-ashift-right-digits (bignum digits)
1024 (declare (type bignum bignum)
1025 (type bignum-length digits))
1026 (let* ((res-len (- (%bignum-length bignum) digits))
1027 (res (%allocate-bignum res-len)))
1028 (declare (type bignum-length res-len)
1029 (type bignum res))
1030 (bignum-replace res bignum :start2 digits)
1031 (%normalize-bignum res res-len)))
1033 ;;; GCD uses this for an in-place shifting operation. This is different enough
1034 ;;; from BIGNUM-ASHIFT-RIGHT that it isn't worth folding the bodies into a
1035 ;;; macro, but they share the basic algorithm. This routine foregoes a first
1036 ;;; test for digits being greater than or equal to bignum-len since that will
1037 ;;; never happen for its uses in GCD. We did fold the last branch into a macro
1038 ;;; since it was duplicated a few times, and the fifth argument to it
1039 ;;; references locals established by the macro.
1040 (defun bignum-buffer-ashift-right (bignum bignum-len x)
1041 (declare (type bignum-length bignum-len) (fixnum x))
1042 (multiple-value-bind (digits n-bits) (truncate x digit-size)
1043 (declare (type bignum-length digits))
1044 (cond
1045 ((zerop n-bits)
1046 (let ((new-end (- bignum-len digits)))
1047 (bignum-replace bignum bignum :end1 new-end :start2 digits
1048 :end2 bignum-len)
1049 (%normalize-bignum-buffer bignum new-end)))
1051 (shift-right-unaligned bignum digits n-bits (- bignum-len digits)
1052 ((= j res-len-1)
1053 (setf (%bignum-ref bignum j)
1054 (%ashr (%bignum-ref bignum i) n-bits))
1055 (%normalize-bignum-buffer bignum res-len)))))))
1057 ;;; This handles shifting a bignum buffer to provide fresh bignum data for some
1058 ;;; internal routines. We know bignum is safe when called with bignum-len.
1059 ;;; First we compute the number of whole digits to shift, shifting them
1060 ;;; starting to store farther along the result bignum. If we shift on a digit
1061 ;;; boundary (that is, n-bits is zero), then we just copy digits. The last
1062 ;;; branch handles the general case.
1063 (defun bignum-ashift-left (bignum x &optional bignum-len)
1064 (declare (type bignum bignum)
1065 (type unsigned-byte x)
1066 (type (or null bignum-length) bignum-len))
1067 (if (fixnump x)
1068 (multiple-value-bind (digits n-bits) (truncate x digit-size)
1069 (let* ((bignum-len (or bignum-len (%bignum-length bignum)))
1070 (res-len (+ digits bignum-len 1)))
1071 (when (> res-len sb!kernel::maximum-bignum-length)
1072 (error "can't represent result of left shift"))
1073 (if (zerop n-bits)
1074 (bignum-ashift-left-digits bignum bignum-len digits)
1075 (bignum-ashift-left-unaligned bignum digits n-bits res-len))))
1076 ;; Left shift by a number too big to be represented as a fixnum
1077 ;; would exceed our memory capacity, since a fixnum is big enough
1078 ;; to index any array, including a bit array.
1079 (error "can't represent result of left shift")))
1081 (defun bignum-ashift-left-digits (bignum bignum-len digits)
1082 (declare (type bignum-length bignum-len digits))
1083 (let* ((res-len (+ bignum-len digits))
1084 (res (%allocate-bignum res-len)))
1085 (declare (type bignum-length res-len))
1086 (bignum-replace res bignum :start1 digits :end1 res-len :end2 bignum-len
1087 :from-end t)
1088 res))
1090 ;;; BIGNUM-TRUNCATE uses this to store into a bignum buffer by supplying res.
1091 ;;; When res comes in non-nil, then this foregoes allocating a result, and it
1092 ;;; normalizes the buffer instead of the would-be allocated result.
1094 ;;; We start storing into one digit higher than digits, storing a whole result
1095 ;;; digit from parts of two contiguous digits from bignum. When the loop
1096 ;;; finishes, we store the remaining bits from bignum's first digit in the
1097 ;;; first non-zero result digit, digits. We also grab some left over high
1098 ;;; bits from the last digit of bignum.
1099 (defun bignum-ashift-left-unaligned (bignum digits n-bits res-len
1100 &optional (res nil resp))
1101 (declare (type bignum-length digits res-len)
1102 (type (mod #.digit-size) n-bits))
1103 (let* ((remaining-bits (- digit-size n-bits))
1104 (res-len-1 (1- res-len))
1105 (res (or res (%allocate-bignum res-len))))
1106 (declare (type bignum-length res-len res-len-1))
1107 (do ((i 0 (1+ i))
1108 (j (1+ digits) (1+ j)))
1109 ((= j res-len-1)
1110 (setf (%bignum-ref res digits)
1111 (%ashl (%bignum-ref bignum 0) n-bits))
1112 (setf (%bignum-ref res j)
1113 (%ashr (%bignum-ref bignum i) remaining-bits))
1114 (if resp
1115 (%normalize-bignum-buffer res res-len)
1116 (%normalize-bignum res res-len)))
1117 (declare (type bignum-index i j))
1118 (setf (%bignum-ref res j)
1119 (%logior (%digit-logical-shift-right (%bignum-ref bignum i)
1120 remaining-bits)
1121 (%ashl (%bignum-ref bignum (1+ i)) n-bits))))))
1123 ;;; FIXNUM is assumed to be non-zero and the result of the shift should be a bignum
1124 (defun bignum-ashift-left-fixnum (fixnum count)
1125 (declare (bignum-length count)
1126 (fixnum fixnum))
1127 (multiple-value-bind (right-zero-digits remaining)
1128 (truncate count digit-size)
1129 (let* ((right-half (ldb (byte digit-size 0)
1130 (ash fixnum remaining)))
1131 (sign-bit-p
1132 (logbitp (1- digit-size) right-half))
1133 (left-half (ash fixnum
1134 (- remaining digit-size)))
1135 ;; Even if the left-half is 0 or -1 it might need to be sign
1136 ;; extended based on the left-most bit of the right-half
1137 (left-half-p (if sign-bit-p
1138 (/= left-half -1)
1139 (/= left-half 0)))
1140 (length (+ right-zero-digits
1141 (if left-half-p 2 1)))
1142 (result (%allocate-bignum length)))
1143 (setf (%bignum-ref result right-zero-digits) right-half)
1144 (when left-half-p
1145 (setf (%bignum-ref result (1+ right-zero-digits))
1146 (ldb (byte digit-size 0) left-half)))
1147 result)))
1149 ;;;; relational operators
1151 ;;; This compares two bignums returning -1, 0, or 1, depending on
1152 ;;; whether a is less than, equal to, or greater than b.
1153 (declaim (ftype (function (bignum bignum) (integer -1 1)) bignum-compare))
1154 (defun bignum-compare (a b)
1155 (declare (type bignum a b))
1156 (let* ((len-a (%bignum-length a))
1157 (len-b (%bignum-length b))
1158 (a-plusp (%bignum-0-or-plusp a len-a))
1159 (b-plusp (%bignum-0-or-plusp b len-b)))
1160 (declare (type bignum-length len-a len-b))
1161 (cond ((not (eq a-plusp b-plusp))
1162 (if a-plusp 1 -1))
1163 ((= len-a len-b)
1164 (do ((i (1- len-a) (1- i)))
1165 (())
1166 (declare (type bignum-index i))
1167 (let ((a-digit (%bignum-ref a i))
1168 (b-digit (%bignum-ref b i)))
1169 (declare (type bignum-element-type a-digit b-digit))
1170 (when (> a-digit b-digit)
1171 (return 1))
1172 (when (> b-digit a-digit)
1173 (return -1)))
1174 (when (zerop i) (return 0))))
1175 ((> len-a len-b)
1176 (if a-plusp 1 -1))
1177 (t (if a-plusp -1 1)))))
1179 ;;;; float conversion
1181 ;;; Make a single or double float with the specified significand,
1182 ;;; exponent and sign.
1183 (defun single-float-from-bits (bits exp plusp)
1184 (declare (fixnum exp))
1185 (declare (optimize #-sb-xc-host (inhibit-warnings 3)))
1186 (let ((res (dpb exp
1187 sb!vm:single-float-exponent-byte
1188 (logandc2 (logand #xffffffff
1189 (%bignum-ref bits 1))
1190 sb!vm:single-float-hidden-bit))))
1191 (make-single-float
1192 (if plusp
1194 (logior res (ash -1 sb!vm:float-sign-shift))))))
1195 (defun double-float-from-bits (bits exp plusp)
1196 (declare (fixnum exp))
1197 (declare (optimize #-sb-xc-host (inhibit-warnings 3)))
1198 (let ((hi (dpb exp
1199 sb!vm:double-float-exponent-byte
1200 (logandc2 (ecase sb!vm::n-word-bits
1201 (32 (%bignum-ref bits 2))
1202 (64 (ash (%bignum-ref bits 1) -32)))
1203 sb!vm:double-float-hidden-bit)))
1204 (lo (logand #xffffffff (%bignum-ref bits 1))))
1205 (make-double-float (if plusp
1207 (logior hi (ash -1 sb!vm:float-sign-shift)))
1208 lo)))
1209 #!+(and long-float x86)
1210 (defun long-float-from-bits (bits exp plusp)
1211 (declare (fixnum exp))
1212 (declare (optimize #-sb-xc-host (inhibit-warnings 3)))
1213 (make-long-float
1214 (if plusp
1216 (logior exp (ash 1 15)))
1217 (%bignum-ref bits 2)
1218 (%bignum-ref bits 1)))
1220 ;;; Convert Bignum to a float in the specified Format, rounding to the best
1221 ;;; approximation.
1222 (defun bignum-to-float (bignum format)
1223 (let* ((plusp (bignum-plus-p bignum))
1224 (x (if plusp bignum (negate-bignum bignum)))
1225 (len (bignum-integer-length x))
1226 (digits (float-format-digits format))
1227 (keep (+ digits digit-size))
1228 (shift (- keep len))
1229 (shifted (if (minusp shift)
1230 (bignum-ashift-right x (- shift))
1231 (bignum-ashift-left x shift)))
1232 (low (%bignum-ref shifted 0))
1233 (round-bit (ash 1 (1- digit-size))))
1234 (declare (type bignum-length len digits keep) (fixnum shift))
1235 (labels ((round-up ()
1236 (let ((rounded (add-bignums shifted round-bit)))
1237 (if (> (integer-length rounded) keep)
1238 (float-from-bits (bignum-ashift-right rounded 1)
1239 (1+ len))
1240 (float-from-bits rounded len))))
1241 (float-from-bits (bits len)
1242 (declare (type bignum-length len))
1243 (ecase format
1244 (single-float
1245 (single-float-from-bits
1246 bits
1247 (check-exponent len sb!vm:single-float-bias
1248 sb!vm:single-float-normal-exponent-max)
1249 plusp))
1250 (double-float
1251 (double-float-from-bits
1252 bits
1253 (check-exponent len sb!vm:double-float-bias
1254 sb!vm:double-float-normal-exponent-max)
1255 plusp))
1256 #!+long-float
1257 (long-float
1258 (long-float-from-bits
1259 bits
1260 (check-exponent len sb!vm:long-float-bias
1261 sb!vm:long-float-normal-exponent-max)
1262 plusp))))
1263 (check-exponent (exp bias max)
1264 (declare (type bignum-length len))
1265 (let ((exp (+ exp bias)))
1266 (when (> exp max)
1267 ;; Why a SIMPLE-TYPE-ERROR? Well, this is mainly
1268 ;; called by COERCE, which requires an error of
1269 ;; TYPE-ERROR if the conversion can't happen
1270 ;; (except in certain circumstances when we are
1271 ;; coercing to a FUNCTION) -- CSR, 2002-09-18
1272 (error 'simple-type-error
1273 :format-control "Too large to be represented as a ~S:~% ~S"
1274 :format-arguments (list format x)
1275 :expected-type format
1276 :datum x))
1277 exp)))
1279 (cond
1280 ;; Round down if round bit is 0.
1281 ((not (logtest round-bit low))
1282 (float-from-bits shifted len))
1283 ;; If only round bit is set, then round to even.
1284 ((and (= low round-bit)
1285 (dotimes (i (- (%bignum-length x) (ceiling keep digit-size))
1287 (unless (zerop (%bignum-ref x i)) (return nil))))
1288 (let ((next (%bignum-ref shifted 1)))
1289 (if (oddp next)
1290 (round-up)
1291 (float-from-bits shifted len))))
1292 ;; Otherwise, round up.
1294 (round-up))))))
1296 ;;;; integer length and logbitp/logcount
1298 (defun bignum-buffer-integer-length (bignum len)
1299 (declare (type bignum bignum))
1300 (let* ((len-1 (1- len))
1301 (digit (%bignum-ref bignum len-1)))
1302 (declare (type bignum-length len len-1)
1303 (type bignum-element-type digit))
1304 (+ (integer-length (%fixnum-digit-with-correct-sign digit))
1305 (* len-1 digit-size))))
1307 (defun bignum-integer-length (bignum)
1308 (declare (type bignum bignum))
1309 (bignum-buffer-integer-length bignum (%bignum-length bignum)))
1311 (defun bignum-logbitp (index bignum)
1312 (declare (type bignum bignum)
1313 (type bignum-index index))
1314 (let ((len (%bignum-length bignum)))
1315 (declare (type bignum-length len))
1316 (multiple-value-bind (word-index bit-index)
1317 (floor index digit-size)
1318 (if (>= word-index len)
1319 (not (bignum-plus-p bignum))
1320 (logbitp bit-index (%bignum-ref bignum word-index))))))
1322 (defun bignum-logcount (bignum)
1323 (declare (type bignum bignum)
1324 (optimize speed))
1325 (declare (muffle-conditions compiler-note)) ; returns lispobj, so what.
1326 (let ((length (%bignum-length bignum))
1327 (result 0))
1328 (declare (type bignum-length length)
1329 (fixnum result))
1330 (do ((index 0 (1+ index)))
1331 ((= index length)
1332 (if (%bignum-0-or-plusp bignum length)
1333 result
1334 (- (* length digit-size) result)))
1335 (let ((digit (%bignum-ref bignum index)))
1336 (declare (type bignum-element-type digit))
1337 (incf result (logcount digit))))))
1339 ;;;; logical operations
1341 ;;;; NOT
1343 (defun bignum-logical-not (a)
1344 (declare (type bignum a))
1345 (let* ((len (%bignum-length a))
1346 (res (%allocate-bignum len)))
1347 (declare (type bignum-length len))
1348 (dotimes (i len res)
1349 (declare (type bignum-index i))
1350 (setf (%bignum-ref res i) (%lognot (%bignum-ref a i))))))
1352 ;;;; AND
1354 (defun bignum-logical-and (a b)
1355 (declare (type bignum a b))
1356 (let* ((len-a (%bignum-length a))
1357 (len-b (%bignum-length b))
1358 (a-plusp (%bignum-0-or-plusp a len-a))
1359 (b-plusp (%bignum-0-or-plusp b len-b)))
1360 (declare (type bignum-length len-a len-b))
1361 (cond
1362 ((< len-a len-b)
1363 (if a-plusp
1364 (logand-shorter-positive a len-a b (%allocate-bignum len-a))
1365 (logand-shorter-negative a len-a b len-b (%allocate-bignum len-b))))
1366 ((< len-b len-a)
1367 (if b-plusp
1368 (logand-shorter-positive b len-b a (%allocate-bignum len-b))
1369 (logand-shorter-negative b len-b a len-a (%allocate-bignum len-a))))
1370 (t (logand-shorter-positive a len-a b (%allocate-bignum len-a))))))
1372 ;;; This takes a shorter bignum, a and len-a, that is positive. Because this
1373 ;;; is AND, we don't care about any bits longer than a's since its infinite 0
1374 ;;; sign bits will mask the other bits out of b. The result is len-a big.
1375 (defun logand-shorter-positive (a len-a b res)
1376 (declare (type bignum a b res)
1377 (type bignum-length len-a))
1378 (dotimes (i len-a)
1379 (declare (type bignum-index i))
1380 (setf (%bignum-ref res i)
1381 (%logand (%bignum-ref a i) (%bignum-ref b i))))
1382 (%normalize-bignum res len-a))
1384 ;;; This takes a shorter bignum, a and len-a, that is negative. Because this
1385 ;;; is AND, we just copy any bits longer than a's since its infinite 1 sign
1386 ;;; bits will include any bits from b. The result is len-b big.
1387 (defun logand-shorter-negative (a len-a b len-b res)
1388 (declare (type bignum a b res)
1389 (type bignum-length len-a len-b))
1390 (dotimes (i len-a)
1391 (declare (type bignum-index i))
1392 (setf (%bignum-ref res i)
1393 (%logand (%bignum-ref a i) (%bignum-ref b i))))
1394 (do ((i len-a (1+ i)))
1395 ((= i len-b))
1396 (declare (type bignum-index i))
1397 (setf (%bignum-ref res i) (%bignum-ref b i)))
1398 (%normalize-bignum res len-b))
1400 ;;;; IOR
1402 (defun bignum-logical-ior (a b)
1403 (declare (type bignum a b))
1404 (let* ((len-a (%bignum-length a))
1405 (len-b (%bignum-length b))
1406 (a-plusp (%bignum-0-or-plusp a len-a))
1407 (b-plusp (%bignum-0-or-plusp b len-b)))
1408 (declare (type bignum-length len-a len-b))
1409 (cond
1410 ((< len-a len-b)
1411 (if a-plusp
1412 (logior-shorter-positive a len-a b len-b (%allocate-bignum len-b))
1413 (logior-shorter-negative a len-a b len-b (%allocate-bignum len-b))))
1414 ((< len-b len-a)
1415 (if b-plusp
1416 (logior-shorter-positive b len-b a len-a (%allocate-bignum len-a))
1417 (logior-shorter-negative b len-b a len-a (%allocate-bignum len-a))))
1418 (t (logior-shorter-positive a len-a b len-b (%allocate-bignum len-a))))))
1420 ;;; This takes a shorter bignum, a and len-a, that is positive. Because this
1421 ;;; is IOR, we don't care about any bits longer than a's since its infinite
1422 ;;; 0 sign bits will mask the other bits out of b out to len-b. The result
1423 ;;; is len-b long.
1424 (defun logior-shorter-positive (a len-a b len-b res)
1425 (declare (type bignum a b res)
1426 (type bignum-length len-a len-b))
1427 (dotimes (i len-a)
1428 (declare (type bignum-index i))
1429 (setf (%bignum-ref res i)
1430 (%logior (%bignum-ref a i) (%bignum-ref b i))))
1431 (do ((i len-a (1+ i)))
1432 ((= i len-b))
1433 (declare (type bignum-index i))
1434 (setf (%bignum-ref res i) (%bignum-ref b i)))
1435 (%normalize-bignum res len-b))
1437 ;;; This takes a shorter bignum, a and len-a, that is negative. Because this
1438 ;;; is IOR, we just copy any bits longer than a's since its infinite 1 sign
1439 ;;; bits will include any bits from b. The result is len-b long.
1440 (defun logior-shorter-negative (a len-a b len-b res)
1441 (declare (type bignum a b res)
1442 (type bignum-length len-a len-b))
1443 (dotimes (i len-a)
1444 (declare (type bignum-index i))
1445 (setf (%bignum-ref res i)
1446 (%logior (%bignum-ref a i) (%bignum-ref b i))))
1447 (do ((i len-a (1+ i))
1448 (sign (%sign-digit a len-a)))
1449 ((= i len-b))
1450 (declare (type bignum-index i))
1451 (setf (%bignum-ref res i) sign))
1452 (%normalize-bignum res len-b))
1454 ;;;; XOR
1456 (defun bignum-logical-xor (a b)
1457 (declare (type bignum a b))
1458 (let ((len-a (%bignum-length a))
1459 (len-b (%bignum-length b)))
1460 (declare (type bignum-length len-a len-b))
1461 (if (< len-a len-b)
1462 (bignum-logical-xor-aux a len-a b len-b (%allocate-bignum len-b))
1463 (bignum-logical-xor-aux b len-b a len-a (%allocate-bignum len-a)))))
1465 ;;; This takes the shorter of two bignums in a and len-a. Res is len-b
1466 ;;; long. Do the XOR.
1467 (defun bignum-logical-xor-aux (a len-a b len-b res)
1468 (declare (type bignum a b res)
1469 (type bignum-length len-a len-b))
1470 (dotimes (i len-a)
1471 (declare (type bignum-index i))
1472 (setf (%bignum-ref res i)
1473 (%logxor (%bignum-ref a i) (%bignum-ref b i))))
1474 (do ((i len-a (1+ i))
1475 (sign (%sign-digit a len-a)))
1476 ((= i len-b))
1477 (declare (type bignum-index i))
1478 (setf (%bignum-ref res i) (%logxor sign (%bignum-ref b i))))
1479 (%normalize-bignum res len-b))
1481 ;;;; There used to be a bunch of code to implement "efficient" versions of LDB
1482 ;;;; and DPB here. But it apparently was never used, so it's been deleted.
1483 ;;;; --njf, 2007-02-04
1485 ;; This could be used by way of a transform, though for now it's specifically
1486 ;; a helper for %LDB in the limited case that it recognizes as non-consing.
1487 (defun ldb-bignum=>fixnum (byte-size byte-pos bignum)
1488 (declare (type (integer 0 #.sb!vm:n-positive-fixnum-bits) byte-size)
1489 (type bit-index byte-pos))
1490 (multiple-value-bind (word-index bit-index) (floor byte-pos digit-size)
1491 (let ((n-digits (%bignum-length bignum)))
1492 (cond ((>= word-index n-digits) ; load from the infinitely extended sign word
1493 (ldb (byte byte-size 0) (%sign-digit bignum n-digits)))
1494 ((<= (+ bit-index byte-size) digit-size) ; contained in one word
1495 ;; This case takes care of byte-size = 0 also.
1496 (ldb (byte byte-size bit-index) (%bignum-ref bignum word-index)))
1498 ;; At least one bit is obtained from each of two words,
1499 ;; and not more than two words.
1500 (let* ((low-part-size
1501 (truly-the (integer 1 #.(1- sb!vm:n-positive-fixnum-bits))
1502 (- digit-size bit-index)))
1503 (high-part-size
1504 (truly-the (integer 1 #.(1- sb!vm:n-positive-fixnum-bits))
1505 (- byte-size low-part-size))))
1506 (logior (truly-the (and fixnum unsigned-byte) ; high part
1507 (let ((word-index (1+ word-index)))
1508 (if (< word-index n-digits) ; next word exists
1509 (ash (ldb (byte high-part-size 0)
1510 (%bignum-ref bignum word-index))
1511 low-part-size)
1512 (mask-field (byte high-part-size low-part-size)
1513 (%sign-digit bignum n-digits)))))
1514 (ldb (byte low-part-size bit-index) ; low part
1515 (%bignum-ref bignum word-index)))))))))
1517 ;;;; TRUNCATE
1519 ;;; This is the original sketch of the algorithm from which I implemented this
1520 ;;; TRUNCATE, assuming both operands are bignums. I should modify this to work
1521 ;;; with the documentation on my functions, as a general introduction. I've
1522 ;;; left this here just in case someone needs it in the future. Don't look at
1523 ;;; this unless reading the functions' comments leaves you at a loss. Remember
1524 ;;; this comes from Knuth, so the book might give you the right general
1525 ;;; overview.
1527 ;;; (truncate x y):
1529 ;;; If X's magnitude is less than Y's, then result is 0 with remainder X.
1531 ;;; Make x and y positive, copying x if it is already positive.
1533 ;;; Shift y left until there's a 1 in the 30'th bit (most significant, non-sign
1534 ;;; digit)
1535 ;;; Just do most sig digit to determine how much to shift whole number.
1536 ;;; Shift x this much too.
1537 ;;; Remember this initial shift count.
1539 ;;; Allocate q to be len-x minus len-y quantity plus 1.
1541 ;;; i = last digit of x.
1542 ;;; k = last digit of q.
1544 ;;; LOOP
1546 ;;; j = last digit of y.
1548 ;;; compute guess.
1549 ;;; if x[i] = y[j] then g = (1- (ash 1 digit-size))
1550 ;;; else g = x[i]x[i-1]/y[j].
1552 ;;; check guess.
1553 ;;; %UNSIGNED-MULTIPLY returns b and c defined below.
1554 ;;; a = x[i-1] - (logand (* g y[j]) #xFFFFFFFF).
1555 ;;; Use %UNSIGNED-MULTIPLY taking low-order result.
1556 ;;; b = (logand (ash (* g y[j-1]) (- digit-size)) (1- (ash 1 digit-size))).
1557 ;;; c = (logand (* g y[j-1]) (1- (ash 1 digit-size))).
1558 ;;; if a < b, okay.
1559 ;;; if a > b, guess is too high
1560 ;;; g = g - 1; go back to "check guess".
1561 ;;; if a = b and c > x[i-2], guess is too high
1562 ;;; g = g - 1; go back to "check guess".
1563 ;;; GUESS IS 32-BIT NUMBER, SO USE THING TO KEEP IN SPECIAL REGISTER
1564 ;;; SAME FOR A, B, AND C.
1566 ;;; Subtract g * y from x[i - len-y+1]..x[i]. See paper for doing this in step.
1567 ;;; If x[i] < 0, guess is screwed up.
1568 ;;; negative g, then add 1
1569 ;;; zero or positive g, then subtract 1
1570 ;;; AND add y back into x[len-y+1..i].
1572 ;;; q[k] = g.
1573 ;;; i = i - 1.
1574 ;;; k = k - 1.
1576 ;;; If k>=0, goto LOOP.
1578 ;;; Now quotient is good, but remainder is not.
1579 ;;; Shift x right by saved initial left shifting count.
1581 ;;; Check quotient and remainder signs.
1582 ;;; x pos y pos --> q pos r pos
1583 ;;; x pos y neg --> q neg r pos
1584 ;;; x neg y pos --> q neg r neg
1585 ;;; x neg y neg --> q pos r neg
1587 ;;; Normalize quotient and remainder. Cons result if necessary.
1590 ;;; This used to be split into multiple functions, which shared state
1591 ;;; in special variables *TRUNCATE-X* and *TRUNCATE-Y*. Having so many
1592 ;;; special variable accesses in tight inner loops was having a large
1593 ;;; effect on performance, so the helper functions have now been
1594 ;;; refactored into local functions and the special variables into
1595 ;;; lexicals. There was also a lot of boxing and unboxing of
1596 ;;; (UNSIGNED-BYTE 32)'s going on, which this refactoring
1597 ;;; eliminated. This improves the performance on some CL-BENCH tests
1598 ;;; by up to 50%, which is probably signigicant enough to justify the
1599 ;;; reduction in readability that was introduced. --JES, 2004-08-07
1600 (defun bignum-truncate (x y)
1601 (declare (type bignum x y))
1602 (declare (muffle-conditions compiler-note)) ; returns lispobj, so what.
1603 (let (truncate-x truncate-y)
1604 (labels
1605 ;;; Divide X by Y when Y is a single bignum digit. BIGNUM-TRUNCATE
1606 ;;; fixes up the quotient and remainder with respect to sign and
1607 ;;; normalization.
1609 ;;; We don't have to worry about shifting Y to make its most
1610 ;;; significant digit sufficiently large for %BIGFLOOR to return
1611 ;;; digit-size quantities for the q-digit and r-digit. If Y is
1612 ;;; a single digit bignum, it is already large enough for
1613 ;;; %BIGFLOOR. That is, it has some bits on pretty high in the
1614 ;;; digit.
1615 ((bignum-truncate-single-digit (x len-x y)
1616 (declare (type bignum-length len-x))
1617 (let ((y (%bignum-ref y 0)))
1618 (declare (type bignum-element-type y))
1619 (if (not (logtest y (1- y)))
1620 ;; Y is a power of two.
1621 ;; SHIFT-RIGHT-UNALIGNED won't do the right thing
1622 ;; with a shift count of 0 or -1, so special case this.
1623 (cond ((= y 0)
1624 (error 'division-by-zero :operation 'truncate
1625 :operands (list x y)))
1626 ((= y 1)
1627 ;; We could probably get away with (VALUES X 0)
1628 ;; here, but it's not clear that some of the
1629 ;; normalization logic further down would avoid
1630 ;; mutilating X. Just go ahead and cons, consing's
1631 ;; cheap.
1632 (values (copy-bignum x len-x) 0))
1634 (let ((n-bits (1- (integer-length y))))
1635 (values
1636 (shift-right-unaligned x 0 n-bits len-x
1637 ((= j res-len-1)
1638 (setf (%bignum-ref res j)
1639 (%ashr (%bignum-ref x i) n-bits))
1640 res)
1641 res)
1642 (logand (%bignum-ref x 0) (1- y))))))
1643 (do ((i (1- len-x) (1- i))
1644 (q (%allocate-bignum len-x))
1645 (r 0))
1646 ((minusp i)
1647 (let ((rem (%allocate-bignum 1)))
1648 (setf (%bignum-ref rem 0) r)
1649 (values q rem)))
1650 (declare (type bignum-element-type r))
1651 (multiple-value-bind (q-digit r-digit)
1652 (%bigfloor r (%bignum-ref x i) y)
1653 (declare (type bignum-element-type q-digit r-digit))
1654 (setf (%bignum-ref q i) q-digit)
1655 (setf r r-digit))))))
1656 ;;; This returns a guess for the next division step. Y1 is the
1657 ;;; highest y digit, and y2 is the second to highest y
1658 ;;; digit. The x... variables are the three highest x digits
1659 ;;; for the next division step.
1661 ;;; From Knuth, our guess is either all ones or x-i and x-i-1
1662 ;;; divided by y1, depending on whether x-i and y1 are the
1663 ;;; same. We test this guess by determining whether guess*y2
1664 ;;; is greater than the three high digits of x minus guess*y1
1665 ;;; shifted left one digit:
1666 ;;; ------------------------------
1667 ;;; | x-i | x-i-1 | x-i-2 |
1668 ;;; ------------------------------
1669 ;;; ------------------------------
1670 ;;; - | g*y1 high | g*y1 low | 0 |
1671 ;;; ------------------------------
1672 ;;; ... < guess*y2 ???
1673 ;;; If guess*y2 is greater, then we decrement our guess by one
1674 ;;; and try again. This returns a guess that is either
1675 ;;; correct or one too large.
1676 (bignum-truncate-guess (y1 y2 x-i x-i-1 x-i-2)
1677 (declare (type bignum-element-type y1 y2 x-i x-i-1 x-i-2))
1678 (let ((guess (if (= x-i y1)
1679 all-ones-digit
1680 (%bigfloor x-i x-i-1 y1))))
1681 (declare (type bignum-element-type guess))
1682 (loop
1683 (multiple-value-bind (high-guess*y1 low-guess*y1)
1684 (%multiply guess y1)
1685 (declare (type bignum-element-type low-guess*y1
1686 high-guess*y1))
1687 (multiple-value-bind (high-guess*y2 low-guess*y2)
1688 (%multiply guess y2)
1689 (declare (type bignum-element-type high-guess*y2
1690 low-guess*y2))
1691 (multiple-value-bind (middle-digit borrow)
1692 (%subtract-with-borrow x-i-1 low-guess*y1 1)
1693 (declare (type bignum-element-type middle-digit)
1694 (fixnum borrow))
1695 ;; Supplying borrow of 1 means there was no
1696 ;; borrow, and we know x-i-2 minus 0 requires
1697 ;; no borrow.
1698 (let ((high-digit (%subtract-with-borrow x-i
1699 high-guess*y1
1700 borrow)))
1701 (declare (type bignum-element-type high-digit))
1702 (if (and (= high-digit 0)
1703 (or (> high-guess*y2 middle-digit)
1704 (and (= middle-digit high-guess*y2)
1705 (> low-guess*y2 x-i-2))))
1706 (setf guess (%subtract-with-borrow guess 1 1))
1707 (return guess)))))))))
1708 ;;; Divide TRUNCATE-X by TRUNCATE-Y, returning the quotient
1709 ;;; and destructively modifying TRUNCATE-X so that it holds
1710 ;;; the remainder.
1712 ;;; LEN-X and LEN-Y tell us how much of the buffers we care about.
1714 ;;; TRUNCATE-X definitely has at least three digits, and it has one
1715 ;;; more than TRUNCATE-Y. This keeps i, i-1, i-2, and low-x-digit
1716 ;;; happy. Thanks to SHIFT-AND-STORE-TRUNCATE-BUFFERS.
1717 (return-quotient-leaving-remainder (len-x len-y)
1718 (declare (type bignum-length len-x len-y))
1719 (let* ((len-q (- len-x len-y))
1720 ;; Add one for extra sign digit in case high bit is on.
1721 (q (%allocate-bignum (1+ len-q)))
1722 (k (1- len-q))
1723 (y1 (%bignum-ref truncate-y (1- len-y)))
1724 (y2 (%bignum-ref truncate-y (- len-y 2)))
1725 (i (1- len-x))
1726 (i-1 (1- i))
1727 (i-2 (1- i-1))
1728 (low-x-digit (- i len-y)))
1729 (declare (type bignum-length len-q)
1730 (type bignum-index k i i-1 i-2 low-x-digit)
1731 (type bignum-element-type y1 y2))
1732 (loop
1733 (setf (%bignum-ref q k)
1734 (try-bignum-truncate-guess
1735 ;; This modifies TRUNCATE-X. Must access
1736 ;; elements each pass.
1737 (bignum-truncate-guess y1 y2
1738 (%bignum-ref truncate-x i)
1739 (%bignum-ref truncate-x i-1)
1740 (%bignum-ref truncate-x i-2))
1741 len-y low-x-digit))
1742 (cond ((zerop k) (return))
1743 (t (decf k)
1744 (decf low-x-digit)
1745 (shiftf i i-1 i-2 (1- i-2)))))
1747 ;;; This takes a digit guess, multiplies it by TRUNCATE-Y for a
1748 ;;; result one greater in length than LEN-Y, and subtracts this result
1749 ;;; from TRUNCATE-X. LOW-X-DIGIT is the first digit of X to start
1750 ;;; the subtraction, and we know X is long enough to subtract a LEN-Y
1751 ;;; plus one length bignum from it. Next we check the result of the
1752 ;;; subtraction, and if the high digit in X became negative, then our
1753 ;;; guess was one too big. In this case, return one less than GUESS
1754 ;;; passed in, and add one value of Y back into X to account for
1755 ;;; subtracting one too many. Knuth shows that the guess is wrong on
1756 ;;; the order of 3/b, where b is the base (2 to the digit-size power)
1757 ;;; -- pretty rarely.
1758 (try-bignum-truncate-guess (guess len-y low-x-digit)
1759 (declare (type bignum-index low-x-digit)
1760 (type bignum-length len-y)
1761 (type bignum-element-type guess))
1762 (let ((carry-digit 0)
1763 (borrow 1)
1764 (i low-x-digit))
1765 (declare (type bignum-element-type carry-digit)
1766 (type bignum-index i)
1767 (fixnum borrow))
1768 ;; Multiply guess and divisor, subtracting from dividend
1769 ;; simultaneously.
1770 (dotimes (j len-y)
1771 (multiple-value-bind (high-digit low-digit)
1772 (%multiply-and-add guess
1773 (%bignum-ref truncate-y j)
1774 carry-digit)
1775 (declare (type bignum-element-type high-digit low-digit))
1776 (setf carry-digit high-digit)
1777 (multiple-value-bind (x temp-borrow)
1778 (%subtract-with-borrow (%bignum-ref truncate-x i)
1779 low-digit
1780 borrow)
1781 (declare (type bignum-element-type x)
1782 (fixnum temp-borrow))
1783 (setf (%bignum-ref truncate-x i) x)
1784 (setf borrow temp-borrow)))
1785 (incf i))
1786 (setf (%bignum-ref truncate-x i)
1787 (%subtract-with-borrow (%bignum-ref truncate-x i)
1788 carry-digit borrow))
1789 ;; See whether guess is off by one, adding one
1790 ;; Y back in if necessary.
1791 (cond ((%digit-0-or-plusp (%bignum-ref truncate-x i))
1792 guess)
1794 ;; If subtraction has negative result, add one
1795 ;; divisor value back in. The guess was one too
1796 ;; large in magnitude.
1797 (let ((i low-x-digit)
1798 (carry 0))
1799 (dotimes (j len-y)
1800 (multiple-value-bind (v k)
1801 (%add-with-carry (%bignum-ref truncate-y j)
1802 (%bignum-ref truncate-x i)
1803 carry)
1804 (declare (type bignum-element-type v))
1805 (setf (%bignum-ref truncate-x i) v)
1806 (setf carry k))
1807 (incf i))
1808 (setf (%bignum-ref truncate-x i)
1809 (%add-with-carry (%bignum-ref truncate-x i)
1810 0 carry)))
1811 (%subtract-with-borrow guess 1 1)))))
1812 ;;; This returns the amount to shift y to place a one in the
1813 ;;; second highest bit. Y must be positive. If the last digit
1814 ;;; of y is zero, then y has a one in the previous digit's
1815 ;;; sign bit, so we know it will take one less than digit-size
1816 ;;; to get a one where we want. Otherwise, we count how many
1817 ;;; right shifts it takes to get zero; subtracting this value
1818 ;;; from digit-size tells us how many high zeros there are
1819 ;;; which is one more than the shift amount sought.
1821 ;;; Note: This is exactly the same as one less than the
1822 ;;; integer-length of the last digit subtracted from the
1823 ;;; digit-size.
1825 ;;; We shift y to make it sufficiently large that doing the
1826 ;;; 2*digit-size by digit-size %BIGFLOOR calls ensures the quotient and
1827 ;;; remainder fit in digit-size.
1828 (shift-y-for-truncate (y)
1829 (let* ((len (%bignum-length y))
1830 (last (%bignum-ref y (1- len))))
1831 (declare (type bignum-length len)
1832 (type bignum-element-type last))
1833 (- digit-size (integer-length last) 1)))
1834 ;;; Stores two bignums into the truncation bignum buffers,
1835 ;;; shifting them on the way in. This assumes x and y are
1836 ;;; positive and at least two in length, and it assumes
1837 ;;; truncate-x and truncate-y are one digit longer than x and
1838 ;;; y.
1839 (shift-and-store-truncate-buffers (x len-x y len-y shift)
1840 (declare (type bignum-length len-x len-y)
1841 (type (integer 0 (#.digit-size)) shift))
1842 (cond ((zerop shift)
1843 (bignum-replace truncate-x x :end1 len-x)
1844 (bignum-replace truncate-y y :end1 len-y))
1846 (bignum-ashift-left-unaligned x 0 shift (1+ len-x)
1847 truncate-x)
1848 (bignum-ashift-left-unaligned y 0 shift (1+ len-y)
1849 truncate-y))))) ;; LABELS
1850 ;;; Divide X by Y returning the quotient and remainder. In the
1851 ;;; general case, we shift Y to set up for the algorithm, and we
1852 ;;; use two buffers to save consing intermediate values. X gets
1853 ;;; destructively modified to become the remainder, and we have
1854 ;;; to shift it to account for the initial Y shift. After we
1855 ;;; multiple bind q and r, we first fix up the signs and then
1856 ;;; return the normalized results.
1857 (let* ((x-plusp (bignum-plus-p x))
1858 (y-plusp (bignum-plus-p y))
1859 (x (if x-plusp x (negate-bignum x nil)))
1860 (y (if y-plusp y (negate-bignum y nil)))
1861 (len-x (%bignum-length x))
1862 (len-y (%bignum-length y)))
1863 (multiple-value-bind (q r)
1864 (cond ((< len-y 2)
1865 (bignum-truncate-single-digit x len-x y))
1866 ((plusp (bignum-compare y x))
1867 (let ((res (%allocate-bignum len-x)))
1868 (dotimes (i len-x)
1869 (setf (%bignum-ref res i) (%bignum-ref x i)))
1870 (values 0 res)))
1872 (let ((len-x+1 (1+ len-x)))
1873 (setf truncate-x (%allocate-bignum len-x+1))
1874 (setf truncate-y (%allocate-bignum (1+ len-y)))
1875 (let ((y-shift (shift-y-for-truncate y)))
1876 (shift-and-store-truncate-buffers x len-x y
1877 len-y y-shift)
1878 (values (return-quotient-leaving-remainder len-x+1
1879 len-y)
1880 ;; Now that RETURN-QUOTIENT-LEAVING-REMAINDER
1881 ;; has executed, we just tidy up the remainder
1882 ;; (in TRUNCATE-X) and return it.
1883 (cond
1884 ((zerop y-shift)
1885 (let ((res (%allocate-bignum len-y)))
1886 (declare (type bignum res))
1887 (bignum-replace res truncate-x :end2 len-y)
1888 (%normalize-bignum res len-y)))
1890 (shift-right-unaligned
1891 truncate-x 0 y-shift len-y
1892 ((= j res-len-1)
1893 (setf (%bignum-ref res j)
1894 (%ashr (%bignum-ref truncate-x i)
1895 y-shift))
1896 (%normalize-bignum res res-len))
1897 res))))))))
1898 (let ((quotient (cond ((eq x-plusp y-plusp) q)
1899 ((typep q 'fixnum) (the fixnum (- q)))
1900 (t (negate-bignum-in-place q))))
1901 (rem (cond (x-plusp r)
1902 ((typep r 'fixnum) (the fixnum (- r)))
1903 (t (negate-bignum-in-place r)))))
1904 (values (if (typep quotient 'fixnum)
1905 quotient
1906 (%normalize-bignum quotient (%bignum-length quotient)))
1907 (if (typep rem 'fixnum)
1909 (%normalize-bignum rem (%bignum-length rem))))))))))
1912 ;;;; There used to be a pile of code for implementing division for bignum digits
1913 ;;;; for machines that don't have a 2*digit-size by digit-size divide instruction.
1914 ;;;; This happens to be most machines, but all the SBCL ports seem to be content
1915 ;;;; to implement SB-BIGNUM:%BIGFLOOR as a VOP rather than using the code here.
1916 ;;;; So it's been deleted. --njf, 2007-02-04
1918 ;;;; general utilities
1920 ;;; Internal in-place operations use this to fixup remaining digits in the
1921 ;;; incoming data, such as in-place shifting. This is basically the same as
1922 ;;; the first form in %NORMALIZE-BIGNUM, but we return the length of the buffer
1923 ;;; instead of shrinking the bignum.
1924 #!-sb-fluid (declaim (maybe-inline %normalize-bignum-buffer))
1925 (defun %normalize-bignum-buffer (result len)
1926 (declare (type bignum result)
1927 (type bignum-length len))
1928 (unless (= len 1)
1929 (do ((next-digit (%bignum-ref result (- len 2))
1930 (%bignum-ref result (- len 2)))
1931 (sign-digit (%bignum-ref result (1- len)) next-digit))
1932 ((not (zerop (logxor sign-digit (%ashr next-digit (1- digit-size))))))
1933 (decf len)
1934 (setf (%bignum-ref result len) 0)
1935 (when (= len 1)
1936 (return))))
1937 len)
1939 ;;; This drops the last digit if it is unnecessary sign information. It repeats
1940 ;;; this as needed, possibly ending with a fixnum. If the resulting length from
1941 ;;; shrinking is one, see whether our one word is a fixnum. Shift the possible
1942 ;;; fixnum bits completely out of the word, and compare this with shifting the
1943 ;;; sign bit all the way through. If the bits are all 1's or 0's in both words,
1944 ;;; then there are just sign bits between the fixnum bits and the sign bit. If
1945 ;;; we do have a fixnum, shift it over for the two low-tag bits.
1946 (defun %normalize-bignum (result len)
1947 (declare (type bignum result)
1948 (type bignum-length len)
1949 (muffle-conditions compiler-note)
1950 #!-sb-fluid (inline %normalize-bignum-buffer))
1951 (let ((newlen (%normalize-bignum-buffer result len)))
1952 (declare (type bignum-length newlen))
1953 (unless (= newlen len)
1954 (%bignum-set-length result newlen))
1955 (if (= newlen 1)
1956 (let ((digit (%bignum-ref result 0)))
1957 (if (= (%ashr digit sb!vm:n-positive-fixnum-bits)
1958 (%ashr digit (1- digit-size)))
1959 (%fixnum-digit-with-correct-sign digit)
1960 result))
1961 result)))
1963 ;;; This drops the last digit if it is unnecessary sign information. It
1964 ;;; repeats this as needed, possibly ending with a fixnum magnitude but never
1965 ;;; returning a fixnum.
1966 (defun %mostly-normalize-bignum (result len)
1967 (declare (type bignum result)
1968 (type bignum-length len)
1969 #!-sb-fluid (inline %normalize-bignum-buffer))
1970 (let ((newlen (%normalize-bignum-buffer result len)))
1971 (declare (type bignum-length newlen))
1972 (unless (= newlen len)
1973 (%bignum-set-length result newlen))
1974 result))
1976 ;;;; hashing
1978 ;;; the bignum case of the SXHASH function
1979 (defun sxhash-bignum (x)
1980 (let ((result 316495330))
1981 (declare (type fixnum result))
1982 (dotimes (i (%bignum-length x))
1983 (declare (type index i))
1984 (let ((xi (%bignum-ref x i)))
1985 (mixf result
1986 (logand most-positive-fixnum
1987 (logxor xi
1988 (ash xi -7))))))
1989 result))