home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
language
/
examples
/
jacobi.lsp
< prev
next >
Wrap
Lisp/Scheme
|
1993-10-23
|
1KB
|
34 lines
;; Jacobi-Symbol-Berechnung
;; Bruno Haible Nov./Dez. 1987
(provide 'jacobi)
; (jacobi a b) liefert für ganze Zahlen a,b mit ungeradem b>0 das Jacobi-Symbol
; (a / b). Es ist =0 genau dann, wenn a und b nicht teilerfremd sind.
(defun jacobi (a b)
(setq a (mod a b)) ; erst 0<= a < b erzwingen.
(let ((v 1))
(loop ; (a/b) * v bleibt invariant
(cond ((= b 1) (return v)) ; Bei b=1 ist (a/b)=1.
((zerop a) (return 0)) ; Bei b>1 und a=0 ist (a/b)=0.
((> (* 2 a) b) ; Bei a > b/2 ist
; (a/b) = (-1/b) * ((b-a)/b) und (-1/b)=-1 falls b=3 mod 4.
(setq a (- b a))
(setq v (* v (ecase (mod b 4) ((1) 1) ((3) -1) ))) )
((evenp a) ; Bei b>1 und a=2a' ist
; (a/b) = (2/b) * (a'/b) und (2/b)=-1 falls b=3,5 mod 8.
(setq a (exquo a 2))
(setq v (* v (ecase (mod b 8)
((1 7) 1) ((3 5) -1) ))) )
(t ; a und b ungerade, 0<a<b/2<b
; (a/b) = (-1)^((a-1)/4)((b-1)/4) * (b/a)
(if (and (= (mod a 4) 3) (= (mod b 4) 3))
(setq v (- v)))
(rotatef a b)
; jetzt ist a > 2*b bekannt, setze a:=a mod b.
(if (>= a (* 8 b))
(setq a (mod a b))
(do () ((< a b)) (setq a (- a b)) )
) ) ) ) ) )