source: trunk/source/level-0/l0-bignum32.lisp

Last change on this file was 16685, checked in by rme, 4 years ago

Update copyright/license headers in files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 72.8 KB
Line 
1;;-*- Mode: Lisp; Package: CCL -*-
2;;;
3;;; Copyright 1994-2009 Clozure Associates
4;;;
5;;; Licensed under the Apache License, Version 2.0 (the "License");
6;;; you may not use this file except in compliance with the License.
7;;; You may obtain a copy of the License at
8;;;
9;;;     http://www.apache.org/licenses/LICENSE-2.0
10;;;
11;;; Unless required by applicable law or agreed to in writing, software
12;;; distributed under the License is distributed on an "AS IS" BASIS,
13;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14;;; See the License for the specific language governing permissions and
15;;; limitations under the License.
16
17(in-package "CCL")
18
19
20#+32-bit-target                         ; the whole shebang
21(eval-when (:compile-toplevel :execute)
22  (require "ARCH")
23  (require "NUMBER-MACROS")
24  (require "NUMBER-CASE-MACRO")
25 
26  (defconstant digit-size 32)
27  (defconstant half-digit-size (/ digit-size 2))
28 
29  (defconstant maximum-bignum-length (1- (ash 1 24)))
30
31  (deftype bignum-index () `(integer 0 (,maximum-bignum-length)))
32  (deftype bignum-element-type () `(unsigned-byte ,digit-size))
33  (deftype bignum-half-element-type () `(unsigned-byte ,half-digit-size))
34  (deftype bignum-type () 'bignum)
35  (defmacro %bignum-digits (bignum)`(uvsize ,bignum))
36
37  (defmacro digit-bind ((&rest digits) form &body body)
38    `(multiple-value-bind ,digits
39                          ,form
40       (declare (type bignum-half-element-type ,@digits))
41       ,@body))
42
43  (defmacro digit-set ((&rest digits) form)
44    `(multiple-value-setq ,digits
45                          ,form))
46
47  (defmacro digit-zerop (h l)
48    `(and (zerop ,h) (zerop ,l)))
49 
50
51
52  ;;;; BIGNUM-REPLACE and WITH-BIGNUM-BUFFERS.
53
54  ;;; BIGNUM-REPLACE -- Internal.
55  ;;;
56  (defmacro bignum-replace (dest src &key (start1 '0) end1 (start2 '0) end2
57                                 from-end)
58    (once-only ((n-dest dest)
59                 (n-src src))
60      (if (and (eq start1 0)(eq start2 0)(null end1)(null end2)(null from-end))
61        ; this is all true for some uses today <<
62        `(%copy-ivector-to-ivector ,n-src 0 ,n-dest 0 (%ilsl 2 (min (the fixnum (%bignum-length ,n-src))
63                                                                    (the fixnum (%bignum-length ,n-dest)))))
64        (let* ((n-start1 (gensym))
65               (n-end1 (gensym))
66               (n-start2 (gensym))
67               (n-end2 (gensym)))
68          `(let ((,n-start1 ,start1)
69                 (,n-start2 ,start2)
70                 (,n-end1 ,(or end1 `(%bignum-length ,n-dest)))
71                 (,n-end2 ,(or end2 `(%bignum-length ,n-src))))
72             ,(if (null from-end)           
73                `(%copy-ivector-to-ivector
74                  ,n-src (%i* 4 ,n-start2) 
75                  ,n-dest (%i* 4 ,n-start1)
76                  (%i* 4 (min (%i- ,n-end2 ,n-start2) 
77                              (%i- ,n-end1 ,n-start1))))
78                `(let ((nwds (min (%i- ,n-end2 ,n-start2)
79                                  (%i- ,n-end1 ,n-start1))))
80                   (%copy-ivector-to-ivector
81                    ,n-src (%ilsl 2 (%i- ,n-end2 nwds))
82                    ,n-dest (%ilsl 2 (%i- ,n-end1 nwds))
83                    (%i* 4 nwds))))))))) 
84 
85
86  ;;;; Shifting.
87 
88  (defconstant all-ones-half-digit #xFFFF) 
89 
90
91 
92
93 
94  (defmacro %logxor (h1 l1 h2 l2)
95    (once-only ((h1v h1)(l1v l1)(h2v h2)(l2v l2))
96      `(values (%ilogxor ,h1v ,h2v)(%ilogxor ,l1v ,l2v))))
97 
98 
99  (defmacro %lognot (h l)
100    (once-only ((h1v h)(l1v l))
101      `(values (%ilognot ,h1v)(%ilognot ,l1v))))
102
103  (defmacro %allocate-bignum (ndigits)
104    `(%alloc-misc ,ndigits target::subtag-bignum))
105
106  (defmacro %normalize-bignum-macro (big)
107    `(%normalize-bignum-2 t ,big))
108
109  (defmacro %mostly-normalize-bignum-macro (big)
110    `(%normalize-bignum-2 nil ,big))
111
112
113;;; %ALLOCATE-BIGNUM must zero all elements.
114;;;
115  (declaim (inline  %bignum-length))
116
117;;; Temp space needed to (Karatsuba)-square N-digit argument
118  (defmacro mpn-kara-mul-n-tsize (n)
119    `(* 8 (+ ,n 32)))
120;;; Need the same amount of space to do Karatsuba multiply.
121  (defmacro mpn-kara-sqr-n-tsize (n)
122    `(mpn-kara-mul-n-tsize ,n))
123 
124)
125
126
127
128
129#+32-bit-target
130(progn
131;;; Extract the length of the bignum.
132;;;
133(defun %bignum-length (bignum)
134  (uvsize bignum)) 
135
136
137
138
139
140;;;; Addition.
141(defun add-bignums (a b)
142  (let* ((len-a (%bignum-length a))
143         (len-b (%bignum-length b)))
144    (declare (bignum-index len-a len-b))
145    (when (> len-b len-a)
146      (rotatef a b)
147      (rotatef len-a len-b))
148    (let* ((len-res (1+ len-a))
149           (res (%allocate-bignum len-res))
150           (carry 0)
151           (sign-b (%bignum-sign b)))
152        (dotimes (i len-b)
153          (setq carry (%add-with-carry res i carry a i b i)))
154        (if (/= len-a len-b)
155          (finish-bignum-add  res carry a sign-b len-b len-a)
156          (%add-with-carry res len-a carry (%bignum-sign a) nil sign-b nil))
157        (%normalize-bignum-macro res))))
158
159;;; Could do better than this, surely.
160(defun add-bignum-and-fixnum (bignum fixnum)
161  (with-small-bignum-buffers ((bigfix fixnum))
162    (add-bignums bignum bigfix)))
163
164
165
166;;; B was shorter than A; keep adding B's sign digit to each remaining
167;;; digit of A, propagating the carry.
168(defun finish-bignum-add (result carry a sign-b start end)
169  (declare (type bignum-index start end))
170  (do* ((i start (1+ i)))
171       ((= i end)
172        (%add-with-carry result end carry (%bignum-sign a) nil sign-b nil))
173    (setq carry (%add-with-carry result i carry a i sign-b nil))))
174
175
176
177
178
179
180;;;; Subtraction.
181(defun subtract-bignum (a b)
182  (let* ((len-a (%bignum-length a))
183         (len-b (%bignum-length b))
184         (len-res (1+ (max len-a len-b)))
185         (res (%allocate-bignum len-res)))
186    (declare (bignum-index len-a len-b len-res))
187    (bignum-subtract-loop a len-a b len-b res)
188    (%normalize-bignum-macro res)))
189
190(defun bignum-subtract-loop (a len-a b len-b res)
191  (declare (bignum-index len-a len-b ))
192  (let* ((len-res (%bignum-length res)))
193    (declare (bignum-index len-res))
194    (let* ((borrow 1)
195           (sign-a (%bignum-sign a))
196           (sign-b (%bignum-sign b)))
197      (dotimes (i (the bignum-index (min len-a len-b)))
198        (setq borrow (%subtract-with-borrow res i borrow a i b i)))
199      (if (< len-a len-b)
200        (do* ((i len-a (1+ i)))
201             ((= i len-b)
202              (if (< i len-res)
203                (%subtract-with-borrow res i borrow sign-a nil sign-b nil)))
204          (setq borrow (%subtract-with-borrow res i borrow sign-a nil b i)))
205        (do* ((i len-b (1+ i)))
206             ((= i len-a)
207              (if (< i len-res)
208                (%subtract-with-borrow res i borrow sign-a nil sign-b nil)))
209          (setq borrow (%subtract-with-borrow res i borrow a i sign-b nil)))))))
210
211
212;;;; Multiplication.
213
214;;; These parameters match GMP's.
215(defvar *sqr-basecase-threshold* 5)
216(defvar *sqr-karatsuba-threshold* 22)
217(defvar *mul-karatsuba-threshold* 10)
218
219;;; Squaring is often simpler than multiplication.  This should never
220;;; be called with (>= N *sqr-karatsuba-threshold*).
221(defun mpn-sqr-basecase (prodp up n)
222  (declare (fixnum prodp up n))
223  (declare (optimize (speed 3) (safety 0) (space 0)))
224  (umulppm up up prodp)
225  (when (> n 1)
226    (%stack-block ((tarr (* 4 (* 2 *sqr-karatsuba-threshold*))))
227      (let* ((tp (macptr->fixnum tarr)))
228        (mpn-mul-1 tp
229                   (the fixnum (1+ up))
230                   (the fixnum (1- n))
231                   up
232                   (the fixnum (+ tp (the fixnum (1- n)))))
233        (do* ((i 2 (1+ i)))
234             ((= i n))
235          (declare (fixnum i))
236          (mpn-addmul-1 (the fixnum (- (the fixnum (+ tp (the fixnum (+ i i))))
237                                       2))
238                        (the fixnum (+ up i))
239                        (the fixnum (- n i))
240                        (the fixnum (+ up (the fixnum (1- i))))
241                        (the fixnum (+ tp (the fixnum (+ n (the fixnum (- i 2))))))))
242        (do* ((i 1 (1+ i))
243              (ul (1+ up) (1+ ul)))
244             ((= i n))
245          (declare (fixnum i ul))
246          (umulppm ul ul (the fixnum (+ prodp (the fixnum (+ i i))))))
247        (let* ((2n-2 (- (the fixnum (+ n n)) 2))
248               (carry (mpn-lshift-1 tp tp 2n-2)))
249          (declare (fixnum 2n-2 carry))
250          (setq carry
251                (+ carry
252                   (the fixnum (mpn-add-n (the fixnum (1+ prodp))
253                                          (the fixnum (1+ prodp))
254                                          tp
255                                          2n-2))))
256          (add-fixnum-to-limb carry (the fixnum (+ prodp
257                                                   (the fixnum (1-
258                                                                (the fixnum
259                                                                  (+ n n))))))))))))
260
261;;; For large enough values of N, squaring via Karatsuba-style
262;;; divide&conquer is faster than in the base case.
263(defun mpn-kara-sqr-n (p a n ws)
264  (declare (fixnum p a n ws))
265  (declare (optimize (speed 3) (safety 0) (space 0)))
266  (%stack-block ((limbs 16))
267    (let* ((w (macptr->fixnum limbs))
268           (w0 (1+ w))
269           (w1 (1+ w0))
270           (xx (1+ w1))
271           (n2 (ash n -1))
272           (x 0)
273           (y 0)
274           (i 0))
275      (declare (fixnum w w0 w1 xx n2 x y i))
276      (cond ((logbitp 0 n)
277             ;; Odd length
278             (let* ((n3 (- n n2))
279                    (n1 0)
280                    (nm1 0))
281               (declare (fixnum n3 n1 nm1))
282               (copy-limb (the fixnum (+ a n2)) w)
283               (if (not (limb-zerop w))
284                 (add-fixnum-to-limb
285                  (the fixnum
286                    (- (the fixnum (mpn-sub-n p a (the fixnum (+ a n3)) n2))))
287                  w)
288                 (progn
289                   (setq i n2)
290                   (loop
291                     (decf i)
292                     (copy-limb (the fixnum (+ a i)) w0)
293                     (copy-limb (the fixnum (+ a (the fixnum (+ n3 i)))) w1)
294                     (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
295                             (= i 0))
296                       (return)))
297                   (if (< (the fixnum (compare-limbs w0 w1)) 0)
298                     (setq x (+ a n3)
299                           y a)
300                     (setq y (+ a n3)
301                           x a))
302                   (mpn-sub-n p x y n2)))
303               (copy-limb w (the fixnum (+ p n2)))
304               (setq n1 (1+ n))
305               (cond ((< n3 *sqr-basecase-threshold*)
306                      (mpn-mul-basecase ws p n3 p n3)
307                      (mpn-mul-basecase p a n3 a n3))
308                     ((< n3 *sqr-karatsuba-threshold*)
309                      (mpn-sqr-basecase ws p n3)
310                      (mpn-sqr-basecase p a n3))
311                     (t
312                      (mpn-kara-sqr-n ws p n3 (the fixnum (+ ws n1)))
313                      (mpn-kara-sqr-n p  a n3 (the fixnum (+ ws n1)))))
314               (cond ((< n2 *sqr-basecase-threshold*)
315                      (mpn-mul-basecase (the fixnum (+ p n1))
316                                        (the fixnum (+ a n3))
317                                        n2
318                                        (the fixnum (+ a n3))
319                                        n2))
320                     ((< n2 *sqr-karatsuba-threshold*)
321                      (mpn-sqr-basecase (the fixnum (+ p n1))
322                                        (the fixnum (+ a n3))
323                                        n2))
324                     (t
325                      (mpn-kara-sqr-n (the fixnum (+ p n1))
326                                      (the fixnum (+ a n3))
327                                      n2
328                                      (the fixnum (+ ws n1)))))
329               (mpn-sub-n ws p ws n1)
330               (setq nm1 (1- n))
331               (unless (zerop (the fixnum
332                                (mpn-add-n ws
333                                           (the fixnum (+ p n1))
334                                           ws
335                                           nm1)))
336                 (copy-limb (the fixnum (+ ws nm1)) xx)
337                 (add-fixnum-to-limb 1 xx)
338                 (copy-limb xx (the fixnum (+ ws nm1)))
339                 (if (limb-zerop xx)
340                   (add-fixnum-to-limb 1 (the fixnum (+ ws n)))))
341               (unless (zerop
342                        (the fixnum
343                          (mpn-add-n (the fixnum (+ p n3))
344                                     (the fixnum (+ p n3))
345                                     ws
346                                     n1)))
347                 (mpn-incr-u (the fixnum (+ p (the fixnum (+ n1 n3))))
348                             1))))
349            (t ; N is even
350             (setq i n2)
351             (loop
352               (decf i)
353               (copy-limb (the fixnum (+ a i)) w0)
354               (copy-limb (the fixnum (+ a (the fixnum (+ n2 i)))) w1)
355               (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
356                       (= i 0))
357                 (return)))
358             (if (< (the fixnum (compare-limbs w0 w1)) 0)
359               (setq x (+ a n2)
360                     y a)
361               (setq y (+ a n2)
362                     x a))
363             (mpn-sub-n p x y n2)
364             (cond ((< n2 *sqr-basecase-threshold*)
365                    (mpn-mul-basecase ws p n2 p n2)
366                    (mpn-mul-basecase p a n2 a n2)
367                    (mpn-mul-basecase (the fixnum (+ p n))
368                                      (the fixnum (+ a n2))
369                                      n2
370                                      (the fixnum (+ a n2))
371                                      n2))
372                   ((< n2 *sqr-karatsuba-threshold*)
373                    (mpn-sqr-basecase ws p n2)
374                    (mpn-sqr-basecase p a n2)
375                    (mpn-sqr-basecase (the fixnum (+ p n))
376                                      (the fixnum (+ a n2))
377                                      n2))
378                   (t
379                    (mpn-kara-sqr-n ws p n2 (the fixnum (+ ws n)))
380                    (mpn-kara-sqr-n p  a n2 (the fixnum (+ ws n)))
381                    (mpn-kara-sqr-n (the fixnum (+ p n))
382                                    (the fixnum (+ a n2))
383                                    n2
384                                    (the fixnum (+ ws n)))))
385             (let* ((ww (- (the fixnum (mpn-sub-n ws p ws n)))))
386               (declare (fixnum ww))
387               (setq ww (+ ww (mpn-add-n ws (the fixnum (+ p n)) ws n)))
388               (setq ww (+ ww (mpn-add-n (the fixnum (+ p n2))
389                                         (the fixnum (+ p n2))
390                                         ws
391                                         n)))
392               (mpn-incr-u (the fixnum (+ p (the fixnum (+ n2 n)))) ww)))))))
393
394;;; Karatsuba subroutine: multiply A and B, store result at P, use WS
395;;; as scrach space.  Treats A and B as if they were both of size N;
396;;; if that's not true, caller must fuss around the edges.
397(defun mpn-kara-mul-n (p a b n ws)
398  (declare (fixnum p a b n ws))
399  (declare (optimize (speed 3) (safety 0) (space 0)))
400  (%stack-block ((limbs 16))
401    (let* ((w (macptr->fixnum limbs))
402           (w0 (1+ w))
403           (w1 (1+ w0))
404           (xx (1+ w1))
405           (x 0)
406           (y 0)
407           (i 0)
408           (n2 (ash n -1))
409           (sign 0))
410      (declare (fixnum w w0 w1 xx x y i n2 sign))
411      (cond ((logbitp 0 n)
412             (let* ((n1 0)
413                    (n3 (- n n2))
414                    (nm1 0))
415               (declare (fixnum n1 n3 nm1))
416               (copy-limb (the fixnum (+ a n2)) w)
417               (if (not (limb-zerop w))
418                 (add-fixnum-to-limb
419                  (the fixnum (- (mpn-sub-n p a (the fixnum (+ a n3)) n2))) w)
420                 (progn
421                   (setq i n2)
422                   (loop
423                     (decf i)
424                     (copy-limb (the fixnum (+ a i)) w0)
425                     (copy-limb (the fixnum (+ a (the fixnum (+ n3 i)))) w1)
426                     (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
427                             (zerop i))
428                       (return)))
429                   (if (< (the fixnum (compare-limbs w0 w1)) 0)
430                     (setq x (+ a n3)
431                           y a
432                           sign -1)
433                     (setq x a
434                           y (+ a n3)))
435                   (mpn-sub-n p x y n2)))
436               (copy-limb w (the fixnum (+ p n2)))
437               (copy-limb (the fixnum (+ b n2)) w)
438               (if (not (limb-zerop w))
439                 (add-fixnum-to-limb
440                  (the fixnum (- (the fixnum (mpn-sub-n (the fixnum (+ p n3))
441                                                        b
442                                                        (the fixnum (+ b n3))
443                                                        n2))))
444                  w)
445                 (progn
446                   (setq i n2)
447                   (loop
448                     (decf i)
449                     (copy-limb (the fixnum (+ b i)) w0)
450                     (copy-limb (the fixnum (+ b (the fixnum (+ n3 i)))) w1)
451                     (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
452                             (zerop i))
453                       (return)))
454                   (if (< (the fixnum (compare-limbs w0 w1)) 0)
455                     (setq x (+ b n3)
456                           y b
457                           sign (lognot sign))
458                     (setq x b
459                           y (+ b n3)))
460                   (mpn-sub-n (the fixnum (+ p n3)) x y n2)))
461               (copy-limb w (the fixnum (+ p n)))
462               (setq n1 (1+ n))
463               (cond
464                 ((< n2 *mul-karatsuba-threshold*)
465                  (cond
466                    ((< n3 *mul-karatsuba-threshold*)
467                     (mpn-mul-basecase ws p n3 (the fixnum (+ p n3)) n3)
468                     (mpn-mul-basecase p a n3 b n3))
469                    (t
470                     (mpn-kara-mul-n ws p (the fixnum (+ p n3)) n3 (the fixnum (+ ws n1)))
471                     (mpn-kara-mul-n p a b n3 (the fixnum (+ ws n1)))))
472                  (mpn-mul-basecase (the fixnum (+ p n1))
473                                    (the fixnum (+ a n3))
474                                    n2
475                                    (the fixnum (+ b n3))
476                                    n2))
477                 (t
478                  (mpn-kara-mul-n ws p (the fixnum (+ p n3)) n3 (the fixnum (+ ws n1)))
479                  (mpn-kara-mul-n p a b n3 (the fixnum (+ ws n1)))
480                  (mpn-kara-mul-n (the fixnum (+ p n1))
481                                  (the fixnum (+ a n3))
482                                  (the fixnum (+ b n3))
483                                  n2
484                                  (the fixnum (+ ws n1)))))
485               (if (not (zerop sign))
486                 (mpn-add-n ws p ws n1)
487                 (mpn-sub-n ws p ws n1))
488               (setq nm1 (1- n))
489               (unless (zerop (the fixnum (mpn-add-n ws
490                                                     (the fixnum (+ p n1))
491                                                     ws
492                                                     nm1)))
493                 (copy-limb (the fixnum (+ ws nm1)) xx)
494                 (add-fixnum-to-limb 1 xx)
495                 (copy-limb xx (the fixnum (+ ws nm1)))
496                 (if (limb-zerop xx)
497                   (add-fixnum-to-limb 1 (the fixnum (+ ws n)))))
498               (unless (zerop (the fixnum
499                                (mpn-add-n (the fixnum (+ p n3))
500                                           (the fixnum (+ p n3))
501                                           ws
502                                           n1)))
503                 (mpn-incr-u (the fixnum
504                               (+ p (the fixnum (+ n1 n3)))) 1))))
505            (t                          ; even length
506             (setq i n2)
507             (loop
508               (decf i)
509               (copy-limb (the fixnum (+ a i)) w0)
510               (copy-limb (the fixnum (+ a (the fixnum (+ n2 i)))) w1)
511               (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
512                       (zerop i))
513                 (return)))
514             (setq sign 0)
515             (if (< (the fixnum (compare-limbs w0 w1)) 0)
516               (setq x (+ a n2)
517                     y a
518                     sign -1)
519               (setq x a
520                     y (+ a n2)))
521             (mpn-sub-n p x y n2)
522             (setq i n2)
523             (loop
524               (decf i)
525               (copy-limb (the fixnum (+ b i)) w0)
526               (copy-limb (the fixnum (+ b (the fixnum (+ n2 i)))) w1)
527               (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
528                       (zerop i))
529                 (return)))           
530             (if (< (the fixnum (compare-limbs w0 w1)) 0)
531               (setq x (+ b n2)
532                     y b
533                     sign (lognot sign))
534               (setq x b
535                     y (+ b n2)))
536             (mpn-sub-n (the fixnum (+ p n2)) x y n2)
537             (cond
538               ((< n2 *mul-karatsuba-threshold*)
539                (mpn-mul-basecase ws p n2 (the fixnum (+ p n2)) n2)
540                (mpn-mul-basecase p a n2 b n2)
541                (mpn-mul-basecase (the fixnum (+ p n))
542                                  (the fixnum (+ a n2))
543                                  n2
544                                  (the fixnum (+ b n2))
545                                  n2))
546               (t
547                (mpn-kara-mul-n ws p (the fixnum (+ p n2)) n2
548                                (the fixnum (+ ws n)))
549                (mpn-kara-mul-n p a b n2 (the fixnum (+ ws n)))
550                (mpn-kara-mul-n (the fixnum (+ p n))
551                                (the fixnum (+ a n2))
552                                (the fixnum (+ b n2))
553                                n2
554                                (the fixnum (+ ws n)))))
555             (let* ((ww (if (not (zerop sign))
556                          (mpn-add-n ws p ws n)
557                          (- (the fixnum (mpn-sub-n ws p ws n))))))
558               (declare (fixnum ww))
559               (setq ww (+ ww (mpn-add-n ws (the fixnum (+ p n)) ws n)))
560               (setq ww (+ ww (mpn-add-n (the fixnum (+ p n2))
561                                         (the fixnum (+ p n2))
562                                         ws
563                                         n)))
564               (mpn-incr-u (the fixnum (+ p (the fixnum (+ n2 n)))) ww)))))))
565
566;;; Square UP, of length UN.  I wonder if a Karatsuba multiply might be
567;;; faster than a basecase square.
568(defun mpn-sqr-n (prodp up un)
569  (declare (fixnum prodp up un))
570  (declare (optimize (speed 3) (safety 0) (space 0)))
571  (if (< un *sqr-basecase-threshold*)
572    (mpn-mul-basecase prodp up un up un)
573    (if (< un *sqr-karatsuba-threshold*)
574      (mpn-sqr-basecase prodp up un)
575      (%stack-block ((wsptr (mpn-kara-sqr-n-tsize un)))
576        (mpn-kara-sqr-n prodp up un (macptr->fixnum wsptr))))))
577
578;;; Subroutine: store AxB at P.  Assumes A & B to be of length N
579(defun mpn-mul-n (p a b n)
580  (declare (fixnum p a b n))
581  (declare (optimize (speed 3) (safety 0) (space 0))) 
582  (if (< n *mul-karatsuba-threshold*)
583    (mpn-mul-basecase p a n b n)
584    (%stack-block ((wsptr (mpn-kara-mul-n-tsize n)))
585      (mpn-kara-mul-n p a b n (macptr->fixnum wsptr)))))
586
587
588;;; Multiply [UP,UN] by [VP,VN].  UN must not be less than VN.
589;;; This does Karatsuba if operands are big enough; if they are
590;;; and they differ in size, this computes the product of the
591;;; smaller-size slices, then fixes up the resut.
592(defun mpn-mul (prodp up un vp vn)
593  (declare (fixnum prodp up un vp vn))
594  (declare (optimize (speed 3) (safety 0) (space 0)))
595  ;(assert (>= un vn 1))
596  (if (and (= up vp) (= un vn))
597    (mpn-sqr-n prodp up un)
598    (if (< vn *mul-karatsuba-threshold*)
599      (mpn-mul-basecase prodp up un vp vn)
600      (let* ((l vn))
601        (declare (fixnum l))
602        (mpn-mul-n prodp up vp vn)
603        (unless (= un vn)
604          (incf prodp vn)
605          (incf up vn)
606          (decf un vn)
607          (if (< un vn)
608            (psetq un vn vn un up vp vp up))
609          (%stack-block ((wsptr
610                          (the fixnum
611                            (+ 8
612                               (the fixnum
613                                 (* 4
614                                    (the fixnum
615                                      (+ vn
616                                         (if (>= vn *mul-karatsuba-threshold*)
617                                           vn
618                                           un)))))))))
619            (setf (%get-unsigned-long wsptr 0) 0
620                  (%get-unsigned-long wsptr 4) 0)
621            (let* ((tt (macptr->fixnum wsptr))
622                   (c (1+ tt))
623                   (ws (1+ c)))
624              (declare (fixnum tt c ws ))
625              (do* ()
626                   ((< vn *mul-karatsuba-threshold*))
627                (mpn-mul-n ws up vp vn)
628                (cond ((<= l (the fixnum (+ vn vn)))
629                       (add-fixnum-to-limb (mpn-add-n prodp prodp ws l) tt)
630                       (unless (= l (the fixnum (+ vn vn)))
631                         (copy-fixnum-to-limb
632                          (mpn-add-1 (the fixnum (+ prodp l))
633                                     (the fixnum (+ ws l))
634                                     (the fixnum (- (the fixnum (+ vn vn)) l))
635                                     tt)
636                          tt)
637                         (setq l (the fixnum (+ vn vn)))))
638                      (t
639                       (copy-fixnum-to-limb
640                        (mpn-add-n prodp prodp ws (the fixnum (+ vn vn))) c)
641                       (add-fixnum-to-limb
642                        (mpn-add-1 (the fixnum (+ prodp (the fixnum (+ vn vn))))
643                                   (the fixnum (+ prodp (the fixnum (+ vn vn))))
644                                   (the fixnum (- l (the fixnum (+ vn vn))))
645                                   c)
646                        tt)))
647                (incf prodp vn)
648                (decf l vn)
649                (incf up vn)
650                (decf un vn)
651                (if (< un vn)
652                  (psetq up vp vp up un vn vn un)))
653              (unless (zerop vn)
654                (mpn-mul-basecase ws up un vp vn)
655                (cond ((<= l (the fixnum (+ un vn)))
656                       (add-fixnum-to-limb
657                        (mpn-add-n prodp prodp ws l)
658                        tt)
659                       (unless (= l (the fixnum (+ un vn)))
660                         (copy-fixnum-to-limb
661                          (mpn-add-1 (the fixnum (+ prodp l))
662                                     (the fixnum (+ ws l))
663                                     (the fixnum (- (the fixnum (+ un vn)) l))
664                                     tt)
665                          tt)))
666                      (t
667                       (copy-fixnum-to-limb
668                        (mpn-add-n prodp prodp ws (the fixnum (+ un vn)))
669                        c)
670                       (add-fixnum-to-limb
671                        (mpn-add-1
672                         (the fixnum (+ prodp (the fixnum (+ un vn))))
673                         (the fixnum (+ prodp (the fixnum (+ un vn))))
674                         (the fixnum (- (the fixnum (- l un)) vn))
675                         c)
676                        tt)))))))))))
677
678(defun multiply-bignums (a b)
679  (let* ((signs-differ (not (eq (bignum-minusp a) (bignum-minusp b)))))
680    (flet ((multiply-unsigned-bignums (a b)
681             (let* ((len-a (%bignum-length a))
682                    (len-b (%bignum-length b))
683                    (len-res (+ len-a len-b))
684                    (res (%allocate-bignum len-res)) )
685               (declare (bignum-index len-a len-b len-res))
686               (if (and (>= len-a 16)
687                        (>= len-b 16)
688                        #+(or x8632-target arm-target)
689                        nil)
690                 (let* ((ubytes (* len-a 4))
691                        (vbytes (* len-b 4))
692                        (rbytes (* len-res 4)))
693                   (declare (fixnum ubytes vbytes rbytes))
694                   (%stack-block ((uptr ubytes)
695                                  (vptr vbytes)
696                                  (rptr rbytes))
697                     (let* ((up (macptr->fixnum uptr))
698                            (vp (macptr->fixnum vptr))
699                            (rp (macptr->fixnum rptr)))
700                       (declare (fixnum up vp rp))
701                       (%copy-ivector-to-ptr a 0 uptr 0 ubytes)
702                       (if (eq a b)     ; maybe try eql ..
703                         (mpn-mul rp up len-a up len-a)
704                         (progn
705                           (%copy-ivector-to-ptr b 0 vptr 0 vbytes)
706                           (if (< len-a len-b)
707                             (mpn-mul rp vp len-b up len-a)
708                             (mpn-mul rp up len-a vp len-b)))))
709                     (%copy-ptr-to-ivector rptr 0 res 0 rbytes)))
710                 (dotimes (i len-a)
711                   (declare (type bignum-index i))
712                   (%multiply-and-add-harder-loop-2 a b res i len-b)))
713                 res)))
714      (let* ((res (with-negated-bignum-buffers a b multiply-unsigned-bignums)))
715        (if signs-differ (negate-bignum-in-place res))
716        (%normalize-bignum-macro res)))))
717
718
719(defun multiply-bignum-and-fixnum (bignum fixnum)
720  (declare (type bignum-type bignum) (fixnum fixnum))
721  (let* ((bignum-len (%bignum-length bignum))
722         (bignum-plus-p (bignum-plusp bignum))
723         (fixnum-plus-p (not (minusp fixnum)))
724         (negate-res (neq bignum-plus-p fixnum-plus-p)))
725    (declare (type bignum-type bignum)
726             (type bignum-index bignum-len))
727    (flet ((do-it (bignum fixnum  negate-res)
728             (let* ((bignum-len (%bignum-length bignum))
729                    (result (%allocate-bignum (the fixnum (1+ bignum-len)))))
730               (declare (type bignum-type bignum)
731                        (type bignum-index bignum-len))
732               (%multiply-and-add-fixnum-loop bignum-len bignum fixnum result)
733               (when negate-res
734                 (negate-bignum-in-place result))
735               (%normalize-bignum-macro result ))))
736      (declare (dynamic-extent #'do-it))
737      (if bignum-plus-p
738        (do-it bignum (if fixnum-plus-p fixnum (- fixnum))  negate-res)
739        (with-bignum-buffers ((b1 (the fixnum (1+ bignum-len))))
740          (negate-bignum bignum nil b1)
741          (do-it b1 (if fixnum-plus-p fixnum (- fixnum))  negate-res))))))
742
743;; assume we already know result won't fit in a fixnum
744;; only caller is fixnum-*-2
745;;
746
747(defun multiply-fixnums (a b)
748  (declare (fixnum a b))
749  (* a b))
750
751
752;;;; GCD.
753
754
755;;; Both args are > 0.
756(defun bignum-fixnum-gcd (bignum fixnum)
757  (let* ((rem (bignum-truncate-by-fixnum-no-quo bignum fixnum)))
758    (declare (fixnum rem))
759    (if (zerop rem)
760      fixnum
761      (%fixnum-gcd rem fixnum))))
762
763
764
765;;; NEGATE-BIGNUM -- Public.
766;;;
767;;; Fully-normalize is an internal optional.  It cause this to always return
768;;; a bignum, without any extraneous digits, and it never returns a fixnum.
769;;;
770(defun negate-bignum (x &optional (fully-normalize t) res)
771  (declare (type bignum-type x))
772  (let* ((len-x (%bignum-length x))
773         (len-res (1+ len-x))
774         (minusp (bignum-minusp x)))
775    (declare (type bignum-index len-x len-res))
776    (if (not res) (setq res (%allocate-bignum len-res))) ;Test len-res for range?
777    (let ((carry (bignum-negate-loop-really x len-x res)))  ; i think carry is always 0
778      (if (eq carry 0)
779        (if minusp (%bignum-set res len-x 0 0)(%bignum-set res len-x #xffff #xffff))
780        (digit-bind (h l)
781                    (if minusp 
782                      (%add-the-carry 0 0 carry)
783                      (%add-the-carry #xffff #xffff carry))
784                   
785          (%bignum-set res len-x h l))))
786    (if fully-normalize
787      (%normalize-bignum-macro res)
788      (%mostly-normalize-bignum-macro res))))
789
790;;; NEGATE-BIGNUM-IN-PLACE -- Internal.
791;;;
792;;; This assumes bignum is positive; that is, the result of negating it will
793;;; stay in the provided allocated bignum.
794;;;
795(defun negate-bignum-in-place (bignum)
796  (bignum-negate-loop-really bignum (%bignum-length bignum) bignum)
797  bignum)
798
799
800 
801
802(defun copy-bignum (bignum)
803  (let ((res (%allocate-bignum (%bignum-length bignum))))
804    (bignum-replace res bignum)
805    res))
806
807
808
809;;; BIGNUM-ASHIFT-RIGHT -- Public.
810;;;
811;;; First compute the number of whole digits to shift, shifting them by
812;;; skipping them when we start to pick up bits, and the number of bits to
813;;; shift the remaining digits into place.  If the number of digits is greater
814;;; than the length of the bignum, then the result is either 0 or -1.  If we
815;;; shift on a digit boundary (that is, n-bits is zero), then we just copy
816;;; digits.  The last branch handles the general case which uses a macro that a
817;;; couple other routines use.  The fifth argument to the macro references
818;;; locals established by the macro.
819;;;
820
821
822(defun bignum-ashift-right (bignum x)
823  (declare (type bignum-type bignum)
824           (fixnum x))
825  (let ((bignum-len (%bignum-length bignum)))
826    (declare (type bignum-index bignum-len))
827    (multiple-value-bind (digits n-bits) (truncate x digit-size)
828      (declare (type bignum-index digits)(fixnum n-bits))
829      (cond
830       ((>= digits bignum-len)
831        (if (bignum-plusp bignum) 0 -1))
832       ((eql 0 n-bits)
833        (bignum-ashift-right-digits bignum digits))
834       (t
835        (let* ((res-len (- bignum-len digits))
836               (res (%allocate-bignum res-len))
837               (len-1 (1- res-len)))
838          (declare (fixnum res-len len-1))
839          (bignum-shift-right-loop-1 n-bits res bignum len-1 digits)         
840          (%normalize-bignum-macro res )))))))
841
842                               
843
844
845
846;;; BIGNUM-ASHIFT-RIGHT-DIGITS -- Internal.
847;;;
848(defun bignum-ashift-right-digits (bignum digits)
849  (declare (type bignum-type bignum)
850           (type bignum-index digits))
851  (let* ((res-len (- (%bignum-length bignum) digits))
852         (res (%allocate-bignum res-len)))
853    (declare (type bignum-index res-len)
854             (type bignum-type res))
855    (bignum-replace res bignum :start2 digits)
856    (%normalize-bignum-macro res)))
857
858
859;;; BIGNUM-BUFFER-ASHIFT-RIGHT -- Internal.
860;;;
861;;; GCD uses this for an in-place shifting operation.  This is different enough
862;;; from BIGNUM-ASHIFT-RIGHT that it isn't worth folding the bodies into a
863;;; macro, but they share the basic algorithm.  This routine foregoes a first
864;;; test for digits being greater than or equal to bignum-len since that will
865;;; never happen for its uses in GCD.  We did fold the last branch into a macro
866;;; since it was duplicated a few times, and the fifth argument to it
867;;; references locals established by the macro.
868;;;
869#|
870(defun bignum-buffer-ashift-right (bignum bignum-len x)
871  (declare (type bignum-index bignum-len) (fixnum x))
872  (multiple-value-bind (digits n-bits)
873                       (truncate x digit-size)
874    (declare (type bignum-index digits))
875    (cond
876     ((zerop n-bits)
877      (let ((new-end (- bignum-len digits)))
878        (bignum-replace bignum bignum :end1 new-end :start2 digits
879                        :end2 bignum-len)
880        (%normalize-bignum-buffer bignum new-end)))
881     (t
882      (shift-right-unaligned bignum digits n-bits (- bignum-len digits)
883                             ((= j res-len-1)
884                              (digit-bind (h l) (%bignum-ref bignum i)
885                                (digit-set (h l) (%ashr h l n-bits))
886                                (%bignum-set bignum j h l))
887                              (%normalize-bignum-buffer bignum res-len)))))))
888|#
889#|
890(defun bignum-buffer-ashift-right (bignum bignum-len x)
891  (declare (type bignum-index bignum-len) (fixnum x))
892  (multiple-value-bind (digits n-bits) (truncate x digit-size)
893    (declare (type bignum-index digits)(fixnum n-bits))
894    (macrolet ((clear-high-digits ()
895                 `(do* ((i (1- (the fixnum (%bignum-length bignum))) (1- i))
896                        (j digits (1- j)))
897                       ((= 0 j))
898                    (declare (fixnum i j))
899                    (%bignum-set bignum i 0 0))))
900      (cond
901       ((zerop n-bits)
902        (let* ((new-end (- bignum-len digits)))
903          (declare (fixnum new-end))
904          (bignum-replace bignum bignum :end1 new-end :start2 digits
905                          :end2 bignum-len)
906          (clear-high-digits)
907          (%normalize-bignum-buffer bignum new-end)))
908       (t
909        (let* ((res-len (- bignum-len digits))
910               (len-1 (1- res-len)))
911          (declare (fixnum res-len len-1))
912          (bignum-shift-right-loop-1 n-bits bignum bignum len-1 digits)
913          ; clear the old high order digits - assume always positive
914          ; (when (neq 0 digits)(push digits poof))
915          (clear-high-digits)
916          (%normalize-bignum-buffer bignum res-len)))))))
917|#
918
919 
920
921;;; BIGNUM-ASHIFT-LEFT -- Public.
922;;;
923;;; This handles shifting a bignum buffer to provide fresh bignum data for some
924;;; internal routines.  We know bignum is safe when called with bignum-len.
925;;; First we compute the number of whole digits to shift, shifting them
926;;; starting to store farther along the result bignum.  If we shift on a digit
927;;; boundary (that is, n-bits is zero), then we just copy digits.  The last
928;;; branch handles the general case.
929;;;
930(defun bignum-ashift-left (bignum x &optional bignum-len)
931  (declare (type bignum-type bignum)
932           (fixnum x)
933           (type (or null bignum-index) bignum-len))
934  (multiple-value-bind (digits n-bits)
935                       (truncate x digit-size)
936    (declare (fixnum digits n-bits))
937    (let* ((bignum-len (or bignum-len (%bignum-length bignum)))
938           (res-len (+ digits bignum-len 1)))
939      (declare (fixnum bignum-len res-len))
940      (when (> res-len maximum-bignum-length)
941        (error "Can't represent result of left shift."))
942      (if (zerop n-bits)
943        (bignum-ashift-left-digits bignum bignum-len digits)
944        (bignum-ashift-left-unaligned bignum digits n-bits res-len)))))
945
946;;; BIGNUM-ASHIFT-LEFT-DIGITS -- Internal.
947;;;
948(defun bignum-ashift-left-digits (bignum bignum-len digits)
949  (declare (type bignum-index bignum-len digits))
950  (let* ((res-len (+ bignum-len digits))
951         (res (%allocate-bignum res-len)))
952    (declare (type bignum-index res-len))
953    (bignum-replace res bignum :start1 digits :end1 res-len :end2 bignum-len
954                    :from-end t)
955    res))
956
957;;; BIGNUM-ASHIFT-LEFT-UNALIGNED -- Internal.
958;;;
959;;; BIGNUM-TRUNCATE uses this to store into a bignum buffer by supplying res.
960;;; When res comes in non-nil, then this foregoes allocating a result, and it
961;;; normalizes the buffer instead of the would-be allocated result.
962;;;
963;;; We start storing into one digit higher than digits, storing a whole result
964;;; digit from parts of two contiguous digits from bignum.  When the loop
965;;; finishes, we store the remaining bits from bignum's first digit in the
966;;; first non-zero result digit, digits.  We also grab some left over high
967;;; bits from the last digit of bignum.
968;;;
969
970(defun bignum-ashift-left-unaligned (bignum digits n-bits res-len
971                                              &optional (res nil resp))
972  (declare (type bignum-index digits res-len)
973           (type (mod #.digit-size) n-bits))
974  (let* (;(remaining-bits (- digit-size n-bits))
975         (res-len-1 (1- res-len))
976         (res (or res (%allocate-bignum res-len))))
977    (declare (type bignum-index res-len res-len-1))
978    (bignum-shift-left-loop n-bits res bignum res-len-1 (the fixnum (1+ digits)))
979    ; if resp provided we don't care about returned value
980    (if (not resp) (%normalize-bignum-macro res))))
981
982
983
984
985;;;; Relational operators.
986
987
988
989;;; BIGNUM-COMPARE -- Public.
990;;;
991;;; This compares two bignums returning -1, 0, or 1, depending on whether a
992;;; is less than, equal to, or greater than b.
993;;;
994;(proclaim '(function bignum-compare (bignum bignum) (integer -1 1)))
995(defun bignum-compare (a b)
996  (declare (type bignum-type a b))
997  (let* ((a-plusp (bignum-plusp a))
998         (b-plusp (bignum-plusp b)))
999    (if (eq a-plusp b-plusp)
1000      (let* ((len-a (%bignum-length a))
1001             (len-b (%bignum-length b)))
1002        (declare (type bignum-index len-a len-b))
1003        (cond ((= len-a len-b)
1004               (do* ((i (1- len-a) (1- i)))
1005                    ((zerop i) (%compare-digits a b 0))
1006                 (declare (fixnum i))
1007                 (let* ((signum (%compare-digits a b i)))
1008                   (declare (fixnum signum))
1009                   (unless (zerop signum)
1010                     (return signum)))))
1011              ((> len-a len-b)
1012               (if a-plusp 1 -1))
1013              (t (if a-plusp -1 1))))
1014      (if a-plusp 1 -1))))
1015
1016
1017
1018
1019
1020
1021;;;; Integer length and logcount
1022
1023
1024(defun bignum-integer-length (big)
1025  (the fixnum (- (the fixnum (ash (the fixnum (%bignum-length big)) 5))
1026                 (the fixnum (%bignum-sign-bits big)))))
1027
1028; (not (zerop (logand integer1 integer2)
1029
1030(defun bignum-logtest (num1 num2)
1031  (let* ((length1 (%bignum-length num1))
1032         (length2 (%bignum-length num2))
1033         (n1-minusp (bignum-minusp num1))
1034         (n2-minusp (bignum-minusp num2)))
1035    (declare (fixnum length1 length2))
1036    (if (and n1-minusp n2-minusp) ; both neg, get out quick
1037      T       
1038      (let ((val (bignum-logtest-loop (min length1 length2) num1 num2)))
1039                 #|(do* ((index 0 (1+ index)))
1040                      ((= index (min length1 length2)) nil)
1041                   ; maybe better to start from high end of shorter?
1042                   (multiple-value-bind (hi1 lo1)(%bignum-ref num1 index)
1043                     (multiple-value-bind (hi2 lo2)(%bignum-ref num2 index)
1044                       (when (or (not (zerop (%ilogand hi1 hi2)))
1045                                 (not (zerop (%ilogand lo1 lo2))))
1046                         (return t)))))))|#
1047        (or val
1048            (when (not (eql length1 length2)) ; lengths same => value nil
1049              (if (< length1 length2)
1050                n1-minusp
1051                n2-minusp)))))))
1052
1053
1054
1055(defun logtest-fix-big (fix big)
1056  (declare (fixnum fix))
1057  (if (eql 0 (the fixnum fix))
1058    nil
1059    (if (> (the fixnum fix) 0) 
1060      (let ()
1061        (multiple-value-bind (hi lo)(%bignum-ref big 0)
1062          (declare (fixnum hi lo))
1063          (or (not (zerop (logand fix lo)))
1064              (not (zerop (logand (ash fix (- 16)) hi))))))
1065      t)))
1066
1067
1068(defun bignum-logcount (bignum)
1069  (declare (type bignum-type bignum))
1070  (let* ((length (%bignum-length bignum))
1071         (plusp (bignum-plusp bignum))
1072         (result 0))
1073    (declare (type bignum-index length)
1074             (fixnum result))
1075    (if plusp
1076      (dotimes (index length result)
1077        (incf result (the fixnum (%logcount bignum index))))
1078      (dotimes (index length result)
1079        (incf result (the fixnum (%logcount-complement bignum index)))))))
1080
1081
1082;;;; Logical operations.
1083
1084;;; NOT.
1085;;;
1086
1087;;; BIGNUM-LOGICAL-NOT -- Public.
1088;;;
1089(defun bignum-logical-not (a)
1090  (declare (type bignum-type a))
1091  (let* ((len (%bignum-length a))
1092         (res (%allocate-bignum len)))
1093    (declare (type bignum-index len))
1094    (dotimes (i len res)
1095      (%bignum-lognot i a res))))
1096
1097
1098
1099
1100;;; AND.
1101;;;
1102
1103;;; BIGNUM-LOGICAL-AND -- Public.
1104;;;
1105(defun bignum-logical-and (a b)
1106  (declare (type bignum-type a b))
1107  (let* ((len-a (%bignum-length a))
1108         (len-b (%bignum-length b))
1109         (a-plusp (bignum-plusp a))
1110         (b-plusp (bignum-plusp b)))
1111    (declare (type bignum-index len-a len-b))
1112    (cond
1113      ((< len-a len-b)
1114       (if a-plusp
1115         (logand-shorter-positive a len-a b (%allocate-bignum len-a))
1116         (logand-shorter-negative a len-a b len-b (%allocate-bignum len-b))))
1117      ((< len-b len-a)
1118       (if b-plusp
1119         (logand-shorter-positive b len-b a (%allocate-bignum len-b))
1120         (logand-shorter-negative b len-b a len-a (%allocate-bignum len-a))))
1121      (t (logand-shorter-positive a len-a b (%allocate-bignum len-a))))))
1122
1123;;; LOGAND-SHORTER-POSITIVE -- Internal.
1124;;;
1125;;; This takes a shorter bignum, a and len-a, that is positive.  Because this
1126;;; is AND, we don't care about any bits longer than a's since its infinite 0
1127;;; sign bits will mask the other bits out of b.  The result is len-a big.
1128;;;
1129(defun logand-shorter-positive (a len-a b res)
1130  (declare (type bignum-type a b res)
1131           (type bignum-index len-a))
1132  (dotimes (i len-a)
1133    (%bignum-logand i a b res))
1134  (%normalize-bignum-macro res))
1135
1136;;; LOGAND-SHORTER-NEGATIVE -- Internal.
1137;;;
1138;;; This takes a shorter bignum, a and len-a, that is negative.  Because this
1139;;; is AND, we just copy any bits longer than a's since its infinite 1 sign
1140;;; bits will include any bits from b.  The result is len-b big.
1141;;;
1142(defun logand-shorter-negative (a len-a b len-b res)
1143  (declare (type bignum-type a b res)
1144           (type bignum-index len-a len-b))
1145  (dotimes (i len-a)
1146    (%bignum-logand i a b res))
1147  (bignum-replace res b :start1 len-a :start2 len-a :end1 len-b :end2 len-b)
1148  (%normalize-bignum-macro res))
1149
1150
1151
1152;;;
1153;;;
1154;;; bignum-logandc2
1155
1156(defun bignum-logandc2 (a b)
1157  (declare (type bignum-type a b))
1158  (let* ((len-a (%bignum-length a))
1159         (len-b (%bignum-length b))
1160         (a-plusp (bignum-plusp a))
1161         (b-plusp (bignum-plusp b)))
1162    (declare (type bignum-index len-a len-b))
1163    (cond
1164     ((< len-a len-b)
1165      (logandc2-shorter-any a len-a b len-b (if a-plusp (%allocate-bignum len-a) (%allocate-bignum len-b))))
1166     ((< len-b len-a) ; b shorter
1167      (logandc1-shorter-any b len-b a len-a (if b-plusp (%allocate-bignum len-a)(%allocate-bignum len-b))))
1168     (t (logandc2-shorter-any a len-a b len-b (%allocate-bignum len-a))))))
1169
1170(defun logandc2-shorter-any (a len-a b len-b res)
1171  (declare (type bignum-type a b res)
1172           (type bignum-index len-a len-b))
1173  (dotimes (i len-a)
1174    (%bignum-logandc2 i a b res))
1175  (if (bignum-minusp a)
1176    (do ((i len-a (1+ i)))
1177          ((= i len-b))
1178        (declare (type bignum-index i))
1179        (digit-bind (h l) (%bignum-ref b i)
1180          (%bignum-set res i (%ilognot h) (%ilognot l)))))
1181  (%normalize-bignum-macro res))
1182
1183
1184
1185(defun logandc1-shorter-any (a len-a b len-b res)
1186  (declare (type bignum-type a b res)
1187           (type bignum-index len-a len-b))
1188  (dotimes (i len-a)
1189    (%bignum-logandc1 i a b res))
1190  (if (bignum-plusp a)
1191    (if (neq len-a len-b)
1192      (bignum-replace res b :start1 len-a :start2 len-a :end1 len-b :end2 len-b)))
1193  (%normalize-bignum-macro res))
1194
1195
1196
1197(defun fix-big-logand (fix big)
1198  (let* ((len-b (%bignum-length big))
1199         (res (if (< fix 0)(%allocate-bignum len-b))))
1200    (declare (fixnum fix len-b))       
1201    (let ((val (fix-digit-logand fix big res)))
1202      (if res
1203        (progn
1204          (bignum-replace res big :start1 1 :start2 1 :end1 len-b :end2 len-b)
1205          (%normalize-bignum-macro res))
1206        val))))
1207 
1208
1209(defun fix-big-logandc2 (fix big)
1210  (let* ((len-b (%bignum-length big))
1211         (res (if (< fix 0)(%allocate-bignum len-b))))
1212    (declare (fixnum fix len-b))       
1213    (let ((val (fix-digit-logandc2 fix big res)))
1214      (if res
1215        (progn
1216          (do ((i 1 (1+ i)))
1217              ((= i len-b))
1218            (declare (type bignum-index i))
1219            (digit-lognot-move i big res))
1220          (%normalize-bignum-macro res))
1221        val))))
1222
1223(defun fix-big-logandc1 (fix big)
1224  (let* ((len-b (%bignum-length big))
1225         (res (if (>= fix 0)(%allocate-bignum len-b))))
1226    (declare (fixnum fix len-b))       
1227    (let ((val (fix-digit-logandc1 fix big res)))
1228      (if res
1229        (progn 
1230          (bignum-replace res big :start1 1 :start2 1 :end1 len-b :end2 len-b)
1231          (%normalize-bignum-macro res))
1232        val))))
1233
1234
1235
1236
1237
1238
1239
1240;;; IOR.
1241;;;
1242
1243;;; BIGNUM-LOGICAL-IOR -- Public.
1244;;;
1245(defun bignum-logical-ior (a b)
1246  (declare (type bignum-type a b))
1247  (let* ((len-a (%bignum-length a))
1248         (len-b (%bignum-length b))
1249         (a-plusp (bignum-plusp a))
1250         (b-plusp (bignum-plusp b)))
1251    (declare (type bignum-index len-a len-b))
1252    (cond
1253     ((< len-a len-b)
1254      (if a-plusp
1255          (logior-shorter-positive a len-a b len-b (%allocate-bignum len-b))
1256          (logior-shorter-negative a len-a b len-b (%allocate-bignum len-b))))
1257     ((< len-b len-a)
1258      (if b-plusp
1259          (logior-shorter-positive b len-b a len-a (%allocate-bignum len-a))
1260          (logior-shorter-negative b len-b a len-a (%allocate-bignum len-a))))
1261     (t (logior-shorter-positive a len-a b len-b (%allocate-bignum len-a))))))
1262
1263;;; LOGIOR-SHORTER-POSITIVE -- Internal.
1264;;;
1265;;; This takes a shorter bignum, a and len-a, that is positive.  Because this
1266;;; is IOR, we don't care about any bits longer than a's since its infinite
1267;;; 0 sign bits will mask the other bits out of b out to len-b.  The result
1268;;; is len-b long.
1269;;;
1270(defun logior-shorter-positive (a len-a b len-b res)
1271  (declare (type bignum-type a b res)
1272           (type bignum-index len-a len-b))
1273  (dotimes (i len-a)
1274    (%bignum-logior i a b res))
1275  (if (not (eql len-a len-b))
1276    (bignum-replace res b :start1 len-a :start2 len-a :end1 len-b :end2 len-b))
1277  (%normalize-bignum-macro res))
1278
1279;;; LOGIOR-SHORTER-NEGATIVE -- Internal.
1280;;;
1281;;; This takes a shorter bignum, a and len-a, that is negative.  Because this
1282;;; is IOR, we just copy any bits longer than a's since its infinite 1 sign
1283;;; bits will include any bits from b.  The result is len-b long.
1284;;;
1285(defun logior-shorter-negative (a len-a b len-b res)
1286  (declare (type bignum-type a b res)
1287           (type bignum-index len-a len-b))
1288  (dotimes (i len-a)
1289    (%bignum-logior i a b res))
1290  ; silly to propagate sign and then normalize it away
1291  ; but may need to do at least once - but we are only normalizing from len-a?
1292  ; ah but the sign needs to be correct
1293  (do ((i len-a (1+ i)))
1294      ((= i len-b))
1295    (declare (type bignum-index i))
1296    (%bignum-set res i #xffff #xffff))
1297  (%normalize-bignum-macro res))
1298
1299
1300
1301
1302;;; XOR.
1303;;;
1304
1305;;; BIGNUM-LOGICAL-XOR -- Public.
1306;;;
1307(defun bignum-logical-xor (a b)
1308  (declare (type bignum-type a b))
1309  (let ((len-a (%bignum-length a))
1310        (len-b (%bignum-length b)))
1311    (declare (type bignum-index len-a len-b))
1312    (if (< len-a len-b)
1313        (bignum-logical-xor-aux a len-a b len-b (%allocate-bignum len-b))
1314        (bignum-logical-xor-aux b len-b a len-a (%allocate-bignum len-a)))))
1315
1316;;; BIGNUM-LOGICAL-XOR-AUX -- Internal.
1317;;;
1318;;; This takes the the shorter of two bignums in a and len-a.  Res is len-b
1319;;; long.  Do the XOR.
1320;;;
1321(defun bignum-logical-xor-aux (a len-a b len-b res)
1322  (declare (type bignum-type a b res)
1323           (type bignum-index len-a len-b))
1324  (dotimes (i len-a)
1325    (%bignum-logxor i a b res))
1326  (unless (= len-a len-b)
1327    (let ((sign (if (bignum-minusp a) #xffff 0)))
1328      (do ((i len-a (1+ i)))
1329          ((= i len-b))
1330        (declare (type bignum-index i))
1331        (digit-bind (h l) (%bignum-ref b i)
1332          (%bignum-set res i (%ilogxor sign h)(%ilogxor sign l))))))
1333  (%normalize-bignum-macro res))
1334
1335
1336
1337
1338
1339;;;; LDB (load byte)
1340
1341; [slh] 'twas all commented out - thank gawd
1342
1343
1344;;;; TRUNCATE.
1345
1346;;; This is the original sketch of the algorithm from which I implemented this
1347;;; TRUNCATE, assuming both operands are bignums.  I should modify this to work
1348;;; with the documentation on my functions, as a general introduction.  I've
1349;;; left this here just in case someone needs it in the future.  Don't look
1350;;; at this unless reading the functions' comments leaves you at a loss.
1351;;; Remember this comes from Knuth, so the book might give you the right general
1352;;; overview.
1353;;;
1354;;;
1355;;; (truncate x y):
1356;;;
1357;;; If X's magnitude is less than Y's, then result is 0 with remainder X.
1358;;;
1359;;; Make x and y positive, copying x if it is already positive.
1360;;;
1361;;; Shift y left until there's a 1 in the 30'th bit (most significant, non-sign
1362;;;       digit)
1363;;;    Just do most sig digit to determine how much to shift whole number.
1364;;; Shift x this much too.
1365;;; Remember this initial shift count.
1366;;;
1367;;; Allocate q to be len-x minus len-y quantity plus 1.
1368;;;
1369;;; i = last digit of x.
1370;;; k = last digit of q.
1371;;;
1372;;; LOOP
1373;;;
1374;;; j = last digit of y.
1375;;;
1376;;; compute guess.
1377;;; if x[i] = y[j] then g = #xFFFFFFFF
1378;;; else g = x[i]x[i-1]/y[j].
1379;;;
1380;;; check guess.
1381;;; %UNSIGNED-MULTIPLY returns b and c defined below.
1382;;;    a = x[i-1] - (logand (* g y[j]) #xFFFFFFFF).
1383;;;       Use %UNSIGNED-MULTIPLY taking low-order result.
1384;;;    b = (logand (ash (* g y[j-1]) -32) #xFFFFFFFF).
1385;;;    c = (logand (* g y[j-1]) #xFFFFFFFF).
1386;;; if a < b, okay.
1387;;; if a > b, guess is too high
1388;;;    g = g - 1; go back to "check guess".
1389;;; if a = b and c > x[i-2], guess is too high
1390;;;    g = g - 1; go back to "check guess".
1391;;; GUESS IS 32-BIT NUMBER, SO USE THING TO KEEP IN SPECIAL REGISTER
1392;;; SAME FOR A, B, AND C.
1393;;;
1394;;; Subtract g * y from x[i - len-y+1]..x[i].  See paper for doing this in step.
1395;;; If x[i] < 0, guess is fucked.
1396;;;    negative g, then add 1
1397;;;    zero or positive g, then subtract 1
1398;;; AND add y back into x[len-y+1..i].
1399;;;
1400;;; q[k] = g.
1401;;; i = i - 1.
1402;;; k = k - 1.
1403;;;
1404;;; If k>=0, goto LOOP.
1405;;;
1406;;;
1407;;; Now quotient is good, but remainder is not.
1408;;; Shift x right by saved initial left shifting count.
1409;;;
1410;;; Check quotient and remainder signs.
1411;;; x pos y pos --> q pos r pos
1412;;; x pos y neg --> q neg r pos
1413;;; x neg y pos --> q neg r neg
1414;;; x neg y neg --> q pos r neg
1415;;;
1416;;; Normalize quotient and remainder.  Cons result if necessary.
1417;;;
1418
1419
1420
1421
1422;;; BIGNUM-TRUNCATE -- Public.
1423;;;
1424;;; This divides x by y returning the quotient and remainder.  In the general
1425;;; case, we shift y to setup for the algorithm, and we use two buffers to save
1426;;; consing intermediate values.  X gets destructively modified to become the
1427;;; remainder, and we have to shift it to account for the initial Y shift.
1428;;; After we multiple bind q and r, we first fix up the signs and then return
1429;;; the normalized results.
1430;;;
1431
1432
1433(defun bignum-truncate (x1 y1 &optional no-rem)
1434  (declare (type bignum-type x1 y1))
1435  (let* ((x-plusp (bignum-plusp x1))
1436         (y-plusp (bignum-plusp y1)))
1437    (flet 
1438      ((do-it (x y) 
1439         (let* ((len-x (%bignum-length x))
1440                (len-y (%bignum-length y)))
1441           (declare (fixnum len-x len-y))
1442           
1443           (let ((c (bignum-compare y x)))
1444             (cond 
1445              ((eql c 1)  ; >
1446               (return-from bignum-truncate (values 0 x1)))
1447              ((eql c 0)(values 1 0))  ; =  might as well since did compare anyway
1448              ((< len-y 2)
1449               (multiple-value-bind (q r)
1450                                    (bignum-truncate-single-digit x len-x y no-rem)
1451                 (values q
1452                         (unless no-rem
1453                           (cond (x-plusp r)
1454                                 ((typep r 'fixnum) (the fixnum (- (the fixnum r))))
1455                                 (t (negate-bignum-in-place r)
1456                                    (%normalize-bignum-macro r )))))))
1457              (t
1458               (let* ((len-x+1 (1+ len-x)))
1459                 (declare (fixnum len-x+1))
1460                 (with-bignum-buffers ((truncate-x len-x+1)
1461                                       (truncate-y (the fixnum (1+ len-y))))
1462                   (let ((y-shift (shift-y-for-truncate y)))
1463                     (shift-and-store-truncate-buffers truncate-x truncate-y x len-x y len-y y-shift)
1464                     (values (do-truncate truncate-x truncate-y len-x+1 len-y)
1465                             ;; DO-TRUNCATE must execute first.
1466                             (when (not no-rem)                               
1467                               (when (not (eql 0 y-shift))                                 
1468                                 (let* ((res-len-1 (1- len-y)))
1469                                   (declare (fixnum res-len-1))
1470                                   (bignum-shift-right-loop-1 y-shift truncate-x truncate-x res-len-1 0)))                               
1471                               (let ((the-res (%normalize-bignum-macro truncate-x )))
1472                                 (if (not (fixnump the-res))
1473                                   (if x-plusp (copy-bignum the-res) (negate-bignum the-res))
1474                                   (if x-plusp the-res (the fixnum (- (the fixnum the-res)))))
1475                                     ))))))))))))
1476      (multiple-value-bind (q r)(with-negated-bignum-buffers x1 y1 do-it)
1477        (let ((quotient (cond ((eq x-plusp y-plusp) q)
1478                              ((typep q 'fixnum) (the fixnum (- (the fixnum q))))
1479                              (t (negate-bignum-in-place q)
1480                                 (%normalize-bignum-macro q )))))
1481          (if no-rem
1482            quotient           
1483            (values quotient r)))))))
1484
1485(defun bignum-rem (x1 y1)
1486  (declare (type bignum-type x1 y1)) 
1487  (let* ((x-plusp (bignum-plusp x1)))
1488    (flet 
1489      ((do-it (x y) 
1490         (let* ((len-x (%bignum-length x))
1491                (len-y (%bignum-length y)))
1492           (declare (fixnum len-x len-y))           
1493           (let ((c (bignum-compare y x)))
1494             (cond 
1495              ((eql c 1) (return-from bignum-rem x1))
1496              ((eql c 0) 0)  ; =  might as well since did compare anyway
1497              ((< len-y 2)
1498               (let ((r (bignum-truncate-single-digit-no-quo x len-x y)))  ; phooey
1499                 (cond (x-plusp r)
1500                       ((typep r 'fixnum) (the fixnum (- (the fixnum r))))
1501                       (t (negate-bignum-in-place r)
1502                          (%normalize-bignum-macro r )))))
1503              (t
1504               (let* ((len-x+1 (1+ len-x)))
1505                 (declare (fixnum len-x+1))
1506                 (with-bignum-buffers ((truncate-x len-x+1)
1507                                       (truncate-y (the fixnum (1+ len-y))))
1508                   (let ((y-shift (shift-y-for-truncate y)))
1509                     (shift-and-store-truncate-buffers truncate-x truncate-y x len-x y len-y y-shift)
1510                     (do-truncate-no-quo truncate-x truncate-y len-x+1 len-y)
1511                     (when (not (eql 0 y-shift))                                 
1512                       (let* ((res-len-1 (1- len-y)))
1513                         (declare (fixnum res-len-1))
1514                         (bignum-shift-right-loop-1 y-shift truncate-x truncate-x res-len-1 0)))
1515                     (let ((the-res (%normalize-bignum-macro truncate-x)))
1516                       (if (not (fixnump the-res))
1517                         (if x-plusp (copy-bignum the-res) (negate-bignum the-res))
1518                         (if x-plusp the-res (the fixnum (- (the fixnum the-res)))))))))))))))
1519      (declare (dynamic-extent #'do-it))
1520      (with-negated-bignum-buffers x1 y1 do-it))))
1521
1522
1523
1524;;; BIGNUM-TRUNCATE-SINGLE-DIGIT -- Internal.
1525;;;
1526;;; This divides x by y when y is a single bignum digit.  BIGNUM-TRUNCATE fixes
1527;;; up the quotient and remainder with respect to sign and normalization.
1528;;;
1529;;; We don't have to worry about shifting y to make its most significant digit
1530;;; sufficiently large for %FLOOR to return 32-bit quantities for the q-digit
1531;;; and r-digit.  If y is a single digit bignum, it is already large enough
1532;;; for %FLOOR.  That is, it has some bits on pretty high in the digit.
1533;;;
1534;;; x is positive
1535(defun bignum-truncate-single-digit (x len-x y &optional no-rem)
1536  (declare (type bignum-index len-x))
1537  (let* ((maybe-q (%allocate-bignum 2))
1538         (q (if (<= len-x 2) maybe-q (%allocate-bignum len-x)))
1539         (r-h 0)
1540         (r-l 0))
1541    (declare (dynamic-extent maybe-q))
1542    (digit-bind (y-h y-l) (%bignum-ref y 0)
1543      (multiple-value-setq (r-h r-l)(%floor-loop-quo x q y-h y-l))     
1544      (if (eq q maybe-q)
1545        (progn 
1546          (setq q (%normalize-bignum-macro q))
1547          (if (not (fixnump q)) (setq q (copy-bignum q))))
1548        (setq q (%normalize-bignum-macro q )))
1549      ;; might as well make a fixnum if possible
1550      (if no-rem
1551        q
1552        (if (> (%digits-sign-bits r-h r-l)  target::fixnumshift)
1553          (values q (%ilogior (%ilsl 16 r-h) r-l))
1554          (let ((rem (%allocate-bignum 1)))
1555            (%bignum-set rem 0 r-h r-l)
1556            (values q rem)))))))
1557
1558;;; aka rem
1559(defun bignum-truncate-single-digit-no-quo (x len-x y)
1560  (declare (type bignum-index len-x))
1561  (declare (ignore len-x))
1562  (let (;(q (%allocate-bignum len-x))
1563        (r-h 0)
1564        (r-l 0))
1565    (progn
1566      (digit-bind (y-h y-l) (%bignum-ref y 0)
1567        (multiple-value-setq (r-h r-l)(%floor-loop-no-quo x y-h y-l))
1568        ; might as well make a fixnum if possible
1569        (if (> (%digits-sign-bits r-h r-l)  target::fixnumshift)
1570          (%ilogior (%ilsl 16 r-h) r-l)
1571          (let ((rem (%allocate-bignum 1)))
1572            (%bignum-set rem 0 r-h r-l)
1573            rem))))))
1574
1575;; so big deal - we save a one digit bignum for y
1576;; and bigger deal if x is negative - we copy or negate x, computing result destructively
1577;;  - thus avoiding making a negated x in addition to result
1578;;
1579(defun bignum-truncate-by-fixnum (x y)
1580  (declare (fixnum y))
1581  (when (eql y 0)(error (make-condition 'division-by-zero :operation 'truncate :operands (list x y))))
1582  (let* ((len-x (%bignum-length x))
1583         (x-minus (bignum-minusp x))
1584         (maybe-q (%allocate-bignum 3))
1585         (q (if x-minus
1586              (if (<= len-x 2)
1587                (dotimes (i 3 (negate-bignum-in-place maybe-q))
1588                  (if (< i len-x)
1589                    (multiple-value-bind (hi lo) (%bignum-ref x i)
1590                      (%bignum-set maybe-q i hi lo))
1591                    (%bignum-set maybe-q i 65535 65535)))
1592                (negate-bignum x))
1593              (if (<= len-x 2) ; this was broken if negative because bignum-replace just copies min len-a len-b digits
1594                (progn
1595                  (bignum-replace maybe-q x)               
1596                  maybe-q)
1597                (%allocate-bignum len-x))))      ;  q is new big or -x
1598         ;(len-q (%bignum-length q))
1599         (y-minus (minusp y))         
1600         (y (if y-minus (- y) y)))
1601    (declare (fixnum y))
1602    (declare (type bignum-index len-x))
1603    (declare (dynamic-extent maybe-q))
1604    (let* ((r-h 0)
1605           (r-l 0)
1606           (y-h (%ilogand #xffff (%iasr 16 y)))
1607           (y-l (%ilogand #xffff y)))
1608      (multiple-value-setq (r-h r-l)(%floor-loop-quo (if x-minus q x) q y-h y-l))     
1609      (let* ((r (%ilogior (%ilsl 16 r-h) r-l)))
1610        (declare (fixnum r))
1611        (when (neq x-minus y-minus)(negate-bignum-in-place q))
1612        (setq q (%normalize-bignum-macro q ))
1613        (values (if (eq q maybe-q) (copy-bignum q) q)
1614                (if x-minus (the fixnum (- r)) r))))))
1615
1616(defun bignum-truncate-by-fixnum-no-quo (x y)
1617  (declare (fixnum y))
1618  (when (eql y 0)(error (make-condition 'division-by-zero :operation 'truncate :operands (list x Y))))
1619  (let* ((len-x (%bignum-length x))
1620         (x-minus (bignum-minusp x))
1621         (y-minus (minusp y))         
1622         (y (if y-minus (- y) y)))
1623    (declare (fixnum y))
1624    (declare (type bignum-index len-x))
1625      (let* (;(LEN-Q (%BIGNUM-LENGTH Q))
1626             (r-h 0)
1627             (r-l 0)
1628             (y-h (%ilogand #xffff (%iasr 16 y)))
1629             (y-l (%ilogand #xffff y)))
1630        (if x-minus
1631          (with-bignum-buffers ((q (the fixnum (1+ len-x))))
1632            (negate-bignum x nil q)
1633            (multiple-value-setq (r-h r-l)(%floor-loop-no-quo q y-h y-l)))
1634          (multiple-value-setq (r-h r-l)(%floor-loop-no-quo x y-h y-l)))       
1635        (let* ((r (%ilogior (%ilsl 16 r-h) r-l)))
1636          (declare (fixnum r))
1637          (if x-minus (the fixnum (- r)) r)))))
1638
1639
1640;;; DO-TRUNCATE -- Internal.
1641;;;
1642;;; This divides *truncate-x* by *truncate-y*, and len-x and len-y tell us how
1643;;; much of the buffers we care about.  TRY-BIGNUM-TRUNCATE-GUESS modifies
1644;;; *truncate-x* on each interation, and this buffer becomes our remainder.
1645;;;
1646;;; *truncate-x* definitely has at least three digits, and it has one more than
1647;;; *truncate-y*.  This keeps i, i-1, i-2, and low-x-digit happy.  Thanks to
1648;;; SHIFT-AND-STORE-TRUNCATE-BUFFERS.
1649;;;
1650
1651
1652(defun do-truncate (truncate-x truncate-y len-x len-y)
1653  (declare (type bignum-index len-x len-y))
1654  (let* ((len-q (- len-x len-y))
1655         ;; Add one for extra sign digit in case high bit is on.
1656         (len-res (1+ len-q))
1657         (maybe-q (%allocate-bignum 2))         
1658         (q (if (<= len-res 2) maybe-q (%allocate-bignum len-res)))
1659         (k (1- len-q))
1660         (i (1- len-x))
1661         (low-x-digit (- i len-y)))
1662    (declare (type bignum-index len-q len-res k i  low-x-digit))
1663    (declare (dynamic-extent maybe-q))
1664    (loop
1665      (digit-bind (h l)
1666                  (digit-bind (guess-h guess-l)
1667                              (bignum-truncate-guess-2 truncate-x i truncate-y (the fixnum (1- len-y)))                                 
1668                    (try-bignum-truncate-guess truncate-x truncate-y guess-h guess-l len-y low-x-digit))
1669        (%bignum-set q k h l))
1670      (cond ((zerop k) (return))
1671            (t (decf k)
1672               (decf low-x-digit)
1673               (setq i (1- i)))))
1674    (if (eq q maybe-q)
1675      (progn 
1676        (setq q (%normalize-bignum-macro q))
1677        (if (fixnump q) q (copy-bignum q)))
1678      (%normalize-bignum-macro q))))
1679
1680(defun do-truncate-no-quo (truncate-x truncate-y len-x len-y)
1681  (declare (type bignum-index len-x len-y))
1682  (let* ((len-q (- len-x len-y))
1683         (k (1- len-q))
1684         (i (1- len-x))
1685         (low-x-digit (- i len-y)))
1686    (declare (type bignum-index len-q k i  low-x-digit))
1687    (loop
1688      (digit-bind (guess-h guess-l) (bignum-truncate-guess-2 truncate-x i truncate-y (the fixnum (1- len-y)))                                 
1689        (try-bignum-truncate-guess truncate-x truncate-y guess-h guess-l len-y low-x-digit)
1690        (cond ((zerop k) (return))
1691              (t (decf k)
1692                 (decf low-x-digit)
1693                 (setq i (1- i))))))
1694    nil))
1695
1696;;; TRY-BIGNUM-TRUNCATE-GUESS -- Internal.
1697;;;
1698;;; This takes a digit guess, multiplies it by *truncate-y* for a result one
1699;;; greater in length than len-y, and subtracts this result from *truncate-x*.
1700;;; Low-x-digit is the first digit of x to start the subtraction, and we know x
1701;;; is long enough to subtract a len-y plus one length bignum from it.  Next we
1702;;; check the result of the subtraction, and if the high digit in x became
1703;;; negative, then our guess was one too big.  In this case, return one less
1704;;; than guess passed in, and add one value of y back into x to account for
1705;;; subtracting one too many.  Knuth shows that the guess is wrong on the order
1706;;; of 3/b, where b is the base (2 to the digit-size power) -- pretty rarely.
1707;;;
1708
1709(defun try-bignum-truncate-guess (truncate-x truncate-y guess-h guess-l len-y low-x-digit)
1710  (declare (type bignum-index low-x-digit len-y))
1711
1712  (let ((carry-digit-h 0)
1713        (carry-digit-l 0)
1714        (borrow 1)
1715        (i low-x-digit))
1716    (declare (type bignum-index i)
1717             (fixnum borrow carry-digit-h carry-digit-l))
1718    ;; Multiply guess and divisor, subtracting from dividend simultaneously.
1719    (dotimes (j len-y)
1720      (multiple-value-bind (y-h y-l) (%bignum-ref truncate-y j)
1721        (multiple-value-bind (high-h high-l low-h low-l)
1722            (%multiply-and-add-1 guess-h
1723                               guess-l
1724                               y-h
1725                               y-l
1726                               carry-digit-h
1727                               carry-digit-l)
1728          (setq carry-digit-h high-h
1729                carry-digit-l high-l)
1730          (multiple-value-bind (tx-h tx-l) (%bignum-ref truncate-x i)
1731            (multiple-value-bind (x-h x-l temp-borrow)
1732                (%subtract-with-borrow-1 tx-h tx-l low-h low-l borrow)
1733              (%bignum-set truncate-x i x-h x-l)
1734              (setq borrow temp-borrow)))))
1735      (incf i))
1736    (multiple-value-bind (tx-h tx-l) (%bignum-ref truncate-x i)
1737      (multiple-value-bind (x-h x-l)
1738          (%subtract-with-borrow-1 tx-h tx-l carry-digit-h carry-digit-l borrow)
1739        (%bignum-set truncate-x i x-h x-l)))
1740    ;; See if guess is off by one, adding one Y back in if necessary.
1741
1742
1743    (cond ((%digit-0-or-plusp truncate-x i)
1744           (values guess-h guess-l))
1745          (t
1746           ;; If subtraction has negative result, add one divisor value back
1747           ;; in.  The guess was one too large in magnitude.
1748           ;; hmm - happens about 1.6% of the time
1749           (bignum-add-loop-+ low-x-digit truncate-x truncate-y len-y)
1750           (%subtract-one guess-h guess-l)
1751           ;(%subtract-with-borrow guess-h guess-l 0 1 1)
1752           ))))
1753
1754
1755
1756;;; BIGNUM-TRUNCATE-GUESS -- Internal.
1757;;;
1758;;; This returns a guess for the next division step.  Y1 is the highest y
1759;;; digit, and y2 is the second to highest y digit.  The x... variables are
1760;;; the three highest x digits for the next division step.
1761;;;
1762;;; From Knuth, our guess is either all ones or x-i and x-i-1 divided by y1,
1763;;; depending on whether x-i and y1 are the same.  We test this guess by
1764;;; determining whether guess*y2 is greater than the three high digits of x
1765;;; minus guess*y1 shifted left one digit:
1766;;;    ------------------------------
1767;;;   |    x-i    |   x-i-1  | x-i-2 |
1768;;;    ------------------------------
1769;;;    ------------------------------
1770;;; - | g*y1 high | g*y1 low |   0   |
1771;;;    ------------------------------
1772;;;                ...                   <   guess*y2     ???
1773;;; If guess*y2 is greater, then we decrement our guess by one and try again.
1774;;; This returns a guess that is either correct or one too large.
1775;;;
1776;;; the y's come from *truncate-y*, x's from *truncate-x*
1777;;; doing this in lap is not screamingly difficult - x's at i, i-1, i-2
1778
1779
1780
1781
1782
1783(defun bignum-truncate-guess-2 (x xidx y yidx)
1784  (digit-bind (guess-h guess-l)
1785              (%floor-99 x xidx y yidx)
1786    (truncate-guess-loop guess-h guess-l x xidx y yidx)))
1787
1788
1789
1790   
1791
1792;;; SHIFT-Y-FOR-TRUNCATE -- Internal.
1793;;;
1794;;; This returns the amount to shift y to place a one in the second highest
1795;;; bit.  Y must be positive.  If the last digit of y is zero, then y has a
1796;;; one in the previous digit's sign bit, so we know it will take one less
1797;;; than digit-size to get a one where we want.  Otherwise, we count how many
1798;;; right shifts it takes to get zero; subtracting this value from digit-size
1799;;; tells us how many high zeros there are which is one more than the shift
1800;;; amount sought.
1801;;;
1802;;; Note: This is exactly the same as one less than the integer-length of the
1803;;; last digit subtracted from the digit-size.
1804;;;
1805;;; We shift y to make it sufficiently large that doing the 64-bit by 32-bit
1806;;; %FLOOR calls ensures the quotient and remainder fit in 32-bits.
1807;;;
1808(defun shift-y-for-truncate (y)
1809  (the fixnum (1- (the fixnum (%bignum-sign-bits y)))))
1810
1811;;; SHIFT-AND-STORE-TRUNCATE-BUFFERS -- Internal.
1812;;;
1813;;; Stores two bignums into the truncation bignum buffers, shifting them on the
1814;;; way in.  This assumes x and y are positive and at least two in length, and
1815;;; it assumes *truncate-x* and *truncate-y* are one digit longer than x and y.
1816;;;
1817(defun shift-and-store-truncate-buffers (truncate-x truncate-y x len-x y len-y shift)
1818  (declare (type bignum-index len-x len-y)
1819           (type (integer 0 (#.digit-size)) shift))
1820  (cond ((eql 0 shift)
1821         (bignum-replace truncate-x x :end1 len-x)
1822         (bignum-replace truncate-y y :end1 len-y))
1823        (t
1824         (bignum-ashift-left-unaligned x 0 shift (the fixnum (1+ len-x)) truncate-x)
1825         (bignum-ashift-left-unaligned y 0 shift (the fixnum (1+ len-y)) truncate-y))))
1826
1827
1828
1829
1830;;;; General utilities.
1831
1832
1833;;; %NORMALIZE-BIGNUM-BUFFER -- Internal.
1834;;;
1835;;; Internal in-place operations use this to fixup remaining digits in the
1836;;; incoming data, such as in-place shifting.  This is basically the same as
1837;;; the first form in %NORMALIZE-BIGNUM, but we return the length of the buffer
1838;;; instead of shrinking the bignum.
1839;;;
1840
1841
1842
1843   
1844
1845
1846
1847
1848;;; %NORMALIZE-BIGNUM -- Internal.
1849;;;
1850;;; This drops the last digit if it is unnecessary sign information.  It
1851;;; repeats this as needed, possibly ending with a fixnum.  If the resulting
1852;;; length from shrinking is one, see if our one word is a fixnum.  Shift the
1853;;; possible fixnum bits completely out of the word, and compare this with
1854;;; shifting the sign bit all the way through.  If the bits are all 1's or 0's
1855;;; in both words, then there are just sign bits between the fixnum bits and
1856;;; the sign bit.  If we do have a fixnum, shift it over for the two low-tag
1857;;; bits.
1858;;;
1859
1860(defun %normalize-bignum (res)
1861  ;(declare (optimize (speed 3)(safety 0)))
1862  (%normalize-bignum-2 t res))
1863
1864;;; %MOSTLY-NORMALIZE-BIGNUM -- Internal.
1865;;;
1866;;; This drops the last digit if it is unnecessary sign information.  It
1867;;; repeats this as needed, possibly ending with a fixnum magnitude but never
1868;;; returning a fixnum.
1869;;;
1870
1871(defun %mostly-normalize-bignum (res &optional len)
1872  (declare (ignore len))
1873  (%normalize-bignum-2 nil res))
1874
1875
1876
1877
1878; think its ok
1879(defun ldb32 (hi-data lo-data size pos)
1880  (declare (fixnum hi-data lo-data size pos))
1881  (let* ((hi-bit (+ pos size))
1882         (mask (%i- (%ilsl size 1) 1)))
1883    (declare (fixnum hi-bit mask))   
1884    (%ilogand mask (if (< hi-bit 16)
1885                     (%iasr pos lo-data)
1886                     (if (>= pos 16)
1887                       (%ilsr (the fixnum (- pos 16)) hi-data)
1888                       (%ilogior 
1889                         (%iasr pos lo-data)
1890                         (%ilsl (the fixnum (- 16 pos)) hi-data)))))))
1891
1892
1893
1894
1895
1896; this was wrong for negative bigs when byte includes or exceeds sign
1897(defun %ldb-fixnum-from-bignum (bignum size position)
1898  (declare (fixnum size position))
1899  (let* ((low-idx (ash position -5))
1900         (low-bit (logand position 31))
1901         (hi-bit (+ low-bit size))
1902         (len (%bignum-length bignum))
1903         (minusp (bignum-minusp bignum)))
1904    (declare (fixnum size position low-bit hi-bit low-idx len))
1905    (if (>= low-idx len)
1906      (if minusp (1- (ash 1 size)) 0)     
1907      (multiple-value-bind (hi lo)(%bignum-ref bignum low-idx)
1908        (let ((chunk-lo (ldb32 hi lo (min size (%i- 32 low-bit)) low-bit)))
1909          (let ((val
1910                 (if (< hi-bit 32) 
1911                   chunk-lo
1912                   (progn
1913                     (setq low-idx (1+ low-idx))
1914                     (multiple-value-setq (hi lo)
1915                       (if (>= low-idx len)
1916                         (if minusp (values #xffff #xffff)(values 0 0))
1917                         (%bignum-ref bignum low-idx)))
1918                     (let ((chunk-hi (ldb32 hi lo (%i- size (%i- 32 low-bit)) 0)))
1919                       (%ilogior (ash chunk-hi (%i- 32 low-bit)) chunk-lo))))))
1920            val))))))
1921
1922(defun load-byte (size position integer)
1923  (if (and (bignump integer)
1924           (<= size (- 31 target::fixnumshift))
1925           (fixnump position))
1926    (%ldb-fixnum-from-bignum integer size position)
1927    (let ((mask (byte-mask size)))
1928      (if (and (fixnump mask) (fixnump integer)(fixnump position))
1929        (%ilogand mask (%iasr position integer))
1930        (logand mask (ash integer (- position)))))))   
1931
1932
1933#+safe-but-slow
1934(defun %bignum-bignum-gcd (u v)
1935  (setq u (abs u) v (abs v))
1936  (do* ((g 1 (ash g 1)))
1937       ((or (oddp u) (oddp v))
1938        (do* ()
1939             ((zerop u) (* g v))
1940          (cond ((evenp u) (setq u (ash u -1)))
1941                ((evenp v) (setq v (ash v -1)))
1942                (t (let* ((temp (ash (abs (- u v)) -1)))
1943                     (if (< u v)
1944                       (setq v temp)
1945                       (setq u temp)))))))
1946    (setq u (ash u -1) v (ash v -1))))
1947
1948
1949(defun %positive-bignum-bignum-gcd (u0 v0)
1950  (let* ((u-len (%bignum-length u0))
1951         (v-len (%bignum-length v0)))
1952    (declare (fixnum u-len v-len))
1953    (if (or (< u-len v-len)
1954            (and (= u-len v-len)
1955                 (< (bignum-compare u0 v0) 0)))
1956      (psetq u0 v0 v0 u0 u-len v-len v-len u-len))
1957    (with-bignum-buffers ((u u-len)
1958                          (u2 u-len)
1959                          (v v-len)
1960                          (v2 v-len))
1961      (bignum-replace u u0)
1962      (bignum-replace v v0)
1963      (let* ((u-trailing-0-bits (%bignum-count-trailing-zero-bits u))
1964             (u-trailing-0-digits (ash u-trailing-0-bits -5))
1965             (v-trailing-0-bits (%bignum-count-trailing-zero-bits v))
1966             (v-trailing-0-digits (ash v-trailing-0-bits -5)))
1967        (declare (fixnum u-trailing-0-bits v-trailing-0-bits))
1968        (unless (zerop u-trailing-0-bits)
1969          (bignum-shift-right-loop-1
1970           (logand u-trailing-0-bits 31)
1971           u2
1972           u
1973           (the fixnum (1- (the fixnum (- u-len u-trailing-0-digits ))))
1974           u-trailing-0-digits)
1975          (rotatef u u2)
1976          (%mostly-normalize-bignum-macro u)
1977          (setq u-len (%bignum-length u)))
1978        (unless (zerop v-trailing-0-bits)
1979          (bignum-shift-right-loop-1
1980           (logand v-trailing-0-bits 31)
1981           v2
1982           v
1983           (the fixnum (1- (the fixnum (- v-len v-trailing-0-digits))))
1984           v-trailing-0-digits)
1985          (rotatef v v2)
1986          (%mostly-normalize-bignum-macro v)
1987          (setq v-len (%bignum-length v)))
1988        (let* ((shift (min u-trailing-0-bits
1989                           v-trailing-0-bits)))
1990          (loop
1991            (let* ((fix-u (and (= u-len 1)
1992                               (let* ((hi-u (%bignum-ref-hi u 0)))
1993                                 (declare (fixnum hi-u))
1994                                 (= hi-u (the fixnum
1995                                           (logand hi-u (ash target::target-most-positive-fixnum -16)))))
1996                               (uvref u 0)))
1997                   (fix-v (and (= v-len 1)
1998                               (let* ((hi-v (%bignum-ref-hi v 0)))
1999                                 (declare (fixnum hi-v))
2000                                 (= hi-v (the fixnum
2001                                           (logand hi-v (ash target::target-most-positive-fixnum -16)))))
2002                               (uvref v 0))))
2003              (if fix-v
2004                (if fix-u
2005                  (return (ash (%fixnum-gcd fix-u fix-v) shift))
2006                  (return (ash (bignum-fixnum-gcd u fix-v) shift)))
2007                (if fix-u
2008                  (return (ash (bignum-fixnum-gcd v fix-u) shift)))))
2009             
2010            (let* ((signum (if (> u-len v-len)
2011                             1
2012                             (if (< u-len v-len)
2013                               -1
2014                               (bignum-compare u v)))))
2015              (declare (fixnum signum))
2016              (case signum
2017                (0                      ; (= u v)
2018                 (if (zerop shift)
2019                   (let* ((copy (%allocate-bignum u-len)))
2020                     (bignum-replace copy u)
2021                     (return copy))
2022                   (return (ash u shift))))
2023                (1                      ; (> u v)
2024                 (bignum-subtract-loop u u-len v v-len u)
2025                 (%mostly-normalize-bignum-macro u)
2026                 (setq u-len (%bignum-length u))
2027                 (setq u-trailing-0-bits
2028                       (%bignum-count-trailing-zero-bits u)
2029                       u-trailing-0-digits
2030                       (ash u-trailing-0-bits -5))
2031                 (unless (zerop u-trailing-0-bits)
2032                   (%init-misc 0 u2)
2033                   (bignum-shift-right-loop-1
2034                    (logand u-trailing-0-bits 31)
2035                    u2
2036                    u
2037                    (the fixnum (1- (the fixnum (- u-len
2038                                                   u-trailing-0-digits))))
2039                    u-trailing-0-digits)
2040                   (rotatef u u2)
2041                   (%mostly-normalize-bignum-macro u)
2042                   (setq u-len (%bignum-length u))))
2043                (t                      ; (> v u)
2044                 (bignum-subtract-loop v v-len u u-len v)
2045                 (%mostly-normalize-bignum-macro v)
2046                 (setq v-len (%bignum-length v))
2047                 (setq v-trailing-0-bits
2048                       (%bignum-count-trailing-zero-bits v)
2049                       v-trailing-0-digits
2050                       (ash v-trailing-0-bits -5))
2051                 (unless (zerop v-trailing-0-bits)
2052                   (%init-misc 0 v2)
2053                   (bignum-shift-right-loop-1
2054                    (logand v-trailing-0-bits 31)
2055                    v2
2056                    v
2057                    (the fixnum (1- (the fixnum (- v-len v-trailing-0-digits))))
2058                    v-trailing-0-digits)
2059                   (rotatef v v2)
2060                   (%mostly-normalize-bignum-macro v)
2061                   (setq v-len (%bignum-length v))))))))))))
2062
2063(defun %bignum-bignum-gcd (u v)
2064  (with-negated-bignum-buffers u v %positive-bignum-bignum-gcd))
2065
2066(defun unsignedwide->integer (uwidep)
2067  (with-bignum-buffers ((b 3))
2068    (setf (uvref b 0) (%get-unsigned-long uwidep 4)
2069          (uvref b 1) (%get-unsigned-long uwidep 0))
2070    (let* ((n (%normalize-bignum b)))
2071      (if (typep n 'bignum)
2072        (copy-bignum n)
2073        n))))
2074
2075(defun one-bignum-factor-of-two (a) 
2076  (declare (type bignum-type a))
2077  (let ((len (%bignum-length a)))
2078    (declare (fixnum len))
2079    (dotimes (i len)
2080      (multiple-value-bind (a-h a-l) (%bignum-ref a i)
2081        (declare (fixnum a-h a-l))
2082        (unless (and (= a-h 0)(= a-l 0))
2083          (return (+ (%ilsl 5 i)
2084                     (let* ((j 0)
2085                            (a a-l))
2086                       (declare (fixnum a j))
2087                       (if (= a-l 0) (setq j 16 a a-h))
2088                       (dotimes (i 16)           
2089                         (if (oddp a)
2090                           (return (%i+ j i))
2091                           (setq a (%iasr 1 a))))))))))))
2092
2093(defun logbitp (index integer)
2094  "Predicate returns T if bit index of integer is a 1."
2095  (number-case index
2096    (fixnum
2097     (if (minusp (the fixnum index))(report-bad-arg index '(integer 0))))
2098    (bignum
2099     ;; assuming bignum cant have more than most-positive-fixnum bits
2100     ;; (2 expt 24 longs)
2101     (if (bignum-minusp index)(report-bad-arg index '(integer 0)))
2102     ;; should error if integer isn't
2103     (return-from logbitp (minusp (require-type integer 'integer)))))
2104  (number-case integer
2105    (fixnum
2106     (if (%i< index (- target::nbits-in-word target::fixnumshift))
2107       (%ilogbitp index integer)
2108       (minusp (the fixnum integer))))
2109    (bignum
2110     (let ((bidx (%iasr 5 index))
2111           (bbit (%ilogand index 31)))
2112       (declare (fixnum bidx bbit))
2113       (if (>= bidx (%bignum-length integer))
2114         (bignum-minusp integer)
2115         (multiple-value-bind (hi lo) (%bignum-ref integer bidx)
2116           (declare (fixnum hi lo))
2117           (if (> bbit 15)
2118             (%ilogbitp (%i- bbit 16) hi)
2119             (%ilogbitp bbit lo))))))))
2120
2121) ; #+32-bit-target
Note: See TracBrowser for help on using the repository browser.