[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9. Große Gleitkommazahlen


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1 Darstellung großer Gleitkommazahlen


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2 Globale Variablen für große Gleitkommazahlen

Globale Variable: $float2bf

Standardwert: t

Hat die Optionsvariable $float2bf den Wert t, wird eine Warnung ausgegeben, wenn eine Gleitkommazahl von der Funktion float2fp in eine große Gleitkommazahl umgewandelt wird, da die Umwandlung zu einem Verlust an Genauigkeit führen kann.

Globale Variable: $bftorat

Standardwert: nil

Die Optionsvariable bftorat kontrolliert die Umwandlung von großen Gleitkommazahlen in rationale Zahlen mit der Funktion bigfloat2rat. . Hat bftorat den Wert false, wird die Genauigkeit der Umwandlung von der Optionsvariablen $ratepsilon kontrolliert. Hat dagegen bftorat den Wert true, wird die große Gleitkommazahl exakt durch die rationale Zahl repräsentiert.

Optionsvariable: $bftrunc

Standardwert: t

Optionsvariable: $fpprintprec

Standardwert: 0

Anzahl der Stellen einer Gleitkommazahl. Ist der Wert 0, dann wird die maximale Anzahl an Stellen benutzt, die in der Variablen $maxfpprintprec abgelegt ist.

Optionsvariable: $maxfpprintprec

Standardwert: (ceiling (log (expt 2 (float-digits 1.0)) 10.0)))

Maximale Anzahl an Stellen für die Anzeige einer Gleitkommazahl. Für SBCL und einer 32-Bit Implementation hat *maxfpprintprec* den Wert 16.

Optionsvariable: $ratprint

Standardwert: t

Optionsvariable: $keepfloat

Standardwert: nil

Optionsvariable: $ratepsilon

Standardwert: 2.0d-15

Optionsvariable: $fpprec

Standardwert: (ceiling (log (expt 2 (float-digits 1.0)) 10.0)))

Globale Variable: bigfloatzero

Standardwert: '((bigfloat simp 56) 0 0))

Repräsentiert den Wert Null in einer Darstellung als große Gleitkommazahl. Der Standardwert wird mit einer Genauigkeit für $fpprec von 16 initialisiert.

Globale Variable: bigfloatone

Standardwert: '((bigfloat simp 56) #.(expt 2 55) 1))

Repräsentiert den Wert Eins in einer Darstellung als große Gleitkommazahl. Der Standardwert wird mit einer Genauigkeit für $fpprec von 16 initialisiert.

Globale Variable: bfhalf

Standardwert: '((bigfloat simp 56) #.(expt 2 55) 0))

Repräsentiert den Wert 1/2 in einer Darstellung als große Gleitkommazahl. Der Standardwert wird mit einer Genauigkeit für $fpprec von 16 initialisiert.

Globale Variable: bfmhalf

Standardwert: '((bigfloat simp 56) #.(- (expt 2 55)) 0))

Repräsentiert den Wert -1/2 in einer Darstellung als große Gleitkommazahl. Der Standardwert wird mit einer Genauigkeit für $fpprec von 16 initialisiert.

Globale Variable: fpprec

Standardwert: keiner

Globale Variable: *m

Standardwert: keiner

Globale Variable: *cancelled

Standardwert: keiner

Globale Variable: *decfp*

Standardwert: nil

Die globale Variable *decfp* wird in der Funktion fpformat an den Wert t gebunden, um die Mantisse einer großen Gleitkommazahl für die Ausgabe in eine Dezimalzahl umzuwandeln. Die Funktionen fpround, fpshift und fpone beachten den Wert von *decfp*.

Bemerkung:

Im Original Maxima hat die Variable den Namen *decfp.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3 Implementierung großer Gleitkommazahlen

Funktion: hipart x n

Für eine ganze Zahl vom Typ fixnum wird die Funktion haipart aufgerufen, die n Bits der Zahl x zurück gibt. Ist n positiv werden die oberen Bits und ansonsten die unteren Bits zurückgegeben.

Quelltext:

(defun hipart (x n)
  (if (bignump n)
      (abs x)
      (haipart x n)))

Funktion: haipart x n

Das Argument x ist die Mantisse einer großen Gleitkommazahl. Mit dem Argument n wird angegeben, wie viele Stellen der Mantisse zurückgeben werden sollen. Ist n eine positive ganze Zahl werden die oberen Stellen zurückgegeben und für einen negativen Wert die unteren Stellen.

Beispiele:

* (let ((*print-base* 2) (*print-radix* t)) (princ (haipart 29 1)))
#b1
1
* (let ((*print-base* 2) (*print-radix* t)) (princ (haipart 29 2)))
#b11
3
* (let ((*print-base* 2) (*print-radix* t)) (princ (haipart 29 3)))
#b111
7
* (let ((*print-base* 2) (*print-radix* t)) (princ (haipart 29 4)))
#b1110
14
* (let ((*print-base* 2) (*print-radix* t)) (princ (haipart 29 5)))
#b11101
29

Quelltext:

(defun haipart (x n)
  (let ((x (abs x)))
    (if (< n 0)
        (if (< (integer-length x) (- n))
            x
            (logand x (1- (ash 1 (- n)))))
        (ash x (min (- n (integer-length x)) 0)))))

Funktion: fpprec1 assign-var q

fpprec1 ist eine assign-Funktion der Optionsvariablen $fpprec. Immer wenn der Optionsvariablen $fpprec ein neuer Wert zugewiesen wird, erhält auch die globale Variable fpprec einen neuen Wert.

Quelltext:

(defprop $fpprec fpprec1 assign)

(defun fpprec1 (assign-var q)
  (declare (ignore assign-var))
  (if (or (not (fixnump q))
          (< q 1))
      (merror "fpprec: value must be a positive integer; found: ~M" q)
      (progn
        (setq fpprec (+ 2 (integer-length (expt 10 q)))
              bigfloatone ($bfloat 1)
              bigfloatzero ($bfloat 0)
              bfhalf (list (car bigfloatone) (cadr bigfloatone) 0)
              bfmhalf (list (car bigfloatone) (- (cadr bigfloatone)) 0))
        q)))

Funktion: bcons x

Das Argument x ist eine große Gleitkommazahl in der internen Darstellung. Die Rückgabe ist eine große Gleitkommazahl, die mit dem Attribut simp und der aktuellen Genauigkeit fpprec versehen wird.

Quelltext:

