From b6942c0c37a504e00c717c8c74bfa9dcd208c931 Mon Sep 17 00:00:00 2001
From: Paul Eggert
Date: Sun, 10 Nov 2019 15:01:06 0800
Subject: [PATCH] Document Lisp floats a bit better
MIMEVersion: 1.0
ContentType: text/plain; charset=UTF8
ContentTransferEncoding: 8bit
* doc/lispref/numbers.texi (Float Basics):
* doc/misc/cl.texi (Implementation Parameters):
* lisp/emacslisp/cllib.el (clmostpositivefloat)
(clleastpositivefloat)
(clleastpositivenormalizedfloat, clfloatepsilon)
(clfloatnegativeepsilon):
Document IEEE floating point better. Donâ€™t suggest that Emacs
might use some floatingpoint format other than IEEE format, as
Emacs currently assumes IEEE in several places and there seems
little point in removing those assumptions.

doc/lispref/numbers.texi  8 ++++
doc/misc/cl.texi  54 +++++++++++++++++
lisp/emacslisp/cllib.el  16 +++++
3 files changed, 37 insertions(+), 41 deletions()
diff git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index 0c71387a8a..939ad5c85a 100644
 a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ 218,8 +218,12 @@ considered to be valid as a character. @xref{Character Codes}.
Floatingpoint numbers are useful for representing numbers that are
not integral. The range of floatingpoint numbers is
the same as the range of the C data type @code{double} on the machine
you are using. On all computers currently supported by Emacs, this is
doubleprecision @acronym{IEEE} floating point.
+you are using. On all computers supported by Emacs, this is
+@acronym{IEEE} binary64 floating point format, which is standardized by
+@url{https://standards.ieee.org/standard/7542019.html,,IEEE Std 7542019}
+and is discussed further in David Goldberg's paper
+``@url{https://docs.oracle.com/cd/E1995701/8063568/ncg_goldberg.html,
+What Every Computer Scientist Should Know About FloatingPoint Arithmetic}''.
The read syntax for floatingpoint numbers requires either a decimal
point, an exponent, or both. Optional signs (@samp{+} or @samp{})
diff git a/doc/misc/cl.texi b/doc/misc/cl.texi
index 246f86bfd1..cfdbc7c41b 100644
 a/doc/misc/cl.texi
+++ b/doc/misc/cl.texi
@@ 3113,48 +3113,42 @@ function that must be called before the parameters can be used.
@defun clfloatlimits
This function makes sure that the Common Lisp floatingpoint parameters
like @code{clmostpositivefloat} have been initialized. Until it is
called, these parameters will be @code{nil}.
@c If this version of Emacs does not support floats, the parameters will
@c remain @code{nil}.
+called, these parameters have unspecified values.
If the parameters have already been initialized, the function returns
immediately.

The algorithm makes assumptions that will be valid for almost all
machines, but will fail if the machine's arithmetic is extremely
unusual, e.g., decimal.
@end defun
Since true Common Lisp supports up to four different kinds of floatingpoint
numbers, it has families of constants like
@code{mostpositivesinglefloat}, @code{mostpositivedoublefloat},
@code{mostpositivelongfloat}, and so on. Emacs has only one
kind of floatingpoint number, so this package just uses single constants.
+@code{mostpositivelongfloat}, and so on. This package uses just
+one set of constants because Emacs has only one kind of
+floatingpoint number, namely the IEEE binary64 floatingpoint format.
+@xref{Float Basics,,,elisp,GNU Emacs Lisp Reference Manual}.
@defvar clmostpositivefloat
This constant equals the largest value a Lisp float can hold.
For those systems whose arithmetic supports infinities, this is
the largest @emph{finite} value. For IEEE machines, the value
is approximately @code{1.79e+308}.
+This constant equals the largest finite value a Lisp float can hold.
+For IEEE binary64 format, this equals @code{( (expt 2 1024) ( 2
+971))}, which equals @code{1.7976931348623157e+308}.
@end defvar
@defvar clmostnegativefloat
This constant equals the most negative value a Lisp float can hold.
(It is assumed to be equal to @code{( clmostpositivefloat)}.)
+This constant equals the most negative finite value a Lisp float can hold.
+For IEEE binary64 format, this equals @code{( clmostpositivefloat)}.
@end defvar
@defvar clleastpositivefloat
This constant equals the smallest Lisp float value greater than zero.
For IEEE machines, it is about @code{4.94e324} if denormals are
supported or @code{2.22e308} if not.
+@defvar clleastpositivenormalizedfloat
+This constant equals the smallest positive Lisp float that is
+@dfn{normalized}, i.e., that has full precision.
+For IEEE binary64 format, this equals @code{(expt 2 1022)},
+which equals @code{2.2250738585072014e308}.
@end defvar
@defvar clleastpositivenormalizedfloat
This constant equals the smallest @emph{normalized} Lisp float greater
than zero, i.e., the smallest value for which IEEE denormalization
will not result in a loss of precision. For IEEE machines, this
value is about @code{2.22e308}. For machines that do not support
the concept of denormalization and gradual underflow, this constant
will always equal @code{clleastpositivefloat}.
+@defvar clleastpositivefloat
+This constant equals the smallest Lisp float value greater than zero.
+For IEEE binary64 format, this equals @code{5e324} (which equals
+@code{(expt 2 1074)}) if subnormal numbers are supported, and
+@code{clleastpositivenormalizedfloat} otherwise.
@end defvar
@defvar clleastnegativefloat
@@ 3169,14 +3163,14 @@ This constant is the negative counterpart of
@defvar clfloatepsilon
This constant is the smallest positive Lisp float that can be added
to 1.0 to produce a distinct value. Adding a smaller number to 1.0
will yield 1.0 again due to roundoff. For IEEE machines, epsilon
is about @code{2.22e16}.
+will yield 1.0 again due to roundoff. For IEEE binary64 format, this
+equals @code{(expt 2 52)}, which equals @code{2.220446049250313e16}.
@end defvar
@defvar clfloatnegativeepsilon
This is the smallest positive value that can be subtracted from
1.0 to produce a distinct value. For IEEE machines, it is about
@code{1.11e16}.
+1.0 to produce a distinct value. For IEEE binary64 format, this
+equals @code{(expt 2 53)}, which equals @code{1.1102230246251565e16}.
@end defvar
@node Sequences
diff git a/lisp/emacslisp/cllib.el b/lisp/emacslisp/cllib.el
index ff09691817..7d0df27e14 100644
 a/lisp/emacslisp/cllib.el
+++ b/lisp/emacslisp/cllib.el
@@ 299,7 +299,7 @@ If true return the decimal value of digit CHAR in RADIX."
(defconst clmostpositivefloat nil
"The largest value that a Lisp float can hold.
If your system supports infinities, this is the largest finite value.
For IEEE machines, this is approximately 1.79e+308.
+For Emacs, this equals 1.7976931348623157e+308.
Call `clfloatlimits' to set this.")
(defconst clmostnegativefloat nil
@@ 309,8 +309,8 @@ Call `clfloatlimits' to set this.")
(defconst clleastpositivefloat nil
"The smallest value greater than zero that a Lisp float can hold.
For IEEE machines, it is about 4.94e324 if denormals are supported,
or 2.22e308 if they are not.
+For Emacs, this equals 5e324 if subnormal numbers are supported,
+`clleastpositivenormalizedfloat' if they are not.
Call `clfloatlimits' to set this.")
(defconst clleastnegativefloat nil
@@ 320,10 +320,8 @@ Call `clfloatlimits' to set this.")
(defconst clleastpositivenormalizedfloat nil
"The smallest normalized Lisp float greater than zero.
This is the smallest value for which IEEE denormalization does not lose
precision. For IEEE machines, this value is about 2.22e308.
For machines that do not support the concept of denormalization
and gradual underflow, this constant equals `clleastpositivefloat'.
+This is the smallest value that has full precision.
+For Emacs, this equals 2.2250738585072014e308.
Call `clfloatlimits' to set this.")
(defconst clleastnegativenormalizedfloat nil
@@ 334,12 +332,12 @@ Call `clfloatlimits' to set this.")
(defconst clfloatepsilon nil
"The smallest positive float that adds to 1.0 to give a distinct value.
Adding a number less than this to 1.0 returns 1.0 due to roundoff.
For IEEE machines, epsilon is about 2.22e16.
+For Emacs, this equals 2.220446049250313e16.
Call `clfloatlimits' to set this.")
(defconst clfloatnegativeepsilon nil
"The smallest positive float that subtracts from 1.0 to give a distinct value.
For IEEE machines, it is about 1.11e16.
+For Emacs, this equals 1.1102230246251565e16.
Call `clfloatlimits' to set this.")

2.24.1