From: Hallvard B Furuseth
Subject: How precise are floating-point operations?
Date: 
Message-ID: <HBF.20030331q5mr@bombur.uio.no>
Is it possible to ask Lisp how precise its floating-point operations
are?  Specifically, I need to know how much precision to trust
    (log (coerce some-integer 'long-float) 2.0L0)
with in clisp.

I didn't find anything like DBL_EPSILON from <float.h> in C, so I tried

(defun float-epsilon-add (one dv)
  (+ one dv))                           ;don't want this optimized away

(defun float-epsilon (type)
  (let* ((one (coerce 1 type))
         (dv one))
    (loop until (equal one (float-epsilon-add one dv))
          do (setq dv (/ dv 2)))
    dv))

That told me the precision of +, but I have no idea if it says that log
is equally precise, and I don't quite know how to do the same for log.

-- 
Hallvard

From: Raymond Toy
Subject: Re: How precise are floating-point operations?
Date: 
Message-ID: <4nk7efichs.fsf@edgedsp4.rtp.ericsson.se>
>>>>> "Hallvard" == Hallvard B Furuseth <············@usit.uio.no> writes:

    Hallvard> Is it possible to ask Lisp how precise its floating-point operations
    Hallvard> are?  Specifically, I need to know how much precision to trust
    Hallvard>     (log (coerce some-integer 'long-float) 2.0L0)
    Hallvard> with in clisp.

Probably pretty good, say within a couple of bits or so.  But you'd
have to ask the clisp folks for the real answer.

    Hallvard> I didn't find anything like DBL_EPSILON from <float.h> in C, so I tried

    Hallvard> (defun float-epsilon-add (one dv)
    Hallvard>   (+ one dv))                           ;don't want this optimized away

    Hallvard> (defun float-epsilon (type)
    Hallvard>   (let* ((one (coerce 1 type))
    Hallvard>          (dv one))
    Hallvard>     (loop until (equal one (float-epsilon-add one dv))
    Hallvard>           do (setq dv (/ dv 2)))
    Hallvard>     dv))

    Hallvard> That told me the precision of +, but I have no idea if it says that log
    Hallvard> is equally precise, and I don't quite know how to do the same for log.

You could have gotten the same info[1] by looking at
single-float-epsilon, double-float-epsilon, etc.

Ray


Footnotes: 
[1]  Except for x86 which is a bit strange in this area with it's
habit of doing all FP arithmetic with 80-bit registers.
From: Gareth McCaughan
Subject: Re: How precise are floating-point operations?
Date: 
Message-ID: <slrnb8hh6b.nfk.Gareth.McCaughan@g.local>
Hallvard B Furuseth wrote:

>  Is it possible to ask Lisp how precise its floating-point operations
>  are?  Specifically, I need to know how much precision to trust
>      (log (coerce some-integer 'long-float) 2.0L0)
>  with in clisp.

I don't know of *any* language that exposes that sort of
information. As Raymond Toy already told you, you can get
the "machine epsilon" via <whatever>-FLOAT-EPSILON, but
that's not what you're after...

By the way, I take it you're aware that in CLISP[1] the
precision of long-floats can be increased without limit[2]?
If you're prepared to bet that LOG doesn't lose more than,
say, 16 bits of precision -- and I'd be *horrified* if it
were anywhere near that bad -- then you can just do
(setf (long-float-digits) N) where N is large enough
that even with whatever inaccuracy you expect LOG to
incur your calculations are safe.

Experiment suggests that CLISP always gives values
correct to within 1 ulp for LOG on long-floats.
Specifically, for all integers from 3 to 10000,
and on at least 10000 random integers below 10^9,
and on at least 2000 random integers below 2^256,
let A be the value computed with 256 bits and B
the value computed with 512; then -log_2(|A-B|/B)
is > 255 for all those numbers. I've done fewer
tests with other lengths, with similar results.


[1] I'm assuming that when you say "clisp" you mean the
    Common Lisp implementation called "CLISP", not just
    "Common Lisp".

[2] Well, almost :-).

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc
From: Hallvard B Furuseth
Subject: Re: How precise are floating-point operations?
Date: 
Message-ID: <HBF.20030401d03n@bombur.uio.no>
Gareth McCaughan <················@pobox.com> wrote:

> I don't know of *any* language that exposes that sort of information.

Oops:-)

> As Raymond Toy already told you, you can get the "machine epsilon" via
> <whatever>-FLOAT-EPSILON, but that's not what you're after...

Yes, I hoped I had missed something like that.

> By the way, I take it you're aware that in CLISP[1] the precision of
> long-floats can be increased without limit[2]?

Well, I do now.

> If you're prepared to bet that LOG doesn't lose more than, say, 16
> bits of precision -- and I'd be *horrified* if it were anywhere near
> that bad -- then you can just do (setf (long-float-digits) N) where N
> is large enough that even with whatever inaccuracy you expect LOG to
> incur your calculations are safe.  (...)

Done.  Thanks.

-- 
Hallvard
From: Adam Warner
Subject: Re: How precise are floating-point operations?
Date: 
Message-ID: <pan.2003.04.01.08.02.33.832501@consulting.net.nz>
Hi Hallvard B Furuseth,

> Is it possible to ask Lisp how precise its floating-point operations
> are?  Specifically, I need to know how much precision to trust
>     (log (coerce some-integer 'long-float) 2.0L0)
> with in clisp.

CLISP has arbitrary precision floats:
http://clisp.cons.org/impnotes/num-concepts.html#lfd

Some operators are precise to the arbitrary precision, like PI. Some less
so, like the implementation notes warn:

http://clisp.cons.org/impnotes/num-dict.html

   "Function EXPT. (EXPT base exponent) is not very precise if exponent
   has a large absolute value."

That limitation aside it appears to be as precise as you want:

[1]> (setf (ext:long-float-digits) 220)
220
[2]> (expt 2.0l0 (log 10.0l0 2.0L0))

WARNING:
Floating point operation combines numbers of different precision.
See ANSI CL 12.1.4.4 and the CLISP impnotes for details.
The result's actual precision is controlled by
*floating-point-contagion-ansi*.
To shut off this warning, set *warn-on-floating-point-contagion* to nil.
10.0000000000000000000000000000000000000000000000000000000000000000006L0

In long floating point CLISP really excels.

Regards,
Adam