;========================================================================== ; ; Le←Lisp v15.2 : L'arithme'tique ge'ne'rique R. ; ;=========================================================================== ; (c) Jean Vuillemin, 1984 ; Institut National de Recherche en Informatique et Automatique ; B.P. 105, 78153 Le Chesnay Cedex, France. vuillemin@inria ;=========================================================================== (unless (>= (version) 15.2) (error 'load 'errifc 'gen)) (unless (featurep 'kern) (loadmodule 'bnkern)) (add-feature 'gen) (setq #:backup:majuscules #:SYSTEM:READ-CASE-FLAG #:SYSTEM:READ-CASE-FLAG ()) ; .Chapitre I "Arithme'tique ge'ne'rique R" ; Ce module facilite l'e'criture d'extensions a` l'arithme'tique LeLisp. ; Il re'alise la conversion par de'faut des se'mantiques binaires ; - / quomod en 0- 1/ et truncate respectivement. ; Il effectue la conversion flottante en temps qu'option de dernier ; recours. Il suffit pour cela que les objets programme's re'pondent ; a` la se'mantique float. ; Pour l'utiliser, on pourra, soit installer ses objets comme sous type ; de R, soit simplement charger ce module. (setq #:sys-package:colon 'R) ; .Section "Ope'rations Binaires" ; Les se'mantiques ge'ne'riques binaires sont : ; + - * / <?> quomod power ; Re'duction de la soustraction binaire - a` l'oppose' 0- unaire: (de :- (n1 n2) (+ n1 (0- n2))) ; Re'duction de la division binaire / a` l'inverse 1/: (de :/ (n1 n2) (* n1 (1/ n2))) (defvar #:ex:mod 0) ; Re'duction de la division entie`re au plancher floor: (de :quomod (n1 n2) (lets ((an2 (abs n2)) (q (floor (/ n1 an2)))) (setq #:ex:mod (* #:ex:mod an2)) (if (< n2 0) (0- q) q))) ; .Section "Ope'rations Unaires" ; Les se'mantiques ge'ne'riques unaires sont : ; abs 0- 1/ float truncate exp log sqrt sin cos asin acos atan ; prin eval numberp integerp rationalp (de :eval (n) n) (de :numberp (n) n) ; Par de'faut, les R ne sont pas des entiers: (de :integerp (r) ()) ; Par de'faut, les R ne sont pas des rationnels: (de :rationalp (r) ()) ; .Section "Plancher" ; Renvoie le plus grand entier relatif z tel que z<=r: (de floor (r) (cond ((not (numberp r)) (:error 'floor 'ERRNNA r)) ((integerp r) (setq #:ex:mod 0) r) (T (send 'floor r)))) (de :truncate (r) (setq r (send 'floor r)) (when (< r 0) (setq r (+ 1 r) #:ex:mod (- #:ex:mod 1))) r) (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))))) ; .Section "Re`glage de l'e'criture" (defvar :prec t) (de precision k (unless (null k) (setq :prec (car k))) :prec) ; .Section "Erreurs Arithme'tiques" (de :error (nomf msg lapp) (error nomf (selectq msg (RDIV0 "Division entie`re par 0 : ") (RNOTZ "L'argument n'est pas un entier: ") (RNOTC "Complexe mal forme'") (RINC "Argument Complexe") (T msg)) lapp)) ; .Section "Contagion flottante" (setq #:sys-package:colon 'float) (de :* (x y) (fmul x (float y))) (de :+ (x y) (fadd x (float y))) (de :<?> (x y) (<?> x (float y))) (defvar :b 32760) (defvar :fb (float :b)) (defvar :-fb (- :fb)) (de :quomod (f1 f2) (setq f2 (float f2)) (let ((q (:truncate (fdiv f1 f2)))) (setq #:ex:mod (fsub f1 (fmul f1 (float q)))) q)) (de :floor (f) (:truncate f)) (de :truncate (f) (if (< f 0) (- (:truncate (- f))) (ftrunc f))) #| Retour a l'ancienne version de ratio (de ftrunc (f) (if (< :-fb f :fb) (fix f) (lets ((f1 (fdiv f :fb)) (z1 (ftrunc f1)) (f0 (fsub f (fmul f1 :fb)))) (+ (* z1 :b) (ftrunc f0))))) |# (de ftrunc (f) (if (< :-fb f :fb) (fix f) (lets ((f1 (fdiv f :fb)) (z1 (ftrunc f1)) (f0 (- f (* z1 :fb)))) (+ (* z1 :b) (ftrunc f0))))) (de #:fix:<?> (x y) (0- (<?> y x))) (defvar #:sys-package:genarith 'R) (setq #:SYSTEM:READ-CASE-FLAG #:backup:majuscules)