@cindex comparing numbers
To test numbers for numerical equality, you should normally use
- @code{=}, not @code{eq}. There can be many distinct floating-point
- and large integer objects with the same numeric value. If you use
- @code{eq} to compare them, then you test whether two values are the
- same @emph{object}. By contrast, @code{=} compares only the numeric
- values of the objects.
+ @code{=} instead of non-numeric comparison predicates like @code{eq},
-@code{eql} and @code{equal}. Distinct floating-point objects can be
-numerically equal. If you use @code{eq} to compare them, you test
-whether they are the same @emph{object}; if you use @code{eql} or
-@code{equal}, you test whether their values are
++@code{eql} and @code{equal}. Distinct floating-point and large
++integer objects can be numerically equal. If you use @code{eq} to
++compare them, you test whether they are the same @emph{object}; if you
++use @code{eql} or @code{equal}, you test whether their values are
+ @emph{indistinguishable}. In contrast, @code{=} uses numeric
+ comparison, and sometimes returns @code{t} when a non-numeric
+ comparison would return @code{nil} and vice versa. @xref{Float
+ Basics}.
- In Emacs Lisp, each integer is a unique Lisp object.
-Therefore, @code{eq} is equivalent to @code{=} where integers are
+ In Emacs Lisp, each small integer is a unique Lisp object.
+Therefore, @code{eq} is equivalent to @code{=} where small integers are
concerned. It is sometimes convenient to use @code{eq} for comparing
an unknown value with an integer, because @code{eq} does not report an
error if the unknown value is not a number---it accepts arguments of
** When formatting a floating-point number as an octal or hexadecimal
integer, Emacs now signals an error if the number is too large for the
- implementation to format (Bug#30408).
+ implementation to format.
-+++
-** The Lisp reader now signals an overflow for plain decimal integers
-that do not end in '.' and are outside Emacs range. Formerly the Lisp
-reader silently converted them to floating-point numbers, and signaled
-overflow only for integers with a radix that are outside machine range.
-To get the old behavior, set the new, experimental variable
-read-integer-overflow-as-float to t and please email
-30408@debbugs.gnu.org if you need that.
-
---
** Some functions and variables obsolete since Emacs 22 have been removed:
archive-mouse-extract, assoc-ignore-case, assoc-ignore-representation,
+++
** New function 'proper-list-p'.
Given a proper list as argument, this predicate returns its length;
- otherwise, it returns nil.
+ otherwise, it returns nil. 'format-proper-list-p' is now an obsolete
+ alias for the new function.
++++
+** Emacs Lisp integers can be of arbitrary precision. The new
+predicates 'bignump' and 'fixnump' can be used to distinguish between
+the types of integers.
+
** define-minor-mode automatically documents the meaning of ARG
+++
carelt = XCAR (elt);
/* If it is (if X Y), look at Y. */
if (EQ (carelt, Qif)
- && EQ (Fnthcdr (make_fixnum (3), elt), Qnil))
- && NILP (Fnthcdr (make_number (3), elt)))
- elt = Fnth (make_number (2), elt);
++ && NILP (Fnthcdr (make_fixnum (3), elt)))
+ elt = Fnth (make_fixnum (2), elt);
/* If it is (when ... Y), look at Y. */
else if (EQ (carelt, Qwhen))
{
Lisp_Object val;
CHECK_CHAR_TABLE (char_table);
- if (EQ (range, Qnil))
+ if (NILP (range))
val = XCHAR_TABLE (char_table)->defalt;
else if (CHARACTERP (range))
- val = CHAR_TABLE_REF (char_table, XFASTINT (range));
+ val = CHAR_TABLE_REF (char_table, XFIXNAT (range));
else if (CONSP (range))
{
int from, to;
for (i = 0; i < chartab_size[0]; i++)
set_char_table_contents (char_table, i, value);
}
- else if (EQ (range, Qnil))
+ else if (NILP (range))
set_char_table_defalt (char_table, value);
else if (CHARACTERP (range))
- char_table_set (char_table, XINT (range), value);
+ char_table_set (char_table, XFIXNUM (range), value);
else if (CONSP (range))
{
CHECK_CHARACTER_CAR (range);
`dbus-send-signal', into corresponding C values appended as
arguments to a D-Bus message. */
#define XD_OBJECT_TO_DBUS_TYPE(object) \
- ((EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN \
+ ((EQ (object, Qt) || NILP (object)) ? DBUS_TYPE_BOOLEAN \
- : (NATNUMP (object)) ? DBUS_TYPE_UINT32 \
- : (INTEGERP (object)) ? DBUS_TYPE_INT32 \
+ : (FIXNATP (object)) ? DBUS_TYPE_UINT32 \
+ : (FIXNUMP (object)) ? DBUS_TYPE_INT32 \
: (FLOATP (object)) ? DBUS_TYPE_DOUBLE \
: (STRINGP (object)) ? DBUS_TYPE_STRING \
: (XD_DBUS_TYPE_P (object)) ? xd_symbol_to_dbus_type (object) \
> (BUF_Z (b) - BUF_BEG (b)) * 13)
/* A short file is likely to change a large fraction;
spare the user annoying messages. */
- && XFASTINT (BVAR (b, save_length)) > 5000
+ && XFIXNAT (BVAR (b, save_length)) > 5000
/* These messages are frequent and annoying for `*mail*'. */
- && !EQ (BVAR (b, filename), Qnil)
+ && !NILP (BVAR (b, filename))
&& NILP (no_message))
{
/* It has shrunk too much; turn off auto-saving here. */
}
\f
DEFUN ("eql", Feql, Seql, 2, 2, 0,
- doc: /* Return t if the two args are the same Lisp object.
- Floating-point numbers of equal value are `eql', but they may not be `eq'. */)
+ doc: /* Return t if the two args are `eq' or are indistinguishable numbers.
+ Floating-point values with the same sign, exponent and fraction are `eql'.
+ This differs from numeric comparison: (eql 0.0 -0.0) returns nil and
+ \(eql 0.0e+NaN 0.0e+NaN) returns t, whereas `=' does the opposite. */)
(Lisp_Object obj1, Lisp_Object obj2)
{
- if (FLOATP (obj1) || BIGNUMP (obj1))
+ if (FLOATP (obj1))
+ return FLOATP (obj2) && same_float (obj1, obj2) ? Qt : Qnil;
++ else if (BIGNUMP (obj1))
+ return equal_no_quit (obj1, obj2) ? Qt : Qnil;
else
return EQ (obj1, obj2) ? Qt : Qnil;
}
static ptrdiff_t
HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx)
{
- return XINT (AREF (h->index, idx));
+ return XFIXNUM (AREF (h->index, idx));
}
- /* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
- HASH2 in hash table H using `eql'. Value is true if KEY1 and
- KEY2 are the same. */
+ /* Compare KEY1 and KEY2 in hash table HT using `eql'. Value is true
+ if KEY1 and KEY2 are the same. KEY1 and KEY2 must not be eq. */
static bool
cmpfn_eql (struct hash_table_test *ht,
Lisp_Object key1,
Lisp_Object key2)
{
- return FLOATP (key1) && FLOATP (key2) && same_float (key1, key2);
+ if (FLOATP (key1)
+ && FLOATP (key2)
- && XFLOAT_DATA (key1) == XFLOAT_DATA (key2))
++ && same_float (key1, key2))
+ return true;
+ return (BIGNUMP (key1)
+ && BIGNUMP (key2)
+ && mpz_cmp (XBIGNUM (key1)->value, XBIGNUM (key2)->value) == 0);
}
cipher = intern (SSDATA (cipher));
if (SYMBOLP (cipher))
- info = XCDR (Fassq (cipher, Fgnutls_ciphers ()));
+ {
+ info = Fassq (cipher, Fgnutls_ciphers ());
+ if (!CONSP (info))
+ xsignal2 (Qerror,
+ build_string ("GnuTLS cipher is invalid or not found"),
+ cipher);
+ info = XCDR (info);
+ }
- else if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, cipher))
- gca = XINT (cipher);
+ else if (TYPE_RANGED_FIXNUMP (gnutls_cipher_algorithm_t, cipher))
+ gca = XFIXNUM (cipher);
else
info = cipher;
hash_method = intern (SSDATA (hash_method));
if (SYMBOLP (hash_method))
- info = XCDR (Fassq (hash_method, Fgnutls_macs ()));
+ {
+ info = Fassq (hash_method, Fgnutls_macs ());
+ if (!CONSP (info))
+ xsignal2 (Qerror,
+ build_string ("GnuTLS MAC-method is invalid or not found"),
+ hash_method);
+ info = XCDR (info);
+ }
- else if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, hash_method))
- gma = XINT (hash_method);
+ else if (TYPE_RANGED_FIXNUMP (gnutls_mac_algorithm_t, hash_method))
+ gma = XFIXNUM (hash_method);
else
info = hash_method;
digest_method = intern (SSDATA (digest_method));
if (SYMBOLP (digest_method))
- info = XCDR (Fassq (digest_method, Fgnutls_digests ()));
+ {
+ info = Fassq (digest_method, Fgnutls_digests ());
+ if (!CONSP (info))
+ xsignal2 (Qerror,
+ build_string ("GnuTLS digest-method is invalid or not found"),
+ digest_method);
+ info = XCDR (info);
+ }
- else if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, digest_method))
- gda = XINT (digest_method);
+ else if (TYPE_RANGED_FIXNUMP (gnutls_digest_algorithm_t, digest_method))
+ gda = XFIXNUM (digest_method);
else
info = digest_method;
/* Write c to the dribble file. If c is a lispy event, write
the event's symbol to the dribble file, in <brackets>. Bleaugh.
If you, dear reader, have a better idea, you've got the source. :-) */
- if (dribble)
+ if (dribble && NILP (Vexecuting_kbd_macro))
{
block_input ();
- if (INTEGERP (c))
+ if (FIXNUMP (c))
{
- if (XUINT (c) < 0x100)
- putc_unlocked (XUINT (c), dribble);
+ if (XUFIXNUM (c) < 0x100)
+ putc_unlocked (XUFIXNUM (c), dribble);
else
- fprintf (dribble, " 0x%"pI"x", XUINT (c));
+ fprintf (dribble, " 0x%"pI"x", XUFIXNUM (c));
}
else
{
if (MARKERP (marker) && XMARKER (marker)->buffer == 0)
XSETFASTINT (marker, 0);
- CHECK_NUMBER_COERCE_MARKER (marker);
- if (PTRDIFF_MIN <= XINT (from) && XINT (from) <= PTRDIFF_MAX
- && PTRDIFF_MIN <= XINT (marker)
- && XINT (marker) <= PTRDIFF_MAX)
+ CHECK_FIXNUM_COERCE_MARKER (marker);
- if ((XFIXNUM (from) < 0
- ? TYPE_MINIMUM (regoff_t) <= XFIXNUM (from)
- : XFIXNUM (from) <= TYPE_MAXIMUM (regoff_t))
- && (XFIXNUM (marker) < 0
- ? TYPE_MINIMUM (regoff_t) <= XFIXNUM (marker)
- : XFIXNUM (marker) <= TYPE_MAXIMUM (regoff_t)))
++ if (PTRDIFF_MIN <= XFIXNUM (from) && XFIXNUM (from) <= PTRDIFF_MAX
++ && PTRDIFF_MIN <= XFIXNUM (marker)
++ && XFIXNUM (marker) <= PTRDIFF_MAX)
{
- search_regs.start[i] = XINT (from);
- search_regs.end[i] = XINT (marker);
+ search_regs.start[i] = XFIXNUM (from);
+ search_regs.end[i] = XFIXNUM (marker);
}
else
{
if (!inhibit_modification_hooks)
{
hooks = Fnreverse (hooks);
- while (! EQ (hooks, Qnil))
+ while (! NILP (hooks))
{
- call_mod_hooks (Fcar (hooks), make_number (start),
- make_number (end));
+ call_mod_hooks (Fcar (hooks), make_fixnum (start),
+ make_fixnum (end));
hooks = Fcdr (hooks);
}
}
= Fdelq (aelt, mode_line_proptrans_alist);
elt = Fcopy_sequence (elt);
- Fset_text_properties (make_fixnum (0), Flength (elt),
- props, elt);
+ /* PROPS might cause set-text-properties to signal
+ an error, so we call it via internal_condition_case_n,
+ to avoid an infloop in redisplay due to the error. */
+ internal_condition_case_n (safe_set_text_properties,
+ 4,
+ ((Lisp_Object [])
- {make_number (0),
++ {make_fixnum (0),
+ Flength (elt),
+ props,
+ elt}),
+ Qt, safe_eval_handler);
/* Add this item to mode_line_proptrans_alist. */
mode_line_proptrans_alist
= Fcons (Fcons (elt, props),
(should-error (format "%x" 18446744073709551616.0)
:type 'overflow-error))
(ert-deftest read-large-integer ()
- (should-error (read (format "%d0" most-negative-fixnum))
- :type 'overflow-error)
- (should-error (read (format "%+d" (* -8.0 most-negative-fixnum)))
- :type 'overflow-error)
- (should-error (read (substring (format "%d" most-negative-fixnum) 1))
- :type 'overflow-error)
+ (should (eq (type-of (read (format "%d0" most-negative-fixnum))) 'integer))
+ (should (eq (type-of (read (format "%+d" (* -8.0 most-negative-fixnum))))
+ 'integer))
+ (should (eq (type-of (read (substring (format "%d" most-negative-fixnum) 1)))
+ 'integer))
+ (should (eq (type-of (read (format "#x%x" most-negative-fixnum)))
+ 'integer))
+ (should (eq (type-of (read (format "#o%o" most-negative-fixnum)))
+ 'integer))
+ (should (eq (type-of (read (format "#32rG%x" most-positive-fixnum)))
- 'integer)))
++ 'integer))
+ (let ((binary-as-unsigned nil))
+ (dolist (fmt '("%d" "%s" "#o%o" "#x%x"))
+ (dolist (val (list most-negative-fixnum (1+ most-negative-fixnum)
+ -1 0 1
+ (1- most-positive-fixnum) most-positive-fixnum))
- (should (eq val (read (format fmt val)))))))
- (should-error (read (format "#32rG%x" most-positive-fixnum))
- :type 'overflow-error))
++ (should (eq val (read (format fmt val))))))))
(ert-deftest format-%o-invalid-float ()
(should-error (format "%o" -1e-37)