; .EnTete "Le-Lisp (c) version 15.2" " " "L'arithme'tique ge'ne'rique mixte"
; .EnPied "genarith.ll" "E-%" " "
; .Annexe E "L'Arithme'tique Ge'ne'rique mixte"
; .nr % 1
;
; .Centre "*****************************************************************"
; .Centre " Ce fichier est en lecture seule hors du projet ALE de l'INRIA. "
; .Centre " Il est maintenu par ILOG SA, 2 Avenue Gallie'ni, 94250 Gentilly "
; .Centre " (c) Le-Lisp est une marque de'pose'e de l'INRIA "
; .Centre "*****************************************************************"
; .Centre "$Header: genarith.ll,v 4.1 88/01/13 12:19:50 kuczynsk Rel $"
(unless (>= (version) 15.2)
(error 'load 'erricf 'genarith))
; Le chargement de ce fichier transforme les appels de l'arithme'tique
; ge'ne'rique en arithme'tique mixte, supprimant ainsi les erreurs ERRGEN
; en cas de de'bordement entier.
;
; Seules les me'thodes : + - 0- * / 1/ ont un sens ici.
(de #:genarith:+ (n1 n2)
(if (and (fixp n1) (fixp n2))
(fadd (float n1) (float n2))
(#:genarith:error '+ n1 n2)))
(de #:genarith:- (n1 n2)
(if (and (fixp n1) (fixp n2))
(fsub (float n1) (float n2))
(#:genarith:error '- n1 n2)))
(de #:genarith:0- (n)
(if (fixp n)
(fsub 0.0 (float n))
(#:genarith:error '0- n)))
(de #:genarith:* (n1 n2)
(if (and (fixp n1) (fixp n2))
(fmul (float n1) (float n2))
(#:genarith:error '* n1 n2)))
(de #:genarith:/ (n1 n2)
(if (and (fixp n1) (fixp n2))
(if (eqn 0 n2)
(error '/ err0dv (list n1 n2))
(fdiv (float n1) (float n2)))
(#:genarith:error '/ n1 n2)))
(de #:genarith:1/ (n)
(if (fixp n)
(if (eqn n 0)
(error '1/ err0dv n)
(fdiv 1.0 (float n)))
(#:genarith:error '1/ n)))
(defvar #:ex:mod 0)
(de #:genarith:quomod (n1 n2)
(let ((q (floor (/ n1 (abs n2)))))
(setq #:ex:mod (- n1 (* (abs n2) q)))
(if (< n2 0) (- q) q)))
(de #:genarith:error (f . l)
(while l
(if (or (fixp (car l)) (floatp (car l)))
(nextl l)
(error f 'ERRNNA (car l)))))
(defvar #:sys-package:genarith 'genarith)
; Re'glage de la fonction QUOTIENT/QUOMOD canonique
; (courtesy of Jean Vuillemin)
(de floor (r)
; Renvoie le plus grand entier relatif z tel que z<=r:
(ifn (numberp r)
(error 'floor 'ERRNNA r)
(let ((z (truncate r)))
(if (> z r)
(- z 1)
z))))
(de ceiling (r)
(let ((z (floor r)))
(if (< z r) (+ z 1) z))) ; !!
; n=dq+r -d<2r<=d ou -d-r<r<=d-r
(de round (n d)
(cond ((< d 0) (0- (round n (0- d))))
((< n 0)
(if (= #:ex:mod (- d #:ex:mod))
(- -1 (round (0- n) d))
(setq n (0- (round (0- n) d)) #:ex:mod (0- #:ex:mod))
n))
((setq n (quotient n d) d (- d #:ex:mod))
(if (< d #:ex:mod)
(setq #:ex:mod (0- d) n (+ 1 n))
n)))))