(defun bcons (x)
  `((bigfloat simp ,fpprec) . ,x))

Funktion: check-bigfloat x

Die Funktion check-bigfloat prüft, ob das Argument x eine große Gleitkommazahl ist. Ist dies der Fall, wird gegebenenfalls die Genauigkeit der großen Gleitkommazahl an die aktuelle Genauigkeit angepasst, die in der globalen Variablen fpprec abgelegt ist.

Quelltext:

(defun check-bigfloat (x)
  (prog ()
    (cond ((not (bigfloatp x)) (return nil))
          ((= fpprec (caddar x))
           (return x))
          ((> fpprec (caddar x))
           (setq x (bcons (list (fpshift (cadr x) (- fpprec (caddar x)))
                                (caddr x)))))
          (t
           (setq x (bcons (list (fpround (cadr x))
                                (+ (caddr x) *m fpprec (- (caddar x))))))))
    (return (if (eql (cadr x) 0) (bcons (list 0 0)) x))))

Funktion: intofp x

Wandelt das Argument x, das eine ganze Zahl, eine Gleitkommazahl oder eine der Konstanten $%e, $%e, $%gamma, $%phi ist, in eine große Gleitkommazahl um und gibt das Ergebnis in der internen Darstellung zurück.

Bemerkung:

Im Unterschied zum Original Maxima testet diese Implementierung nicht, ob das Argument ein Atom ist und gibt für diesen Fall einen Lisp-Fehler. Weiterhin ist zusätzlich die numerische Konstante $%phi an dieser Stelle implementiert, so dass die Funktion $bfloat entsprechend vereinfacht werden kann.

Quelltext:

(defun intofp (x)
  (cond ((floatp x) (float2fp x))
        ((eql x 0) '(0 0))
        ((eq x '$%pi) (fppi))
        ((eq x '$%e) (fpe))
        ((eq x '$%gamma) (fpgamma))
        ((eq x '$%phi)
         (cdr ($bfloat '((mtimes simp)
                         ((rat simp) 1 2)
                         ((mplus simp) 1
                          ((mexpt simp) 5 ((rat simp) 1 2)))))))
        (t (list (fpround x) (+ *m fpprec)))))

Funktion: fpround x

Die Funktion fpround rundet die Mantisse einer großen Gleitkommazahl auf die aktuelle Genauigkeit fpprec. Das Argument x ist die Mantisse einer großen Gleitkommazahl. Die Rückgabe ist die gerundete Mantisse.

Hat die globale Variable *decfp* den Wert t, wird die Mantisse in eine Dezimalzahl für die Ausgabe formatiert.

Beispiele:

* (let ((*decfp* nil) (fpprec 8)) (fpround (car (intofp 123))))
246
* (let ((*decfp* nil) (fpprec 16)) (fpround (car (intofp 123))))
62976
* (let ((*decfp* t) (fpprec 16)) (fpround (car (intofp 123))))
1230000000000000

Quelltext:

(defun fpround (x &aux (*print-base* 10) *print-radix*)
  (prog (adjust)
     (cond
       ((null *decfp*)
        (setq *m (- (integer-length x) fpprec))
        (cond ((= *m 0)
               (setq *cancelled 0)
               (return x))
              (t
               (setq adjust (fpshift 1 (1- *m)))
               (when (minusp x) (setq adjust (- adjust)))
               (incf x adjust)
               (setq *m (- (integer-length x) fpprec))
               (setq *cancelled (abs *m))
               (cond ((zerop (hipart x (- *m)))
                      (return (fpshift (fpshift x (- -1 *m)) 1)))
                     (t (return (fpshift x (- *m))))))))
       (t
        (setq *m (- (length (exploden (abs x))) fpprec))
        (setq adjust (fpshift 1 (1- *m)))
        (when (minusp x) (setq adjust (- adjust)))
        (setq adjust (* 5 adjust))
        (setq *m (- (length (exploden (abs (setq x (+ x adjust))))) fpprec))
        (return (fpshift x (- *m)))))))

Funktion: fpshift l n

Verschiebt die Mantisse x um n Stellen nach links oder rechts. Für n = +/- 1 entspricht dies der Multiplikation oder der Division mit 2. fpshift beachtet den Wert der globalen Variablen *decfp*. . Hat *decfp* den Wert t wird die Mantisse als Dezimal angenommen und mit dem entsprechenden Faktor multipliziert.

Beispiele:

* (mdisplay (bcons (cons (fpshift (car (fpone)) 1) (cdr (fpone)))))
2.0b0
NIL
* (mdisplay (bcons (cons (fpshift (car (fpone)) -1) (cdr (fpone)))))
5.0b-1
NIL

Quelltext:

(defun fpshift (x n)
  (cond ((null *decfp*)
         (cond ((and (minusp n) (minusp x))
                (- (ash (- x) n)))
               (t (ash x n))))
        ((> n 0)
         (* x (expt 10 n)))
        ((< n 0)
         (truncate x (expt 10 (- n))))
        (t x)))

Funktion: fpintpart x

Gibt den ganzzahligen Anteil der Mantisse sowie den Rest zurück. Das Argument x ist eine große Gleitkommazahl in der internen Darstellung. Die Rückgabe ist der ganzzahlige Anteil als ganze Zahl und als zweiter Wert die Mantisse des Restes.

Beispiele:

* (fpintpart (intofp 2))
2
0
* (fpintpart (intofp 2.5))
2
9007199254740992
* (fpintpart (intofp 3))
3
0

Quelltext:

(defun fpintpart (x)
  (let ((m (- fpprec (cadr x))))
     (if (> m 0)
         (truncate (car x) (expt 2 m))
         (* (car x) (expt 2 (- m))))))

Funktion: fpend x

Ist das Argument x eine große Gleitkommazahl in der internen Darstellung wird die Mantisse auf die aktuelle Genauigkeit gerundet, der Exponent wird angepasst und das Argument als eine große Gleitkommazahl zurückgegeben. Ist das Argument x keine große Gleitkommazahl sondern ein Ausdruck wird x selbst zurückgegeben. Im Falle eines Atoms wird jedoch ein Lisp-Fehler generiert.

Beispiele:

* (fpend (intofp 0))
((BIGFLOAT SIMP 56) 0 0)
* (fpend (intofp 1))
((BIGFLOAT SIMP 56) 36028797018963968 -7)
* (fpend '((mplus) $a $b))
((MPLUS) $A $B)

Quelltext:

(defun fpend (x)
  (cond ((eql (car x) 0) (bcons x))
        ((numberp (car x))
         (bcons (list (fpround (car x)) (+ -8 *m (cadr x)))))
        (t x)))

Funktion: fparcsimp x

Die Funktion fparcsimp prüft, ob das Argument e ein Ausdruck ist, der eine komplexe Zahl a + %i * b repräsentiert, wobei a und b große Gleitkommazahlen sind. Ist dies der Fall, wird der imaginäre Anteil dann entfernt, wenn der Exponent kleiner als -fpprec + 2.

Beispiel:

* (fparcsimp (add ($bfloat 1) (mul '$%i ($bfloat 1))))
((MPLUS SIMP) ((BIGFLOAT SIMP 56) 36028797018963968 1)
 ((MTIMES SIMP) ((BIGFLOAT SIMP 56) 36028797018963968 1) $%I))
* (fparcsimp (add ($bfloat 1) (mul '$%i ($bfloat 1e-17))))
((BIGFLOAT SIMP 56) 36028797018963968 1)

Quelltext:

(defun fparcsimp (x)
  (if (and (mplusp x)
           (null (cdddr x))
           (mtimesp (caddr x))
           (null (cdddr (caddr x)))
           (bigfloatp (cadr (caddr x)))
           (eq (caddr (caddr x)) '$%i)
           (< (caddr (cadr (caddr x))) (+ (- fpprec) 2)))
      (cadr x)
      x))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4 Umwandlung großer Gleitkommazahlen

Funktion: bigfloat2rat x

Quelltext:

(defun bigfloat2rat (x)
  (declare (special $ratprint))
  (setq x (check-bigfloat x))
  (let (($float2bf t)
        (exp nil)
        (y nil)
        (sign nil))
    (setq exp (cond ((minusp (cadr x))
                     (setq sign t
                           y (fpration1 (cons (car x) (fpabs (cdr x)))))
                     (rplaca y (* -1 (car y))))
                    (t (fpration1 x))))
    (when $ratprint
      (princ "`rat' replaced ")
      (when sign (princ "-"))
      (princ (maknam (fpformat (cons (car x) (fpabs (cdr x))))))
      (princ " by ")
      (princ (car exp))
      (write-char #\/)
      (princ (cdr exp))
      (princ " = ")
      (setq x ($bfloat (list '(rat simp) (car exp) (cdr exp))))
      (when sign (princ "-"))
      (princ (maknam (fpformat (cons (car x) (fpabs (cdr x))))))
      (terpri))
    exp))

Funktion: fpration1

Quelltext:

(defun fpration1 (x)
  (let ((fprateps (cdr ($bfloat (if $bftorat
                                    (list '(rat simp) 1
                                          (exptrl 2 (1- fpprec)))
                                    $ratepsilon)))))
    (or (and (equal x bigfloatzero)
             (cons 0 1))
        (prog (y a)
          (return
            (do ((xx x (setq y
                             (invertbigfloat
                               (bcons (fpsub (cdr xx)
                                             (cdr ($bfloat a)))))))
                 (num (setq a (fpentier x))
                      (+ (* (setq a (fpentier y)) num) onum))
                 (den 1 (+ (* a den) oden))
                 (onum 1 num)
                 (oden 0 den))
                ((and (not (zerop den))
                      (not (fpgreaterp
                             (fpabs (fpdiv (fpsub (cdr x)
                                                  (fpdiv (cdr ($bfloat num))
                                                         (cdr ($bfloat den))))
                                 (cdr x)))
                             fprateps)))
                 (cons num den))))))))

Funktion: float-nan-p x

Quelltext:

(defun float-nan-p (x)
  (and (floatp x)
       (not (= x x))))

Funktion: float-inf-p

Quelltext:

(defun float-inf-p (x)
  (labels ((extreme-float-values (x)
             (case (type-of x)
               (short-float
                 (values most-negative-short-float
                         most-positive-short-float))
               (single-float
                 (values most-negative-single-float
                         most-positive-single-float))
               (double-float
                 (values most-negative-double-float
                         most-positive-double-float))
               (long-float
                 (values most-negative-long-float
                         most-positive-long-float))))
           (beyond-extreme-values (x)
             (multiple-value-bind (most-negative most-positive)
                 (extreme-float-values x)
               (cond ((< x 0) (< x most-negative))
                     ((> x 0) (> x most-positive))
                     (t nil)))))
    (and (floatp x)
         (not (float-nan-p x))
         (beyond-extreme-values x))))

Funktion: float2fp x

Konvertiert eine einfache Gleitkommazahl x in eine große Gleitkommazahl. Das Argument x muss eine Gleitkommazahl sein, ansonsten wird ein Lisp-Fehler generiert. Die Rückgabe ist eine große Gleitkommazahl in der internen Darstellung.

Bemerkung:

Im Original Maxima hat diese Funktionen den Namen floattofp.

Quelltext:

(defun float2fp (x)
  (when (float-nan-p x)
    (merror
      "bfloat: attempted conversion of floating point NaN (not-a-number).~%"))
  (when (float-inf-p x)
    (merror "bfloat: attempted conversion of floating-point infinity.~%"))
  (unless $float2bf
    (format t "bfloat: converting float ~S to bigfloat.~%" x))
  (if (zerop x)
      (list 0 0)
      (multiple-value-bind (frac exp sign)
          (integer-decode-float x)
        (let ((scale (- fpprec (integer-length frac))))
          (list (ash (* sign frac) scale)
                (+ fpprec (- exp scale)))))))

Funktion: fp2float x

Konvertiert eine große Gleitkommazahl x in eine einfache Gleitkommazahl.

Bemerkung:

Die Funktion hat im Original Maxima den Namen fp2flo.

Quelltext:

(defun fp2float (x)
  (let ((precision (caddar x))
        (mantissa (cadr x))
        (exponent (caddr x))
        (fpprec +machine-mantissa-precision+)
        (*m 0))
    (setq mantissa
          (/ (fpround mantissa) (expt 2.0 +machine-mantissa-precision+)))
    (let ((e (+ exponent (- precision) *m +machine-mantissa-precision+)))
      (if (>= e 1025)
          (merror "float: floating point overflow converting ~:M" x)
          (scale-float mantissa e)))))

Funktion: rat2fp x

Die Funktion rat2fp wird von $bfloat aufgerufen, um eine rationale Zahl in eine große Gleitkommazahl umzuwandeln. Das Argument ist eine Liste mit zwei Elementen. Das erste Element ist der Zähler und das zweite Argument der Nenner der rationalen Zahl. Die Argumente müssen eine vereinfachte rationale Zahl repräsentieren. Die Rückgabe ist eine große Gleitkommazahl im internen Format (mantissa exponent).

Bemerkung:

Im Original Maxima heißt die Funktion float-ratio. Weiterhin wird diese Funktion im Unterschied zu Maxima direkt von $bfloat aufgerufen.

Quelltext:

(defun rat2fp (x)
  (let* ((signed-num (first x))
         (plusp (plusp signed-num))
         (num (if plusp signed-num (- signed-num)))
         (den (second x))
         (digits fpprec)
         (scale 0))
    (declare (fixnum digits scale))
    (let ((den-twos (1- (integer-length (logxor den (1- den))))))
      (declare (fixnum den-twos))
      (decf scale den-twos)
      (setq den (ash den (- den-twos))))
    (let* ((num-len (integer-length num))
           (den-len (integer-length den))
           (delta (- den-len num-len))
           (shift (1+ (the fixnum (+ delta digits))))
           (shifted-num (ash num shift)))
      (declare (fixnum delta shift))
      (decf scale delta)
      (labels ((float-and-scale (bits)
                 (let* ((bits (ash bits -1))
                        (len (integer-length bits)))
                   (cond ((> len digits)
                          (assert (= len (the fixnum (1+ digits))))
                          (multiple-value-bind (f0)
                              (floatit (ash bits -1))
                            (list (first f0) (+ (second f0)
                                                (1+ scale)))))
                         (t
                          (multiple-value-bind (f0)
                              (floatit bits)
                            (list (first f0) (+ (second f0) scale)))))))
               (floatit (bits)
                 (let ((sign (if plusp 1 -1)))
                   (list (* sign bits) 0))))
        (loop
          (multiple-value-bind (fraction-and-guard rem)
              (truncate shifted-num den)
            (let ((extra (- (integer-length fraction-and-guard) digits)))
              (declare (fixnum extra))
              (cond ((/= extra 1)
                     (assert (> extra 1)))
                    ((oddp fraction-and-guard)
                     (return
                       (if (zerop rem)
                           (float-and-scale
                             (if (zerop (logand fraction-and-guard 2))
                                 fraction-and-guard
                                 (1+ fraction-and-guard)))
                           (float-and-scale (1+ fraction-and-guard)))))
                    (t
                     (return (float-and-scale fraction-and-guard)))))
            (setq shifted-num (ash shifted-num -1))
            (incf scale)))))))

Funktion: $bfloat x

Quelltext:

(defun $bfloat (x)
  (declare (special $ratprint))
  (let (y)
    (cond ((check-bigfloat x))
          ((or (numberp x)
               (member x '($%e $%pi $%gamma) :test #'eq))
           (bcons (intofp x)))
          ((or (atom x)
               (member 'array (cdar x) :test #'eq))
           (if (eq x '$%phi)
               ($bfloat '((mtimes simp)
                          ((rat simp) 1 2)
                          ((mplus simp) 1 ((mexpt simp) 5 ((rat simp) 1 2)))))
               x))
          ((eq (caar x) 'rat)
           (bcons (rat2fp (cdr x))))
          ((eq (caar x) 'mexpt)
           (if (eq (cadr x) '$%e)
               (fpexp* ($bfloat (caddr x)))
               (exptbigfloat ($bfloat (cadr x)) (caddr x))))
          ((eq (caar x) 'mncexpt)
           (list '(mncexpt) ($bfloat (cadr x)) (caddr x)))
          ((setq y (getprop (caar x) 'floatprog))
           (funcall y (mapcar #'$bfloat (cdr x))))
          (t (recur-apply #'$bfloat x)))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5 Arithmetik mit grossen Gleitkommazahlen

Funktion: addbigfloat args

Die Funktion addbigfloat wird von $bfloat aufgerufen, wenn eine Summe in große Gleitkommazahlen umzuwandeln ist. Dazu wird addbigfloat zum Indikator floatprog auf der Eigenschaftsliste des Operators mplus abgelegt. Die Terme der Summe werden als Liste mit dem Argument args übergeben, die beliebige können kMaxima-Ausdrücke sein können. addbigfloat kann voraussetzen, dass alle Terme bereits in eine große Gleitkommazahl umgewandelt sind. Die Rückgabe ist eine vereinfachte Summe, in der alle Zahlen in große Gleitkommazahlen umgewandelt und numerische Rechnungen ausgeführt sind.

Beispiele:

* (addbigfloat (mapcar '$bfloat '(1 2 3)))
((BIGFLOAT SIMP 56) 54043195528445952 3)
* (addbigfloat (mapcar '$bfloat '(1 2 3 x x)))
((MPLUS SIMP) ((BIGFLOAT SIMP 56) 54043195528445952 3) ((MTIMES SIMP) 2 X))

Quelltext:

(defprop mplus addbigfloat floatprog)

(defun addbigfloat (args)
  (let ((fans (intofp 0))
        nfans)
    (do ((l args (cdr l)))
        ((null l)
         (cond ((null nfans) (bcons fans))
               ((zerop (car fans)) (addn nfans nil))
               (t (addn (cons (bcons fans) nfans) nil))))
      (cond ((bigfloatp (car l))
             (setq fans (fpadd (cdr (check-bigfloat (car l))) fans)))
            (t
             (setq nfans (cons (car l) nfans)))))))

Funktion: fpadd a b

Die Funktion fpadd addiert zwei große Gleitkommazahlen a und b und gibt das Ergebnis in der internen Darstellung (mantissa exponent) zurück. Die Argumente müssen in der internen Darstellung übergeben werden.

fpadd wird im Code für die Addition von großen Gleitkommazahlen aufgerufen. Weiterhin wird die Funktion von addbigfloat aufgerufen, wenn eine Summe von $bfloat in große Gleitkommazahlen umzuwandeln ist.

Bemerkung:

Im Original Maxima hat die Funktion den Namen fpplus.

Quelltext:

(defun fpadd (a b)
  (prog (*m expo man sticky)
    (setq *cancelled 0)
    (cond ((eql (car a) 0) (return b))
          ((eql (car b) 0) (return a)))
    (setq expo (- (cadr a) (cadr b)))
    (setq man (cond ((eql expo 0)
                     (setq sticky 0)
                     (fpshift (+ (car a) (car b)) 2))
                    ((> expo 0)
                     (setq sticky (hipart (car b) (- 1 expo)))
                     (setq sticky (cond ((zerop sticky) 0)
                                        ((< (car b) 0) -1)
                                        (t 1)))
                     (+ (fpshift (car a) 2)
                        (fpshift (car b) (- 2 expo))))
                    (t
                     (setq sticky (hipart (car a) (1+ expo)))
                     (setq sticky (cond ((zerop sticky) 0)
                                        ((< (car a) 0) -1)
                                        (t 1)))
                     (+ (fpshift (car b) 2)
                        (fpshift (car a) (+ 2 expo))))))
    (setq man (+ man sticky))
    (return (cond ((eql man 0) '(0 0))
                  (t
                   (setq man (fpround man))
                   (setq expo (+ -2 *m (max (cadr a) (cadr b))))
                   (list man expo))))))

Funktion: timesbigfloat args

Die Funktion timesbigfloat wird von $bfloat aufgerufen, wenn ein Produkt in eine große Gleitkommazahl umzuwandeln ist. Dazu wird timesbigfloat zum Indikator floatprog auf der Eigenschaftsliste des Operators mtimes abgelegt. Die Faktoren des Produkts werden als Liste mit dem Argument args übergeben, die beliebige können kMaxima-Ausdrücke sein können. timesbigfloat kann voraussetzen, dass alle Terme bereits in eine große Gleitkommazahl umgewandelt sind. Die Rückgabe ist ein vereinfachtes Produkt, in der alle Zahlen in große Gleitkommazahlen umgewandelt und numerische Rechnungen ausgeführt sind.

Beispiele:

* (timesbigfloat (mapcar '$bfloat '(1 2 3)))
((BIGFLOAT SIMP 56) 54043195528445952 3)
* (timesbigfloat (mapcar '$bfloat '(1 2 3 x x)))
((MTIMES SIMP) ((BIGFLOAT SIMP 56) 54043195528445952 3) ((MEXPT SIMP) X 2))

Quelltext:

(defprop mtimes timesbigfloat floatprog)

(defun timesbigfloat (args)
  (let ((fans (fpone))
        nfans)
    (do ((l args (cdr l)))
        ((null l)
         (if (null nfans)
             (bcons fans)
             (muln (cons (bcons fans) nfans) nil)))
      (if (bigfloatp (car l))
          (setq fans (fpmul (cdr (check-bigfloat (car l))) fans))
          (setq nfans (cons (car l) nfans))))))

Funktion: fpmul a b

Die Funktion fpmul multipliziert zwei große Gleitkommazahlen a und b und gibt das Ergebnis in der internen Darstellung (mantissa exponent) zurück. Die Argumente müssen in der internen Darstellung übergeben werden.

fpmul wird im Code für die Multiplikation von großen Gleitkommazahlen aufgerufen. Weiterhin wird die Funktion von timesbigfloat aufgerufen, wenn ein Produkt von $bfloat in große Gleitkommazahlen umzuwandeln ist.

Bemerkung:

Im Original Maxima hat die Funktion den Namen fptimes*.

Quelltext:

(defun fpmul (a b)
  (if (or (zerop (car a)) (zerop (car b)))
      (intofp 0)
      (list (fpround (* (car a) (car b)))
            (+ *m (cadr a) (cadr b) (- fpprec)))))

Funktion: fpexp* arg

Berechnet die Exponentialfunktion für das Argument arg. Das Argument arg kann ein beliebiger kMaxima-Ausdruck sein. Ist das Argument arg eine große Gleitkommazahl, wird ein numerisches Ergebnis mit der Funktion fpexp berechnet. Ansonsten wird ein mexpt-Ausdruck zurückgegeben.

Bemerkung:

Im Original Maxima hat die Funktionen den Namen *fpexp.

Quelltext:

(defun fpexp* (arg)
  (fpend (let ((fpprec (+ 8 fpprec)))
           (if (bigfloatp arg)
               (fpexp (cdr (check-bigfloat arg)))
               (list '(mexpt) '$%e arg)))))

Funktion: fpexp x

Berechnet die Exponentialfunktion für das Argument x. Das Argument x ist eine große Gleitkommazahl in der internen Darstellung. Die Rückgabe ist eine wieder eine große Gleitkommazahl in der internen Darstellung.

Ist x eine negative Zahl, wird exp(-x) = 1/exp(x) berechnet. Ein positives Argument x wird in x = n + r zerlegt, wobei n der ganzzahlige Anteil und r der Rest ist, so dass exp(x) = exp(r) * exp(n) gilt. Für die Berechnung von exp(r) wird die Funktion fpexp1 aufgerufen, die eine Taylorreihenentwicklung für kleine Argument nutzt. Der ganzzahlige Anteil wird mit der Funktion fpexpt berechnet.

Quelltext:

(defun fpexp (x)
  (if (< (car x) 0)
      (fpdiv (fpone) (fpexp (fpminus x)))
      (let ((n (fpintpart x)))
        (cond ((< n 2)
               (fpexp1 x))
              (t
               (fpmul (fpexp1 (fpsub x (intofp n)))
                      (cdr (check-bigfloat
                             (let ((fpprec (+ fpprec (integer-length n) -1))
                                   (n n))
                               (bcons (fpexpt (fpe) n)))))))))))

Funktion: fpexp1 x

Berechnet die Exponentialfunktion exp(x) für ein positive Argument x, das kleiner als 1 ist. Das Argument x ist eine große Gleitkommazahl in der internen Darstellung. Die Rückgabe ist eine große Gleitkommazahl in der internen Darstellung.

Für die Berechnung wird eine Taylorreihenentwicklung genutzt:

                   2    3    4    5
      x           x    x    x    x
    %e  = 1 + x + -- + -- + -- + --- + . . .
                  2    6    24   120

Quelltext:

(defun fpexp1 (x)
  (do ((n 1 (1+ n))
       (ans (fpone))
       (term (fpone))
       oans)
      ((equal ans oans) ans)
    (setq term (fpdiv (fpmul x term) (intofp n)))
    (setq oans ans)
    (setq ans (fpadd ans term))))

Funktion: exptbigfloat p n

Berechnet die Exponentiation der großen Gleitkommazahl p und der Potenz n. Beide Argumente können beliebige kMaxima-Ausdrücke sein. Kann ein numerisches Ergebnis nicht berechnet werden, wird ein Ausdruck zurückgegeben.

Quelltext:

(defun exptbigfloat (p n)
  (declare (special $numer $float $keepfloat $ratprint))
  (cond ((eql n 1) p)
        ((eql n 0) ($bfloat 1))
        ((not (bigfloatp p)) (list '(mexpt) p n))
        ((eql (cadr p) 0) ($bfloat 0))
        ((and (< (cadr p) 0)
              (ratnump n))
         (mul (let ($numer $float $keepfloat $ratprint)
                 (power -1 n))
              (exptbigfloat (bcons (fpminus (cdr p))) n)))
        ((and (< (cadr p) 0)
              (not (integerp n)))
         (cond ((or (eql n 0.5) (equal n bfhalf))
                (exptbigfloat p '((rat simp) 1 2)))
               ((or (eql n -0.5) (equal n bfmhalf))
                (exptbigfloat p '((rat simp) -1 2)))
               ((bigfloatp (setq n ($bfloat n)))
                (cond ((equal n ($bfloat (fpentier n)))
                       (exptbigfloat p (fpentier n)))
                      (t
                       (setq p (exptbigfloat (bcons (fpminus (cdr p))) n)
                             n ($bfloat `((mtimes) $%pi ,n)))
                       (add ($bfloat `((mtimes) ,p ,(fpsin* n nil)))
                            `((mtimes simp)
                              ,($bfloat `((mtimes) ,p ,(fpsin* n t)))
                              $%i)))))
               (t (list '(mexpt) p n))))
        ((and (ratnump n)
              (< (caddr n) 10))
         (bcons (fpexpt (fproot p (caddr n)) (cadr n))))
        ((not (integerp n))
         (setq n ($bfloat n))
         (cond ((not (bigfloatp n)) (list '(mexpt) p n))
               (t
                (let ((extrabits (max 1 (+ (caddr n)
                                           (integer-length (caddr p))))))
                  (setq p
                        (let ((fpprec (+ extrabits fpprec)))
                          (fpexp (fpmul (cdr (check-bigfloat n))
                                        (fplog (cdr (check-bigfloat p)))))))
                  (setq p
                        (list (fpround (car p))
                              (+ (- extrabits) *m (cadr p))))
                  (bcons p)))))
        ((< n 0) (invertbigfloat (exptbigfloat p (- n))))
        (t (bcons (fpexpt (cdr p) n)))))

Funktion: fpexpt p nn

Die Funktion fpexpt berechnet die nn-te Potenz der großen Gleitkommazahl p. Das Argument nn muss eine ganze Zahl sein und das Argument p eine große Gleitkommazahl in der internen Darstellung. Das Ergebnis ist eine große Gleitkommazahl in der internen Darstellung.

Der Algorithmus behandelt die Sonderfälle nn = 0 und nn = 1. Für eine negative ganze Zahl wird wird 1/p^(-nn) berechnet. Ist nn eine positive ganze Zahl größer als 1 wird vom Algorithmus die entsprechende Anzahl an Multiplikation ausgeführt.

Quelltext:

(defun fpexpt (p nn)
  (cond ((zerop nn) (fpone))
        ((eql nn 1) p)
        ((< nn 0) (fpquotient (fpone) (fpexpt p (- nn))))
        (t
         (prog (u)
           (if (oddp nn)
               (setq u p)
               (setq u (fpone)))
           (do ((ii (truncate nn 2) (truncate ii 2)))
               ((zerop ii))
             (setq p (fptimes* p p))
             (when (oddp ii) (setq u (fptimes* u p))))
           (return u)))))

Funktion: fpsub a b

Berechnet die Differenz der großen Gleitkommazahlen a und b, die in der internen Darstellung als Argument übergeben werden. Das Ergebnis ist eine große Gleitkommazahl in der internen Darstellung.

Quelltext:

(defun fpsub (a b)
  (fpadd a (fpminus b)))

Funktion: fpminus x

Die große Gleitkommazahl x wird negiert. Das Ergebnis ist eine große Gleitkommazahl in der internen Darstellung.

Quelltext:

(defun fpminus (x)
  (if (eql (car x) 0)
      x
      (list (- (car x)) (cadr x))))

Funktion: invertbigfloat a

Quelltext:

(defun invertbigfloat (a)
  (if (bigfloatp a)
      (bcons (fpdiv (fpone) (cdr (check-bigfloat a))))
      (simplifya (list '(mexpt) a -1) nil)))

Funktion: fpdiv a b

Quelltext:

(defun fpdiv (a b)
  (cond ((eql (car b) 0)
         (merror "pquotient: attempted quotient by zero."))
        ((eql (car a) 0) (intofp 0))
        (t
         (list (fpround (truncate (fpshift (car a) (+ 3 fpprec)) (car b)))
               (+ -3 (- (cadr a) (cadr b)) *m)))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6 Testfunktionen und weitere Funktionen

Funktion: fpgreaterp a b

Quelltext:

(defun fpgreaterp (a b)
  (fpposp (fpsub a b)))

Funktion: fplessp a b

Quelltext:

(defun fplessp (a b)
  (fpposp (fpsub b a)))

Funktion: fpposp x

Quelltext:

(defun fpposp (x)
  (> (car x) 0))

Funktion: fpmin arg1 &rest args

Quelltext:

(defun fpmin (arg1 &rest args)
  (let ((min arg1))
    (mapc #'(lambda (u) (if (fplessp u min) (setq min u))) args)
    min))

Funktion: fpmax arg1 &rest args

Quelltext:

(defun fpmax (arg1 &rest args)
  (let ((max arg1))
    (mapc #'(lambda (u) (if (fpgreaterp u max) (setq max u))) args)
    max))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.7 Mathematische Konstanten

Funktion: fpone

Quelltext:

(defun fpone ()
  (cond (*decfp* (intofp 1))
        ((= fpprec (caddar bigfloatone)) (cdr bigfloatone))
        (t (intofp 1))))

Funktion: fpe

Berechnet den numerischen Wert der Konstante %e als große Gleitkommazahl. Die Rückgabe ist große Gleitkommazahl in der internen Darstellung.

Quelltext:

(let ((table (make-hash-table)))
  (defun fpe ()
    (labels ((compe (prec)
               (let (s h (n 1) d (k (isqrt prec))) 
                 (setq h (ash 1 prec))
                 (setq s h)
                 (do ((i k (+ i k)))
                     ((zerop h))
                   (setq d (do ((j 1 (1+ j)) (p i))
                               ((> j (1- k)) (* p n))
                             (setq p (* p (- i j)))) )
                   (setq n (do ((j (- k 2) (1- j)) (p 1))
                               ((< j 0) p)
                             (setq p (1+ (* p (- i j))))))
                   (setq h (truncate (* h n) d))
                   (setq s (+ s h)))
                 s))
             (fpe1 ()
               (bcons (list (fpround (compe (+ fpprec 12))) (+ -12 *m)))))
      (let ((value (gethash fpprec table)))
        (if value
            value
            (setf (gethash fpprec table) (cdr (fpe1))))))))

Funktion: fppi

Berechnet den numerischen Wert der Konstante %pi als große Gleitkommazahl. Die Rückgabe ist große Gleitkommazahl in der internen Darstellung.

Quelltext:

(let ((table (make-hash-table)))
  (defun fppi ()
    (labels ((fprt18231 ()
               (let ((a 1823176476672000))
                 (setq a (ash a (* 2 fpprec)))
                 (destructuring-bind (mantissa expo)
                     (intofp (isqrt a))
                   (list mantissa (- expo fpprec)))))
             (comppi (prec)
               (let (s h n d)
                 (setq s (ash 13591409 prec))
                 (setq h (neg (truncate (ash 67047785160 prec)
                                        262537412640768000)))
                 (setq s (+ s h))
                 (do ((i 2 (1+ i)))
                     ((zerop h))
                   (setq n (* 12
                              (- (* 6 i) 5)
                              (- (* 6 i) 4)
                              (- (* 2 i) 1)
                              (- (* 6 i) 1)
                              (+ (* i 545140134) 13591409)))
                   (setq d (* (- (* 3 i) 2)
                              (expt i 3)
                              (- (* i 545140134) 531548725)
                              262537412640768000))
                   (setq h (neg (truncate (* h n) d)))
                   (setq s (+ s h)))
                 s))
             (fppi1 ()
               (bcons (fpdiv (fprt18231)
                             (list (fpround (comppi (+ fpprec 12)))
                                   (+ -12 *m))))))
      (let ((value (gethash fpprec table)))
        (if value
            value
            (setf (gethash fpprec table) (cdr (fppi1))))))))

Funktion: fpgamma

Berechnet den numerischen Wert der Konstante %gamma als große Gleitkommazahl. Die Rückgabe ist große Gleitkommazahl in der internen Darstellung.

Quelltext:

(let ((table (make-hash-table)))
  (defun fpgamma ()
    (labels ((compgamma (prec)
               (let* ((fpprec prec)
                      (big-n (floor (* 1/4 prec (log 2.0))))
                      (big-n-sq (intofp (* big-n big-n)))
                      (beta 3.591121476668622136649223)
                      (limit (floor (* beta big-n)))
                      (one (fpone))
                      (term (intofp 1))
                      (harmonic (intofp 0))
                      (a-sum (intofp 0))
                      (b-sum (intofp 1)))
                 (do ((n 1 (1+ n)))
                     ((> n limit))
                   (let ((bf-n (intofp n)))
                     (setf term (fpdiv (fpmul term big-n-sq)
                                       (fpmul bf-n bf-n)))
                     (setf harmonic (fpadd harmonic (fpdiv one bf-n)))
                     (setf a-sum (fpadd a-sum (fpmul term harmonic)))
                     (setf b-sum (fpadd b-sum term))))
                 (fpadd (fpdiv a-sum b-sum)
                        (fpminus (fplog (intofp big-n))))))
             (fpgamma1 ()
               (bcons (list (fpround (first (compgamma (+ fpprec 8)))) 0))))
      (let ((value (gethash fpprec table)))
        (if value
            value
            (setf (gethash fpprec table) (cdr (fpgamma1))))))))

Funktion: fplog2

Berechnet den numerischen Wert von log(2) als große Gleitkommazahl. Die Rückgabe ist große Gleitkommazahl in der internen Darstellung.

Quelltext:

(let ((table (make-hash-table)))
  (defun fplog2 ()
    (labels ((fast-atanh (k)
               (let* ((term (fpdiv (intofp 1) (intofp k)))
                      (fact (fpmul term term))
                      (oldsum (intofp 0))
                      (sum term))
                 (loop for m from 3 by 2
                       until (equal oldsum sum)
                       do
                       (setf oldsum sum)
                       (setf term (fpmul term fact))
                       (setf sum (fpadd sum (fpdiv term (intofp m)))))
                 sum))
             (comp-log2 ()
               (let ((result
                       (let ((fpprec (+ fpprec 8)))
                         (fpadd (fpsub (fpmul (intofp 18) (fast-atanh 26))
                                       (fpmul (intofp 2) (fast-atanh 4801)))
                                (fpmul (intofp 8) (fast-atanh 8749))))))
                 (list (fpround (car result))
                       (+ -8 *m)))))
      (let ((value (gethash fpprec table)))
        (if value
	    value
	    (setf (gethash fpprec table) (comp-log2)))))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.8 Mathematische Funktionen

Funktion: fpentier x

Quelltext:

(defun fpentier (x)
  (let ((fpprec (caddar x)))
    (fpintpart (cdr x))))

Funktion: mabsbigfloat arg

Quelltext:

(defprop mabs mabsbigfloat floatprog)

(defun mabsbigfloat (arg)
  (if (bigfloatp (setq arg (car arg)))
      (bcons (fpabs (cdr (check-bigfloat arg))))
      (list '(mabs) arg)))

Funktion: fpabs x

Quelltext:

(defun fpabs (x)
  (if (>= (car x) 0)
      x
      (cons (- (car x)) (cdr x))))

Funktion: big-float-sqrt x &optional y

Quelltext:

(defun big-float-sqrt (x &optional y)
  (if y
      (multiple-value-bind (u v) (complex-sqrt x y)
        (add (bcons u) (mul '$%i (bcons v))))
      (let ((fp-x (cdr (check-bigfloat x))))
        (if (fplessp fp-x (intofp 0))
            (mul '$%i (bcons (fproot (bcons (fpminus fp-x)) 2)))
            (bcons (fproot x 2))))))

Funktion: complex-sqrt xx yy

Quelltext:

(defun complex-sqrt (xx yy)
  (let* ((x (cdr (check-bigfloat xx)))
         (y (cdr (check-bigfloat yy)))
         (rho (fpadd (fptimes* x x)
                      (fptimes* y y))))
    (setf rho (fpadd (fpabs x) (fproot (bcons rho) 2)))
    (setf rho (fpadd rho rho))
    (setf rho (fpquotient (fproot (bcons rho) 2) (intofp 2)))
    (let ((eta rho)
          (nu y))
      (when (fpgreaterp rho (intofp 0))
        (setf nu (fpquotient (fpquotient nu rho) (intofp 2)))
        (when (fplessp x (intofp 0))
          (setf eta (fpabs nu))
          (setf nu (if (minusp (car y))
                       (fpminus rho)
                       rho))))
      (values eta nu))))

Funktion: fproot a n

Quelltext:

(defun fproot (a n)
  (if (eq (cadr a) 0)
      '(0 0)
      (progn
        (let* ((ofprec fpprec)
               (fpprec (+ fpprec 2))
               (bk (fpexpt
                     (intofp 2)
                     (1+ (truncate
                           (cadr (setq a (cdr (check-bigfloat a)))) n)))))
          (do ((x bk (fpsub
                       x
                       (setq bk
                             (fpquotient
                               (fpsub x (fpquotient a (fpexpt x n1)))
                               n))))
               (n1 (1- n))
               (n (intofp n)))
              ((or (equal bk '(0 0))
                   (> (- (cadr x) (cadr bk)) ofprec))
               (setq a x))))
        (list (fpround (car a)) (+ -2 *m (cadr a))))))

Funktion: big-float-log x &optional y

Quelltext:

(defun big-float-log (x &optional y)
  (if y
      (multiple-value-bind (u v) (complex-log x y)
        (add (bcons u) (mul '$%i (bcons v))))
      (flet ((%log (x)
               (cdr
                 (let* ((extra 8)
                        (fpprec (+ fpprec extra))
                        (log-frac
                          (fplog (list (ash (car x) extra) 0)))
                        (log-exp (fptimes* (intofp (second x)) (fplog2)))
                        (result (bcons (fpadd log-frac log-exp))))
                   (let ((fpprec (- fpprec extra)))
                     (check-bigfloat result))))))
        (let ((fp-x (cdr (check-bigfloat x))))
          (if (fplessp fp-x (intofp 0))
              (add (bcons (%log (fpminus fp-x)))
                   (mul '$%i (bcons (fppi))))
              (bcons (%log fp-x)))))))

Funktion: complex-log x y

Quelltext:

(defun complex-log (x y)
  (let* ((x (cdr (check-bigfloat x)))
         (y (cdr (check-bigfloat y)))
         (t1 (let (($float2bf t)) (floattofp 1.2)))
         (t2 (intofp 3))
         (rho (fpadd (fptimes* x x) (fptimes* y y)))
         (abs-x (fpabs x))
         (abs-y (fpabs y))
         (beta (fpmax abs-x abs-y))
         (theta (fpmin abs-x abs-y)))
    (values (if (or (fpgreaterp t1 beta)
                    (fplessp rho t2))
                (fpquotient
                  (fplog1p (fpadd (fptimes* (fpsub beta (fpone))
                                             (fpadd beta (fpone)))
                                   (fptimes* theta theta)))
                 (intofp 2))
                (fpquotient (fplog rho) (intofp 2)))
            (fpatan2 y x))))

Funktion: logbigfloat a

Quelltext:

(defprop %log logbigfloat floatprog)

(defun logbigfloat (a)
  (cond ((bigfloatp (car a))
         (big-float-log ($bfloat (car a))))
        (t
         (list '(%log) (car a)))))

Funktion: fplog x

Quelltext:

(defun fplog (x)
  (prog (over two ans oldans term e sum)
    (unless (> (car x) 0)
      (merror "fplog: argument must be positive; found: ~M" (car x)))
    (setq e (fpe)
          over (fpquotient (fpone) e)
          ans 0)
    (do ()
        (nil)
      (cond ((equal x e) (setq x nil) (return nil))
            ((and (fplessp x e) (fplessp over x))
             (return nil))
            ((fplessp x over)
             (setq x (fptimes* x e))
             (decf ans))
            (t
             (incf ans)
             (setq x (fpquotient x e)))))
    (when (null x) (return (intofp (1+ ans))))
    (setq x (fpsub  x (fpone))
          ans (intofp ans))
    (setq x
          (fpexpt (setq term (fpquotient x (fpadd x (setq two (intofp 2)))))
                  2))
    (setq sum (intofp 0))
    (do ((n 1 (+ n 2)))
        ((equal sum oldans))
      (setq oldans sum)
      (setq sum (fpadd sum (fpquotient term (intofp n))))
      (setq term (fptimes* term x)))
    (return (fpadd ans (fptimes* two sum)))))

Funktion: fplog1p x

Quelltext:

(defun fplog1p (x)
  (cond ((fpgreaterp (fpabs x) (fpone))
         (fplog (fpadd x (fpone))))
        (t
         (let* ((sum (intofp 0))
                (term (fpquotient x (fpadd x (intofp 2))))
                (f (fptimes* term term))
                (oldans nil))
           (do ((n 1 (+ n 2)))
               ((equal sum oldans))
             (setq oldans sum)
             (setq sum (fpadd sum (fpquotient term (intofp n))))
             (setq term (fptimes* term f)))
           (fptimes* sum (intofp 2))))))

Funktion: sinbigfloat

Quelltext:

(defprop %sin sinbigfloat floatprog)

(defun sinbigfloat (x)
  (fpsin* (car x) t))

Funktion: fpsin* a fl

Quelltext:

(defun fpsin* (a fl)
  (fpend (let ((fpprec (+ 8 fpprec)))
           (cond ((bigfloatp a) (fpsin (cdr ($bfloat a)) fl))
                 (fl (list '(%sin) a))
                 (t (list '(%cos) a))))))

Funktion: fpsin x fl

Quelltext:

(defun fpsin (x fl)
  (prog (piby2 r sign res k *cancelled)
    (setq sign (cond (fl (> (car x) 0))
                     (t))
          x (fpabs x))
    (when (eql (car x) 0)
      (return (if fl (intofp 0) (intofp 1))))
    (return
      (cdr
        (check-bigfloat
          (let ((fpprec (max fpprec (+ fpprec (cadr x))))
                (xt (bcons x))
                (*cancelled 0)
                (oldprec fpprec))
            (prog (x)
            loop
              (setq x (cdr (check-bigfloat xt)))
              (setq piby2 (fpdiv (fppi) (intofp 2)))
              (setq r (fpintpart (fpdiv x piby2)))
              (setq x (fpadd x (fpmul (intofp (- r)) piby2)))
              (setq k *cancelled)
              (fpadd x (fpminus piby2))
              (setq *cancelled (max k *cancelled))
              (cond ((not (> oldprec (- fpprec *cancelled)))
                     (setq r (rem r 4))
                     (setq res
                           (cond (fl
                                  (cond ((= r 0) (fpsin1 x))
                                        ((= r 1) (fpcos1 x))
                                        ((= r 2) (fpminus (fpsin1 x)))
                                        ((= r 3) (fpminus (fpcos1 x)))))
                                 (t
                                  (cond ((= r 0) (fpcos1 x))
                                        ((= r 1) (fpminus (fpsin1 x)))
                                        ((= r 2) (fpminus (fpcos1 x)))
                                        ((= r 3) (fpsin1 x))))))
                     (return (bcons (if sign res (fpminus res)))))
                    (t
                     (incf fpprec *cancelled)
                     (go loop))))))))))

Funktion: fpcos1 x

Quelltext:

(defun fpcos1 (x)
  (fpsincos1 x nil))

Funktion: fpsin1 x

Quelltext:

(defun fpsin1 (x)
  (fpsincos1 x t))

1

Funktion: fpsincos1 x fl

Quelltext:

(defun fpsincos1 (x fl)
  (prog (ans term oans x2)
     (setq ans (if fl x (intofp 1))
           x2 (fpminus(fpmul x x)))
     (setq term ans)
     (do ((n (if fl 3 2) (+ n 2)))
         ((equal ans oans))
       (setq term (fpmul term (fpdiv x2 (intofp (* n (1- n))))))
       (setq oans ans
             ans (fpadd ans term)))
     (return ans)))

Funktion: cosbigfloat x

Quelltext:

(defprop %cos cosbigfloat floatprog)

(defun cosbigfloat (x)
  (fpsin* (car x) nil))

Funktion: tanbigfloat a

Quelltext:

(defprop %tan tanbigfloat floatprog)

(defun tanbigfloat (a)
  (fpend (let ((fpprec (+ 8 fpprec)))
           (cond ((bigfloatp (setq a (car a)))
                  (setq a (cdr (check-bigfloat a)))
                  (fpdiv (fpsin a t) (fpsin a nil)))
                 (t (list '(%tan) a))))))

Funktion: big-float-asin x &optional y

Quelltext:

(defun big-float-asin (x &optional y)
  (if y
      (multiple-value-bind (u v)
          (complex-asin x y)
        (add u (mul '$%i v)))
      (fpasin x)))

Funktion: complex-asin x y

Quelltext:

(defun complex-asin (x y)
  (let ((x (cdr (check-bigfloat x)))
        (y (cdr (check-bigfloat y))))
    (multiple-value-bind (re-sqrt-1-z im-sqrt-1-z)
        (complex-sqrt (bcons (fpsub (intofp 1) x))
                      (bcons (fpminus y)))
      (multiple-value-bind (re-sqrt-1+z im-sqrt-1+z)
          (complex-sqrt (bcons (fpadd (intofp 1) x))
                        (bcons y))
        (values (bcons (let ((d (fpsub (fpmul re-sqrt-1-z re-sqrt-1+z)
                                       (fpmul im-sqrt-1-z im-sqrt-1+z))))
                         (cond ((eql (car d) 0)
                                (if (fplessp x '(0 0))
                                    (fpminus (fpdiv (fppi) (intofp 2))
                                             (fpdiv (fppi) (intofp 2)))))
                               (t (fpatan (fpdiv x d))))))
                (fpasin (bcons (fpsub (fpmul re-sqrt-1-z im-sqrt-1+z)
                                      (fpmul im-sqrt-1-z re-sqrt-1+z)))))))))

Funktion: fpasin x

Quelltext:

(defun fpasin (x)
  ($bfloat (fpasin-core x)))

Funktion: fpasin-core

Quelltext:

(defun fpasin-core (x)
  (let ((fp-x (cdr (check-bigfloat x))))
    (cond ((minusp (car fp-x))
           (mul -1 (fpasin (bcons (fpminus fp-x)))))
          ((fplessp fp-x (cdr bfhalf))
           (bcons (fpatan (fpdiv fp-x
                                 (fproot (bcons (fpmul (fpsub (fpone) fp-x)
                                                       (fpadd (fpone) fp-x)))
                                         2)))))
          ((fpgreaterp fp-x (fpone))
           (let ((arg (fpadd fp-x
                             (fproot (bcons (fpmul (fpsub fp-x (fpone))
                                                   (fpadd fp-x (fpone))))
                                     2))))
             (add (div '$%pi 2)
                  (mul -1 '$%i (bcons (fplog arg))))))
          (t
           (add (div '$%pi 2)
                (mul -1
                     (bcons
                       (fpatan
                         (fpdiv (fproot (bcons (fpmul (fpsub (fpone) fp-x)
                                                      (fpadd (fpone) fp-x)))
                                        2)
                                fp-x)))))))))

Funktion: big-float-acos x &optional y

Quelltext:

(defun big-float-acos (x &optional y)
  (if y
      (multiple-value-bind (u v)
          (complex-acos x y)
        (add u (mul '$%i v)))
      (fpacos x)))

Funktion: complex-acos x y

Quelltext:

(defun complex-acos (x y)
  (let ((x (cdr (check-bigfloat x)))
        (y (cdr (check-bigfloat y))))
    (multiple-value-bind (re-sqrt-1-z im-sqrt-1-z)
        (complex-sqrt (bcons (fpsub (intofp 1) x))
                      (bcons (fpminus y)))
      (multiple-value-bind (re-sqrt-1+z im-sqrt-1+z)
          (complex-sqrt (bcons (fpadd (intofp 1) x))
                        (bcons y))
        (values (bcons (fpmul (intofp 2)
                              (fpatan (fpdiv re-sqrt-1-z re-sqrt-1+z))))
                (fpasinh (bcons (fpsub (fpmul re-sqrt-1+z im-sqrt-1-z)
                                       (fpmul im-sqrt-1+z re-sqrt-1-z)))))))))

Funktion: fpacos

Quelltext:

(defun fpacos (x)
  ($bfloat (add (div '$%pi 2) (mul -1 (fpasin-core x)))))

Funktion: atanbigfloat x

Quelltext:

(defprop %atan atanbigfloat floatprog)

(defun atanbigfloat (x)
  (fpatan* (car x) (cdr x)))

Funktion: fpatan* a y

Bemerkung:

Im Original Maxima hat diese Funktion den Namen *fpatan.

Quelltext:

(defun fpatan* (a y)
  (fpend (let ((fpprec (+ 8 fpprec)))
           (if (null y)
               (if (bigfloatp a)
                   (fpatan (cdr (check-bigfloat a)))
                   (list '(%atan) a))
               (fpatan2 (cdr (check-bigfloat a))
                        (cdr (check-bigfloat (car y))))))))

Funktion: fpatan

Quelltext:

(defun fpatan (x)
  (prog (term x2 ans oans one two tmp)
    (setq one (intofp 1) two (intofp 2))
    (cond ((fpgreaterp (fpabs x) one)
           (setq tmp (fpdiv (fppi) two))
           (setq ans (fpsub tmp (fpatan (fpdiv one x))))
           (return (cond ((fplessp x (intofp 0))
                          (fpsub ans (fppi)))
                         (t ans))))
          ((fpgreaterp (fpabs x) (fpdiv one two))
           (setq tmp (fpdiv x (fpadd (fpmul x x) one)))
           (setq x2 (fpmul x tmp) term (setq ans one))
           (do ((n 0 (1+ n)))
               ((equal ans oans))
             (setq term
                   (fpmul term
                          (fpmul x2
                                 (fpdiv (intofp (+ 2 (* 2 n)))
                                        (intofp (+ (* 2 n) 3))))))
             (setq oans ans
                   ans (fpadd term ans)))
           (setq ans (fpmul tmp ans)))
          (t
           (setq ans x
                 x2 (fpminus (fpmul x x)) term x)
           (do ((n 3 (+ n 2)))
               ((equal ans oans))
             (setq term (fpmul term x2))
             (setq oans ans
                   ans (fpadd ans (fpdiv term (intofp n)))))))
    (return ans)))

Funktion: fpatan2 y x

Quelltext:

(defun fpatan2 (y x)
  (cond ((eql (car x) 0)
         (cond ((equal (car y) 0)
                (merror "atan2: atan2(0, 0) is undefined."))
               ((minusp (car y))
                (fpdiv (fppi) (intofp -2)))
               (t
                (fpdiv (fppi) (intofp 2)))))
        ((> (car x) 0)
         (fpatan (fpdiv y x)))
        ((> (car y) 0)
         (fpadd (fppi) (fpatan (fpdiv y x))))
        (t
         (fpsub (fpatan (fpdiv y x)) (fppi)))))

Funktion: big-float-sinh x &optional y

Quelltext:

(defun big-float-sinh (x &optional y)
  (unless y
    (fpsinh x)))

Funktion: fpsinh x

Quelltext:

(defun fpsinh (x)
  (cond ((eql 0 (cadr x))
         (check-bigfloat x))
        ((fpposp (cdr x))
         (let ((d (fpexpm1 (cdr (check-bigfloat x)))))
           (bcons (fpdiv (fpadd d (fpdiv d (fpadd d (fpone))))
                         (intofp 2)))))
        (t
         (bcons 
           (fpminus
             (cdr (fpsinh (bcons (fpminus (cdr (check-bigfloat x)))))))))))

Funktion: fpexpm1 x

Quelltext:

(defun fpexpm1 (x)
  (cond ((fpgreaterp (fpabs x) (fpone))
         (fpsub (fpexp x) (fpone)))
        (t
         (let ((ans x)
               (oans nil)
               (term x))
           (do ((n 2 (1+ n)))
               ((equal ans oans))
             (setf term (fpdiv (fpmul x term) (intofp n)))
             (setf oans ans)
             (setf ans (fpadd ans term)))
           ans))))

Funktion: big-float-tanh x &optional y

Quelltext:

(defun big-float-tanh (x &optional y)
  (if y
      (multiple-value-bind (u v)
          (complex-tanh x y)
        (add u (mul '$%i v)))
      (fptanh x)))

Funktion: complex-tanh x y

Quelltext:

(defun complex-tanh (x y)
  (let* ((tv (cdr (tanbigfloat (list y))))
	 (beta (fpadd (fpone) (fpmul tv tv)))
	 (s (cdr (fpsinh x)))
	 (s^2 (fpmul s s))
	 (rho (fproot (bcons (fpadd (fpone) s^2)) 2))
	 (den (fpadd (fpone) (fpmul beta s^2))))
    (values (bcons (fpdiv (fpmul beta (fpmul rho s)) den))
	    (bcons (fpdiv tv den)))))

Funktion: fptanh x

Quelltext:

(defun fptanh (x)
  (let* ((two (intofp 2))
         (fp (cdr (check-bigfloat x)))
         (d (fpexpm1 (fpmul fp two))))
    (bcons (fpdiv d (fpadd d two)))))

Funktion: big-float-asinh x &optional y

Quelltext:

(defun big-float-asinh (x &optional y)
  (if y
      (multiple-value-bind (u v)
          (complex-asinh x y)
        (add u (mul '$%i v)))
      (fpasinh x)))

Funktion: complex-asinh x y

Quelltext:

(defun complex-asinh (x y)
  (multiple-value-bind (u v)
      (complex-asin (mul -1 y) x)
    (values v (bcons (fpminus (cdr u))))))

Funktion: fpasinh x

Quelltext:

(defun fpasinh (x)
  (let* ((fp-x (cdr (check-bigfloat x)))
         (absx (fpabs fp-x))
         (one (fpone))
         (two (intofp 2))
         (minus (minusp (car fp-x)))
         result)
    (cond ((fpgreaterp absx two)
           (setf result
                 (fplog
                   (fpadd (fpmul absx two)
                          (fpdiv one
                                 (fpadd absx
                                        (fproot (bcons (fpadd one
                                                              (fpmul absx
                                                                     absx)))
                                                2)))))))
          (t
           (let ((x*x (fpmul absx absx)))
             (setq result
                   (fplog1p
                     (fpadd absx
                            (fpdiv x*x
                                   (fpadd one
                                          (fproot (bcons (fpadd one x*x))
                                                  2)))))))))
    (if minus
        (bcons (fpminus result))
        (bcons result))))

Funktion: big-float-atanh x &optional y

Quelltext:

(defun big-float-atanh (x &optional y)
  (if y
      (multiple-value-bind (u v)
          (complex-atanh x y)
        (add u (mul '$%i v)))
      (fpatanh x)))

Funktion: complex-atanh x y

Quelltext:

(defun complex-atanh (x y)
  (let* ((fpx (cdr (check-bigfloat x)))
         (fpy (cdr (check-bigfloat y)))
         (beta (if (minusp (car fpx))
                   (fpminus (fpone))
                   (fpone)))
         (x-lt-minus-1 (fplessp (fpadd fpx (fpone)) '(0 0)))
         (x-gt-plus-1 (fpgreaterp fpy (fpone)))
         (y-equals-0 (equal y '((bigfloat) 0 0)))
         (x (fpmul beta fpx))
         (y (fpmul beta (fpminus fpy)))
         (rho (intofp 0))
         (t1 (fpadd (fpabs y) rho))
         (t1^2 (fpmul t1 t1))
         (1-x (fpsub (fpone) x))
         (eta (fpdiv (fplog1p (fpdiv (fpmul (intofp 4) x)
                                     (fpadd (fpmul 1-x 1-x) t1^2)))
                     (intofp 4)))
         (nu (if y-equals-0
                 (fpminus
                   (if x-lt-minus-1
                       (cdr ($bfloat '((mquotient) $%pi 2)))
                       (if x-gt-plus-1
                           (cdr ($bfloat '((mminus) ((mquotient) $%pi 2))))
                           (merror "COMPLEX-ATANH: HOW DID I GET HERE?"))))
                 (fpmul (cdr bfhalf)
                        (fpatan2 (fpmul (intofp 2) y)
                                 (fpsub (fpmul 1-x (fpadd (fpone) x))
                                        t1^2))))))
    (values (bcons (fpmul beta eta))
            (bcons (fpminus (fpmul beta nu))))))

Funktion: fpatanh x

Quelltext:

(defun fpatanh (x)
  (let* ((fp-x (cdr (check-bigfloat x))))
    (cond ((fplessp fp-x (intofp 0))
           (mul -1 (fpatanh (bcons (fpminus fp-x)))))
          ((fpgreaterp fp-x (fpone))
           (multiple-value-bind (u v)
               (complex-atanh x (bcons (intofp 0)))
             (add u (mul '$%i v))))
          ((fpgreaterp fp-x (cdr bfhalf))
           (bcons (fpmul (cdr bfhalf)
                         (fplog1p (fpdiv (fpmul (intofp 2) fp-x)
                                         (fpsub (fpone) fp-x))))))
          (t
           (let ((2x (fpmul (intofp 2) fp-x)))
             (bcons (fpmul (cdr bfhalf)
                           (fplog1p (fpadd 2x
                                           (fpdiv (fpmul 2x fp-x)
                                                  (fpsub (fpone)
                                                         fp-x)))))))))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.9 Anzeige großer Gleitkommazahlen

Funktion: msize-bigfloat x l r

Quelltext:

(defprop bigfloat msize-bigfloat grind)

(defun msize-bigfloat (x l r)
  (msz (fpformat x) l r))

Funktion: dim-bigfloat form result

Quelltext:

(defun dim-bigfloat (form result)
  (declare (special $lispdispflag))
  (let (($lispdispflag nil))
    (dimension-string (fpformat form) result)))

Funktion: fpformat l

Quelltext:

(defun fpformat (l)
  (if (not (member 'simp (cdar l) :test #'eq))
      (setq l (cons (cons (caar l) (cons 'simp (cdar l))) (cdr l))))
  (cond ((eql (cadr l) 0)
         (if (not (eql (caddr l) 0))
             (merror "fpformat: detected an incorrect form of 0.0b0: ~M, ~M~%"
                    (cadr l) (caddr l)))
         (list #\0 #\. #\0 #\b #\0))
        (t
         (let ((extradigs (floor (1+ (/ (integer-length (caddr l))
                                        #.(/ (log 10.0) (log 2.0))))))
               (*m 1)
               (*cancelled 0))
           (setq l
                 (let ((*decfp* t)
                       (fpprec (+ extradigs (decimalsin (- (caddar l) 2))))
                       (of (caddar l))
                       (l (cdr l))
                       (expon nil))
                   (setq expon (- (cadr l) of))
                   (setq l (if (minusp expon)
                               (fpdiv (intofp (car l))
                                      (fpintexpt 2 (- expon) of))
                               (fpmul (intofp (car l))
                                      (fpintexpt 2 expon of))))
                   (incf fpprec (- extradigs))
                   (list (fpround (car l)) (+ (- extradigs) *m (cadr l))))))
         (let ((*print-base* 10)
               *print-radix*
               (l1 nil))
           (setq l1 (if (not $bftrunc)
                        (coerce (print-invert-case (car l)) 'list)
                        (do ((l (nreverse
                                  (coerce (print-invert-case (car l)) 'list))
                                (cdr l)))
                            ((not (eql #\0 (car l))) (nreverse l)))))
           (nconc (ncons (car l1))
                  (ncons #\. )
                  (or (and (cdr l1)
                           (cond ((or (zerop $fpprintprec)
                                      (not (< $fpprintprec $fpprec))
                                      (null (cddr l1)))
                                  (cdr l1))
                                 (t
                                  (setq l1 (cdr l1))
                                  (do ((i $fpprintprec (1- i))
                                       (l2))
                                      ((or (< i 2) (null l1))
                                       (cond ((not $bftrunc) (nreverse l2))
                                             (t
                                              (do ((l3 l2 (cdr l3)))
                                                  ((not (eql #\0 (car l3)))
                                                   (nreverse l3))))))
                                    (setq l2 (cons (car l1) l2)
                                          l1 (cdr l1))))))
                      (ncons #\0))
                  (ncons #\b)
                  (coerce (print-invert-case (1- (cadr l))) 'list))))))

Funktion: decimalsin x

Quelltext:

(defun decimalsin (x)
  (do ((i (truncate (* 59 x) 196) (1+ i)))
      (nil)
    (when (> (integer-length (expt 10 i)) x)
      (return (1- i)))))

Funktion: fpintexpt int nn fixprec

Quelltext:

(defun fpintexpt (int nn fixprec)
  (setq fixprec (truncate fixprec (1- (integer-length int))))
  (let ((bas (intofp (expt int (min nn fixprec)))))
    (if (> nn fixprec)
        (fpmul (intofp (expt int (rem nn fixprec)))
               (fpexpt bas (truncate nn fixprec)))
        bas)))

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Dieter Kaiser on Dezember, 13 2011 using texi2html 1.76.