Subject: [clisp-list] *-float-*-epsilon in clisp

From: Stefan Kain <[email-masked]>
Date: Sat Feb 9 10:40:03 2002

Hi fellow clisp-ers,

I have written the following functions
which determine the various floating-point-epsilons.

I get discrepancies for the double-float-*-epsilon values
on my machine. I don't think, that my FP-Coprocessor is
wrong. Maybe there is just a wrong definition shipped
with clisp. If you  want to read, what this all is about,
have a look at: 

<http://www.xanalys.com/software_tools/reference/
HyperSpec/Body/convar_short-_tive-epsilon.html>

Simply load the functions given below and enter
into the repl:

(test-epsilons)

Could you give them a try and report your results for your
local installation to clisp-devel?

That would be very kind! Thanks!

Bye,
Stefan

===============================================================
(defun test-pos-epsilon (<EPSILON>)
  (= (float 1 <EPSILON>) (+ (float 1 <EPSILON>) <EPSILON>)))

(defun test-neg-epsilon (<EPSILON>)
  (= (float 1 <EPSILON>) (- (float 1 <EPSILON>) <EPSILON>)))

(defun binary-search (lower_bound upper_bound old_string precision test-fun)
  (let* ((new_bound (/ (+ (float lower_bound precision)
                          (float upper_bound precision)) 2))
         (new_string (format nil "~E" (float new_bound precision))))
    (if (string= old_string new_string)
      ;; then
      ;; (format t "~A ~A~%" old_string new_string)
      (float upper_bound precision)
      ;; else
      (progn 
        ;;  (format t "~A ~A~%" (float lower_bound precision)
        ;;          (float upper_bound precision))
        (if (funcall test-fun new_bound)
          ;; then
          (binary-search new_bound upper_bound new_string
                         precision test-fun)
          ;; else
          (binary-search lower_bound new_bound new_string
                         precision test-fun))))))

;;;; test:      
(defun test-epsilons ()
  (let ((fmt "~30E~30E~30E~%"))
    (progn
      (format t "~30<~A~>~30<~A~>~30<~A~>~%"
              "system value"
              "computed value"
              "difference")

      ;; short-float-epsilon:
      (format t "short-float-epsilon:~%")
      (format t fmt
              short-float-epsilon
              (binary-search 0.0 1.0 "0.0" 1.0s0 #'test-pos-epsilon)
              (- (binary-search 0.0 1.0 "0.0" 1.0s0 #'test-pos-epsilon)
                 short-float-epsilon))

      ;; short-float-negative-epsilon:
      (format t "short-float-negative-epsilon:~%")
      (format t fmt 
              short-float-negative-epsilon
              (binary-search 0.0 1.0 "0.0" 1.0s0 #'test-neg-epsilon)
              (- (binary-search 0.0 1.0 "0.0" 1.0s0 #'test-neg-epsilon)
                 short-float-negative-epsilon))

      ;; single-float-epsilon:
      (format t "single-float-epsilon:~%")
      (format t fmt 
              single-float-epsilon
              (binary-search 0.0 1.0 "0.0" 1.0 #'test-pos-epsilon)
              (- (binary-search 0.0 1.0 "0.0" 1.0 #'test-pos-epsilon)
                 single-float-epsilon))

      ;; single-float-negative-epsilon:
      (format t "single-float-negative-epsilon:~%")
      (format t fmt 
              single-float-negative-epsilon
              (binary-search 0.0 1.0 "0.0" 1.0 #'test-neg-epsilon)
              (- (binary-search 0.0 1.0 "0.0" 1.0 #'test-neg-epsilon)
                 single-float-negative-epsilon))

      ;; double-float-epsilon:
      (format t "double-float-epsilon:~%")
      (format t fmt
              double-float-epsilon
              (binary-search 0.0 1.0 "0.0" 1.0d0 #'test-pos-epsilon)
              (- (binary-search 0.0 1.0 "0.0" 1.0d0 #'test-pos-epsilon)
                 double-float-epsilon))

      ;; double-float-negative-epsilon:
      (format t "double-float-negative-epsilon:~%")
      (format t fmt
              double-float-negative-epsilon
              (binary-search 0.0 1.0 "0.0" 1.0d0 #'test-neg-epsilon)
              (- (binary-search 0.0 1.0 "0.0" 1.0d0 #'test-neg-epsilon)
                 double-float-negative-epsilon))

      ;; long-float-epsilon:
      (format t "long-float-epsilon:~%")
      (format t fmt 
              long-float-epsilon
              (binary-search 0.0 1.0 "0.0" 1.0l0 #'test-pos-epsilon)
              (- (binary-search 0.0 1.0 "0.0" 1.0l0 #'test-pos-epsilon)
                 long-float-epsilon))

      ;;long-float-negative-epsilon:
      (format t "long-float-negative-epsilon:~%")
      (format t fmt
              long-float-negative-epsilon
              (binary-search 0.0 1.0 "0.0" 1.0l0 #'test-neg-epsilon)
              (- (binary-search 0.0 1.0 "0.0" 1.0l0 #'test-neg-epsilon)
                 long-float-negative-epsilon)))))

---

From: Raymond Toy <[email-masked]>
Date: Mon Feb 11 06:12:03 2002

>>>>> "Stefan" == Stefan Kain <[email-masked]> writes:

    Stefan> Could you give them a try and report your results for your
    Stefan> local installation to clisp-devel?

Clisp on an Ultrasparc II running Solaris 2.7:
"2.27.2 (released 2001-10-05) (built 3216661407) (memory 3216748156)"

As expected:

(test-epsilons)
                  system value                computed value                    difference
short-float-epsilon:
                     7.6295s-6                     7.6295s-6                        0.0s+0
short-float-negative-epsilon:
                    3.81477s-6                    3.81477s-6                        0.0s+0
single-float-epsilon:
                   5.960465E-8                   5.960465E-8                        0.0E+0
single-float-negative-epsilon:
                  2.9802325E-8                  2.9802325E-8                        0.0E+0
double-float-epsilon:
        1.1102230246251567d-16        1.1102230246251567d-16                        0.0d+0
double-float-negative-epsilon:
         5.551115123125784d-17         5.551115123125784d-17                        0.0d+0
long-float-epsilon:
     5.4210108624275221706L-20     5.4210108624275221706L-20                        0.0L+0
long-float-negative-epsilon:
     2.7105054312137610853L-20     2.7105054312137610853L-20                        0.0L+0

I still think the epsilon problem only happens on x86 and that's
because of the 80-bit precision that it has.

Ray