axiom-developer
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Axiom-developer] Re: Boot, Virtual Machine


From: Waldek Hebisch
Subject: Re: [Axiom-developer] Re: Boot, Virtual Machine
Date: Fri, 25 May 2007 13:24:48 +0200 (CEST)

Gabriel Dos Reis wrote:
> On Wed, 23 May 2007, Waldek Hebisch wrote:
> 
> | There is a few snippets which were really converted to work around
> | limitations of Boot.  In fact I yesterday commited one such
> | snippet:  I needed double precision numeric constants, but both
> | old Boot and Shoe were mangling them.
> 
> Please, be more specific. Show the codes so that we know how to deal 
> with them.  I've have lots of emails coming in (over thousand) per day
> I don't necessary go into great depth into every program generated emails.
> 

That is a Lisp function I added.  In comment you may find Boot version.
My problem is that old boot read '1.0d0' as '1.0' followed by
identifier 'd0'.  Shoe is doing slightly different thing: it reads
the number as is (maybe using Lisp read) but then reads extra 
identifier 'd0'.

BTW: The Lisp formatting may shock Lispers, but my objective was
to have line-by-line correspondence between Boot and Lisp code
and formating follows Boot version.


(defun |axiom_log_10| (u)
    ;;; k := INTEGER_-LENGTH(u)
    (let
    ((k (INTEGER-LENGTH u)))
    ;;; k > MOST_-POSITIVE_-DOUBLE_-FLOAT =>
    ;;;    SAY("Number too big")
    ;;;    THROW('outputFailure,'outputFailure)
    (if (> k MOST-POSITIVE-DOUBLE-FLOAT)
        (progn
        (SAY '|Number too big|)
        (THROW '|outputFailure| '|outputFailure|)))

    (let ((l10 0.0d0))
    (declare (double-float l10))

    ;;; if (k < 61) then
    (if (< k 61)
    ;;;    l10 := LOG10 (FLOAT (u, 1.0d0))
       (setf l10 (LOG10 (FLOAT u 1.0d0)))
    ;;; else
    ;;;    su := ASH(u, - (k - 54))
    ;;;    l10 := LOG10 (FLOAT (su, 1.0d0))
    ;;;          -- we want full double precision here because the second
    ;;;          -- term may be much bigger than the first one, so we use
    ;;;          -- very precise estimate of log(2)/log(10)
    ;;;          + 0.301029995663981195213738894724d0 * FLOAT ((k - 54), 1.0d0)
       (progn
       (let ((su (ASH u (- (- k 54)))))
       (setf l10 (+ (LOG10 (FLOAT su 1.0d0))
                    (* 0.301029995663981195213738894724d0
                       (FLOAT (- k 54) 1.0d0)))))))
    ;;; -- Add bias to l10 to have only one-sided error
    ;;; l10i := FLOOR(l10 + 1.0d-9)
    (let ((l10i (FLOOR (+ l10 1.0d-9))))
    ;;; l10i < 10000 =>
    (if (< l10i 10000)
          (progn
    ;;;   -- Check if sure
    ;;;   l10 - 1.0d-9 > l10i => l10i
          (if (> (- l10 1.0d-9) l10i)
              (return-from |axiom_log_10| l10i))
    ;;;   u < EXPT(10, l10i) => l10i - 1
          (if (< u (EXPT 10 l10i))
              (return-from |axiom_log_10| (- l10i 1)))
    ;;;   l10i
          (return-from |axiom_log_10| l10i)))
    ;;; -- width is very large, it would be expensive to compute it
    ;;; -- accuratly, so we just make sure that we overestimate.
    ;;; -- l10 should have about 14 digits of accuracy
    ;;; FLOOR(l10 * (1.0d0 + 1.0d-12))
    (FLOOR (* l10 (+ 1.0d0 1.0d-12)))))))


-- 
                              Waldek Hebisch
address@hidden 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]