* Using the GNU GMP Library for Bignums in Emacs
@ 2018-04-21 14:15 Siraphob (Ben) Phipathananunth
2018-04-21 14:34 ` Eli Zaretskii
` (3 more replies)
0 siblings, 4 replies; 281+ messages in thread
From: Siraphob (Ben) Phipathananunth @ 2018-04-21 14:15 UTC (permalink / raw)
To: emacs-devel
Emacs Calc was written many years ago, and as a result its current
implementation implements bignums purely in Emacs Lisp. Its bignum
operations also use a lot of hacks (such as performing carry
operations). Arbitrary precision arithmetic could be faster if Emacs
had GNU GMP linked to it, with the relevant Emacs Lisp functions added
in C.
What is the consensus on linking the GNU GMP library to Emacs so that
packages such as Emacs Calc (and others) could benefit from using
native types (i.e. "mpz_t") rather than reinventing the wheel?
The benefits of linking GNU GMP are clear. It would make it easier to
extend the math capabilities of Emacs, while making it faster and less
error-prone. However, the downsides, if any exist, should be discussed
as well, to gauge whether pursuing such a task would be fruitful.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 14:15 Using the GNU GMP Library for Bignums in Emacs Siraphob (Ben) Phipathananunth
@ 2018-04-21 14:34 ` Eli Zaretskii
2018-04-21 15:01 ` Siraphob (Ben) Phipathananunth
2018-04-21 16:46 ` Markus Triska
` (2 subsequent siblings)
3 siblings, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-04-21 14:34 UTC (permalink / raw)
To: Siraphob (Ben) Phipathananunth; +Cc: emacs-devel
> From: "Siraphob (Ben) Phipathananunth" <siraben@disroot.org>
> Date: Sat, 21 Apr 2018 21:15:08 +0700
>
> Emacs Calc was written many years ago, and as a result its current
> implementation implements bignums purely in Emacs Lisp. Its bignum
> operations also use a lot of hacks (such as performing carry
> operations). Arbitrary precision arithmetic could be faster if Emacs
> had GNU GMP linked to it, with the relevant Emacs Lisp functions added
> in C.
>
> What is the consensus on linking the GNU GMP library to Emacs so that
> packages such as Emacs Calc (and others) could benefit from using
> native types (i.e. "mpz_t") rather than reinventing the wheel?
I think the consensus is we want that, it's just a matter of someone
doing the job of making it happen.
The design should IMO be discussed up front, because we want not only
to be able to use bignums and arbitrary-precision floating-point
numbers in C, but also in Lisp. How exactly to expose them to Lisp is
something we should talk about, I think.
Thanks.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 14:34 ` Eli Zaretskii
@ 2018-04-21 15:01 ` Siraphob (Ben) Phipathananunth
2018-04-21 15:23 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Siraphob (Ben) Phipathananunth @ 2018-04-21 15:01 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
One approach would be to implement a minimal subset of functions
exposed in Emacs Lisp that would allow one to recreate the following
functions that are defined in calc.el :
Function Name Arguments
============================================
math-bignum (a)
math-bignum-big (a)
math-div10-bignum (a)
math-scale-left-bignum (a n)
math-scale-right-bignum (a n)
math-add-bignum (a b)
math-sub-bignum (a b)
math-mul-bignum (a b)
math-mul-bignum-digit (a d c)
math-div-bignum (a b)
math-div-bignum-digit (a b)
math-div-bignum-big (a b alen blen)
math-div-bignum-part (a b blen)
math-div-bignum-try (a b c guess)
math-format-bignum (a)
math-format-bignum-decimal (a)
math-read-bignum (s)
There are other functions scattered throughout the calc sources, but
this is the rough idea of the type of functions we would need. This
list would have to be shortened, as when we migrate bignums we would
no longer need the following functions (at least, could be more):
math-mul-bignum-digit (a d c)
math-div-bignum-digit (a b)
These functions exist because bignums are implemented as a list of
digits.
I think that keeping the function names the same would be good (for
some backwards compatibility). The /actual/ value of the bignum
(internally, in C) would be a tagged pointer to the mpz_t data type
stored somewhere so that it could be marked for GC (very important to
mark for GC).
With respect to floating points, though, things get a little hairy.
As quoted from the GMP Library
(https://gmplib.org/manual/Floating_002dpoint-Functions.html):
> The exponent of each float has fixed precision, one machine word on
> most systems. In the current implementation the exponent is a count of
> limbs, so for example on a 32-bit system this means a range of roughly
> 2^-68719476768 to 2^68719476736, or on a 64-bit system this will be
> much greater. Note however that mpf_get_str can only return an
> exponent which fits an mp_exp_t and currently mpf_set_str doesn’t
> accept exponents bigger than a long.
Fortunately, it links to another project called MPFR
http://www.mpfr.org/sample.html which allows us to computing floating
points at arbitrary precision.
However, I'm concerned that adding two different libraries could lead
to issues regarding interoperability (for example, a floating point
number that needs to be converted to a bignum, and vice versa). If
anyone has used MPFR + GMP in the past, please chime in.
GC shouldn't be ignored as well, because as the name implies, these
data objects would be very large.
Thanks,
Siraphob (Ben) Phipathananunth
Eli Zaretskii wrote:
>> From: "Siraphob (Ben) Phipathananunth" <siraben@disroot.org>
>> Date: Sat, 21 Apr 2018 21:15:08 +0700
>>
>> Emacs Calc was written many years ago, and as a result its current
>> implementation implements bignums purely in Emacs Lisp. Its bignum
>> operations also use a lot of hacks (such as performing carry
>> operations). Arbitrary precision arithmetic could be faster if Emacs
>> had GNU GMP linked to it, with the relevant Emacs Lisp functions added
>> in C.
>>
>> What is the consensus on linking the GNU GMP library to Emacs so that
>> packages such as Emacs Calc (and others) could benefit from using
>> native types (i.e. "mpz_t") rather than reinventing the wheel?
>
> I think the consensus is we want that, it's just a matter of someone
> doing the job of making it happen.
>
> The design should IMO be discussed up front, because we want not only
> to be able to use bignums and arbitrary-precision floating-point
> numbers in C, but also in Lisp. How exactly to expose them to Lisp is
> something we should talk about, I think.
>
> Thanks.
>
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 15:01 ` Siraphob (Ben) Phipathananunth
@ 2018-04-21 15:23 ` Paul Eggert
2018-04-21 15:36 ` Eli Zaretskii
` (2 more replies)
0 siblings, 3 replies; 281+ messages in thread
From: Paul Eggert @ 2018-04-21 15:23 UTC (permalink / raw)
To: Siraphob (Ben) Phipathananunth, Eli Zaretskii; +Cc: emacs-devel
Siraphob (Ben) Phipathananunth wrote:
> One approach would be to implement a minimal subset of functions
> exposed in Emacs Lisp that would allow one to recreate the following
> functions that are defined in calc.el :
Surely we should just add bignum support to existing functions +, -, etc.
Wouldn't that suffice for 'calc'? If not, why not? (Of course 'calc' would need
to be changed to exploit the bignums properly, no matter how we add bignums.)
> With respect to floating points, though, things get a little hairy.
This should be a separate task. Bignums alone are quite a large-enough project.
I'm not even sure we should do rationals.
> The /actual/ value of the bignum
> (internally, in C) would be a tagged pointer to the mpz_t data type
> stored somewhere so that it could be marked for GC
For bignums I would think that Emacs shouldn't use the mpz_t data type, as this
would complicate garbage collection. Emacs can use the mp_limb_t data type and
stick with the mpn_* functions.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 15:23 ` Paul Eggert
@ 2018-04-21 15:36 ` Eli Zaretskii
2018-04-21 15:40 ` Siraphob (Ben) Phipathananunth
2018-04-22 12:43 ` Helmut Eller
2 siblings, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-04-21 15:36 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel
> Cc: emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sat, 21 Apr 2018 08:23:33 -0700
>
> Siraphob (Ben) Phipathananunth wrote:
> > One approach would be to implement a minimal subset of functions
> > exposed in Emacs Lisp that would allow one to recreate the following
> > functions that are defined in calc.el :
>
> Surely we should just add bignum support to existing functions +, -, etc.
Exactly my thoughts.
> > With respect to floating points, though, things get a little hairy.
>
> This should be a separate task. Bignums alone are quite a large-enough project.
> I'm not even sure we should do rationals.
Right.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 15:23 ` Paul Eggert
2018-04-21 15:36 ` Eli Zaretskii
@ 2018-04-21 15:40 ` Siraphob (Ben) Phipathananunth
2018-04-21 15:54 ` Eli Zaretskii
` (2 more replies)
2018-04-22 12:43 ` Helmut Eller
2 siblings, 3 replies; 281+ messages in thread
From: Siraphob (Ben) Phipathananunth @ 2018-04-21 15:40 UTC (permalink / raw)
To: Paul Eggert, Eli Zaretskii; +Cc: emacs-devel
Paul Eggert wrote:
> Surely we should just add bignum support to existing functions +, -,
> etc. Wouldn't that suffice for 'calc'? If not, why not? (Of course
> 'calc' would need to be changed to exploit the bignums properly, no
> matter how we add bignums.)
Of course we could to do that. Hopefully there isn't existing
Emacs Lisp code that relies on unsafe arithmetic /anywhere/. If the
functions + - * / operate on bignums (instead of dedicated bignum
functions), would that mean we drop 32/64 bit integers entirely?
Eli Zaretskii wrote:
> The design should IMO be discussed up front, because we want not only
> to be able to use bignums and arbitrary-precision floating-point
> numbers in C, but also in Lisp.
I thought that Eli was talking about how we should interface bignums
to Emacs Lisp; the + - * / operators are defined in C source
code. Bignums would decrease performance in areas where the usual
32/64 bit integers are sufficient, and lead to higher memory usage. It
would make much more sense to have separate math functions for 32/64
bit numbers and for bignums. In doing so, it should be obvious to the
Emacs Lisp programmer when to use what.
Paul Eggert wrote:
> This should be a separate task. Bignums alone are quite a large-enough
> project. I'm not even sure we should do rationals.
Rationals would be a part of Emacs Calc, once we have bignums it
should be trivial to reimplement rationals.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 15:40 ` Siraphob (Ben) Phipathananunth
@ 2018-04-21 15:54 ` Eli Zaretskii
2018-04-21 16:08 ` Paul Eggert
2018-04-21 22:42 ` Richard Stallman
2 siblings, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-04-21 15:54 UTC (permalink / raw)
To: Siraphob (Ben) Phipathananunth; +Cc: eggert, emacs-devel
> Cc: emacs-devel@gnu.org
> From: "Siraphob (Ben) Phipathananunth" <siraben@disroot.org>
> Date: Sat, 21 Apr 2018 22:40:05 +0700
>
> I thought that Eli was talking about how we should interface bignums
> to Emacs Lisp; the + - * / operators are defined in C source
> code.
I never thought we could consider not using + - * etc. with bignums,
so I didn't even raise that issue.
> Bignums would decrease performance in areas where the usual
> 32/64 bit integers are sufficient, and lead to higher memory usage. It
> would make much more sense to have separate math functions for 32/64
> bit numbers and for bignums. In doing so, it should be obvious to the
> Emacs Lisp programmer when to use what.
When the arguments are bignums, these operators should automatically
invoke the relevant GMP functions. That is how we behave elsewhere in
Emacs; Emacs Lisp does support polymorphism on the level of primitive
functions. E.g., that's how these operators support both Lisp
integers and Lisp floats (and markers, for that matter).
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 15:40 ` Siraphob (Ben) Phipathananunth
2018-04-21 15:54 ` Eli Zaretskii
@ 2018-04-21 16:08 ` Paul Eggert
2018-04-26 3:17 ` Tom Tromey
2018-04-21 22:42 ` Richard Stallman
2 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-21 16:08 UTC (permalink / raw)
To: Siraphob (Ben) Phipathananunth, Eli Zaretskii; +Cc: emacs-devel
Siraphob (Ben) Phipathananunth wrote:
> Hopefully there isn't existing
> Emacs Lisp code that relies on unsafe arithmetic /anywhere/.
I'm afraid your hope will be in vain....
And it depends on what we mean by "unsafe". Is it safe to assume that (eq (1+ 0)
1) returns t, for example? The Scheme standard says "no" but we might decide
that 'eq' should "work" for fixnums in Emacs Lisp. That sort of thing.
> If the functions + - * / operate on bignums (instead of dedicated bignum
> functions), would that mean we drop 32/64 bit integers entirely?
No, it'd mean we'd still have fixnums vs bignums internally, and most programs
wouldn't care whether an integer is represented via fixnum or bignum, as it'd be
an issue merely of efficiency. Some programs would probably still care though
(for efficiency reasons), and GNU Calc quite possibly would be one such program.
> It would make much more sense to have separate math functions for 32/64
> bit numbers and for bignums. In doing so, it should be obvious to the
> Emacs Lisp programmer when to use what.
That's not how other Lisps work, by and large. They have just one integer type
and one set of functions. The goal is to simplify the job of writing a program.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 14:15 Using the GNU GMP Library for Bignums in Emacs Siraphob (Ben) Phipathananunth
2018-04-21 14:34 ` Eli Zaretskii
@ 2018-04-21 16:46 ` Markus Triska
2018-04-21 17:09 ` Eli Zaretskii
2018-04-21 18:37 ` Paul Eggert
2018-04-24 18:56 ` Emanuele Santoro
2018-04-26 15:52 ` Glenn Morris
3 siblings, 2 replies; 281+ messages in thread
From: Markus Triska @ 2018-04-21 16:46 UTC (permalink / raw)
To: emacs-devel
"Siraphob (Ben) Phipathananunth" <siraben@disroot.org> writes:
> The benefits of linking GNU GMP are clear. It would make it easier to
> extend the math capabilities of Emacs, while making it faster and less
> error-prone. However, the downsides, if any exist, should be discussed
> as well, to gauge whether pursuing such a task would be fruitful.
Using GMP has a significant downside if you run out of memory: There’s
currently no defined way for the allocation functions to recover from an
error such as out of memory, they must *terminate* program execution.
Please see the following page for details:
https://gmplib.org/manual/Custom-Allocation.html
Thus, situtations where you can currently throw an Emacs error that can
be handled in user code would instead terminate the Emacs process. This
can for example arise from malicious input that involves very large
integers as results (7^7^7^7 etc.), and of course also elsewhere.
Also, it may become hard to stop long GMP calculations, whereas you can
easily stop computations that are written in Elisp. Thus, long GMP
calculations may lead to denial of editing attacks.
All the best,
Markus
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 16:46 ` Markus Triska
@ 2018-04-21 17:09 ` Eli Zaretskii
2018-04-21 17:27 ` Markus Triska
2018-04-21 18:37 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-04-21 17:09 UTC (permalink / raw)
To: Markus Triska; +Cc: emacs-devel
> From: Markus Triska <triska@metalevel.at>
> Date: Sat, 21 Apr 2018 18:46:07 +0200
>
> Using GMP has a significant downside if you run out of memory: There’s
> currently no defined way for the allocation functions to recover from an
> error such as out of memory, they must *terminate* program execution.
>
> Please see the following page for details:
>
> https://gmplib.org/manual/Custom-Allocation.html
>
> Thus, situtations where you can currently throw an Emacs error that can
> be handled in user code would instead terminate the Emacs process. This
> can for example arise from malicious input that involves very large
> integers as results (7^7^7^7 etc.), and of course also elsewhere.
>
> Also, it may become hard to stop long GMP calculations, whereas you can
> easily stop computations that are written in Elisp. Thus, long GMP
> calculations may lead to denial of editing attacks.
How are those dangers different from using any other external
library. Like the JSON library, for excample, or libxml2?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 17:09 ` Eli Zaretskii
@ 2018-04-21 17:27 ` Markus Triska
0 siblings, 0 replies; 281+ messages in thread
From: Markus Triska @ 2018-04-21 17:27 UTC (permalink / raw)
To: emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
> How are those dangers different from using any other external
> library. Like the JSON library, for excample, or libxml2?
Please note that in particular the first issue I mentioned is quite
specific to GMP: It could be solved by providing a different API, or by
generalizing the existing API to let applications safely handle such
situations. Some of the libraries you mention may support this.
The second issue I mentioned is also quite specific to GMP, since short
arithmetic expressions may cause long running times for calculations. Of
course, this issue may in principle also arise in other libraries.
All the best,
Markus
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 16:46 ` Markus Triska
2018-04-21 17:09 ` Eli Zaretskii
@ 2018-04-21 18:37 ` Paul Eggert
2018-04-21 22:42 ` Richard Stallman
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-21 18:37 UTC (permalink / raw)
To: Markus Triska, emacs-devel
Markus Triska wrote:
> Using GMP has a significant downside if you run out of memory: There’s
> currently no defined way for the allocation functions to recover from an
> error such as out of memory, they must *terminate* program execution.
This should not be a problem if we use GMP's mpn_* functions. They never
allocate memory; it is the user's responsibility to allocate it. This should fit
better with how Emacs does things internally.
> Also, it may become hard to stop long GMP calculations, whereas you can
> easily stop computations that are written in Elisp. Thus, long GMP
> calculations may lead to denial of editing attacks.
Yes, this could be a problem. Perhaps we'll need to extend GMP to fix it. On the
other hand, no doubt there are other, similar problems in GNU Emacs (just look
for calls to memcpy :-), and perhaps this problem could just be added to the list.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 15:40 ` Siraphob (Ben) Phipathananunth
2018-04-21 15:54 ` Eli Zaretskii
2018-04-21 16:08 ` Paul Eggert
@ 2018-04-21 22:42 ` Richard Stallman
2018-04-22 2:48 ` dancol
2018-04-22 8:00 ` Siraphob (Ben) Phipathananunth
2 siblings, 2 replies; 281+ messages in thread
From: Richard Stallman @ 2018-04-21 22:42 UTC (permalink / raw)
To: Siraphob (Ben) Phipathananunth; +Cc: eliz, eggert, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Of course we could to do that. Hopefully there isn't existing
> Emacs Lisp code that relies on unsafe arithmetic /anywhere/. If the
> functions + - * / operate on bignums (instead of dedicated bignum
> functions), would that mean we drop 32/64 bit integers entirely?
To eliminate the current types for small integers would
require rewriting of much of the C code in Emacs.
It would be better to represent small integers as now,
and have a different structure for larger integers.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 18:37 ` Paul Eggert
@ 2018-04-21 22:42 ` Richard Stallman
2018-04-22 2:43 ` Eli Zaretskii
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-04-21 22:42 UTC (permalink / raw)
To: Paul Eggert; +Cc: triska, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Yes, this could be a problem. Perhaps we'll need to extend GMP to fix it.
The only things that might interrupt Lisp code are signals.
If C-g is detected by a signal, it can interrupt almost anything in C,
including computation in a GMP function,
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 22:42 ` Richard Stallman
@ 2018-04-22 2:43 ` Eli Zaretskii
2018-04-23 3:34 ` Richard Stallman
0 siblings, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-04-22 2:43 UTC (permalink / raw)
To: rms; +Cc: eggert, triska, emacs-devel
> From: Richard Stallman <rms@gnu.org>
> Date: Sat, 21 Apr 2018 18:42:52 -0400
> Cc: triska@metalevel.at, emacs-devel@gnu.org
>
> The only things that might interrupt Lisp code are signals.
> If C-g is detected by a signal, it can interrupt almost anything in C,
> including computation in a GMP function,
We've changed how signals are processed in Emacs several years ago.
Nowadays, a signal handler just sets a flag, and the Lisp interpreter
tests that flag "when appropriate" (normally, as part of maybe_quit).
This change was done to avoid non-trivial processing inside signal
handlers.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 22:42 ` Richard Stallman
@ 2018-04-22 2:48 ` dancol
2018-04-22 13:00 ` Philipp Stephani
2018-04-22 8:00 ` Siraphob (Ben) Phipathananunth
1 sibling, 1 reply; 281+ messages in thread
From: dancol @ 2018-04-22 2:48 UTC (permalink / raw)
To: rms; +Cc: eliz, eggert, emacs-devel
> [[[ To any NSA and FBI agents reading my email: please consider ]]]
> [[[ whether defending the US Constitution against all enemies, ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
> > Of course we could to do that. Hopefully there isn't existing
> > Emacs Lisp code that relies on unsafe arithmetic /anywhere/. If the
> > functions + - * / operate on bignums (instead of dedicated bignum
> > functions), would that mean we drop 32/64 bit integers entirely?
>
> To eliminate the current types for small integers would
> require rewriting of much of the C code in Emacs.
> It would be better to represent small integers as now,
> and have a different structure for larger integers.
>
I'd love to see Emacs get transparent bigint support. Python semantics are
fine, as is using a normal int representation at the C level. Adding
transparent bigints as Lisp types doesn't require us to increase various
Emacs core limits right away.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 22:42 ` Richard Stallman
2018-04-22 2:48 ` dancol
@ 2018-04-22 8:00 ` Siraphob (Ben) Phipathananunth
2018-04-22 9:06 ` Paul Eggert
2018-04-23 3:36 ` Richard Stallman
1 sibling, 2 replies; 281+ messages in thread
From: Siraphob (Ben) Phipathananunth @ 2018-04-22 8:00 UTC (permalink / raw)
To: rms; +Cc: eliz, eggert, emacs-devel
Richard Stallman wrote:
> To eliminate the current types for small integers would
> require rewriting of much of the C code in Emacs.
> It would be better to represent small integers as now,
> and have a different structure for larger integers.
From what I understand, we would want to use fixnums by default in the
C code, and convert to bignums automatically (in lisp) when the number
exceeds the range of a fixnum, while retaining behavior as before,
using the regular math operations + - * / (and more) to interface this
to Lisp.
Paul Eggert wrote:
> programs wouldn't care whether an integer is represented via fixnum or
> bignum, as it'd be an issue merely of efficiency.
Would it not slow down computation to have to constantly convert
between the two types? (especially if the computation is switching
above/below the fixnum/bignum boundary). In such a case, a fix could
be to convert lisp numbers exceeding fixnum limits to bignums for the
rest of the number's life (until GC). This ensures memory usage is kept
low for fixnum computations.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 8:00 ` Siraphob (Ben) Phipathananunth
@ 2018-04-22 9:06 ` Paul Eggert
2018-04-23 5:19 ` Helmut Eller
2018-04-23 3:36 ` Richard Stallman
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-22 9:06 UTC (permalink / raw)
To: Siraphob (Ben) Phipathananunth, rms; +Cc: eliz, emacs-devel
Siraphob (Ben) Phipathananunth wrote:
> Would it not slow down computation to have to constantly convert
> between the two types?
A bit perhaps, but it shouldn't be that big a deal. Most integer computation
will likely be fixnum only, and the only slowdown there will be integer overflow
checking that we currently aren't doing. With decent hardware and compiler, I'd
guess this would cost us three machine instructions per Lisp arithmetic
operation, including the conditional branch that is typically not taken. Hardly
anybody will notice.
> In such a case, a fix could
> be to convert lisp numbers exceeding fixnum limits to bignums for the
> rest of the number's life (until GC). This ensures memory usage is kept
> low for fixnum computations.
Yes, the idea is to use bignums to represent numbers outside of fixnum range,
and to use fixnums to represent numbers inside fixnum range. Bignums require
garbage collection; fixnums do not.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 15:23 ` Paul Eggert
2018-04-21 15:36 ` Eli Zaretskii
2018-04-21 15:40 ` Siraphob (Ben) Phipathananunth
@ 2018-04-22 12:43 ` Helmut Eller
2018-04-22 17:47 ` Paul Eggert
2018-04-23 3:03 ` Stefan Monnier
2 siblings, 2 replies; 281+ messages in thread
From: Helmut Eller @ 2018-04-22 12:43 UTC (permalink / raw)
To: emacs-devel
On Sat, Apr 21 2018, Paul Eggert wrote:
> Surely we should just add bignum support to existing functions +, -,
> etc.
I'm not so sure of that. E.g. (format "%x" -1) => "3fffffffffffffff".
That doesn't make any sense on if -1 is a bignum.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 2:48 ` dancol
@ 2018-04-22 13:00 ` Philipp Stephani
2018-04-22 17:43 ` Paul Eggert
2018-04-23 3:39 ` Richard Stallman
0 siblings, 2 replies; 281+ messages in thread
From: Philipp Stephani @ 2018-04-22 13:00 UTC (permalink / raw)
To: dancol; +Cc: eliz, eggert, rms, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1661 bytes --]
<dancol@dancol.org> schrieb am So., 22. Apr. 2018 um 04:49 Uhr:
> > [[[ To any NSA and FBI agents reading my email: please consider ]]]
> > [[[ whether defending the US Constitution against all enemies, ]]]
> > [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> >
> > > Of course we could to do that. Hopefully there isn't existing
> > > Emacs Lisp code that relies on unsafe arithmetic /anywhere/. If the
> > > functions + - * / operate on bignums (instead of dedicated bignum
> > > functions), would that mean we drop 32/64 bit integers entirely?
> >
> > To eliminate the current types for small integers would
> > require rewriting of much of the C code in Emacs.
> > It would be better to represent small integers as now,
> > and have a different structure for larger integers.
> >
>
> I'd love to see Emacs get transparent bigint support. Python semantics are
> fine, as is using a normal int representation at the C level. Adding
> transparent bigints as Lisp types doesn't require us to increase various
> Emacs core limits right away.
>
>
>
We need to be very careful with transparent bigint support though, as a
naive design will break many invariants. For example, integers are
currently documented to use modular arithmetic (
https://www.gnu.org/software/emacs/manual/html_node/elisp/Integer-Type.html
,
https://www.gnu.org/software/emacs/manual/html_node/elisp/Integer-Basics.html),
and they are documented to be pure value types, i.e. same-valued integers
are the same object (
https://www.gnu.org/software/emacs/manual/html_node/elisp/Equality-Predicates.html).
Especially the second property is widely used.
[-- Attachment #2: Type: text/html, Size: 2354 bytes --]
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 13:00 ` Philipp Stephani
@ 2018-04-22 17:43 ` Paul Eggert
2018-04-22 18:04 ` Daniel Colascione
2018-04-23 3:39 ` Richard Stallman
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-22 17:43 UTC (permalink / raw)
To: Philipp Stephani, dancol; +Cc: eliz, rms, emacs-devel
Philipp Stephani wrote:
> integers are currently documented to use modular arithmetic (
We'll need to change the documentation for modular arithmetic, since integers
will no longer overflow.
> and they are documented to be pure value types, i.e. same-valued integers
> are the same objects. Especially the second property is widely used.
This property is used only for fixnums now (since bignums do not exist yet), and
we can keep this property for fixnums. We could also keep it for bignums, by
hashing all bignums, though I doubt whether it's worth the expense.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 12:43 ` Helmut Eller
@ 2018-04-22 17:47 ` Paul Eggert
2018-04-23 3:39 ` Richard Stallman
2018-04-23 3:03 ` Stefan Monnier
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-22 17:47 UTC (permalink / raw)
To: Helmut Eller, emacs-devel
Helmut Eller wrote:
> (format "%x" -1) => "3fffffffffffffff".
Any program that assumes that behavior is already unportable, since the
expression returns "3fffffff" on 32-bit platforms.
The usual approach for this is to format negative numbers with a leading minus
sign, so that (format "%x" -1) returns "-1". This is what Emac Lisp should have
been doing anyway as it is more intuitive and more portable. Obviously there
will be compatibility concerns here, and we'll need to address them.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 17:43 ` Paul Eggert
@ 2018-04-22 18:04 ` Daniel Colascione
2018-04-22 18:34 ` Clément Pit-Claudel
0 siblings, 1 reply; 281+ messages in thread
From: Daniel Colascione @ 2018-04-22 18:04 UTC (permalink / raw)
To: Paul Eggert, Philipp Stephani; +Cc: eliz, rms, emacs-devel
On 04/22/2018 10:43 AM, Paul Eggert wrote:
> Philipp Stephani wrote:
>> integers are currently documented to use modular arithmetic (
>
> We'll need to change the documentation for modular arithmetic, since
> integers will no longer overflow.
Bugs will inevitably arise. One possibility is just dealing with them;
another might be to predicate bignum support on a lexical-binding-like flag.
>> and they are documented to be pure value types, i.e. same-valued integers
>> are the same objects. Especially the second property is widely used.
>
> This property is used only for fixnums now (since bignums do not exist
> yet), and we can keep this property for fixnums. We could also keep it
> for bignums, by hashing all bignums, though I doubt whether it's worth
> the expense.
That's a good idea, IMHO. It preserves identity without complicating eq
itself.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 18:04 ` Daniel Colascione
@ 2018-04-22 18:34 ` Clément Pit-Claudel
0 siblings, 0 replies; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-04-22 18:34 UTC (permalink / raw)
To: emacs-devel
On 2018-04-22 14:04, Daniel Colascione wrote:
> On 04/22/2018 10:43 AM, Paul Eggert wrote:
>> Philipp Stephani wrote:
>>> integers are currently documented to use modular arithmetic (
>>
>> We'll need to change the documentation for modular arithmetic, since integers will no longer overflow.
>
> Bugs will inevitably arise. One possibility is just dealing with them; another might be to predicate bignum support on a lexical-binding-like flag.
Or we could make them different types: the usual operators on fixnums would return fixnums, and the usual operators on bignums would return bignums. Mixing both would always return a bignum.
The difficulty is whether we should change existing Emacs function to return bignums.
Clément.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 12:43 ` Helmut Eller
2018-04-22 17:47 ` Paul Eggert
@ 2018-04-23 3:03 ` Stefan Monnier
2018-07-05 21:29 ` Tom Tromey
1 sibling, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-04-23 3:03 UTC (permalink / raw)
To: emacs-devel
>> Surely we should just add bignum support to existing functions +, -,
>> etc.
> I'm not so sure of that. E.g. (format "%x" -1) => "3fffffffffffffff".
> That doesn't make any sense on if -1 is a bignum.
Note that (format "%x" -1) does not necessarily use functions
in "+, -, etc..."
There are several steps to adding GMP support. Some of those steps
might involve non-trivial decisions. But the first few steps should be
straightforward enough:
A- add a new "bignum" type
B- add new operations on them (this might be enough to start using them in Calc)
C- add support for bignums to some of the pre-existing functions (e.g. +)
D- add support for bignums to more of the pre-existing functions
E- add support for bignums "everywhere" where numbers are usually allowed.
Anything before D/E should be fairly straightforward.
I consider "support for read&print" to fall somewhere in D or maybe E.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 2:43 ` Eli Zaretskii
@ 2018-04-23 3:34 ` Richard Stallman
2018-04-23 4:21 ` Paul Eggert
2018-04-23 15:18 ` Eli Zaretskii
0 siblings, 2 replies; 281+ messages in thread
From: Richard Stallman @ 2018-04-23 3:34 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: eggert, triska, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> We've changed how signals are processed in Emacs several years ago.
> Nowadays, a signal handler just sets a flag, and the Lisp interpreter
> tests that flag "when appropriate" (normally, as part of maybe_quit).
> This change was done to avoid non-trivial processing inside signal
> handlers.
Quiting always worked by setting a flag, tested by the QUIT macro.
However, as I implemented it, some constructs used to specify to quit
immediately straight from the signal handler.
I see that this feature has been deleted. That is going to cause a
bad results. There are quite a few places in the C code of Emacs
where execution can get stuck; that's why I added immediate quitting.
The problems I fixed that way have all come back.
What was the reason for this change?
I think we need to revert it, and fix whatever problem
in another way.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 8:00 ` Siraphob (Ben) Phipathananunth
2018-04-22 9:06 ` Paul Eggert
@ 2018-04-23 3:36 ` Richard Stallman
1 sibling, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-04-23 3:36 UTC (permalink / raw)
To: Siraphob (Ben) Phipathananunth; +Cc: eliz, eggert, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> From what I understand, we would want to use fixnums by default in the
> C code, and convert to bignums automatically (in lisp) when the number
> exceeds the range of a fixnum, while retaining behavior as before,
> using the regular math operations + - * / (and more) to interface this
> to Lisp.
Yes, exactly.
> Would it not slow down computation to have to constantly convert
> between the two types? (especially if the computation is switching
> above/below the fixnum/bignum boundary). In such a case, a fix could
> be to convert lisp numbers exceeding fixnum limits to bignums for the
> rest of the number's life (until GC). This ensures memory usage is kept
> low for fixnum computations.
I am not sure that makes sense. Emacs works with numbers, and
computes (or otherwise generates) new numbers, but it never changes an
existing number.
Numbers that are in the range of non-bignum integers MUST be
represented as non-bignum integers so that the existing C code can
work on them without change. Some places ought to be able to handle
larger numbers, and we will need to change them, However, many places
could continue to handle only small numbers.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 13:00 ` Philipp Stephani
2018-04-22 17:43 ` Paul Eggert
@ 2018-04-23 3:39 ` Richard Stallman
1 sibling, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-04-23 3:39 UTC (permalink / raw)
To: Philipp Stephani; +Cc: eliz, dancol, emacs-devel, eggert
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Integer-Basics.html),
> and they are documented to be pure value types, i.e. same-valued integers
> are the same object (
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Equality-Predicates.html).
> Especially the second property is widely used.
This will continue to be true for all the integers that are currently
representable. If we document that, maybe we won't have a lot of
places to fix.
> Or we could make them different types: the usual operators on
> fixnums would return fixnums, and the usual operators on bignums
> would return bignums. Mixing both would always return a bignum.
Having two data types for integers would be a nuisance for many Lisp
programs. It won't simplify anything, and it won't reduce the changes
needed in Lisp programs because of bignums.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 17:47 ` Paul Eggert
@ 2018-04-23 3:39 ` Richard Stallman
2018-04-23 4:41 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-04-23 3:39 UTC (permalink / raw)
To: Paul Eggert; +Cc: eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> The usual approach for this is to format negative numbers with a leading minus
> sign, so that (format "%x" -1) returns "-1". This is what Emac Lisp should have
I think that change is likely to break things. If you WANT a hex
string, you probably want it to be all hex, regardless of value.
I would expect that each use of %x probably has a certain number of bits
in mind. Perhaps %x should take a number of bits and output modularly.
So %24x would output 24 bits' worth. Always unsigned.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 3:34 ` Richard Stallman
@ 2018-04-23 4:21 ` Paul Eggert
2018-04-23 13:13 ` Stefan Monnier
2018-04-24 2:54 ` Richard Stallman
2018-04-23 15:18 ` Eli Zaretskii
1 sibling, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-04-23 4:21 UTC (permalink / raw)
To: rms, Eli Zaretskii; +Cc: triska, emacs-devel
Richard Stallman wrote:
> There are quite a few places in the C code of Emacs
> where execution can get stuck; that's why I added immediate quitting.
> The problems I fixed that way have all come back.
I hope they haven't come back. We tried to be methodical about preventing Emacs
from getting stuck.
> What was the reason for this change?
Allowing immediate quitting from arbitrary points in execution causes problems
when Emacs internals assume that actions are done in a certain order and are not
just partly done when interrupted by a quit. In the old days we could assume
that execution order at the machine level was the same order as in the C program
source code, which meant that as long as the C source code did things in the
right order Emacs could survive immediate quitting. That assumption is no longer
true. To do things safely now, we need to either (1) add critical sections to
Emacs where appropriate, or (2) test the quit flag at appropriate intervals. In
practice (2) is easier to implement and to maintain.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 3:39 ` Richard Stallman
@ 2018-04-23 4:41 ` Paul Eggert
2018-04-24 2:54 ` Richard Stallman
2018-04-24 2:54 ` Richard Stallman
0 siblings, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-04-23 4:41 UTC (permalink / raw)
To: rms; +Cc: eller.helmut, emacs-devel
Richard Stallman wrote:
> > The usual approach for this is to format negative numbers with a leading minus
> > sign, so that (format "%x" -1) returns "-1". This is what Emac Lisp should have
>
> I think that change is likely to break things. If you WANT a hex
> string, you probably want it to be all hex, regardless of value.
No doubt people occasionally want C-like formatting (i.e., print a negative
number modulo 2**W where W is the word width), but once we have bignums the
notion of the "word width" becomes dubious, and in practice it's cleaner and
more useful to print hexadecimal integers in the usual mathematical way. That's
the tradition in Common Lisp, in Python, and in every other language I know that
has bignums and has the %x format or something similar.
> I would expect that each use of %x probably has a certain number of bits
> in mind. Perhaps %x should take a number of bits and output modularly.
> So %24x would output 24 bits' worth.
We could invent a special syntax along those lines, though it would need to
differ from "%24x" which already means pad with spaces to 24 characters.
However, there's little point to a special syntax since one can easily achieve
the same effect without it. For example, to format the low-order 24 bits of N,
one can already use (format "%x" (logand N #xffffff)) and this will continue to
work even if bignums are introduced.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-22 9:06 ` Paul Eggert
@ 2018-04-23 5:19 ` Helmut Eller
2018-04-23 8:39 ` Andreas Schwab
0 siblings, 1 reply; 281+ messages in thread
From: Helmut Eller @ 2018-04-23 5:19 UTC (permalink / raw)
To: emacs-devel
On Sun, Apr 22 2018, Paul Eggert wrote:
> Most integer
> computation will likely be fixnum only, and the only slowdown there
> will be integer overflow checking that we currently aren't doing. With
> decent hardware and compiler, I'd guess this would cost us three
> machine instructions per Lisp arithmetic operation, including the
> conditional branch that is typically not taken. Hardly anybody will
> notice.
Out of curiousity: what's the quickest way to detect overflow on
multiplication in ANSI C? E.g.
int64_t x, y, result;
result = x * y;
if (<how to detect overflow?>)
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 5:19 ` Helmut Eller
@ 2018-04-23 8:39 ` Andreas Schwab
2018-04-23 14:36 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Andreas Schwab @ 2018-04-23 8:39 UTC (permalink / raw)
To: Helmut Eller; +Cc: emacs-devel
On Apr 23 2018, Helmut Eller <eller.helmut@gmail.com> wrote:
> Out of curiousity: what's the quickest way to detect overflow on
> multiplication in ANSI C? E.g.
>
> int64_t x, y, result;
> result = x * y;
> if (<how to detect overflow?>)
There is no way to detect overflow after the fact because overflow
invokes undefined behaviour. You need to either check the range
beforehand, or use special builtins offered by the compiler
(eg. __builtin_smul_overflow in GCC).
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 4:21 ` Paul Eggert
@ 2018-04-23 13:13 ` Stefan Monnier
2018-04-24 2:54 ` Richard Stallman
1 sibling, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-04-23 13:13 UTC (permalink / raw)
To: emacs-devel
>> There are quite a few places in the C code of Emacs
>> where execution can get stuck; that's why I added immediate quitting.
>> The problems I fixed that way have all come back.
[...]
>> What was the reason for this change?
The main reason was that you can't do it reliably in X11 because to
detect a C-g requires non-trivial processing which can't be performed
reliably from a signal handler.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 8:39 ` Andreas Schwab
@ 2018-04-23 14:36 ` Paul Eggert
2018-04-23 19:22 ` Helmut Eller
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-23 14:36 UTC (permalink / raw)
To: Andreas Schwab, Helmut Eller; +Cc: emacs-devel
Andreas Schwab wrote:
> There is no way to detect overflow after the fact because overflow
> invokes undefined behaviour. You need to either check the range
> beforehand, or use special builtins offered by the compiler
> (eg. __builtin_smul_overflow in GCC).
All true, and Emacs lib/intprops.h has an INT_MULTIPLY_OVERFLOW macro that
arranges for all that. On the x86-64 with GCC, it costs one additional
instruction (typically a conditional branch that is not taken) to check for
overflow in machine-word integer multiplication. Checking for fixnum overflow
(as opposed to machine-word overflow) requires one more conditional branch after
some quick bit-twiddling.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 3:34 ` Richard Stallman
2018-04-23 4:21 ` Paul Eggert
@ 2018-04-23 15:18 ` Eli Zaretskii
1 sibling, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-04-23 15:18 UTC (permalink / raw)
To: rms; +Cc: eggert, triska, emacs-devel
> From: Richard Stallman <rms@gnu.org>
> CC: eggert@cs.ucla.edu, triska@metalevel.at, emacs-devel@gnu.org
> Date: Sun, 22 Apr 2018 23:34:58 -0400
>
> Quiting always worked by setting a flag, tested by the QUIT macro.
> However, as I implemented it, some constructs used to specify to quit
> immediately straight from the signal handler.
This still happens, but much less frequently: only on text-mode
frames, and only when Emacs waits for input.
> I see that this feature has been deleted. That is going to cause a
> bad results. There are quite a few places in the C code of Emacs
> where execution can get stuck; that's why I added immediate quitting.
> The problems I fixed that way have all come back.
>
> What was the reason for this change?
The main reasons were described and discussed in bug#12471, in the
context of making signal handling in Emacs more robust. I reproduce
that description below.
In addition, the asynchronous input code caused problems and
limitations, the most (in)famous being that we needed to refrain from
calling malloc in places that could be potentially run from the signal
handler.
Also note this discussion about actually making synchronous input the
default one:
http://lists.gnu.org/archive/html/emacs-devel/2008-03/msg00410.html
And here's your agreement to making that the default:
http://lists.gnu.org/archive/html/emacs-devel/2008-03/msg01268.html
----------------------------------------------------------------------
* Signal handlers can interrupt each other, leading to races.
* Signals can be mishandled if they arrive right in the middle of
code that is keeping track of whether signals have arrived.
* Some variables are modified by signal handlers but are not
declared 'volatile', which means accesses to them could be
incorrectly optimized.
* When debugging, the debugging code can get into an infinite
signal-handling loop if there's a bug in the fatal error handler.
* There are some bugs involving running out of memory in the middle
of a vfork, in which signal handlers aren't restored correctly and
Emacs is likely to misbehave.
* Signals are always redirected to the main thread, resulting in
incorrect backtraces when, for example, a subsidiary thread has
a segmentation violation. Thread-specific signals like SIGSEGV
should have thread-specific backtraces.
* When in batch mode, Emacs doesn't ignore SIGINT if the invoker has
purposely ignored SIGINT. Similarly for SIGTERM. Emacs gets
SIGHUP right, but the other two signals should be consistent
with the usual behavior for batch programs.
* Emacs isn't consistent about what tests it uses to decide whether
it is in batch mode, leading to glitches when the tests disagree.
* Emacs catches SIGPIPE, but it's better to ignore it, as this avoids
races.
* Emacs catches SIGFPE, but on IEEE hosts catching SIGFPE isn't
needed and can mask bugs; it's better to catch SIGFPE only on (the
now quite rare) non-IEEE hosts.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 14:36 ` Paul Eggert
@ 2018-04-23 19:22 ` Helmut Eller
2018-04-23 20:26 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Helmut Eller @ 2018-04-23 19:22 UTC (permalink / raw)
To: emacs-devel; +Cc: Paul Eggert, Andreas Schwab
Paul Eggert wrote:
> Andreas Schwab wrote:
>> There is no way to detect overflow after the fact because overflow
>> invokes undefined behaviour. You need to either check the range
>> beforehand, or use special builtins offered by the compiler
>> (eg. __builtin_smul_overflow in GCC).
>
> All true, and Emacs lib/intprops.h has an INT_MULTIPLY_OVERFLOW macro
> that arranges for all that. On the x86-64 with GCC, it costs one
> additional instruction (typically a conditional branch that is not
> taken) to check for overflow in machine-word integer
> multiplication.
If I read the code in in data.c correctly, than Emacs uses the
INT_MULTIPLY_WRAPV macro which boils down to the __builtin_mul_overflow.
Which indeed produces nice machine code. But the original question was
about ANSI C, which seems to require a division and 3 conditional jumps
for the range check (with gcc 6).
> Checking for fixnum overflow (as opposed to machine-word overflow)
> requires one more conditional branch after some quick bit-twiddling.
Does INT_MULTIPLY_WRAPV macro even perform fixnum overflow tests?
Anyway, I find it curios that the following two expression yield
different values:
(* (* most-positive-fixnum 2) 1.0) => -2.0
(* most-positive-fixnum 2 1.0) => 4.611686018427388e+18
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 19:22 ` Helmut Eller
@ 2018-04-23 20:26 ` Paul Eggert
0 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-04-23 20:26 UTC (permalink / raw)
To: Helmut Eller; +Cc: Emacs development discussions
On 04/23/2018 12:22 PM, Helmut Eller wrote:
> If I read the code in in data.c correctly, than Emacs uses the
> INT_MULTIPLY_WRAPV macro which boils down to the __builtin_mul_overflow.
> Which indeed produces nice machine code. But the original question was
> about ANSI C, which seems to require a division and 3 conditional jumps
> for the range check (with gcc 6).
Yes, in general INT_MULTIPLY_WRAPV does require a division on platforms
that do not support overflow-checking builtins. In practice, though,
this tends to not be an issue, as the major compilers are moving in the
direction of supporting such builtins.
> Does INT_MULTIPLY_WRAPV macro even perform fixnum overflow tests?
No, it checks only for machine-level overflow. We could come up with a
variant that does both machine-level and fixnum-level checking
simultaneously; I'm not sure it's worth the trouble, though, as most
arithmetic operations are addition and subtraction and for these,
fixnum-level checking suffixes.
> Anyway, I find it curios that the following two expression yield
> different values:
>
> (* (* most-positive-fixnum 2) 1.0) => -2.0
>
> (* most-positive-fixnum 2 1.0) => 4.611686018427388e+18
Cool, huh? That's done on purpose; see this Emacs commit:
https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=0ae6bdee0085b05028108325b0a4ce979eadb24e
The idea is to produce a floating-point answer that is more
mathematically-correct, while sticking to Common Lisp-style rules for
contagion and argument processing.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 4:21 ` Paul Eggert
2018-04-23 13:13 ` Stefan Monnier
@ 2018-04-24 2:54 ` Richard Stallman
2018-04-24 4:34 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-04-24 2:54 UTC (permalink / raw)
To: Paul Eggert; +Cc: eliz, triska, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Allowing immediate quitting from arbitrary points in execution causes problems
Immediate quitting was never allowed from arbitrary points in execution.
Only in places where immediate_quit was nonzero.
Those were generally code whose side effects would not matter
unless they were allowed to finish.
> In the old days we could assume that execution order at the
> machine level was the same order as in the C program source code,
> which meant that as long as the C source code did things in the
> right order Emacs could survive immediate quitting. That
> assumption is no longer true.
That problem exists in theory. Did the problem actually occur?
> To do things safely now, we need to either (1) add critical
> sections to Emacs where appropriate, or (2) test the quit flag at
> appropriate intervals
... in each and every place where immediate_quit was formerly used.
In practice (2) is easier to implement and
> to maintain.
If (2) means to check for quitting as needed in each and every place
code where immediate_quit was formerly used, that would thoroughly do
the job, but did we handle all of those places?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 4:41 ` Paul Eggert
@ 2018-04-24 2:54 ` Richard Stallman
2018-04-24 2:54 ` Richard Stallman
1 sibling, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-04-24 2:54 UTC (permalink / raw)
To: Paul Eggert; +Cc: eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> We could invent a special syntax along those lines, though it would need to
> differ from "%24x" which already means pad with spaces to 24 characters.
> However, there's little point to a special syntax since one can easily achieve
> the same effect without it. For example, to format the low-order 24 bits of N,
> one can already use (format "%x" (logand N #xffffff)) and this will continue to
The reason to invent a special syntax is to get the commonly desired
result in a simpler way. If I am right that this is what people
want, why make it hard?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 4:41 ` Paul Eggert
2018-04-24 2:54 ` Richard Stallman
@ 2018-04-24 2:54 ` Richard Stallman
2018-04-24 4:35 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-04-24 2:54 UTC (permalink / raw)
To: Paul Eggert; +Cc: eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> No doubt people occasionally want C-like formatting (i.e., print a
> negative number modulo 2**W where W is the word width), but once
> we have bignums the notion of the "word width" becomes dubious,
In a theoretical sense, yes -- but I doubt that that matters in
practice. In practice, I think, the cases where one wants hexadecimal
are cases where there is a word width.
> and in practice it's cleaner and more useful to print hexadecimal
> integers in the usual mathematical way.
Would you tell me about some of the cases where you wanted hexadecimal
output and you wanted negative numbers to use a minus sign?
I ask because I am skeptical that such cases exist.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-24 2:54 ` Richard Stallman
@ 2018-04-24 4:34 ` Paul Eggert
2018-04-25 1:05 ` Richard Stallman
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-24 4:34 UTC (permalink / raw)
To: rms; +Cc: eliz, triska, emacs-devel
Richard Stallman wrote:
> > In the old days we could assume that execution order at the
> > machine level was the same order as in the C program source code,
> > which meant that as long as the C source code did things in the
> > right order Emacs could survive immediate quitting. That
> > assumption is no longer true.
>
> That problem exists in theory. Did the problem actually occur?
As Eli wrote, we did make the change in response to a bug report. I do not
recall all the details offhand. The theory is pretty clear, though.
> If (2) means to check for quitting as needed in each and every place
> code where immediate_quit was formerly used, that would thoroughly do
> the job, but did we handle all of those places?
We attempted to check for quitting at every place where a check is needed to
avoid unbounded or too-long computation, and I recall using the immediate_quits
in the old code as a cue for where to check for quitting in the new code. We
tried to be conservative about this, and as I recall we put in some checks even
when we weren't sure they were needed. Perhaps we missed some places, but if so
we can fix them as problems arise (and in this sense the new method is similar
to the old one).
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-24 2:54 ` Richard Stallman
@ 2018-04-24 4:35 ` Paul Eggert
2018-04-24 5:45 ` Helmut Eller
2018-04-25 1:05 ` Richard Stallman
0 siblings, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-04-24 4:35 UTC (permalink / raw)
To: rms; +Cc: eller.helmut, emacs-devel
Richard Stallman wrote:
> In practice, I think, the cases where one wants hexadecimal
> are cases where there is a word width.
Although that is true in traditional usage where word width is assumed, it's not
true for most applications using bignums, the original context of this thread.
In such applications, it's routine to have hexadecimal numbers that are wider
than 32- or 64-bit words. And these numbers (when printed without a sign) are
routinely treated as nonnegative, not as negative. For an example of this sort
of application, see the OpenSSL C code that deals with bignums: e.g., BN_bn2hex
generates a leading "-" when converting a negative number to a hexadecimal string.
Even in the standard C library (which lacks bignums), the %x printf format is
supposed to be used only with unsigned integers. Nowadays GCC even optionally
warns about using %x on signed integers.
> The reason to invent a special syntax is to get the commonly desired
> result in a simpler way.
If it turns out to be useful to have a shorthand printf format for formatting
the least N bits of an argument, we can add it as needed. I have my doubts,
though, as other bignum formatters seem to get along fine without such a feature.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-24 4:35 ` Paul Eggert
@ 2018-04-24 5:45 ` Helmut Eller
2018-06-03 23:44 ` Jefferson Carpenter
2018-04-25 1:05 ` Richard Stallman
1 sibling, 1 reply; 281+ messages in thread
From: Helmut Eller @ 2018-04-24 5:45 UTC (permalink / raw)
To: emacs-devel; +Cc: Paul Eggert, Richard Stallman
On Mon, Apr 23 2018, Paul Eggert wrote:
> Even in the standard C library (which lacks bignums), the %x printf
> format is supposed to be used only with unsigned integers. Nowadays
> GCC even optionally warns about using %x on signed integers.
Maybe %x should then print the (shortest) two's complement
representation for bignums. In Common Lisp:
(defun 2comp (x)
(format nil "~x" (logand x (1- (ash 1 (+ 1 (integer-length x)))))))
(2comp -1) => "1"
(2comp -2) => "2"
(2comp -3) => "5"
(2comp -15) => "11"
(2comp -16) => "10"
In practice, only integers smaller than most-negative-fixnum would use
this rule.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 14:15 Using the GNU GMP Library for Bignums in Emacs Siraphob (Ben) Phipathananunth
2018-04-21 14:34 ` Eli Zaretskii
2018-04-21 16:46 ` Markus Triska
@ 2018-04-24 18:56 ` Emanuele Santoro
2018-04-26 15:52 ` Glenn Morris
3 siblings, 0 replies; 281+ messages in thread
From: Emanuele Santoro @ 2018-04-24 18:56 UTC (permalink / raw)
To: emacs-devel
On 21/04/2018 16:15, Siraphob (Ben) Phipathananunth wrote:
> What is the consensus on linking the GNU GMP library to Emacs so that
> packages such as Emacs Calc (and others) could benefit from using
> native types (i.e. "mpz_t") rather than reinventing the wheel?
My two cents: this should be added as optional feature and its presence,
if wanted/needed, should be enabled at compilation time.
Maybe in a few years we could see if it has been widely adopted and if
so make GNU GMP usage the default setting (and/or discard the old
implementation). This should allow a smoother transition.
Hope this helps,
--
Emanuele Santoro
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-24 4:34 ` Paul Eggert
@ 2018-04-25 1:05 ` Richard Stallman
0 siblings, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-04-25 1:05 UTC (permalink / raw)
To: Paul Eggert; +Cc: eliz, triska, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
Thanks for explaining.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-24 4:35 ` Paul Eggert
2018-04-24 5:45 ` Helmut Eller
@ 2018-04-25 1:05 ` Richard Stallman
2018-04-25 1:19 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-04-25 1:05 UTC (permalink / raw)
To: Paul Eggert; +Cc: eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> In such applications, it's routine to have hexadecimal numbers that are wider
> than 32- or 64-bit words.
What is the motive for using hexadecimal in a case like that?
> Even in the standard C library (which lacks bignums), the %x printf format is
> supposed to be used only with unsigned integers.
I think that's a misleading statement of what it does in C. The rule
is to use it with an unsigned _type_. The type, not the value, is
supposed to be unsigned.
In practice, what this means is that the hex output is done _treating
the number as unsigned_. So -1, which is 0xffffffff as a 32-bit int,
will print as ffffffff, not as -1.
I contend that we want the same behavior in Emacs Lisp, too.
> If it turns out to be useful to have a shorthand printf format for formatting
> the least N bits of an argument, we can add it as needed. I have my doubts,
> though, as other bignum formatters seem to get along fine without such a feature.
What conclusions we can draw from them, about Emacs Lisp, depends on
the number of bits in a non-bignum integer for each of them. In
Emacs, 0xffffffff will be a bignum. Is it a bignum in those other
systems? If they can treat 32-bit ints as short, many programs that
want to use hex will never operate on a bignum.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-25 1:05 ` Richard Stallman
@ 2018-04-25 1:19 ` Paul Eggert
2018-04-25 22:40 ` Richard Stallman
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-25 1:19 UTC (permalink / raw)
To: rms; +Cc: eller.helmut, emacs-devel
On 04/24/2018 06:05 PM, Richard Stallman wrote:
> > In such applications, it's routine to have hexadecimal numbers that are wider
> > than 32- or 64-bit words.
>
> What is the motive for using hexadecimal in a case like that?
It varies. One motivation is a desire to communicate a number via text
more-efficiently than base 10 would provide.
> > Even in the standard C library (which lacks bignums), the %x printf format is
> > supposed to be used only with unsigned integers.
>
> I think that's a misleading statement of what it does in C. The rule
> is to use it with an unsigned _type_. The type, not the value, is
> supposed to be unsigned.
In C, if the type is unsigned then the corresponding value is
nonnegative. That is, in C there is no such thing as a negative value
with an unsigned type. The %x format is supposed to be used only with
unsigned types, i.e., only with nonnegative values.
> I contend that we want the same behavior in Emacs Lisp, too.
I certainly wouldn't want the behavior you suggest. Among other things,
Emacs Lisp does not have unsigned types, and I'd rather not introduce
such a concept into the language as it'd be needless complexity and an
unnecessary divergence from other Lisps.
> In Emacs, 0xffffffff will be a bignum.
Whether 0xffffffff is a bignum will depend on the platform. On my 64-bit
Emacs, 0xffffffff already is supported as a fixnum, and that wouldn't
change if bignums were introduced to Emacs.
> Is it a bignum in those other systems?
It depends on the system, I expect (just as it would in Emacs).
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-25 1:19 ` Paul Eggert
@ 2018-04-25 22:40 ` Richard Stallman
2018-04-25 23:29 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-04-25 22:40 UTC (permalink / raw)
To: Paul Eggert; +Cc: eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> In C, if the type is unsigned then the corresponding value is
> nonnegative. That is, in C there is no such thing as a negative value
> with an unsigned type.
I know that (of course). It looks like we are miscommunicating.
> I certainly wouldn't want the behavior you suggest. Among other things,
> Emacs Lisp does not have unsigned types, and I'd rather not introduce
> such a concept into the language
I think you have misunderstood what I suggest. I am talking about changing
the behavior of %x, nothing else.
I responded to a statement about what happens in C. Did you misread that
as a proposal to change Emacs?
> > In Emacs, 0xffffffff will be a bignum.
> Whether 0xffffffff is a bignum will depend on the platform. On my 64-bit
> Emacs, 0xffffffff already is supported as a fixnum, and that wouldn't
> change if bignums were introduced to Emacs.
You're right about 64-bit systems. I often forget they exist, since
I never use them.
My argument is valid nonetheless, because that quantity is a bignum on
_some_ systems.
If we were to support _only_ 64-but systems, this argument would cease
to be valid.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-25 22:40 ` Richard Stallman
@ 2018-04-25 23:29 ` Paul Eggert
2018-04-30 3:07 ` Richard Stallman
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-25 23:29 UTC (permalink / raw)
To: rms; +Cc: eller.helmut, emacs-devel
On 04/25/2018 03:40 PM, Richard Stallman wrote:
> If we were to support_only_ 64-bit systems, this argument would cease
> to be valid.
That is easy to arrange; just configure --with-wide-int. This causes
Emacs to use 64-bit words on all platforms (or wider, at least in
theory). If we made --with-wide-int the default (which I'm more and more
thinking would be a good thing, for this and other reasons), then
#xffffffff would work and would format the same on all platforms by
default, and this would happen regardless of whether we also add bignums
to Emacs.
However, I don't see why assuming 64 bits would mean that the argument
would cease to be valid. Even with that assumption, we would continue
have the same problem with numbers like #xffffffffffffffff that exceed
Emacs fixnum range when words are 64 bits.
> I responded to a statement about what happens in C. Did you misread that
> as a proposal to change Emacs?
Yes, because after your response (which talked about what happens in C),
you wrote "I contend that we want the same behavior in Emacs Lisp, too."
Sorry if I misunderstood you.
I think part of the problem here, is that once we have bignums then
there will no problem representing unsigned values that are too large to
fit into (say) 30-bit signed integers, so there will be no problem in
having %x treat integers like Common Lisp and Python do: programs that
want to do I/O of numbers as hexadecimal strings will be able to read
and print them with %x and they'll all work just fine even if the
numbers contain 8 or 16 or more hexadecimal digits. The problem arises
in Emacs Lisp only because it is limited to fixnums now.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 16:08 ` Paul Eggert
@ 2018-04-26 3:17 ` Tom Tromey
2018-04-26 3:33 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-04-26 3:17 UTC (permalink / raw)
To: Paul Eggert; +Cc: Eli Zaretskii, emacs-devel
>>>>> "Paul" == Paul Eggert <eggert@cs.ucla.edu> writes:
Paul> And it depends on what we mean by "unsafe". Is it safe to assume that
Paul> (eq (1+ 0) 1) returns t, for example? The Scheme standard says "no"
Paul> but we might decide that 'eq' should "work" for fixnums in Emacs
Paul> Lisp. That sort of thing.
I would like the "egal" idea to be at least considered: that is, for
immutable objects like bignums (and floats), have "eq" do a value
comparison, not an identity comparison. Ideally we could dispense with
eql entirely.
The upside is that this makes programs simpler to reason about -- to my
mind the eq/eql distinction is letting an implementation leak through
the abstraction.
The downside is that this is less efficient. (Currently my JIT emits
"eq" as a simple comparison, which is nice; but I think on the whole I'd
personally rather trade a bit of performance for the cleaner semantics.)
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-26 3:17 ` Tom Tromey
@ 2018-04-26 3:33 ` Stefan Monnier
2018-04-27 15:56 ` Richard Stallman
0 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-04-26 3:33 UTC (permalink / raw)
To: emacs-devel
> Paul> And it depends on what we mean by "unsafe". Is it safe to assume that
> Paul> (eq (1+ 0) 1) returns t, for example? The Scheme standard says "no"
> Paul> but we might decide that 'eq' should "work" for fixnums in Emacs
> Paul> Lisp. That sort of thing.
> I would like the "egal" idea to be at least considered: that is, for
> immutable objects like bignums (and floats), have "eq" do a value
> comparison, not an identity comparison. Ideally we could dispense with
> eql entirely.
I think I agree, tho I'd describe it differently: the way `eq` is
defined in Common-Lisp, I believe it is valid to make it an alias for
`eql`.
I think Emacs should move in this direction: define `eq` to be the same
as `eql`, then check every use of EQ in the C code to see if it will
necessarily behave identically to "EQL" and where it doesn't, replace it
with EQL.
Obviously, this will cost us some code size and performance, so we'd
also want to try and measure the cost to make sure it's not too serious.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-21 14:15 Using the GNU GMP Library for Bignums in Emacs Siraphob (Ben) Phipathananunth
` (2 preceding siblings ...)
2018-04-24 18:56 ` Emanuele Santoro
@ 2018-04-26 15:52 ` Glenn Morris
3 siblings, 0 replies; 281+ messages in thread
From: Glenn Morris @ 2018-04-26 15:52 UTC (permalink / raw)
To: Siraphob (Ben) Phipathananunth; +Cc: emacs-devel
I don't know how useful it is today, but there is existing work on
this in other-branches/gerd_big.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-26 3:33 ` Stefan Monnier
@ 2018-04-27 15:56 ` Richard Stallman
2018-04-27 16:08 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-04-27 15:56 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> I think Emacs should move in this direction: define `eq` to be the same
> as `eql`, then check every use of EQ in the C code to see if it will
> necessarily behave identically to "EQL" and where it doesn't, replace it
> with EQL.
This is a lot of work and will slow down some loops.
I would rather try the obvious approach: eq treats bignums like floats.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-27 15:56 ` Richard Stallman
@ 2018-04-27 16:08 ` Stefan Monnier
0 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-04-27 16:08 UTC (permalink / raw)
To: emacs-devel
> > I think Emacs should move in this direction: define `eq` to be the same
> > as `eql`, then check every use of EQ in the C code to see if it will
> > necessarily behave identically to "EQL" and where it doesn't, replace it
> > with EQL.
>
> This is a lot of work and will slow down some loops.
It's hard to tell without measuring it first. And I'd expect that
many/most of those loops can be made fast anyway (e.g. member/memql can
delegate to `memq` when the argument is such that eq/eql/equal behave
identically).
> I would rather try the obvious approach: eq treats bignums like floats.
While I'm writing this within the GMP thread, it's orthogonal.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-25 23:29 ` Paul Eggert
@ 2018-04-30 3:07 ` Richard Stallman
2018-04-30 5:00 ` Michael Welsh Duggan
2018-04-30 7:04 ` Paul Eggert
0 siblings, 2 replies; 281+ messages in thread
From: Richard Stallman @ 2018-04-30 3:07 UTC (permalink / raw)
To: Paul Eggert; +Cc: eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> > If we were to support_only_ 64-bit systems, this argument would cease
> > to be valid.
> That is easy to arrange; just configure --with-wide-int. This causes
> Emacs to use 64-bit words on all platforms
That may be correct, but it doesn't respond to the point at hand.
The point at hand is that Emacs does support 32-bit Lisp objecs in
some cases. and that a 32-bit number _in 32-bit builds_ will not
be a fixnum.
If you're suggesting that I personally change to a 64-bit build, that
doesn't respond to the issue at hand. It's not about what happens for
me in particular.
If you're suggesting to eliminate support for 32-bit builds,
I agree that that would eliminate the issue. But I think that change
would have substantial disadvantages.
> However, I don't see why assuming 64 bits would mean that the argument
> would cease to be valid. Even with that assumption, we would continue
> have the same problem with numbers like #xffffffffffffffff that exceed
> Emacs fixnum range when words are 64 bits.
I expect that %x is used only for values meant to interact
with the operating system in certain ways, and that _most of_ those
values will never be more than 32 bits.
I could be mistaken in this, but it is a factual question.
Where else do people use %x?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-30 3:07 ` Richard Stallman
@ 2018-04-30 5:00 ` Michael Welsh Duggan
2018-04-30 12:34 ` Stefan Monnier
2018-05-01 3:01 ` Richard Stallman
2018-04-30 7:04 ` Paul Eggert
1 sibling, 2 replies; 281+ messages in thread
From: Michael Welsh Duggan @ 2018-04-30 5:00 UTC (permalink / raw)
To: emacs-devel
Richard Stallman <rms@gnu.org> writes:
> > However, I don't see why assuming 64 bits would mean that the argument
> > would cease to be valid. Even with that assumption, we would continue
> > have the same problem with numbers like #xffffffffffffffff that exceed
> > Emacs fixnum range when words are 64 bits.
>
> I expect that %x is used only for values meant to interact
> with the operating system in certain ways, and that _most of_ those
> values will never be more than 32 bits.
>
> I could be mistaken in this, but it is a factual question.
> Where else do people use %x?
Well, although I admit I most often use hexadecimal numbers to represent
machine addresses (including on 64-bit addresses, of course), I also use
them to represent memory offsets. I only bring this up because this is
a case when a negative hexadecimal number (-#x1000 or -0x1000) is a more
useful representation than two's complement.
I admit that this may be considered a niche use, however, and I am
seldom working with offsets of sizes greater than 32 bits in size. I
will further admit that I have never needed this in Emacs, but have run
into this problem with writing C and C++ code, since I have been doing a
lot of work lately on static binary analysis.
--
Michael Welsh Duggan
(md5i@md5i.com)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-30 3:07 ` Richard Stallman
2018-04-30 5:00 ` Michael Welsh Duggan
@ 2018-04-30 7:04 ` Paul Eggert
2018-05-01 3:01 ` Richard Stallman
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-04-30 7:04 UTC (permalink / raw)
To: rms; +Cc: eller.helmut, emacs-devel
Richard Stallman wrote:
> I expect that %x is used only for values meant to interact
> with the operating system in certain ways
Hexadecimal is used for many other purposes. For example, the shell command 'git
log' at the top level of Emacs currently outputs a first line containing the
hexadecimal string bca6c4348077c8c0b368503b16378867b6d49659 which represents an
integer containing 160 bits, the integer width of the SHA-1 checksums used by
Git. Although Emacs cannot now process such a number directly, with bignums it
will be able to and %x is the natural way to format such numbers.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-30 5:00 ` Michael Welsh Duggan
@ 2018-04-30 12:34 ` Stefan Monnier
2018-05-01 3:01 ` Richard Stallman
1 sibling, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-04-30 12:34 UTC (permalink / raw)
To: emacs-devel
> a case when a negative hexadecimal number (-#x1000 or -0x1000) is
^^^^^^^
#x-1000
-- Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-30 5:00 ` Michael Welsh Duggan
2018-04-30 12:34 ` Stefan Monnier
@ 2018-05-01 3:01 ` Richard Stallman
1 sibling, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-05-01 3:01 UTC (permalink / raw)
To: Michael Welsh Duggan; +Cc: emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Well, although I admit I most often use hexadecimal numbers to represent
> machine addresses (including on 64-bit addresses, of course), I also use
> them to represent memory offsets.
I think that implies we need a way to specify for %x to use the proper
width for an address on the machine in use.
> I only bring this up because this is
> a case when a negative hexadecimal number (-#x1000 or -0x1000) is a more
> useful representation than two's complement.
If it's useful in Emacs, we should support that. But we may as well take
stock of the need before deciding whether to implement this.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-30 7:04 ` Paul Eggert
@ 2018-05-01 3:01 ` Richard Stallman
2018-05-01 21:45 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-05-01 3:01 UTC (permalink / raw)
To: Paul Eggert; +Cc: eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> log' at the top level of Emacs currently outputs a first line containing the
> hexadecimal string bca6c4348077c8c0b368503b16378867b6d49659 which represents an
> integer containing 160 bits, the integer width of the SHA-1 checksums used by
> Git. Although Emacs cannot now process such a number directly, with bignums it
> will be able to and %x is the natural way to format such numbers.
If the first 20 bits were zero, would you want the output to start
with 00000, or would you want it to be shorter?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-01 3:01 ` Richard Stallman
@ 2018-05-01 21:45 ` Paul Eggert
2018-05-03 3:34 ` Richard Stallman
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-05-01 21:45 UTC (permalink / raw)
To: rms; +Cc: eller.helmut, emacs-devel
On 04/30/2018 08:01 PM, Richard Stallman wrote:
> If the first 20 bits were zero, would you want the output to start
> with 00000, or would you want it to be shorter?
For Git checksums I'd want leading zeros without other decorations like
#x, since that's how Git itself prints those numbers and I'd prefer to
be compatible.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-01 21:45 ` Paul Eggert
@ 2018-05-03 3:34 ` Richard Stallman
2018-05-03 5:53 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-05-03 3:34 UTC (permalink / raw)
To: Paul Eggert; +Cc: eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> For Git checksums I'd want leading zeros without other decorations like
> #x, since that's how Git itself prints those numbers and I'd prefer to
> be compatible.
That means the feature would need to specify the number of hex digits
desired.
Is that the case for all use of hex output?
Is there any counterexample?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-03 3:34 ` Richard Stallman
@ 2018-05-03 5:53 ` Paul Eggert
2018-05-03 6:26 ` Helmut Eller
2018-05-04 4:22 ` Richard Stallman
0 siblings, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-05-03 5:53 UTC (permalink / raw)
To: rms; +Cc: eller.helmut, emacs-devel
Richard Stallman wrote:
> That means the feature would need to specify the number of hex digits
> desired.
We already have such a feature. For example, (format "%09x" 257) returns
"000000101", which is 257 hexadecimal, expressed using leading zeros as needed
so that at least 9 digits are used. Once Emacs supports bignums, the same
feature can print 40-hex-digit SHA-1 checksums by using (format "%040x" n).
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-03 5:53 ` Paul Eggert
@ 2018-05-03 6:26 ` Helmut Eller
2018-05-03 17:49 ` Eli Zaretskii
2018-05-04 4:22 ` Richard Stallman
1 sibling, 1 reply; 281+ messages in thread
From: Helmut Eller @ 2018-05-03 6:26 UTC (permalink / raw)
To: emacs-devel; +Cc: Paul Eggert, rms
On Wed, May 02 2018, Paul Eggert wrote:
> Richard Stallman wrote:
>> That means the feature would need to specify the number of hex digits
>> desired.
>
> We already have such a feature. For example, (format "%09x" 257) returns
> "000000101", which is 257 hexadecimal, expressed using leading zeros
> as needed so that at least 9 digits are used. Once Emacs supports
> bignums, the same feature can print 40-hex-digit SHA-1 checksums by
> using (format "%040x" n).
I think the bitwise operations and the resulting negative numbers are
the problematic part:
E.g.
(format "%016x" (lognot 257)) => "3ffffffffffffefe"
but the 16-hex-digit string should be "fffffffffffffefe".
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-03 6:26 ` Helmut Eller
@ 2018-05-03 17:49 ` Eli Zaretskii
2018-05-03 18:26 ` Paul Eggert
2018-05-03 18:51 ` Helmut Eller
0 siblings, 2 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-05-03 17:49 UTC (permalink / raw)
To: Helmut Eller; +Cc: eggert, rms, emacs-devel
> From: Helmut Eller <eller.helmut@gmail.com>
> Date: Thu, 03 May 2018 08:26:05 +0200
> Cc: Paul Eggert <eggert@cs.ucla.edu>, rms@gnu.org
>
> I think the bitwise operations and the resulting negative numbers are
> the problematic part:
>
> E.g.
>
> (format "%016x" (lognot 257)) => "3ffffffffffffefe"
>
> but the 16-hex-digit string should be "fffffffffffffefe".
But a 16-hex-digit fffffffffffffefe is not a fixnum, right?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-03 17:49 ` Eli Zaretskii
@ 2018-05-03 18:26 ` Paul Eggert
2018-05-04 4:26 ` Richard Stallman
2018-05-03 18:51 ` Helmut Eller
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-05-03 18:26 UTC (permalink / raw)
To: Eli Zaretskii, Helmut Eller; +Cc: rms, emacs-devel
On 05/03/2018 10:49 AM, Eli Zaretskii wrote:
>> (format "%016x" (lognot 257)) => "3ffffffffffffefe"
>>
>> but the 16-hex-digit string should be "fffffffffffffefe".
> But a 16-hex-digit fffffffffffffefe is not a fixnum, right?
Exactly right. If we have bignums, this will be straightforward; it'll
work like Common Lisp, Python, etc. and it'll be obvious what to do. The
problems mentioned in this thread mainly come from the fact that Emacs
does not have bignums now and that some code may depend on fixnum
overflow wrapping around.
Here's another way to think about it. (format "%016x" (lognot 257)) is
already nonportable, as it yields "000000003ffffefe" on 32-bit platforms
and "3ffffffffffffefe" on 64-bit platforms. Once we add bignums, the
same expression should yield "-000000000000102" on all platforms. Code
intended to be portable between old and new regimes already needs to
worry about nonportability in this area, and it shouldn't be hard to
adjust (if it needs adjusting at all). Code intended to run only under
the new regime will be able to safely assume the expression yields
"-000000000000102" on all platforms, regardless of whether the
underlying platform is 32- or 64- or some other number of bits, and in
the long run this will reduce the number of portability issues in Elisp
code.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-03 17:49 ` Eli Zaretskii
2018-05-03 18:26 ` Paul Eggert
@ 2018-05-03 18:51 ` Helmut Eller
[not found] ` <83sh78o6af.fsf@gnu.org>
1 sibling, 1 reply; 281+ messages in thread
From: Helmut Eller @ 2018-05-03 18:51 UTC (permalink / raw)
To: emacs-devel; +Cc: Eli Zaretskii, eggert, rms
On Thu, May 03 2018, Eli Zaretskii wrote:
>> (format "%016x" (lognot 257)) => "3ffffffffffffefe"
>>
>> but the 16-hex-digit string should be "fffffffffffffefe".
>
> But a 16-hex-digit fffffffffffffefe is not a fixnum, right?
Well, (lognot 257) is fixnum. And if we explicity specify the length,
then the 16-hex-digit string "fffffffffffffefe" represents the same
fixnum as the 4-hex-digit string "fefe".
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
[not found] ` <83sh78o6af.fsf@gnu.org>
@ 2018-05-03 20:30 ` Helmut Eller
2018-05-03 21:48 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Helmut Eller @ 2018-05-03 20:30 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: eggert, rms, emacs-devel
On Thu, May 03 2018, Eli Zaretskii wrote:
[...]
> Maybe we are miscommunicating. fffffffffffffefe cannot be a fixnum
> because it invades the bits reserved for the type tag. Emacs fixnums
> are limited to smaller values, as I'm sure you know.
If we interpret "fffffffffffffefe" as the 64 bit two's complement
representation of an integer then it corresponds to the integer -258.
If we interpret "fefe" as the 16 bit two's complement representation of
an integer then we also get the integer -258. And -258 is a fixnum.
Still convinced that "fffffffffffffefe cannot be a fixnum"?.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-03 20:30 ` Helmut Eller
@ 2018-05-03 21:48 ` Paul Eggert
0 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-05-03 21:48 UTC (permalink / raw)
To: Helmut Eller, Eli Zaretskii; +Cc: rms, emacs-devel
On 05/03/2018 01:30 PM, Helmut Eller wrote:
> Still convinced that "fffffffffffffefe cannot be a fixnum"?.
No, Eli's right. Emacs has never interpreted fffffffffffffefe as a
fixnum on any practical platform, as far as I know. In Elisp code on
practical platforms, #xfffffffffffffefe is a fixnum neither in master
(where it is an overflow error) nor in Emacs 25 (where it is typically
converted silently to 1.8446744073709552e+19, with some loss of
information). If Emacs gets bignums, #xfffffffffffffefe will be lossless
and will have the same meaning as 18446744073709551358, which is the
standard interpretation of this hexadecimal number in C and in most
other languages.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-03 5:53 ` Paul Eggert
2018-05-03 6:26 ` Helmut Eller
@ 2018-05-04 4:22 ` Richard Stallman
1 sibling, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-05-04 4:22 UTC (permalink / raw)
To: Paul Eggert; +Cc: eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> We already have such a feature. For example, (format "%09x" 257) returns
> "000000101", which is 257 hexadecimal, expressed using leading zeros as needed
> so that at least 9 digits are used. Once Emacs supports bignums, the same
> feature can print 40-hex-digit SHA-1 checksums by using (format "%040x" n).
Perhaps this way everything would work with all-positive hex numbers.
However, I think we also want a feature to signal an error if the
number doesn't fall in the range that the %x construct can represent.
If the Git hash code is 40 hex digits, any attempt to use as a Git hash code
a number that won't fit in 40 hex digits implies that there has already been
an error.
I suggest %!040x for this. The ! would mean, "Signal an error if the number
doesn't fit in the specified number of digits." It could be implemented
for all %-specs, but if that is a pain in the neck, it could be implemented
only for %x.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-03 18:26 ` Paul Eggert
@ 2018-05-04 4:26 ` Richard Stallman
2018-05-05 5:03 ` Ken Raeburn
2018-05-07 18:40 ` Andreas Schwab
0 siblings, 2 replies; 281+ messages in thread
From: Richard Stallman @ 2018-05-04 4:26 UTC (permalink / raw)
To: Paul Eggert; +Cc: eliz, eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
I don't think people want (format "%x" (lognot 257)) to output "-102".
Not on any platform. It isn't what code expects, and it isn't useful.
Perhaps, with bignums, lognot should take a width operand, measured in bits.
So (lognot 257 32) would produce 0xfffffefe (a positive number)
and (lognot 257 64) would produce 0xfffffffffffffefe (a positive number).
Another idea: %Nx with a negative number should output its 2's
complement representation in 4N bits.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-04 4:26 ` Richard Stallman
@ 2018-05-05 5:03 ` Ken Raeburn
2018-05-06 3:12 ` Richard Stallman
2018-05-07 18:40 ` Andreas Schwab
1 sibling, 1 reply; 281+ messages in thread
From: Ken Raeburn @ 2018-05-05 5:03 UTC (permalink / raw)
To: Richard Stallman; +Cc: eliz, Paul Eggert, eller.helmut, emacs-devel
On May 4, 2018, at 00:26, Richard Stallman <rms@gnu.org> wrote:
>
> [[[ To any NSA and FBI agents reading my email: please consider ]]]
> [[[ whether defending the US Constitution against all enemies, ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
> I don't think people want (format "%x" (lognot 257)) to output "-102".
> Not on any platform. It isn't what code expects, and it isn't useful.
>
> Perhaps, with bignums, lognot should take a width operand, measured in bits.
> So (lognot 257 32) would produce 0xfffffefe (a positive number)
> and (lognot 257 64) would produce 0xfffffffffffffefe (a positive number).
>
> Another idea: %Nx with a negative number should output its 2's
> complement representation in 4N bits.
That's already taken: A leading “-“ means to left-justify the output if the specified width is wider than required.
ELISP> (format "%-16x" 300)
"12c "
ELISP> (format "%16x" 300)
" 12c"
ELISP>
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-05 5:03 ` Ken Raeburn
@ 2018-05-06 3:12 ` Richard Stallman
2018-05-07 17:24 ` Ken Raeburn
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-05-06 3:12 UTC (permalink / raw)
To: Ken Raeburn; +Cc: eliz, eggert, eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> > Another idea: %Nx with a negative number should output its 2's
> > complement representation in 4N bits.
> That's already taken: A leading “-“ means to left-justify the output if the specified width is wider than required.
We are miscommunicating. I'm talking about what %Nx should do when
outputting an argument that is negative, as in (format "%16x" -63).
Sorry that wasn't clear.
You could try p/x -63 in GDB to see what I mean.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-06 3:12 ` Richard Stallman
@ 2018-05-07 17:24 ` Ken Raeburn
2018-05-08 1:55 ` Richard Stallman
0 siblings, 1 reply; 281+ messages in thread
From: Ken Raeburn @ 2018-05-07 17:24 UTC (permalink / raw)
To: Richard Stallman; +Cc: eliz, eggert, eller.helmut, emacs-devel
On May 5, 2018, at 23:12, Richard Stallman <rms@gnu.org> wrote:
>
> [[[ To any NSA and FBI agents reading my email: please consider ]]]
> [[[ whether defending the US Constitution against all enemies, ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
>>> Another idea: %Nx with a negative number should output its 2's
>>> complement representation in 4N bits.
>
>> That's already taken: A leading “-“ means to left-justify the output if the specified width is wider than required.
>
> We are miscommunicating. I'm talking about what %Nx should do when
> outputting an argument that is negative, as in (format "%16x" -63).
>
> Sorry that wasn't clear.
>
> You could try p/x -63 in GDB to see what I mean.
Oh, I see. Yes, I misunderstood. Apologies for my confusion.
So, in this case, would it truncate the output or use a wider field, if the value couldn’t “properly” be shown in the specified size?
E.g., -5000 would display in hex as …ffec78; with a format “%2x” should it return “78” or should it get enough digits to show the minimum number of bits needed to express the real value, much like formatting with “%2d” would still give you “-5000” instead of chopping off relevant digits?
Maybe we can supply both bit count and minimum field width in a format string… “%32!8x” to display the lowest 32 bits in 8 columns but with leading spaces rather than zeros? Or swap the positions of the numbers. And maybe one could be optional; “%32!x” could mean either “%32!8x” (eight columns, leading spaces) or “%32!1x” (minimum one column, i.e., no leading spaces or zeros added).
It would be logical to consider whether the same format extensions would be useful with %o or %d (or others?) being used to format bignums.
Ken
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-04 4:26 ` Richard Stallman
2018-05-05 5:03 ` Ken Raeburn
@ 2018-05-07 18:40 ` Andreas Schwab
1 sibling, 0 replies; 281+ messages in thread
From: Andreas Schwab @ 2018-05-07 18:40 UTC (permalink / raw)
To: Richard Stallman; +Cc: eliz, Paul Eggert, eller.helmut, emacs-devel
On Mai 04 2018, Richard Stallman <rms@gnu.org> wrote:
> Another idea: %Nx with a negative number should output its 2's
> complement representation in 4N bits.
That's what the precision is for.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-05-07 17:24 ` Ken Raeburn
@ 2018-05-08 1:55 ` Richard Stallman
0 siblings, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-05-08 1:55 UTC (permalink / raw)
To: Ken Raeburn; +Cc: eliz, eggert, eller.helmut, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> So, in this case, would it truncate the output or use a wider
> field, if the value couldn’t “properly” be shown in the specified
> size?
I think we want the option of truncating (which includes truncating a
negative number as 2s complement), and the option of signaling an
error when the value does not fit (when it would require truncating).
It would be ok also to have the option of using extra digits, as many
as needed. That option would have to print a minus sign if the number
is negative, since treating it as positive would require infinitely
many digits.
I am not sure that third option is really useful, but if it is, let's
have it.
> It would be logical to consider whether the same format extensions
> would be useful with %o or %d (or others?) being used to format
> bignums.
I don't think these features are useful for decimal output. (Has
anyone ever wanted them?) For octal, I am not sure. Maybe octal
should be treated like hex.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-24 5:45 ` Helmut Eller
@ 2018-06-03 23:44 ` Jefferson Carpenter
0 siblings, 0 replies; 281+ messages in thread
From: Jefferson Carpenter @ 2018-06-03 23:44 UTC (permalink / raw)
To: emacs-devel
On 4/24/2018 5:45 AM, Helmut Eller wrote:
> On Mon, Apr 23 2018, Paul Eggert wrote:
>
>> Even in the standard C library (which lacks bignums), the %x printf
>> format is supposed to be used only with unsigned integers. Nowadays
>> GCC even optionally warns about using %x on signed integers.
>
> Maybe %x should then print the (shortest) two's complement
> representation for bignums. In Common Lisp:
>
> (defun 2comp (x)
> (format nil "~x" (logand x (1- (ash 1 (+ 1 (integer-length x)))))))
>
> (2comp -1) => "1"
> (2comp -2) => "2"
> (2comp -3) => "5"
> (2comp -15) => "11"
> (2comp -16) => "10"
>
> In practice, only integers smaller than most-negative-fixnum would use
> this rule.
>
> Helmut
>
>
I don't think that would make sense, because you can't tell whether a
given output string was generated from a positive or a negative number.
For instance, (2comp -6) = (2comp 10) = "A".
"Two's complement" isn't a representation of integers; "N-bit two's
complement" is a representation of integers from -2^N to 2^N-1, for
positive integer N.
So, I think that function should take another argument, the number of
bits `n` to output.
Jefferson
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-04-23 3:03 ` Stefan Monnier
@ 2018-07-05 21:29 ` Tom Tromey
2018-07-05 21:53 ` John Wiegley
` (2 more replies)
0 siblings, 3 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-05 21:29 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
>>>>> "Stefan" == Stefan Monnier <monnier@iro.umontreal.ca> writes:
Stefan> There are several steps to adding GMP support. Some of those steps
Stefan> might involve non-trivial decisions. But the first few steps should be
Stefan> straightforward enough:
Stefan> A- add a new "bignum" type
Stefan> B- add new operations on them (this might be enough to start using them in Calc)
Stefan> C- add support for bignums to some of the pre-existing functions (e.g. +)
Stefan> D- add support for bignums to more of the pre-existing functions
Stefan> E- add support for bignums "everywhere" where numbers are usually allowed.
Stefan> Anything before D/E should be fairly straightforward.
Stefan> I consider "support for read&print" to fall somewhere in D or maybe E.
I've got some of this working.
I've added configury for GMP and added a new bignum type.
I've made some operations work -- comparisons, abs, float. I haven't
made arith_driver bignum-aware yet, so no "+", "-", etc. This doesn't
look too hard.
Some part of "format" work but I haven't tried to handle all the cases
discussed in this thread.
A few things need to be discussed.
1. Should the C core change the names of things like NUMBERP to FIXNUMP?
Similarly should make_number -> make_fixnum?
I could do this with sed I suppose. In the meantime I've tweaked the
necessary spots in a somewhat ugly way.
2. What is (type-of 5)? Right now 'integer, but arguably perhaps
'fixnum is correct. Gerd's branch did this.
3. Should intbig_to_lisp et al be converted to use bignums?
I'm inclined to say no, for compatibility.
4. Should it be possible to make a "low-valued bignum"? For testing I
have a make-bignum function that turns a fixnum into a like-valued
bignum. However, maybe this should just not be possible. (And most
likely make-bignum should just be deleted before merging any of
this.)
I've pushed this to my github but I could push it to a branch on
savannah if that's useful. I don't know the current branch naming
convention, so I'd need guidance there.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-05 21:29 ` Tom Tromey
@ 2018-07-05 21:53 ` John Wiegley
2018-07-06 20:43 ` Tom Tromey
2018-07-06 21:00 ` Paul Eggert
2 siblings, 0 replies; 281+ messages in thread
From: John Wiegley @ 2018-07-05 21:53 UTC (permalink / raw)
To: Tom Tromey; +Cc: Stefan Monnier, emacs-devel
>>>>> "TT" == Tom Tromey <tom@tromey.com> writes:
TT> 2. What is (type-of 5)? Right now 'integer, but arguably perhaps 'fixnum
TT> is correct. Gerd's branch did this.
Are we still going to have 'integer as a separate type? If not, then I'd stick
with integer, even if it now means fixnum.
--
John Wiegley GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com 60E1 46C4 BD1A 7AC1 4BA2
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-05 21:29 ` Tom Tromey
2018-07-05 21:53 ` John Wiegley
@ 2018-07-06 20:43 ` Tom Tromey
2018-07-06 21:00 ` Paul Eggert
2 siblings, 0 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-06 20:43 UTC (permalink / raw)
To: emacs-devel
Tom> I've made some operations work -- comparisons, abs, float. I haven't
Tom> made arith_driver bignum-aware yet, so no "+", "-", etc. This doesn't
Tom> look too hard.
Last night I converted arith_driver, but this breaks bootstrap.
I haven't debugged this yet.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-05 21:29 ` Tom Tromey
2018-07-05 21:53 ` John Wiegley
2018-07-06 20:43 ` Tom Tromey
@ 2018-07-06 21:00 ` Paul Eggert
2018-07-07 4:27 ` Tom Tromey
` (2 more replies)
2 siblings, 3 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-06 21:00 UTC (permalink / raw)
To: Tom Tromey, Stefan Monnier; +Cc: emacs-devel
Tom Tromey wrote:
> 1. Should the C core change the names of things like NUMBERP to FIXNUMP?
> Similarly should make_number -> make_fixnum?
Yes, we should keep things clear in the C core, and this would definitely be
clearer. Please do it as a separate commit, though.
> 2. What is (type-of 5)? Right now 'integer, but arguably perhaps
> 'fixnum is correct. Gerd's branch did this.
'integer', for the same reason that (type-of 5) doesn't return 'natnum'. fixnum
and natnum are both subtypes of integer, and the basic type is integer. The
other ways of doing this would cause more trouble to user code.
> 3. Should intbig_to_lisp et al be converted to use bignums?
> I'm inclined to say no, for compatibility.
Yes, that function should now return only fixnums and bignums (assuming GMP is
available). Of course the reverse functions that converts lisp to C integer also
needs to work with bignums in C range.
> 4. Should it be possible to make a "low-valued bignum"?
No, as too much Lisp code depends on eq acting like = on fixnums. Although this
will not work for bignums (unless we take Stefan's suggestion...), it should
continue to work on integers that can fit into fixnum range.
Thanks for working on this!
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-06 21:00 ` Paul Eggert
@ 2018-07-07 4:27 ` Tom Tromey
2018-07-07 4:53 ` Paul Eggert
2018-07-10 4:10 ` Stefan Monnier
2018-07-07 23:43 ` Richard Stallman
2018-07-09 20:15 ` Stefan Monnier
2 siblings, 2 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-07 4:27 UTC (permalink / raw)
To: Paul Eggert; +Cc: Tom Tromey, Stefan Monnier, emacs-devel
Tom> 1. Should the C core change the names of things like NUMBERP to FIXNUMP?
Tom> Similarly should make_number -> make_fixnum?
Paul> Yes, we should keep things clear in the C core, and this would
Paul> definitely be clearer. Please do it as a separate commit, though.
Yes, definitely. I ran this and got a big patch:
sed -i 's/INTEGERP/FIXNUMP/g' *.[ch]
sed -i 's/make_number/make_fixnum/g' *.[ch]
sed -i 's/CHECK_NUMBER/CHECK_FIXNUM/g' *.[ch]
I wasn't sure if I should try to rename NUMBERP or NATNUMP.
On the one hand they are really checking only for fixnums.
On the other hand, the logical names seem like they'd be unwieldy.
Also I was not sure what to do with calls like:
#define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qintegerp, x)
Here it is using 'integerp, but that will be a bit false.
Also I found the bug with arith_driver and now the branch can bootstrap
again.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-07 4:27 ` Tom Tromey
@ 2018-07-07 4:53 ` Paul Eggert
2018-07-07 6:20 ` Tom Tromey
2018-07-08 15:59 ` Tom Tromey
2018-07-10 4:10 ` Stefan Monnier
1 sibling, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-07 4:53 UTC (permalink / raw)
To: Tom Tromey; +Cc: Stefan Monnier, emacs-devel
Tom Tromey wrote:
> I was not sure what to do with calls like:
>
> #define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qintegerp, x)
That last line should use Qfixnump, surely.
> I ran this and got a big patch:
>
> sed -i 's/INTEGERP/FIXNUMP/g' *.[ch]
I doubt whether this is the best option. Often, the code should actually be
checking for integers, not for fixnums. So the existing code needs to be
examined more carefully, with only some INTEGERP instances changed to FIXNUMP.
(Code should prefer INTEGERP to FIXNUMP, for generality, but in some cases
FIXNUMP will have to do.)
> sed -i 's/make_number/make_fixnum/g' *.[ch]
This should be OK, at least for now. At some point we may want to have
make_fixnum do proper overflow checking.
> sed -i 's/CHECK_NUMBER/CHECK_FIXNUM/g' *.[ch]
CHECK_NUMBER has always been a misnomer of course, since it excludes floats. But
these uses need to be fixed by hand; some changed to CHECK_INTEGER, and others
to CHECK_FIXNUM, depending on what check is wanted. In that sense this is like
the INTEGERP/FIXNUMP issue.
> I wasn't sure if I should try to rename NUMBERP or NATNUMP.
> On the one hand they are really checking only for fixnums.
> On the other hand, the logical names seem like they'd be unwieldy.
NUMBERP and NATNUMP should not exclude bignums, since their Lisp counterparts
don't. If there is a need for "fixnum or float" (not that likely) or for
"nonnegative fixnum" (more likely), I suggest the names FIXNUM_OR_FLOATP and
FIXNATP.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-07 4:53 ` Paul Eggert
@ 2018-07-07 6:20 ` Tom Tromey
2018-07-07 6:38 ` Paul Eggert
2018-07-08 15:59 ` Tom Tromey
1 sibling, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-07-07 6:20 UTC (permalink / raw)
To: Paul Eggert; +Cc: Tom Tromey, Stefan Monnier, emacs-devel
>> #define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qintegerp, x)
Paul> That last line should use Qfixnump, surely.
The reason I hesitated is that it seems possible for some Lisp code to
notice this change.
This is also why I wasn't sure that intbig_to_lisp et al should be
converted. (This one seems even a little worse since it'll be possible
to build without GMP.)
>> sed -i 's/INTEGERP/FIXNUMP/g' *.[ch]
Paul> I doubt whether this is the best option. Often, the code should
Paul> actually be checking for integers, not for fixnums. So the existing
Paul> code needs to be examined more carefully, with only some INTEGERP
Paul> instances changed to FIXNUMP. (Code should prefer INTEGERP to FIXNUMP,
Paul> for generality, but in some cases FIXNUMP will have to do.)
I probably should have explained a little more.
The basic idea behind the patch series is to do the conversion
incrementally. So, the first patch is just these sed-based renamings --
the resulting Emacs works the same.
Next comes the configury; then the bignum type and type predicate.
After this come some patches to change various operations: eql,
comparisons, arithmetic, printing, the reader, Ffloat, ...
Some of these subsequent patches introduce things like the new INTEGERP:
INLINE bool
INTEGERP (Lisp_Object x)
{
return FIXNUMP (x) || BIGNUMP (x);
}
... or the new make_number, etc.
So, the examination you want is done, just not all in a single patch. I
think this will make review simpler for whoever does that. Also this
avoids having to convert absolutely everything, which I am sure I can't
do alone.
It's not all so clean right now, so if you do happen to look the
patches, don't be worried, I plan to rework the whole series to be
cleaner before submitting it.
I made a few more things work tonight. My "minimal viable feature"
to-do list is down to:
* documentation
* natnump
* since we can't have small bignums we can simplify eql a bit
* logcount
* check how rounding should be done for division and fix the code
* lsh / ash
* logb
* % and mod
Any ideas on things that might be missing from this list?
I wonder if Emacs should (provide 'bignum) when bignums are compiled in.
I still haven't looked at using the mpn_ API.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-07 6:20 ` Tom Tromey
@ 2018-07-07 6:38 ` Paul Eggert
2018-07-09 5:37 ` Tom Tromey
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-07 6:38 UTC (permalink / raw)
To: Tom Tromey; +Cc: Stefan Monnier, emacs-devel
Tom Tromey wrote:
> Any ideas on things that might be missing from this list?
Seems OK for a first cut.
> I wonder if Emacs should (provide 'bignum) when bignums are compiled in.
Not sure it's needed. It should be easy to tell via other means whether bignums
are present, e.g, (natnump (1+ most-positive-fixnum))
> I still haven't looked at using the mpn_ API.
We need to do that before installing this in master, as Emacs must be in charge
of bignum storage allocation. But it isn't needed for a first cut.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-06 21:00 ` Paul Eggert
2018-07-07 4:27 ` Tom Tromey
@ 2018-07-07 23:43 ` Richard Stallman
2018-07-08 4:58 ` Paul Eggert
2018-07-08 5:01 ` Tom Tromey
2018-07-09 20:15 ` Stefan Monnier
2 siblings, 2 replies; 281+ messages in thread
From: Richard Stallman @ 2018-07-07 23:43 UTC (permalink / raw)
To: Paul Eggert; +Cc: tom, monnier, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Yes, that function should now return only fixnums and bignums (assuming GMP is
> available).
In what situations would GMP not be available?
Doesn't it run on all our target platforms?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-07 23:43 ` Richard Stallman
@ 2018-07-08 4:58 ` Paul Eggert
2018-07-08 22:55 ` Richard Stallman
2018-07-08 5:01 ` Tom Tromey
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-08 4:58 UTC (permalink / raw)
To: rms; +Cc: tom, monnier, emacs-devel
Richard Stallman wrote:
> In what situations would GMP not be available?
On operating systems where GMP is not in the base installation. One example is
Solaris 10; I'm sure there are others. We could strongly suggest installing GMP
before building Emacs, as we already do for a GnuTLS and few other libraries;
but at least at first I doubt whether we'd want to absolutely require GMP, just
as we don't require GnuTLS.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-07 23:43 ` Richard Stallman
2018-07-08 4:58 ` Paul Eggert
@ 2018-07-08 5:01 ` Tom Tromey
2018-07-08 22:55 ` Richard Stallman
1 sibling, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-07-08 5:01 UTC (permalink / raw)
To: Richard Stallman; +Cc: Paul Eggert, tom, monnier, emacs-devel
>>>>> "Richard" == Richard Stallman <rms@gnu.org> writes:
Richard> In what situations would GMP not be available?
Richard> Doesn't it run on all our target platforms?
I think it does, and if not could be made to.
The reason I have made this optional so far is that introducing a new
build-time dependency seems like a pain. However, if it isn't really a
pain, then I think Emacs would be better if this were just used
unconditionally.
It's easy to remove the #ifdefs at any time of course, so the decision
doesn't have to be made immediately.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-07 4:53 ` Paul Eggert
2018-07-07 6:20 ` Tom Tromey
@ 2018-07-08 15:59 ` Tom Tromey
2018-07-09 5:43 ` Tom Tromey
1 sibling, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-07-08 15:59 UTC (permalink / raw)
To: Paul Eggert; +Cc: Tom Tromey, Stefan Monnier, emacs-devel
>>>>> "Paul" == Paul Eggert <eggert@cs.ucla.edu> writes:
>> #define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qintegerp, x)
Paul> That last line should use Qfixnump, surely.
Fixing this made me realize that some calls to DEFVAR_PER_BUFFER had to
be updated to use Qfixnump rather than Qintegerp. (With the
restrictions to be lifted piecemeal in the future.)
Also the bytecode interpreter needed some updates; and I changed the
emacs-module API to allow bigger-than-fixnum ints to be converted.
I've implemented all my to-do items, except:
* Update documentation
* Use the mpn_ API. This does not look fun :-(
I still haven't tried cons_to_unsigned et al, out of compatibility
fears.
I've cleaned up the series quite a bit so it is in decent shape if you
want to read through it:
git@github.com:tromey/emacs.git feature/bignum
I tend to rebase and force-push for development branches like this, so
beware of that. No ChangeLogs yet I'm afraid.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-08 5:01 ` Tom Tromey
@ 2018-07-08 22:55 ` Richard Stallman
2018-07-09 5:39 ` Tom Tromey
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-07-08 22:55 UTC (permalink / raw)
To: Tom Tromey; +Cc: eggert, tom, monnier, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> The reason I have made this optional so far is that introducing a new
> build-time dependency seems like a pain. However, if it isn't really a
> pain, then I think Emacs would be better if this were just used
> unconditionally.
I think it will be even more of a pain to support Emacs both with and
without GMO.
How much of a pain would it be to package GMP with Emacs?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-08 4:58 ` Paul Eggert
@ 2018-07-08 22:55 ` Richard Stallman
0 siblings, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-07-08 22:55 UTC (permalink / raw)
To: Paul Eggert; +Cc: tom, monnier, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> On operating systems where GMP is not in the base
> installation. One example is Solaris 10; I'm sure there are
> others. We could strongly suggest installing GMP before building
> Emacs, as we already do for a GnuTLS and few other libraries; but
> at least at first I doubt whether we'd want to absolutely require
> GMP, just as we don't require GnuTLS.
I don't think we should go to very much trouble
just to make installation on Solaris 10 easier.
GMP and GNUtls are not comparable issues. Bignums will have a
pervasive effect on the Emacs C code. I expect TLS affects only a
small part of the code. I expect that supporting with and without TLS
is a small job compared with supporting with and without bignums.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-07 6:38 ` Paul Eggert
@ 2018-07-09 5:37 ` Tom Tromey
2018-07-09 16:22 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-07-09 5:37 UTC (permalink / raw)
To: Paul Eggert; +Cc: Tom Tromey, Stefan Monnier, emacs-devel
>>>>> "Paul" == Paul Eggert <eggert@cs.ucla.edu> writes:
>> I still haven't looked at using the mpn_ API.
Paul> We need to do that before installing this in master, as Emacs must be
Paul> in charge of bignum storage allocation. But it isn't needed for a
Paul> first cut.
I looked into this a little.
The mpn API seems very hard to use. Using it would mean reimplementing
many of the functions provided by GMP.
On the other hand, I see that Guile is using the mpz API. So, maybe in
practice it is safe enough to just set custom allocation functions and
let them throw.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-08 22:55 ` Richard Stallman
@ 2018-07-09 5:39 ` Tom Tromey
0 siblings, 0 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-09 5:39 UTC (permalink / raw)
To: Richard Stallman; +Cc: Tom Tromey, emacs-devel, monnier, eggert
>>>>> "Richard" == Richard Stallman <rms@gnu.org> writes:
Richard> How much of a pain would it be to package GMP with Emacs?
I looked into this and I think one possible answer is "mini-gmp".
This is a single C file that is part of GMP. It provides the same "mpz"
interface that these patches are currently using, though at a
performance cost.
So, one idea would be to put mini-gmp.c into the Emacs source tree, but
only compile it if the real GMP library is not found.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-08 15:59 ` Tom Tromey
@ 2018-07-09 5:43 ` Tom Tromey
0 siblings, 0 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-09 5:43 UTC (permalink / raw)
To: Tom Tromey; +Cc: Paul Eggert, Stefan Monnier, emacs-devel
>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
Tom> * Update documentation
Tom> * Use the mpn_ API. This does not look fun :-(
I made an attempt at updating the documentation, but my heart isn't
really in it, so I tend to doubt that I did all that good of a job.
Also, the issue of whether GMP is required affects the docs quite a bit.
Maybe once the decisions have settled, someone else could look at the
docs.
I replied about the mpn thing already.
I did find a couple more items for the to-do list, though nothing too
pressing:
* cl-isqrt should probably be updated, maybe just sqrt should work on
integers and use GMP (?)
* expt still isn't converted
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-09 5:37 ` Tom Tromey
@ 2018-07-09 16:22 ` Paul Eggert
2018-07-09 22:56 ` Tom Tromey
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-09 16:22 UTC (permalink / raw)
To: Tom Tromey; +Cc: Stefan Monnier, emacs-devel
Tom Tromey wrote:
> On the other hand, I see that Guile is using the mpz API. So, maybe in
> practice it is safe enough to just set custom allocation functions and
> let them throw.
Guile treats memory allocation failure like stack overflow, in the sense that it
relies on undefined behavior in both cases, I guess on the theory that it's
typically better to try to keep running (with undefined behavior) than to give
up and exit right away. GNU Emacs already takes a similar attitude toward stack
overflow, so perhaps it could do the same for memory exhaustion within mpz
routines. (Emacs could soften the blow by using a reserve, as I think it does
already.)
With all that in mind, I guess it's OK to use the mpz API after all.
> one idea would be to put mini-gmp.c into the Emacs source tree, but
> only compile it if the real GMP library is not found.
That sounds like a good idea, given the above. We could also do this if the
installed GMP library is too old for Emacs.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-06 21:00 ` Paul Eggert
2018-07-07 4:27 ` Tom Tromey
2018-07-07 23:43 ` Richard Stallman
@ 2018-07-09 20:15 ` Stefan Monnier
2018-07-09 23:25 ` Paul Eggert
2 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-07-09 20:15 UTC (permalink / raw)
To: emacs-devel
>> 2. What is (type-of 5)? Right now 'integer, but arguably perhaps
>> 'fixnum is correct. Gerd's branch did this.
> 'integer', for the same reason that (type-of 5) doesn't return
> 'natnum'. fixnum and natnum are both subtypes of integer, and the basic type
> is integer. The other ways of doing this would cause more trouble to
> user code.
I think it'd be wrong for (type-of 5) to return the same value as
(type-of <BIGNUM>), especially as long as `eq` doesn't treat bignum
the same as fixnums.
Also, for purposes of cl-generic's dispatch it'd be better for type-of
to return `natnum` or `fixnum` when applicable.
Grepping through Elisp code, `type-of` is very rarely used and it's even
more rare for those uses to depend on the value returned for small
integers, but I did find a few such cases, so it's indeed safer to just
keep returning `integer` for small integers (and probably some other value
for bignums, such as `bignum`).
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-09 16:22 ` Paul Eggert
@ 2018-07-09 22:56 ` Tom Tromey
2018-07-09 23:02 ` Paul Eggert
` (2 more replies)
0 siblings, 3 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-09 22:56 UTC (permalink / raw)
To: Paul Eggert; +Cc: Tom Tromey, Stefan Monnier, emacs-devel
Paul> With all that in mind, I guess it's OK to use the mpz API after all.
I'll make this change shortly.
>> one idea would be to put mini-gmp.c into the Emacs source tree, but
>> only compile it if the real GMP library is not found.
Paul> That sounds like a good idea, given the above. We could also do this
Paul> if the installed GMP library is too old for Emacs.
I did this, and removed all the non-GMP code paths from my branch.
I haven't yet updated the docs or fixed up the tests (they still act as
if bignums might not work).
There's still one failing test.
After those things I guess this is ready to land.
How should I submit the patches for review?
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-09 22:56 ` Tom Tromey
@ 2018-07-09 23:02 ` Paul Eggert
2018-07-09 23:13 ` Tom Tromey
2018-07-10 4:01 ` Tom Tromey
2018-07-10 13:46 ` Tom Tromey
2 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-09 23:02 UTC (permalink / raw)
To: Tom Tromey; +Cc: Stefan Monnier, emacs-devel
Tom Tromey wrote:
> After those things I guess this is ready to land.
> How should I submit the patches for review?
If it's a relatively compact set, you can just use 'git format-patch' send off
an email to bug-gnu-emacs, with the patches attached. If it's a long set, we'd
probably be better off creating a branch for it on savannah. Maybe you can start
with the former and we can evolve to the latter as needed.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-09 23:02 ` Paul Eggert
@ 2018-07-09 23:13 ` Tom Tromey
0 siblings, 0 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-09 23:13 UTC (permalink / raw)
To: Paul Eggert; +Cc: Tom Tromey, Stefan Monnier, emacs-devel
>>>>> "Paul" == Paul Eggert <eggert@cs.ucla.edu> writes:
Paul> Tom Tromey wrote:
>> After those things I guess this is ready to land.
>> How should I submit the patches for review?
Paul> If it's a relatively compact set, you can just use 'git format-patch'
Paul> send off an email to bug-gnu-emacs, with the patches attached. If it's
Paul> a long set, we'd probably be better off creating a branch for it on
Paul> savannah. Maybe you can start with the former and we can evolve to the
Paul> latter as needed.
Right now it is 24 patches. I tend to split things up a bit to make
them easier to follow. The only exception is the first patch, which is
the bulk renaming; since this was done by "sed" it may not require quite
as much reading.
So, once the final things are fixed up, I will write the ChangeLog
entries and push it to savannah and send a note here.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-09 20:15 ` Stefan Monnier
@ 2018-07-09 23:25 ` Paul Eggert
2018-07-10 3:41 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-09 23:25 UTC (permalink / raw)
To: Stefan Monnier, emacs-devel
Stefan Monnier wrote:
> Also, for purposes of cl-generic's dispatch it'd be better for type-of
> to return `natnum` or `fixnum` when applicable.
Isn't the issue of how finely type-of distinguishes integers separable from the
issue of whether to have bignums? type-of could return 'natnum' now, even
without bignums, but it doesn't. If we decide that type-of should return some
value other than 'integer' for some integers, how would we decide what value to
return? For example, if (natnump X) and (bignump X) both succeed, should type-of
return 'natnum' or 'bignum' or both?
All in all I expect Elisp would be a bit easier to use and explain if it treats
'integer' as the fundamental type, and 'characterp', 'fixnump', 'bignump',
'natnump' as predicates that succeed on only some members of that type.
> it's indeed safer to just
> keep returning `integer` for small integers (and probably some other value
> for bignums, such as `bignum`).
Why the latter? That is, when would it be useful in existing code for (type-of
X) to return a value other than 'integer' when (integerp X) returns t?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-09 23:25 ` Paul Eggert
@ 2018-07-10 3:41 ` Stefan Monnier
2018-07-10 5:32 ` Helmut Eller
2018-07-10 16:01 ` Paul Eggert
0 siblings, 2 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-07-10 3:41 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel
>> Also, for purposes of cl-generic's dispatch it'd be better for type-of
>> to return `natnum` or `fixnum` when applicable.
> Isn't the issue of how finely type-of distinguishes integers separable from
> the issue of whether to have bignums? type-of could return 'natnum' now,
> even without bignums, but it doesn't.
Exactly.
I was pointing out that type-of already provides suboptimal results in
this respect, but also that there's some grey area when it comes to
decide what it should return.
The main problem is due to subtyping: natnum is (currently) a subtype of
fixnum which is a subtype of integer, so 5 is all three at the same time
and hence (type-of 5) could return any of those three and claim to
be correct.
In general, we'd want type-of to return the "most precise" type, so
you could argue that `natnum` is the better option. Note that `natnum`
is not a valid type in CommonLisp, tho, so `fixnum` would probably be
a better option (especially if you want to consider positive bignums as
natnums, in which case natnum is not a subtype of fixnum).
> If we decide that type-of should return some value other than
> 'integer' for some integers, how would we decide what value to return?
> For example, if (natnump X) and (bignump X) both succeed, should
> type-of return 'natnum' or 'bignum' or both?
Based on the above (the fact that natnum is neither a subtype nor
a supertype of fixnum or bignum, and the fact that it's not even a type
in Common Lisp), I think we can ignore `natnum` for `type-of` purposes.
> All in all I expect Elisp would be a bit easier to use and explain if it
> treats 'integer' as the fundamental type, and 'characterp', 'fixnump',
> 'bignump', 'natnump' as predicates that succeed on only some members of
> that type.
As long as `eq` treats bignums differently from fixnums, I think type-of
should return different values for the two (ideally, I'd vote for
`bignum` and `fixnum` respectively).
When/if we completely hide the difference between the two (i.e. all
integers behave like bignums and fixnums are just an implementation
detail for optimization purposes), then I'd agree that `type-of` can
return just `integer` for those numbers regardless of their
internal representation. But at that moment I'd also argue that
`fixnump` and `bignump` should disappear.
>> it's indeed safer to just keep returning `integer` for small integers
>> (and probably some other value for bignums, such as `bignum`).
> Why the latter? That is, when would it be useful in existing code for
> (type-of X) to return a value other than 'integer' when (integerp X)
> returns t?
Because it's generally better to return a more precise type than a more
generic one.
E.g. (type-of '(1 2)) returns `cons` not `list` and (type-of [1 2])
returns `vector` rather than `sequence`.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-09 22:56 ` Tom Tromey
2018-07-09 23:02 ` Paul Eggert
@ 2018-07-10 4:01 ` Tom Tromey
2018-07-10 13:46 ` Tom Tromey
2 siblings, 0 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-10 4:01 UTC (permalink / raw)
To: Tom Tromey; +Cc: Paul Eggert, Stefan Monnier, emacs-devel
Tom> I haven't yet updated the docs or fixed up the tests (they still act as
Tom> if bignums might not work).
One thing I've noticed is that the documentation would be simpler if
'eq' worked for bignums. As it is there are a couple of spots that try
to explain the difference between small and large integers.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-07 4:27 ` Tom Tromey
2018-07-07 4:53 ` Paul Eggert
@ 2018-07-10 4:10 ` Stefan Monnier
1 sibling, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-07-10 4:10 UTC (permalink / raw)
To: emacs-devel
> sed -i 's/INTEGERP/FIXNUMP/g' *.[ch]
> sed -i 's/make_number/make_fixnum/g' *.[ch]
> sed -i 's/CHECK_NUMBER/CHECK_FIXNUM/g' *.[ch]
Reminds me that there's also Coccinelle for such systematic changes.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 3:41 ` Stefan Monnier
@ 2018-07-10 5:32 ` Helmut Eller
2018-07-10 13:54 ` Stefan Monnier
2018-07-10 16:01 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Helmut Eller @ 2018-07-10 5:32 UTC (permalink / raw)
To: emacs-devel
On Mon, Jul 09 2018, Stefan Monnier wrote:
> In general, we'd want type-of to return the "most precise" type, so
> you could argue that `natnum` is the better option. Note that `natnum`
> is not a valid type in CommonLisp, tho, so `fixnum` would probably be
> a better option (especially if you want to consider positive bignums as
> natnums, in which case natnum is not a subtype of fixnum).
The most precise type for 5 would be (eql 5) or (integer 5 5). But I
guess for generic function dispatch it would more useful to have
something like a "representation type". Or even "type codes" that are
ordered in some fashion.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-09 22:56 ` Tom Tromey
2018-07-09 23:02 ` Paul Eggert
2018-07-10 4:01 ` Tom Tromey
@ 2018-07-10 13:46 ` Tom Tromey
2 siblings, 0 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-10 13:46 UTC (permalink / raw)
To: Tom Tromey; +Cc: Paul Eggert, Stefan Monnier, emacs-devel
>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
Tom> There's still one failing test.
This turned out to be a giant thinko on my part.
Not sure if that's good or bad, but at least we're one step closer.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 5:32 ` Helmut Eller
@ 2018-07-10 13:54 ` Stefan Monnier
0 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-07-10 13:54 UTC (permalink / raw)
To: emacs-devel
> The most precise type for 5 would be (eql 5) or (integer 5 5).
Indeed, and we don't want that.
> But I guess for generic function dispatch it would more useful to have
> something like a "representation type".
That's right. The most precise possible, but not too precise.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 3:41 ` Stefan Monnier
2018-07-10 5:32 ` Helmut Eller
@ 2018-07-10 16:01 ` Paul Eggert
2018-07-10 16:48 ` Helmut Eller
2018-07-10 20:33 ` Stefan Monnier
1 sibling, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-10 16:01 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
On 07/09/2018 08:41 PM, Stefan Monnier wrote:
> As long as `eq` treats bignums differently from fixnums, I think type-of
> should return different values for the two
I don't see how this folds into your earlier point about cl-generic's
dispatch. I thought the idea of cl-generic was to define a generic
function that finds the most specialized method for its arguments. (I'm
no expert in cl-generic, so please bear with me if I'm wrong.)
If so, why would someone want to specialize a method just for fixnums,
as opposed to a method for integers? The basic operations +, -, * etc.
aren't specialized for fixnums. Are you anticipating adding specialized
variants fixnum-+, fixnum--, fixnum-*, etc., and then having people
write methods with all this in mind? Or maybe having the bytecode
optimizer use them?
If so, I suspect that approach won't be needed for Emacs Lisp. Elisp
programs are not typically intended for that sort of microptimization --
otherwise we'd already have operations like integer-+, integer--,
integer-*, etc. And the complexity of the differing semantics (fixnum-+
would wrap around, whereas + would not) would probably not be worth the
relatively minor performance benefits.
If not, then I'm still not following the advantage of having (type-of 5)
return something other than 'integer'.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 16:01 ` Paul Eggert
@ 2018-07-10 16:48 ` Helmut Eller
2018-07-10 17:45 ` Paul Eggert
2018-07-10 20:33 ` Stefan Monnier
1 sibling, 1 reply; 281+ messages in thread
From: Helmut Eller @ 2018-07-10 16:48 UTC (permalink / raw)
To: emacs-devel
On Tue, Jul 10 2018, Paul Eggert wrote:
> If so, why would someone want to specialize a method just for fixnums,
> as opposed to a method for integers?
Some important functions only for fixnums but not for bignums.
E.g. goto-char or aref.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 16:48 ` Helmut Eller
@ 2018-07-10 17:45 ` Paul Eggert
2018-07-10 19:14 ` Helmut Eller
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-10 17:45 UTC (permalink / raw)
To: Helmut Eller, emacs-devel
On 07/10/2018 09:48 AM, Helmut Eller wrote:
>> If so, why would someone want to specialize a method just for fixnums,
>> as opposed to a method for integers?
> Some important functions only for fixnums but not for bignums.
> E.g. goto-char or aref.
Both of these functions have limits that are not relevant to fixnums;
they have limits based on something else. For example, goto-char is
limited to point-min..point-max, and aref is limited to 0..length-1. We
will want both functions to work on bignums, since we will want to allow
buffer sizes and bool vector lengths that do not fit into fixnums.
And even if these functions' limits were relevant to fixnums, I don't
see why one would want to specialize a method just for fixnums as
opposed to settling for specializing it to integers. The method would
accept an integer, and then if it used a fixnum-only goto-char or aref
that would signal an error, just as it would for any other out-of-range
integer. There would be no need to specialize the method to fixnums.
So I'm still not seeing the actual use cases that would suggest that
(type-of 5) should not continue to return 'integer'.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 17:45 ` Paul Eggert
@ 2018-07-10 19:14 ` Helmut Eller
2018-07-11 1:31 ` Stefan Monnier
2018-07-11 2:04 ` Tom Tromey
0 siblings, 2 replies; 281+ messages in thread
From: Helmut Eller @ 2018-07-10 19:14 UTC (permalink / raw)
To: emacs-devel
On Tue, Jul 10 2018, Paul Eggert wrote:
>> Some important functions only for fixnums but not for bignums.
>> E.g. goto-char or aref.
>
> Both of these functions have limits that are not relevant to fixnums;
> they have limits based on something else. For example, goto-char is
> limited to point-min..point-max, and aref is limited to
> 0..length-1. We will want both functions to work on bignums, since we
> will want to allow buffer sizes and bool vector lengths that do not
> fit into fixnums.
Speak for yourself. I certainly don't want goto-char or aref to work on
bignums. I bed 200 dollars that Emacs will not support buffer sizes or
array lengths beyond most-positive-fixnum within the next year.
And I would be surprised if Emacs would switch to bignums for functions
like, current-time of file-attributes, where it would actually make
sense to use bignums.
> And even if these functions' limits were relevant to fixnums, I don't
> see why one would want to specialize a method just for fixnums as
> opposed to settling for specializing it to integers. The method would
> accept an integer, and then if it used a fixnum-only goto-char or aref
> that would signal an error, just as it would for any other
> out-of-range integer. There would be no need to specialize the method
> to fixnums.
If we follow that argumentation, then no method would ever need any
specialization. The method would accept any type and then if something
doesn't work for the actual type it would signal an error.
> So I'm still not seeing the actual use cases that would suggest that
> (type-of 5) should not continue to return 'integer'.
To write reasonable programs, programmers need to have reasonable models
of how computers work and in particular they need to now how data types
are physically represented. That's why some programmers want know if a
sequence is a list or a vector or if a number is a fixnum, a flonum, or
a bignum.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 16:01 ` Paul Eggert
2018-07-10 16:48 ` Helmut Eller
@ 2018-07-10 20:33 ` Stefan Monnier
2018-07-11 1:52 ` Tom Tromey
1 sibling, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-07-10 20:33 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel
> If so, why would someone want to specialize a method just for fixnums, as
> opposed to a method for integers?
cl-generic has no trouble dispatching on a supertype of that returned by
`type-of`. IOW if `type-of` returns `fixnum` and `bignum` cl-generic
has no difficulty finding that these are applicable for methods that
stipulate an `integer` argument (or a `number` argument for that
matter). But the other way around is a lot more difficult, so as long
as fixnums and bignums are visibly two different types, I think it makes
more sense for `type-of` to return different values for those two cases.
> The basic operations +, -, * etc. aren't specialized for fixnums.
Actually, they are, but this is done by manual type-testing in the
C code, not with cl-defmethod.
> Are you anticipating adding specialized variants fixnum-+, fixnum--,
> fixnum-*, etc., and then having people write methods with all this in
> mind? Or maybe having the bytecode optimizer use them?
Not at all, no.
> If not, then I'm still not following the advantage of having (type-of 5)
> return something other than 'integer'.
For backward compatibility reasons, I agree that (type-of 5) should
continue returning `integer` (tho returning `fixnum` would be better
otherwise), but (type-of <BIGNUM>) doesn't suffer from such a backward
compatibility requirement, so it would be preferable for it to return
`bignum`.
I wonder on the other hand, why you think it'd be bad for (type-of <BIGNUM>)
to return `bignum` instead of `integer`.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 19:14 ` Helmut Eller
@ 2018-07-11 1:31 ` Stefan Monnier
2018-07-11 5:59 ` Helmut Eller
2018-07-11 2:04 ` Tom Tromey
1 sibling, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-07-11 1:31 UTC (permalink / raw)
To: emacs-devel
> Speak for yourself. I certainly don't want goto-char or aref to work on
> bignums. I bed 200 dollars that Emacs will not support buffer sizes or
> array lengths beyond most-positive-fixnum within the next year.
bignums don't make much sense for array sizes and indices, indeed
(except maybe for boolean-vectors), but for buffer sizes they would
allow buffers >512MB (tho still <4GB or likely even <2GB) on 32bit
systems without having to pay for the --wide-int tax.
> To write reasonable programs, programmers need to have reasonable models
> of how computers work and in particular they need to now how data types
> are physically represented. That's why some programmers want know if a
> sequence is a list or a vector or if a number is a fixnum, a flonum, or
> a bignum.
In case there was still a doubt: I fully agree.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 20:33 ` Stefan Monnier
@ 2018-07-11 1:52 ` Tom Tromey
2018-07-11 2:35 ` Paul Eggert
2018-07-11 22:48 ` Richard Stallman
0 siblings, 2 replies; 281+ messages in thread
From: Tom Tromey @ 2018-07-11 1:52 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Paul Eggert, emacs-devel
>>>>> "Stefan" == Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
Stefan> but (type-of <BIGNUM>) doesn't suffer from such a backward
Stefan> compatibility requirement, so it would be preferable for it to return
Stefan> `bignum`.
I read this thread and I still don't know what a use case for this would
be. Do you have something in mind?
Stefan> I wonder on the other hand, why you think it'd be bad for (type-of <BIGNUM>)
Stefan> to return `bignum` instead of `integer`.
Well, for one thing, it's simpler to explain that there are just
integers. In fact after working on the docs for this I think it would
be better if bignums were interned so that eq would work.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-10 19:14 ` Helmut Eller
2018-07-11 1:31 ` Stefan Monnier
@ 2018-07-11 2:04 ` Tom Tromey
2018-07-11 2:36 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-07-11 2:04 UTC (permalink / raw)
To: Helmut Eller; +Cc: emacs-devel
>>>>> "Helmut" == Helmut Eller <eller.helmut@gmail.com> writes:
Helmut> And I would be surprised if Emacs would switch to bignums for functions
Helmut> like, current-time of file-attributes, where it would actually make
Helmut> sense to use bignums.
This was discussed elsewhere in the thread - that is what the
INTEGER_TO_CONS stuff was about. Paul wanted this change:
https://lists.gnu.org/archive/html/emacs-devel/2018-07/msg00160.html
I'm maybe a bit more cautious about it.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-11 1:52 ` Tom Tromey
@ 2018-07-11 2:35 ` Paul Eggert
2018-07-11 3:16 ` Stefan Monnier
2018-07-11 22:48 ` Richard Stallman
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-11 2:35 UTC (permalink / raw)
To: Tom Tromey, Stefan Monnier; +Cc: emacs-devel
> I read this thread and I still don't know what a use case for this would be.
Yes, I'm not seeing it either.
> it's simpler to explain that there are just integers.
Yes, and this is a significant win.
If interning bignums (so that eq works on them) is what it takes to satify
Stefan's concerns, then I'm all for interning them. The idea is to avoid
unnecessary distinctions between fixnums and bignums, so that Lisp programmers
can focus on their problems rather than worry about integer representation.
Although it's OK to have user-visible predicates fixnump and bignump for the few
programmers who really need to know, I'm not seeing use cases for why these
predicates should be any more special than characterp or natnump are.
>> why would someone want to specialize a method just for fixnums, as
>> opposed to a method for integers?
>
> cl-generic has no trouble dispatching on a supertype of that returned by
> `type-of`.
That's fine, but I was asking for use cases not implementation motivation. THat
is, I was wondering why a Lisp programmer would want to use cl-generic that way.
Having cl-generic distinguish fixnums from bignums sounds like more a solution
looking for a problem than a truly useful feature.
>> The basic operations +, -, * etc. aren't specialized for fixnums.
>
> Actually, they are, but this is done by manual type-testing in the
> C code, not with cl-defmethod.
Yes, of course: with basic operations it's done under the hood, and Lisp
programmers don't need to worry about the details. This is a reasonable
programming style for Emacs Lisp, and it'd be a good thing if this style were
used as consistently as possible, to keep things simpler.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-11 2:04 ` Tom Tromey
@ 2018-07-11 2:36 ` Paul Eggert
0 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-11 2:36 UTC (permalink / raw)
To: Tom Tromey, Helmut Eller; +Cc: emacs-devel
Tom Tromey wrote:
> Paul wanted this change:
>
> https://lists.gnu.org/archive/html/emacs-devel/2018-07/msg00160.html
>
> I'm maybe a bit more cautious about it.
It'd be fine to do bignums first, and change intbig_to_lisp to use them later.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-11 2:35 ` Paul Eggert
@ 2018-07-11 3:16 ` Stefan Monnier
2018-07-11 3:30 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-07-11 3:16 UTC (permalink / raw)
To: Paul Eggert; +Cc: Tom Tromey, emacs-devel
>> it's simpler to explain that there are just integers.
> Yes, and this is a significant win.
I'm not sure I understand why a return value of `bignum` for `type-of`
would complicate the doc. AFAICT all it takes is:
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index b94de80b65..3ca5f6399f 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -2034,7 +2034,7 @@ Type Predicates
@defun type-of object
This function returns a symbol naming the primitive type of
-@var{object}. The value is one of the symbols @code{bool-vector},
+@var{object}. The value is one of the symbols @code{bignum}, @code{bool-vector},
@code{buffer}, @code{char-table}, @code{compiled-function},
@code{condition-variable}, @code{cons}, @code{finalizer},
@code{float}, @code{font-entity}, @code{font-object},
There's no need to explain the difference between `integer` and `bignum`
here, just like we don't explain the difference between `subr` and
`compiled-function`.
> If interning bignums (so that eq works on them) is what it takes to satify
> Stefan's concerns, then I'm all for interning them. The idea is to avoid
> unnecessary distinctions between fixnums and bignums, so that Lisp
> programmers can focus on their problems rather than worry about integer
> representation. Although it's OK to have user-visible predicates fixnump and
> bignump for the few programmers who really need to know, I'm not seeing use
> cases for why these predicates should be any more special than characterp or
> natnump are.
[...]
> That's fine, but I was asking for use cases not implementation
> motivation. THat is, I was wondering why a Lisp programmer would want to use
> cl-generic that way. Having cl-generic distinguish fixnums from bignums
> sounds like more a solution looking for a problem than a truly
> useful feature.
I think I'm missing a reality check here. We are talking about
`type-of`, right? Have you looked at how many times it's used in Elisp?
It's a rather obscure function (and indeed the lispref recommends to
use predicates instead: type-of might be handy to implement other things
(like cl-generic) but is otherwise rather inconvenient to use).
So, yes, the motivation is thin because the decision will be irrelevant
in 99.99% of the cases. If you're really dead-set on having it
hide the difference between fixnums and bignums, I won't oppose it.
I just mentioned my preference based on the fact that cl-generic is
(AFAIK) by far the most common user of `type-of` nowadays.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-11 3:16 ` Stefan Monnier
@ 2018-07-11 3:30 ` Paul Eggert
2018-07-11 3:42 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-11 3:30 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Tom Tromey, emacs-devel
Stefan Monnier wrote:
> There's no need to explain the difference between `integer` and `bignum`
> here, just like we don't explain the difference between `subr` and
> `compiled-function`.
subr and compiled-functions are distinct (nonintersecting) types, whereas bignum
is a subset of integer, so these are quite different cases. The manual says
"each object belongs to one and only one primitive type; ‘type-of’ tells you
which one". But if type-of returned 'integer' and bignums are integers (which
they should be), this statement in the manual would become false, and would need
to be rewritten. I don't see this as a win.
> I think I'm missing a reality check here. We are talking about
> `type-of`, right? Have you looked at how many times it's used in Elisp?
True, it's pretty rare. And it is a relic of the old-fashioned days when types
were all disjoint. (Maybe we should remove 'type-of'? :-)
I'm not all that worried about type-of. I am more worried about the idea that
bignums are second-class integers. When at all possible, bignums should be
treated the same way that any other (large) integer is treated. For example,
aref should report that a bignum index is out of range (if it is indeed out of
range) rather than reporting a type error.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-11 3:30 ` Paul Eggert
@ 2018-07-11 3:42 ` Stefan Monnier
0 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-07-11 3:42 UTC (permalink / raw)
To: emacs-devel
> subr and compiled-functions are distinct (nonintersecting) types, whereas
> bignum is a subset of integer, so these are quite different cases. The
> manual says "each object belongs to one and only one primitive type;
> ‘type-of’ tells you which one". But if type-of returned 'integer' and
> bignums are integers (which they should be), this statement in the manual
> would become false, and would need to be rewritten. I don't see this
> as a win.
Actually, the incorrect statement would be when (type-of 5) returns
`integer` since `integer` wouldn't be a primitive type any more.
> True, it's pretty rare. And it is a relic of the old-fashioned days when
> types were all disjoint. (Maybe we should remove 'type-of'? :-)
FWIW, I dislike type-of and would be happy to get rid of it (and
replace it with a cl-generic-specific function instead which would fix
some of its shortcomings for that use-case).
> I'm not all that worried about type-of. I am more worried about the idea
> that bignums are second-class integers. When at all possible, bignums should
> be treated the same way that any other (large) integer is treated.
Fully agreed. I just see `type-of` as a function that reports about the
actual representation so it's OK for it to reveal differences which will
rarely affect normal code.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-11 1:31 ` Stefan Monnier
@ 2018-07-11 5:59 ` Helmut Eller
2018-07-11 14:23 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Helmut Eller @ 2018-07-11 5:59 UTC (permalink / raw)
To: emacs-devel
On Tue, Jul 10 2018, Stefan Monnier wrote:
>> Speak for yourself. I certainly don't want goto-char or aref to work on
>> bignums. I bed 200 dollars that Emacs will not support buffer sizes or
>> array lengths beyond most-positive-fixnum within the next year.
>
> bignums don't make much sense for array sizes and indices, indeed
> (except maybe for boolean-vectors), but for buffer sizes they would
> allow buffers >512MB (tho still <4GB or likely even <2GB) on 32bit
> systems without having to pay for the --wide-int tax.
We'll see if somebody spends his time on this. It seems like a waste of
time to me, now as 64 bit systems are so common.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-11 5:59 ` Helmut Eller
@ 2018-07-11 14:23 ` Stefan Monnier
0 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-07-11 14:23 UTC (permalink / raw)
To: emacs-devel
> We'll see if somebody spends his time on this. It seems like a waste of
> time to me, now as 64 bit systems are so common.
My guess is that it will happen not because someone really cares about
it, but because a "Lisp_Object to EMACS_INT" conversion function (which
also accepts bignums as long as they fit within EMACS_INT) will be
needed elsewhere anyway and once you have that, you might as well call
it XINT so it will "magically work".
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-11 1:52 ` Tom Tromey
2018-07-11 2:35 ` Paul Eggert
@ 2018-07-11 22:48 ` Richard Stallman
2018-07-12 4:51 ` Tom Tromey
1 sibling, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-07-11 22:48 UTC (permalink / raw)
To: Tom Tromey; +Cc: eggert, monnier, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Well, for one thing, it's simpler to explain that there are just
> integers. In fact after working on the docs for this I think it would
> be better if bignums were interned so that eq would work.
Simplifying the documentation is often a good reason to change the
Emacs Lisp language. But it is not automatically decisive. In this
case, there may be important advantages on the other side too.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-11 22:48 ` Richard Stallman
@ 2018-07-12 4:51 ` Tom Tromey
2018-07-12 23:35 ` Richard Stallman
0 siblings, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-07-12 4:51 UTC (permalink / raw)
To: Richard Stallman; +Cc: Tom Tromey, emacs-devel, monnier, eggert
>>>>> "Richard" == Richard Stallman <rms@gnu.org> writes:
Richard> [[[ To any NSA and FBI agents reading my email: please consider ]]]
Richard> [[[ whether defending the US Constitution against all enemies, ]]]
Richard> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>> Well, for one thing, it's simpler to explain that there are just
>> integers. In fact after working on the docs for this I think it would
>> be better if bignums were interned so that eq would work.
Richard> Simplifying the documentation is often a good reason to change the
Richard> Emacs Lisp language. But it is not automatically decisive. In this
Richard> case, there may be important advantages on the other side too.
Yeah, I just don't know what those advantages are; or maybe they were
explained and I missed and/or did not understand them.
Speaking of downsides, I think there is at least one downside of making
'eq' work for bignums, which is that it is slower.
One way to implement this would be to intern each mpz_t in some sort of
weak hash table. This isn't hard to implement but it means a hash
lookup whenever converting a bignum to a Lisp object.
Another way would be to add a special case to eq, though as you said
earlier, this would slow down eq.
I don't know which would be better and I haven't implemented either one.
Instead I plan to push my branch to savannah soon, and then I will send
out an email and everybody can take a look at it and see what they think
about the documentation and the implementation.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-12 4:51 ` Tom Tromey
@ 2018-07-12 23:35 ` Richard Stallman
2018-07-15 15:02 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-07-12 23:35 UTC (permalink / raw)
To: Tom Tromey; +Cc: tom, emacs-devel, monnier, eggert
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Richard> Simplifying the documentation is often a good reason to change the
> Richard> Emacs Lisp language. But it is not automatically decisive. In this
> Richard> case, there may be important advantages on the other side too.
> Yeah, I just don't know what those advantages are; or maybe they were
> explained and I missed and/or did not understand them.
It is this:
> Speaking of downsides, I think there is at least one downside of making
> 'eq' work for bignums, which is that it is slower.
I don't know HOW bad this will be. (It would be nice to find out by
experiment.) That's why I said there _may_ be important advantages on
the other side. I don't know how important they are.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-12 23:35 ` Richard Stallman
@ 2018-07-15 15:02 ` Stefan Monnier
2018-07-18 10:20 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-07-15 15:02 UTC (permalink / raw)
To: Richard Stallman; +Cc: Tom Tromey, emacs-devel, eggert
> I don't know HOW bad this will be. (It would be nice to find out by
> experiment.) That's why I said there _may_ be important advantages on
> the other side. I don't know how important they are.
I recently posted a patch which makes EQ behave like `eql` attached.
I just tried to see its impact on the ELisp compilation time
(i.e. I did `rm **/*.elc; make`).
The original time on my benchmark machine was in the bracket
58.77s..59.13s, and with the patch, the time increased to a bracket of
61.03s..61.68s.
So basically a 4% slow down.
Stefan
diff --git a/src/fns.c b/src/fns.c
index 27c16c6072..4c23bb2488 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2173,10 +2173,7 @@ DEFUN ("eql", Feql, Seql, 2, 2, 0,
Floating-point numbers of equal value are `eql', but they may not be `eq'. */)
(Lisp_Object obj1, Lisp_Object obj2)
{
- if (FLOATP (obj1))
- return equal_no_quit (obj1, obj2) ? Qt : Qnil;
- else
- return EQ (obj1, obj2) ? Qt : Qnil;
+ return EQL (obj1, obj2) ? Qt : Qnil;
}
DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
@@ -2272,7 +2269,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
}
}
- if (EQ (o1, o2))
+ if (lisp_h_EQ (o1, o2))
return true;
if (XTYPE (o1) != XTYPE (o2))
return false;
@@ -3766,7 +3763,7 @@ cmpfn_user_defined (struct hash_table_test *ht,
in a Lisp integer. */
static EMACS_UINT
-hashfn_eq (struct hash_table_test *ht, Lisp_Object key)
+hashfn__eq (struct hash_table_test *ht, Lisp_Object key)
{
return XHASH (key) ^ XTYPE (key);
}
@@ -3788,7 +3785,13 @@ hashfn_equal (struct hash_table_test *ht, Lisp_Object key)
static EMACS_UINT
hashfn_eql (struct hash_table_test *ht, Lisp_Object key)
{
- return FLOATP (key) ? hashfn_equal (ht, key) : hashfn_eq (ht, key);
+ return FLOATP (key) ? hashfn_equal (ht, key) : hashfn__eq (ht, key);
+}
+
+static EMACS_UINT
+hashfn_eq (struct hash_table_test *ht, Lisp_Object key)
+{
+ return hashfn_eql (ht, key);
}
/* Value is a hash code for KEY for use in hash table H which uses as
diff --git a/src/lisp.h b/src/lisp.h
index 0bb7c488f2..26fa477ce4 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -361,7 +361,7 @@ typedef EMACS_INT Lisp_Word;
#define lisp_h_INTEGERP(x) ((XTYPE (x) & (Lisp_Int0 | ~Lisp_Int1)) == Lisp_Int0)
#define lisp_h_MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
#define lisp_h_MISCP(x) (XTYPE (x) == Lisp_Misc)
-#define lisp_h_NILP(x) EQ (x, Qnil)
+#define lisp_h_NILP(x) lisp_h_EQ (x, Qnil)
#define lisp_h_SET_SYMBOL_VAL(sym, v) \
(eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), \
(sym)->u.s.val.value = (v))
@@ -421,7 +421,7 @@ typedef EMACS_INT Lisp_Word;
# define CHECK_SYMBOL(x) lisp_h_CHECK_SYMBOL (x)
# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x)
# define CONSP(x) lisp_h_CONSP (x)
-# define EQ(x, y) lisp_h_EQ (x, y)
+# define EQ(x, y) EQL (x, y)
# define FLOATP(x) lisp_h_FLOATP (x)
# define INTEGERP(x) lisp_h_INTEGERP (x)
# define MARKERP(x) lisp_h_MARKERP (x)
@@ -1141,10 +1141,21 @@ make_natnum (EMACS_INT n)
/* Return true if X and Y are the same object. */
+extern bool equal_no_quit (Lisp_Object o1, Lisp_Object o2);
+
+INLINE bool
+EQL (Lisp_Object x, Lisp_Object y)
+{
+ if (lisp_h_FLOATP (x))
+ return equal_no_quit (x, y);
+ else
+ return lisp_h_EQ (x, y);
+}
+
INLINE bool
(EQ) (Lisp_Object x, Lisp_Object y)
{
- return lisp_h_EQ (x, y);
+ return EQL (x, y);
}
/* True if the possibly-unsigned integer I doesn't fit in a Lisp fixnum. */
@@ -3626,7 +3637,6 @@ extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object);
extern Lisp_Object do_yes_or_no_p (Lisp_Object);
extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
extern Lisp_Object concat3 (Lisp_Object, Lisp_Object, Lisp_Object);
-extern bool equal_no_quit (Lisp_Object, Lisp_Object);
extern Lisp_Object nconc2 (Lisp_Object, Lisp_Object);
extern Lisp_Object assq_no_quit (Lisp_Object, Lisp_Object);
extern Lisp_Object assoc_no_quit (Lisp_Object, Lisp_Object);
^ permalink raw reply related [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-15 15:02 ` Stefan Monnier
@ 2018-07-18 10:20 ` Paul Eggert
2018-07-18 13:17 ` Stefan Monnier
` (2 more replies)
0 siblings, 3 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-18 10:20 UTC (permalink / raw)
To: Stefan Monnier, Richard Stallman; +Cc: Tom Tromey, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 939 bytes --]
Stefan Monnier wrote:
> I recently posted a patch which makes EQ behave like `eql` attached.
> I just tried to see its impact on the ELisp compilation time
> (i.e. I did `rm **/*.elc; make`).
I tried to reproduce this on my machine, and ran into some trouble (the code had
warnings that caused compilation to fail). Although your patch is evidently
intended only as a quick benchmark and not as an actual change, I worry that the
benchmark isn't realistic enough, as some usage of EQ in C code will need to
change to Feql or equivalent. Also, the C code will need to change how hashing
works since XHASH etc. must be consistent with eq.
Looking into this a bit more, I discovered that eql currently operates
incorrectly on NaNs, as it's inconsistent with how hash tables work. I installed
the attached patch into master to fix that.
I'll try to look into doing a benchmark like yours with all the above in mind.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Fix-bug-with-eql-etc.-on-NaNs.patch --]
[-- Type: text/x-patch; name="0001-Fix-bug-with-eql-etc.-on-NaNs.patch", Size: 7709 bytes --]
From c70d22f70b77b053d01c7380122d166ecb728610 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 18 Jul 2018 03:16:54 -0700
Subject: [PATCH] Fix bug with eql etc. on NaNs
Fix a bug where eql, sxhash-eql, memql, and make-hash-table
were not consistent on NaNs. Likewise for equal,
sxhash-equal, member, and make-hash-table. Some of these
functions ignored NaN significands, whereas others treated
them as significant. It's more logical to treat significands
as significant, and this typically makes eql a bit more
efficient on floats, with just one integer comparison instead
of one to three floating-point comparisons.
* doc/lispref/numbers.texi (Float Basics): Document that
NaNs are never numerically equal, but might be eql.
* src/fns.c (WORDS_PER_DOUBLE): Move to top level of this file.
(union double_and_words): Now named, and at the top level of this file.
(same_float): New function.
(Fmemql, Feql, internal_equal, cmpfn_eql): Use it, so that
the corresponding functions treat NaNs consistently.
(sxhash_float): Simplify based on above-mentioned changes.
* test/src/fns-tests.el (fns-tests-equality-nan): New test.
---
doc/lispref/numbers.texi | 9 +++++--
src/fns.c | 68 +++++++++++++++++++++++++-----------------------
test/src/fns-tests.el | 11 ++++++++
3 files changed, 53 insertions(+), 35 deletions(-)
diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index 2fed2b6..6c51b84 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -232,13 +232,18 @@ Float Basics
@cindex negative infinity
@cindex infinity
@cindex NaN
+@findex eql
+@findex sxhash-eql
The @acronym{IEEE} floating-point standard supports positive
infinity and negative infinity as floating-point values. It also
provides for a class of values called NaN, or ``not a number'';
numerical functions return such values in cases where there is no
correct answer. For example, @code{(/ 0.0 0.0)} returns a NaN@.
-Although NaN values carry a sign, for practical purposes there is no other
-significant difference between different NaN values in Emacs Lisp.
+A NaN is never numerically equal to any value, not even to itself.
+NaNs carry a sign and a significand, and non-numeric functions like
+@code{eql} and @code{sxhash-eql} treat two NaNs as equal when their
+signs and significands agree. Significands of NaNs are
+machine-dependent and are not directly visible to Emacs Lisp.
Here are read syntaxes for these special floating-point values:
diff --git a/src/fns.c b/src/fns.c
index c171784..10997da 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1419,6 +1419,29 @@ DEFUN ("elt", Felt, Selt, 2, 2, 0,
return Faref (sequence, n);
}
+enum { WORDS_PER_DOUBLE = (sizeof (double) / sizeof (EMACS_UINT)
+ + (sizeof (double) % sizeof (EMACS_UINT) != 0)) };
+union double_and_words
+{
+ double val;
+ EMACS_UINT word[WORDS_PER_DOUBLE];
+};
+
+/* Return true if X and Y are the same floating-point value.
+ This looks at X's and Y's representation, since (unlike '==')
+ it returns true if X and Y are the same NaN. */
+static bool
+same_float (Lisp_Object x, Lisp_Object y)
+{
+ union double_and_words
+ xu = { .val = XFLOAT_DATA (x) },
+ yu = { .val = XFLOAT_DATA (y) };
+ EMACS_UINT neql = 0;
+ for (int i = 0; i < WORDS_PER_DOUBLE; i++)
+ neql |= xu.word[i] ^ yu.word[i];
+ return !neql;
+}
+
DEFUN ("member", Fmember, Smember, 2, 2, 0,
doc: /* Return non-nil if ELT is an element of LIST. Comparison done with `equal'.
The value is actually the tail of LIST whose car is ELT. */)
@@ -1457,7 +1480,7 @@ The value is actually the tail of LIST whose car is ELT. */)
FOR_EACH_TAIL (tail)
{
Lisp_Object tem = XCAR (tail);
- if (FLOATP (tem) && equal_no_quit (elt, tem))
+ if (FLOATP (tem) && same_float (elt, tem))
return tail;
}
CHECK_LIST_END (tail, list);
@@ -2175,7 +2198,7 @@ Floating-point numbers of equal value are `eql', but they may not be `eq'. */)
(Lisp_Object obj1, Lisp_Object obj2)
{
if (FLOATP (obj1))
- return equal_no_quit (obj1, obj2) ? Qt : Qnil;
+ return FLOATP (obj2) && same_float (obj1, obj2) ? Qt : Qnil;
else
return EQ (obj1, obj2) ? Qt : Qnil;
}
@@ -2266,13 +2289,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
switch (XTYPE (o1))
{
case Lisp_Float:
- {
- double d1 = XFLOAT_DATA (o1);
- double d2 = XFLOAT_DATA (o2);
- /* If d is a NaN, then d != d. Two NaNs should be `equal' even
- though they are not =. */
- return d1 == d2 || (d1 != d1 && d2 != d2);
- }
+ return same_float (o1, o2);
case Lisp_Cons:
if (equal_kind == EQUAL_NO_QUIT)
@@ -3706,24 +3723,20 @@ HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx)
return XINT (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)
- && XFLOAT_DATA (key1) == XFLOAT_DATA (key2));
+ return FLOATP (key1) && FLOATP (key2) && same_float (key1, key2);
}
-/* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
- HASH2 in hash table H using `equal'. Value is true if KEY1 and
- KEY2 are the same. */
+/* Compare KEY1 and KEY2 in hash table HT using `equal'. Value is
+ true if KEY1 and KEY2 are the same. */
static bool
cmpfn_equal (struct hash_table_test *ht,
@@ -3734,9 +3747,8 @@ cmpfn_equal (struct hash_table_test *ht,
}
-/* Compare KEY1 which has hash code HASH1, and KEY2 with hash code
- HASH2 in hash table H using H->user_cmp_function. Value is true
- if KEY1 and KEY2 are the same. */
+/* Compare KEY1 and KEY2 in hash table HT using HT->user_cmp_function.
+ Value is true if KEY1 and KEY2 are the same. */
static bool
cmpfn_user_defined (struct hash_table_test *ht,
@@ -4328,18 +4340,8 @@ static EMACS_UINT
sxhash_float (double val)
{
EMACS_UINT hash = 0;
- enum {
- WORDS_PER_DOUBLE = (sizeof val / sizeof hash
- + (sizeof val % sizeof hash != 0))
- };
- union {
- double val;
- EMACS_UINT word[WORDS_PER_DOUBLE];
- } u;
- int i;
- u.val = val;
- memset (&u.val + 1, 0, sizeof u - sizeof u.val);
- for (i = 0; i < WORDS_PER_DOUBLE; i++)
+ union double_and_words u = { .val = val };
+ for (int i = 0; i < WORDS_PER_DOUBLE; i++)
hash = sxhash_combine (hash, u.word[i]);
return SXHASH_REDUCE (hash);
}
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index d9cca55..e4b9cbe 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -23,6 +23,17 @@
(require 'cl-lib)
+;; Test that equality predicates work correctly on NaNs when combined
+;; with hash tables based on those predicates. This was not the case
+;; for eql in Emacs 26.
+(ert-deftest fns-tests-equality-nan ()
+ (dolist (test (list #'eq #'eql #'equal))
+ (let* ((h (make-hash-table :test test))
+ (nan 0.0e+NaN)
+ (-nan (- nan)))
+ (puthash nan t h)
+ (should (eq (funcall test nan -nan) (gethash -nan h))))))
+
(ert-deftest fns-tests-reverse ()
(should-error (reverse))
(should-error (reverse 1))
--
2.7.4
^ permalink raw reply related [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-18 10:20 ` Paul Eggert
@ 2018-07-18 13:17 ` Stefan Monnier
2018-07-27 21:14 ` Making 'eq' == 'eql' in bignum branch Paul Eggert
2018-07-18 15:55 ` Using the GNU GMP Library for Bignums in Emacs Eli Zaretskii
2018-07-22 12:06 ` Ken Raeburn
2 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-07-18 13:17 UTC (permalink / raw)
To: emacs-devel
> I tried to reproduce this on my machine, and ran into some trouble (the code
> had warnings that caused compilation to fail). Although your patch is
> evidently intended only as a quick benchmark and not as an actual change,
Indeed (tho I have this patch installed in my "regular Emacs", so I use
it daily).
> I worry that the benchmark isn't realistic enough, as some usage of EQ in
> C code will need to change to Feql or equivalent.
I don't understand what you mean: the patch changes `EQ` itself:
-# define EQ(x, y) lisp_h_EQ (x, y)
+# define EQ(x, y) EQL (x, y)
where EQL is the same as Feql (except it returns a boolean instead of
a Lisp_Object). Some uses of EQ admittedly don't need to be
redirected to EQL, so we could improve the patch to reduce its cost, but
I expect the benefit would be small.
> Also, the C code will need to change how hashing works since XHASH
> etc. must be consistent with eq.
The patch does that already, AFAIK.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-18 10:20 ` Paul Eggert
2018-07-18 13:17 ` Stefan Monnier
@ 2018-07-18 15:55 ` Eli Zaretskii
2018-07-18 21:42 ` Paul Eggert
2018-07-22 12:06 ` Ken Raeburn
2 siblings, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-07-18 15:55 UTC (permalink / raw)
To: Paul Eggert; +Cc: tom, emacs-devel, monnier, rms
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Wed, 18 Jul 2018 03:20:40 -0700
> Cc: Tom Tromey <tom@tromey.com>, emacs-devel@gnu.org
>
> +/* Return true if X and Y are the same floating-point value.
> + This looks at X's and Y's representation, since (unlike '==')
> + it returns true if X and Y are the same NaN. */
> +static bool
> +same_float (Lisp_Object x, Lisp_Object y)
> +{
> + union double_and_words
> + xu = { .val = XFLOAT_DATA (x) },
> + yu = { .val = XFLOAT_DATA (y) };
> + EMACS_UINT neql = 0;
> + for (int i = 0; i < WORDS_PER_DOUBLE; i++)
> + neql |= xu.word[i] ^ yu.word[i];
> + return !neql;
> +}
Wouldn't calling this upon every float comparison yield a
non-negligible run-time penalty? Maybe we should use 'isnan' instead?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-18 15:55 ` Using the GNU GMP Library for Bignums in Emacs Eli Zaretskii
@ 2018-07-18 21:42 ` Paul Eggert
0 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-18 21:42 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tom, emacs-devel, monnier, rms
On 07/18/2018 08:55 AM, Eli Zaretskii wrote:
> Wouldn't calling this upon every float comparison yield a
> non-negligible run-time penalty? Maybe we should use 'isnan' instead?
No, it's actually faster (at least on x86-64), since it uses a single
64-bit integer comparison rather than up to three 64-bit floating-point
comparisons. (The for-loop in question is unrolled into a single
execution of its body, among other things.)
isnan would slow us down here, since the code does not need to differ
for NaNs versus non-NaNs.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-18 10:20 ` Paul Eggert
2018-07-18 13:17 ` Stefan Monnier
2018-07-18 15:55 ` Using the GNU GMP Library for Bignums in Emacs Eli Zaretskii
@ 2018-07-22 12:06 ` Ken Raeburn
2018-07-22 16:44 ` Paul Eggert
2018-07-22 19:57 ` Achim Gratz
2 siblings, 2 replies; 281+ messages in thread
From: Ken Raeburn @ 2018-07-22 12:06 UTC (permalink / raw)
To: Paul Eggert; +Cc: Tom Tromey, emacs-devel, Stefan Monnier, Richard Stallman
On Jul 18, 2018, at 06:20, Paul Eggert <eggert@cs.ucla.edu> wrote:
>
> Stefan Monnier wrote:
>> I recently posted a patch which makes EQ behave like `eql` attached.
>> I just tried to see its impact on the ELisp compilation time
>> (i.e. I did `rm **/*.elc; make`).
>
> I tried to reproduce this on my machine, and ran into some trouble (the code had warnings that caused compilation to fail). Although your patch is evidently intended only as a quick benchmark and not as an actual change, I worry that the benchmark isn't realistic enough, as some usage of EQ in C code will need to change to Feql or equivalent. Also, the C code will need to change how hashing works since XHASH etc. must be consistent with eq.
>
> Looking into this a bit more, I discovered that eql currently operates incorrectly on NaNs, as it's inconsistent with how hash tables work. I installed the attached patch into master to fix that.
If we’re going to treat NaNs as having distinguishable bit patterns so we can tell whether two are the same or not, should we also have printable/readable forms that distinguish them? If not, how do we create and use distinguishable NaNs?
For that matter, are we guaranteed that operations like (/ 0.0 0.0) will always generate NaNs with the same bit pattern?
I would’ve guessed that it might be preferable to go the other direction, and use one canonical NaN value in Lisp, which would thus always be eq/eql to all other NaN expressions.
Ken
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-22 12:06 ` Ken Raeburn
@ 2018-07-22 16:44 ` Paul Eggert
2018-08-01 7:57 ` Paul Eggert
2018-07-22 19:57 ` Achim Gratz
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-22 16:44 UTC (permalink / raw)
To: Ken Raeburn; +Cc: Tom Tromey, emacs-devel, Stefan Monnier, Richard Stallman
Ken Raeburn wrote:
> If we’re going to treat NaNs as having distinguishable bit patterns so we can tell whether two are the same or not, should we also have printable/readable forms that distinguish them? If not, how do we create and use distinguishable NaNs?
Good point. It'd make sense to have printable/readable forms; please see below.
> are we guaranteed that operations like (/ 0.0 0.0) will always generate NaNs with the same bit pattern?
No, and this is an issue even with older Emacs. For example, (format "%s" (/ 0.0
0.0)) returns different strings on different platforms, because some machines
return a negative NaN whereas others don't.
> I would’ve guessed that it might be preferable to go the other direction, and use one canonical NaN value in Lisp, which would thus always be eq/eql to all other NaN expressions.
For some time Emacs has been able to distinguish negative from nonnegative NaNs.
Functions like 'format' and 'copysign' depend on a NaN's sign, and (- x)
reliably changes the sign of a NaN.
I see three ways to go here.
1. We change eql, memql, sxhash-eql, etc. to treat all NaNs alike, so that there
is just one NaN value from the Lisp point of view. We also change 'format',
'copysign' etc. to ignore a NaN's sign, and look through any other use of
floating-point values to make sure that NaN signs are ignored.
2. We change eql, memql, sxhash-eql, etc. so that only the sign (not the
significand) of a NaN is looked at, so that there are just two NaN values from
the Lisp point of view.
3. We alter 'read', 'format' etc. to read and generate NaN significands. For
example, (format "%s" NaN) could return "0.1e+NaN" if the significand's
low-order bit was set.
(1) sounds too drastic, as the sign of a NaN can be useful in some cases and
Emacs has long provided for obtaining the sign of a NaN. Although either (2) or
(3) would be OK, I'm inclined to go for (3) as I expect it would be a bit
cleaner and more useful.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-22 12:06 ` Ken Raeburn
2018-07-22 16:44 ` Paul Eggert
@ 2018-07-22 19:57 ` Achim Gratz
1 sibling, 0 replies; 281+ messages in thread
From: Achim Gratz @ 2018-07-22 19:57 UTC (permalink / raw)
To: emacs-devel
Ken Raeburn writes:
> If we’re going to treat NaNs as having distinguishable bit patterns so
> we can tell whether two are the same or not, should we also have
> printable/readable forms that distinguish them? If not, how do we
> create and use distinguishable NaNs?
That would expose the NaN payload, using the non-specified bits of the
mantissa of an NaN to transport (sideband) information. You will
probably find that no one really expects these bits to be used…
> For that matter, are we guaranteed that operations like (/ 0.0 0.0)
> will always generate NaNs with the same bit pattern?
On the same platform? Likely. On different platforms, surely not.
> I would’ve guessed that it might be preferable to go the other
> direction, and use one canonical NaN value in Lisp, which would thus
> always be eq/eql to all other NaN expressions.
Ignoring the payload bits would probably be OK, but that still gives you
at least two different NaN (positive and negative) to deal with.
Regards,
Achim.
--
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+
SD adaptation for Waldorf Blofeld V1.15B11:
http://Synth.Stromeko.net/Downloads.html#WaldorfSDada
^ permalink raw reply [flat|nested] 281+ messages in thread
* Making 'eq' == 'eql' in bignum branch
2018-07-18 13:17 ` Stefan Monnier
@ 2018-07-27 21:14 ` Paul Eggert
2018-07-28 14:26 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-27 21:14 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2228 bytes --]
Ten days ago we were discussing the possibility of changing eq to be equivalent
to eql in the bignum branch, to avoid possible compability issues where 'eq' no
longer agrees with 'eql' (or with '=') on integer arguments. On July 18 Stefan
wrote:
> Some uses of EQ admittedly don't need to be
> redirected to EQL, so we could improve the patch to reduce its cost, but
> I expect the benefit would be small.
It's more than "some", if we count static occurrences. Almost all uses of EQ in
C code don't need to be redirected to EQL, because one can easily tell
statically that at least one of the arguments must be a non-float, or that it's
OK to use pointer comparison for some other reason. I wrote a patch along those
lines (see attached; it's against the master branch), and when compiled with
normal -O2 optimization (Fedora 28 x86-64, AMD Phenom II X4 910e, user+system
time, average of 3 runs), "cd lisp; make compile-always" suffers only a 2.3%
slowdown, better than the 4% slowdown Stefan mentioned with his simpler patch.
Stefan, have you thought about hashing floating-point objects instead, so that
comparing pointers suffices for eql, and eq becomes equivalent to eql in a
different way? That may well have better performance for typical Emacs
applications, since they typically don't create a lot of floating-point numbers.
Also, it'd be less error-prone than the attached patch, which involves static
analysis that would typically be done by hand.
>> Also, the C code will need to change how hashing works since XHASH
>> etc. must be consistent with eq.
>
> The patch does that already, AFAIK.
I still see a problem there in your simpler patch, since cmpfn_eql isn't used in
the eq case, when hashing floating-point values.
>> I worry that the benchmark isn't realistic enough, as some usage of EQ in
>> C code will need to change to Feql or equivalent.
>
> I don't understand what you mean: the patch changes `EQ` itself:
>
> -# define EQ(x, y) lisp_h_EQ (x, y)
> +# define EQ(x, y) EQL (x, y)
>
> where EQL is the same as Feql (except it returns a boolean instead of
> a Lisp_Object).
You're right. Sorry, I missed that.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Make-eq-act-like-eql.patch --]
[-- Type: text/x-patch; name="0001-Make-eq-act-like-eql.patch", Size: 31868 bytes --]
From 91c48f71f4e1a86eceae39642bc88b2781e9bbe4 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Fri, 27 Jul 2018 13:41:10 -0700
Subject: [PATCH] Make eq act like eql
This patch changes the Lisp function eq to act like eql.
The goal is to simplify the introduction of bignums, so
that eq will still be equivalent to eql on integers.
This patch tests this by doing so for floating-point numbers.
* lisp/subr.el (memq, sxhash-eq):
Now aliases for the corresponding eql fns.
* src/bytecode.c (exec_byte_code):
* src/category.c (word_boundary_p):
* src/chartab.c (sub_char_table_ref_and_range)
(char_table_ref_and_range, optimize_sub_char_table)
(map_sub_char_table, uniprop_encode_value_run_length)
(unicode_encode_value_numeric):
* src/data.c (Feq, set_internal, set_default_internal):
* src/dispnew.c (Fframe_or_buffer_changed_p):
* src/emacs-module.c (module_eq):
* src/eval.c (defvaralias, macroexpand, Fthrow)
(process_quit_flag):
* src/fns.c (Fmember, Fassq, Frassq, Fdelq, Fplist_get)
(Fplist_put, Fplist_member, hash_lookup, hash_remove_from_table):
* src/textprop.c (interval_has_all_properties)
(interval_has_some_properties, interval_has_some_properties_list)
(property_value, set_properties, add_properties, remove_properties)
(Fnext_single_char_property_change)
(Fprevious_single_char_property_change)
(Fnext_single_property_change)
(Fprevious_single_property_change, Ftext_property_any)
(Ftext_property_not_all, copy_text_properties, text_property_list):
Use EQL, not EQ, on values not known to be safe for EQ.
* src/fns.c (WORDS_PER_DOUBLE, union double_and_words)
(same_float): Move to src/lisp.h.
(Fmemql): Remove; now written in Lisp.
(Feql): Rewrite in terms of EQL.
(assq_no_quit): Add an assertion that the key is not
a float.
(cmpfn_eql, hashfn_eq): Remove; all uses removed.
(sxhash_float): Now extern. Accept Lisp float, not double.
All uses changed.
(Fsxhash_eql): Remove; all uses removed.
(Fmake_hash_table): Do the same thing for eql as for eq.
* src/lisp.h (lisp_h_XHASH): Look at contents of floats.
(same_float): Now INLINE.
(EQL): New function.
* src/window.c (window_wants_mode_line, window_wants_header_line):
Rewrite to avoid GCC warning.
---
lisp/subr.el | 3 ++
src/bytecode.c | 4 +-
src/category.c | 4 +-
src/chartab.c | 18 +++----
src/data.c | 7 +--
src/dispnew.c | 2 +-
src/emacs-module.c | 2 +-
src/eval.c | 10 ++--
src/fns.c | 123 +++++++++------------------------------------
src/lisp.h | 43 +++++++++++++++-
src/textprop.c | 38 +++++++-------
src/window.c | 10 ++--
12 files changed, 116 insertions(+), 148 deletions(-)
diff --git a/lisp/subr.el b/lisp/subr.el
index 6b30371a86..2ffaa79762 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -680,6 +680,9 @@ assoc-default
(setq tail (cdr tail)))
value))
+(defalias 'memql 'memq)
+(defalias 'sxhash-eql 'sxhash-eq)
+
(defun member-ignore-case (elt list)
"Like `member', but ignore differences in case and text representation.
ELT must be a string. Upper-case and lower-case letters are treated as equal.
diff --git a/src/bytecode.c b/src/bytecode.c
index 772cc982f9..8e4eeddc89 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -518,7 +518,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
CASE (Beq):
{
Lisp_Object v1 = POP;
- TOP = EQ (v1, TOP) ? Qt : Qnil;
+ TOP = EQL (v1, TOP) ? Qt : Qnil;
NEXT;
}
@@ -1418,7 +1418,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
? make_number (h->test.hashfn (&h->test, v1)) : Qnil;
for (i = h->count; 0 <= --i; )
- if (EQ (v1, HASH_KEY (h, i))
+ if (EQL (v1, HASH_KEY (h, i))
|| (h->test.cmpfn
&& EQ (hash_code, HASH_HASH (h, i))
&& h->test.cmpfn (&h->test, v1, HASH_KEY (h, i))))
diff --git a/src/category.c b/src/category.c
index 62bb7f1a6c..c84b747c13 100644
--- a/src/category.c
+++ b/src/category.c
@@ -397,8 +397,8 @@ word_boundary_p (int c1, int c2)
Lisp_Object tail;
bool default_result;
- if (EQ (CHAR_TABLE_REF (Vchar_script_table, c1),
- CHAR_TABLE_REF (Vchar_script_table, c2)))
+ if (EQL (CHAR_TABLE_REF (Vchar_script_table, c1),
+ CHAR_TABLE_REF (Vchar_script_table, c2)))
{
tail = Vword_separating_categories;
default_result = 0;
diff --git a/src/chartab.c b/src/chartab.c
index 89983503ac..d169400cbd 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -283,7 +283,7 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to,
else if (NILP (this_val))
this_val = defalt;
- if (! EQ (this_val, val))
+ if (! EQL (this_val, val))
{
*from = c + 1;
break;
@@ -304,7 +304,7 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to,
is_uniprop);
else if (NILP (this_val))
this_val = defalt;
- if (! EQ (this_val, val))
+ if (! EQL (this_val, val))
{
*to = c - 1;
break;
@@ -356,7 +356,7 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to)
else if (NILP (this_val))
this_val = tbl->defalt;
- if (! EQ (this_val, val))
+ if (! EQL (this_val, val))
{
*from = c + 1;
break;
@@ -376,7 +376,7 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to)
tbl->defalt, is_uniprop);
else if (NILP (this_val))
this_val = tbl->defalt;
- if (! EQ (this_val, val))
+ if (! EQL (this_val, val))
{
*to = c - 1;
break;
@@ -684,7 +684,7 @@ optimize_sub_char_table (Lisp_Object table, Lisp_Object test)
}
if (optimizable
&& (NILP (test) ? NILP (Fequal (this, elt)) /* defaults to `equal'. */
- : EQ (test, Qeq) ? !EQ (this, elt) /* Optimize `eq' case. */
+ : EQ (test, Qeq) ? !EQL (this, elt) /* Optimize `eq' case. */
: NILP (call2 (test, this, elt))))
optimizable = 0;
}
@@ -791,7 +791,7 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object),
{
if (NILP (this))
this = XCHAR_TABLE (top)->defalt;
- if (!EQ (val, this))
+ if (!EQL (val, this))
{
bool different_value = 1;
@@ -811,7 +811,7 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object),
val = map_sub_char_table (c_function, function,
parent, arg, val, range,
parent);
- if (EQ (val, this))
+ if (EQL (val, this))
different_value = 0;
}
}
@@ -1223,7 +1223,7 @@ uniprop_encode_value_run_length (Lisp_Object table, Lisp_Object value)
int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]);
for (i = 0; i < size; i++)
- if (EQ (value, value_table[i]))
+ if (EQL (value, value_table[i]))
break;
if (i == size)
wrong_type_argument (build_string ("Unicode property value"), value);
@@ -1242,7 +1242,7 @@ uniprop_encode_value_numeric (Lisp_Object table, Lisp_Object value)
CHECK_NUMBER (value);
for (i = 0; i < size; i++)
- if (EQ (value, value_table[i]))
+ if (EQL (value, value_table[i]))
break;
value = make_number (i);
if (i == size)
diff --git a/src/data.c b/src/data.c
index c8beeda720..9777010e7f 100644
--- a/src/data.c
+++ b/src/data.c
@@ -186,7 +186,8 @@ DEFUN ("eq", Feq, Seq, 2, 2, 0,
attributes: const)
(Lisp_Object obj1, Lisp_Object obj2)
{
- if (EQ (obj1, obj2))
+ /* EQL not EQ, as Lisp eq is equivalent to Lisp eql. */
+ if (EQL (obj1, obj2))
return Qt;
return Qnil;
}
@@ -1316,7 +1317,7 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
{
case SYMBOL_NOWRITE:
if (NILP (Fkeywordp (symbol))
- || !EQ (newval, Fsymbol_value (symbol)))
+ || !EQL (newval, Fsymbol_value (symbol)))
xsignal1 (Qsetting_constant, symbol);
else
/* Allow setting keywords to their own value. */
@@ -1659,7 +1660,7 @@ set_default_internal (Lisp_Object symbol, Lisp_Object value,
{
case SYMBOL_NOWRITE:
if (NILP (Fkeywordp (symbol))
- || !EQ (value, Fsymbol_value (symbol)))
+ || !EQL (value, Fsymbol_value (symbol)))
xsignal1 (Qsetting_constant, symbol);
else
/* Allow setting keywords to their own value. */
diff --git a/src/dispnew.c b/src/dispnew.c
index fc6f9e2263..ae23c39e52 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -5896,7 +5896,7 @@ pass nil for VARIABLE. */)
goto changed;
if (idx == ASIZE (state))
goto changed;
- if (!EQ (AREF (state, idx++), BVAR (XBUFFER (buf), read_only)))
+ if (!EQL (AREF (state, idx++), BVAR (XBUFFER (buf), read_only)))
goto changed;
if (idx == ASIZE (state))
goto changed;
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 5b9f6629e7..8fae36ec4f 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -510,7 +510,7 @@ static bool
module_eq (emacs_env *env, emacs_value a, emacs_value b)
{
MODULE_FUNCTION_BEGIN_NO_CATCH (false);
- return EQ (value_to_lisp (a), value_to_lisp (b));
+ return EQL (value_to_lisp (a), value_to_lisp (b));
}
static intmax_t
diff --git a/src/eval.c b/src/eval.c
index 5964dd1867..7a6e9bea6c 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -628,8 +628,8 @@ The return value is BASE-VARIABLE. */)
set_internal (base_variable, find_symbol_value (new_alias),
Qnil, SET_INTERNAL_BIND);
else if (!NILP (Fboundp (new_alias))
- && !EQ (find_symbol_value (new_alias),
- find_symbol_value (base_variable)))
+ && !EQL (find_symbol_value (new_alias),
+ find_symbol_value (base_variable)))
call2 (intern ("display-warning"),
list3 (intern ("defvaralias"), intern ("losing-value"), new_alias),
CALLN (Fformat_message,
@@ -1067,7 +1067,7 @@ definitions to shadow the loaded ones for use in file byte-compilation. */)
}
{
Lisp_Object newform = apply1 (expander, XCDR (form));
- if (EQ (form, newform))
+ if (EQL (form, newform))
break;
else
form = newform;
@@ -1186,7 +1186,7 @@ Both TAG and VALUE are evalled. */
{
if (c->type == CATCHER_ALL)
unwind_to_catch (c, Fcons (tag, value));
- if (c->type == CATCHER && EQ (c->tag_or_ch, tag))
+ if (c->type == CATCHER && EQL (c->tag_or_ch, tag))
unwind_to_catch (c, value);
}
xsignal2 (Qno_catch, tag, value);
@@ -1532,7 +1532,7 @@ process_quit_flag (void)
Vquit_flag = Qnil;
if (EQ (flag, Qkill_emacs))
Fkill_emacs (Qnil);
- if (EQ (Vthrow_on_input, flag))
+ if (EQL (Vthrow_on_input, flag))
Fthrow (Vthrow_on_input, Qt);
quit ();
}
diff --git a/src/fns.c b/src/fns.c
index 5247140ead..9a5fbdcdd8 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1441,29 +1441,6 @@ DEFUN ("elt", Felt, Selt, 2, 2, 0,
return Faref (sequence, n);
}
-enum { WORDS_PER_DOUBLE = (sizeof (double) / sizeof (EMACS_UINT)
- + (sizeof (double) % sizeof (EMACS_UINT) != 0)) };
-union double_and_words
-{
- double val;
- EMACS_UINT word[WORDS_PER_DOUBLE];
-};
-
-/* Return true if X and Y are the same floating-point value.
- This looks at X's and Y's representation, since (unlike '==')
- it returns true if X and Y are the same NaN. */
-static bool
-same_float (Lisp_Object x, Lisp_Object y)
-{
- union double_and_words
- xu = { .val = XFLOAT_DATA (x) },
- yu = { .val = XFLOAT_DATA (y) };
- EMACS_UINT neql = 0;
- for (int i = 0; i < WORDS_PER_DOUBLE; i++)
- neql |= xu.word[i] ^ yu.word[i];
- return !neql;
-}
-
DEFUN ("member", Fmember, Smember, 2, 2, 0,
doc: /* Return non-nil if ELT is an element of LIST. Comparison done with `equal'.
The value is actually the tail of LIST whose car is ELT. */)
@@ -1484,31 +1461,12 @@ The value is actually the tail of LIST whose car is ELT. */)
{
Lisp_Object tail = list;
FOR_EACH_TAIL (tail)
- if (EQ (XCAR (tail), elt))
+ if (EQL (XCAR (tail), elt))
return tail;
CHECK_LIST_END (tail, list);
return Qnil;
}
-DEFUN ("memql", Fmemql, Smemql, 2, 2, 0,
- doc: /* Return non-nil if ELT is an element of LIST. Comparison done with `eql'.
-The value is actually the tail of LIST whose car is ELT. */)
- (Lisp_Object elt, Lisp_Object list)
-{
- if (!FLOATP (elt))
- return Fmemq (elt, list);
-
- Lisp_Object tail = list;
- FOR_EACH_TAIL (tail)
- {
- Lisp_Object tem = XCAR (tail);
- if (FLOATP (tem) && same_float (elt, tem))
- return tail;
- }
- CHECK_LIST_END (tail, list);
- return Qnil;
-}
-
DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
doc: /* Return non-nil if KEY is `eq' to the car of an element of LIST.
The value is actually the first element of LIST whose car is KEY.
@@ -1517,18 +1475,20 @@ Elements of LIST that are not conses are ignored. */)
{
Lisp_Object tail = list;
FOR_EACH_TAIL (tail)
- if (CONSP (XCAR (tail)) && EQ (XCAR (XCAR (tail)), key))
+ if (CONSP (XCAR (tail)) && EQL (XCAR (XCAR (tail)), key))
return XCAR (tail);
CHECK_LIST_END (tail, list);
return Qnil;
}
-/* Like Fassq but never report an error and do not allow quits.
- Use only on objects known to be non-circular lists. */
+/* Like Fassq but never report an error and do not allow quits and use
+ EQ not EQL. Use only on objects known to be non-circular lists,
+ and where KEY is not a float. */
Lisp_Object
assq_no_quit (Lisp_Object key, Lisp_Object list)
{
+ eassert (!FLOATP (key));
for (; ! NILP (list); list = XCDR (list))
if (CONSP (XCAR (list)) && EQ (XCAR (XCAR (list)), key))
return XCAR (list);
@@ -1581,7 +1541,7 @@ The value is actually the first element of LIST whose cdr is KEY. */)
{
Lisp_Object tail = list;
FOR_EACH_TAIL (tail)
- if (CONSP (XCAR (tail)) && EQ (XCDR (XCAR (tail)), key))
+ if (CONSP (XCAR (tail)) && EQL (XCDR (XCAR (tail)), key))
return XCAR (tail);
CHECK_LIST_END (tail, list);
return Qnil;
@@ -1621,7 +1581,7 @@ argument. */)
FOR_EACH_TAIL (tail)
{
Lisp_Object tem = XCAR (tail);
- if (EQ (elt, tem))
+ if (EQL (elt, tem))
{
if (NILP (prev))
list = XCDR (tail);
@@ -2084,7 +2044,7 @@ properties on the list. This function never signals an error. */)
{
if (! CONSP (XCDR (tail)))
break;
- if (EQ (prop, XCAR (tail)))
+ if (EQL (prop, XCAR (tail)))
return XCAR (XCDR (tail));
tail = XCDR (tail);
if (EQ (tail, li.tortoise))
@@ -2123,7 +2083,7 @@ The PLIST is modified by side effects. */)
if (! CONSP (XCDR (tail)))
break;
- if (EQ (prop, XCAR (tail)))
+ if (EQL (prop, XCAR (tail)))
{
Fsetcar (XCDR (tail), val);
return plist;
@@ -2221,10 +2181,7 @@ 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))
- return FLOATP (obj2) && same_float (obj1, obj2) ? Qt : Qnil;
- else
- return EQ (obj1, obj2) ? Qt : Qnil;
+ return EQL (obj1, obj2) ? Qt : Qnil;
}
DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
@@ -2959,7 +2916,7 @@ The value is actually the tail of PLIST whose car is PROP. */)
Lisp_Object tail = plist;
FOR_EACH_TAIL (tail)
{
- if (EQ (XCAR (tail), prop))
+ if (EQL (XCAR (tail), prop))
return tail;
tail = XCDR (tail);
if (! CONSP (tail))
@@ -3747,18 +3704,6 @@ HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx)
return XINT (AREF (h->index, idx));
}
-/* 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);
-}
-
-
/* Compare KEY1 and KEY2 in hash table HT using `equal'. Value is
true if KEY1 and KEY2 are the same. */
@@ -3770,7 +3715,6 @@ cmpfn_equal (struct hash_table_test *ht,
return !NILP (Fequal (key1, key2));
}
-
/* Compare KEY1 and KEY2 in hash table HT using HT->user_cmp_function.
Value is true if KEY1 and KEY2 are the same. */
@@ -3782,16 +3726,6 @@ cmpfn_user_defined (struct hash_table_test *ht,
return !NILP (call2 (ht->user_cmp_function, key1, key2));
}
-/* Value is a hash code for KEY for use in hash table H which uses
- `eq' to compare keys. The hash code returned is guaranteed to fit
- in a Lisp integer. */
-
-static EMACS_UINT
-hashfn_eq (struct hash_table_test *ht, Lisp_Object key)
-{
- return XHASH (key) ^ XTYPE (key);
-}
-
/* Value is a hash code for KEY for use in hash table H which uses
`equal' to compare keys. The hash code returned is guaranteed to fit
in a Lisp integer. */
@@ -3809,7 +3743,7 @@ hashfn_equal (struct hash_table_test *ht, Lisp_Object key)
static EMACS_UINT
hashfn_eql (struct hash_table_test *ht, Lisp_Object key)
{
- return FLOATP (key) ? hashfn_equal (ht, key) : hashfn_eq (ht, key);
+ return FLOATP (key) ? hashfn_equal (ht, key) : XHASH (key) ^ XTYPE (key);
}
/* Value is a hash code for KEY for use in hash table H which uses as
@@ -3820,14 +3754,14 @@ static EMACS_UINT
hashfn_user_defined (struct hash_table_test *ht, Lisp_Object key)
{
Lisp_Object hash = call1 (ht->user_hash_function, key);
- return hashfn_eq (ht, hash);
+ return hashfn_eql (ht, hash);
}
struct hash_table_test const
hashtest_eq = { LISPSYM_INITIALLY (Qeq), LISPSYM_INITIALLY (Qnil),
- LISPSYM_INITIALLY (Qnil), 0, hashfn_eq },
+ LISPSYM_INITIALLY (Qnil), 0, hashfn_eql },
hashtest_eql = { LISPSYM_INITIALLY (Qeql), LISPSYM_INITIALLY (Qnil),
- LISPSYM_INITIALLY (Qnil), cmpfn_eql, hashfn_eql },
+ LISPSYM_INITIALLY (Qnil), 0, hashfn_eql },
hashtest_equal = { LISPSYM_INITIALLY (Qequal), LISPSYM_INITIALLY (Qnil),
LISPSYM_INITIALLY (Qnil), cmpfn_equal, hashfn_equal };
@@ -4063,7 +3997,7 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash)
start_of_bucket = hash_code % ASIZE (h->index);
for (i = HASH_INDEX (h, start_of_bucket); 0 <= i; i = HASH_NEXT (h, i))
- if (EQ (key, HASH_KEY (h, i))
+ if (EQL (key, HASH_KEY (h, i))
|| (h->test.cmpfn
&& hash_code == XUINT (HASH_HASH (h, i))
&& h->test.cmpfn (&h->test, key, HASH_KEY (h, i))))
@@ -4120,7 +4054,7 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key)
0 <= i;
i = HASH_NEXT (h, i))
{
- if (EQ (key, HASH_KEY (h, i))
+ if (EQL (key, HASH_KEY (h, i))
|| (h->test.cmpfn
&& hash_code == XUINT (HASH_HASH (h, i))
&& h->test.cmpfn (&h->test, key, HASH_KEY (h, i))))
@@ -4360,9 +4294,10 @@ sxhash_string (char const *ptr, ptrdiff_t len)
/* Return a hash for the floating point value VAL. */
-static EMACS_UINT
-sxhash_float (double val)
+EMACS_UINT
+sxhash_float (Lisp_Object obj)
{
+ double val = XFLOAT_DATA (obj);
EMACS_UINT hash = 0;
union double_and_words u = { .val = val };
for (int i = 0; i < WORDS_PER_DOUBLE; i++)
@@ -4481,7 +4416,7 @@ sxhash (Lisp_Object obj, int depth)
break;
case Lisp_Float:
- hash = sxhash_float (XFLOAT_DATA (obj));
+ hash = sxhash_float (obj);
break;
default:
@@ -4501,14 +4436,6 @@ DEFUN ("sxhash-eq", Fsxhash_eq, Ssxhash_eq, 1, 1, 0,
doc: /* Return an integer hash code for OBJ suitable for `eq'.
If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)). */)
(Lisp_Object obj)
-{
- return make_number (hashfn_eq (NULL, obj));
-}
-
-DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0,
- doc: /* Return an integer hash code for OBJ suitable for `eql'.
-If (eql A B), then (= (sxhash-eql A) (sxhash-eql B)). */)
- (Lisp_Object obj)
{
return make_number (hashfn_eql (NULL, obj));
}
@@ -4574,9 +4501,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
/* See if there's a `:test TEST' among the arguments. */
i = get_key_arg (QCtest, nargs, args, used);
test = i ? args[i] : Qeql;
- if (EQ (test, Qeq))
- testdesc = hashtest_eq;
- else if (EQ (test, Qeql))
+ if (EQ (test, Qeq) || EQ (test, Qeql))
testdesc = hashtest_eql;
else if (EQ (test, Qequal))
testdesc = hashtest_equal;
@@ -5226,7 +5151,6 @@ syms_of_fns (void)
DEFSYM (Qkey_and_value, "key-and-value");
defsubr (&Ssxhash_eq);
- defsubr (&Ssxhash_eql);
defsubr (&Ssxhash_equal);
defsubr (&Smake_hash_table);
defsubr (&Scopy_hash_table);
@@ -5344,7 +5268,6 @@ this variable. */);
defsubr (&Selt);
defsubr (&Smember);
defsubr (&Smemq);
- defsubr (&Smemql);
defsubr (&Sassq);
defsubr (&Sassoc);
defsubr (&Srassq);
diff --git a/src/lisp.h b/src/lisp.h
index 96de60e467..62996b7ee5 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -377,7 +377,7 @@ typedef EMACS_INT Lisp_Word;
#define lisp_h_XCDR(c) XCONS (c)->u.s.u.cdr
#define lisp_h_XCONS(a) \
(eassert (CONSP (a)), XUNTAG (a, Lisp_Cons, struct Lisp_Cons))
-#define lisp_h_XHASH(a) XUINT (a)
+#define lisp_h_XHASH(a) (FLOATP (a) ? sxhash_float (a) : XUINT (a))
#ifndef GC_CHECK_CONS_LIST
# define lisp_h_check_cons_list() ((void) 0)
#endif
@@ -615,6 +615,8 @@ enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false };
/* Forward declarations. */
/* Defined in this file. */
+INLINE bool FLOATP (Lisp_Object);
+INLINE double XFLOAT_DATA (Lisp_Object);
INLINE void set_sub_char_table_contents (Lisp_Object, ptrdiff_t,
Lisp_Object);
@@ -625,6 +627,8 @@ extern void char_table_set (Lisp_Object, int, Lisp_Object);
/* Defined in data.c. */
extern _Noreturn void wrong_type_argument (Lisp_Object, Lisp_Object);
+/* Defined in fns.c. */
+EMACS_UINT sxhash_float (Lisp_Object);
#ifdef CANNOT_DUMP
enum { might_dump = false };
@@ -1125,7 +1129,13 @@ make_natnum (EMACS_INT n)
return USE_LSB_TAG ? make_number (n) : XIL (n + (int0 << VALBITS));
}
-/* Return true if X and Y are the same object. */
+/* Return true if X and Y are the same object. Unlike EQL, this
+ distinguishes floats with the same values but different addresses.
+ The C name EQ is a misnomer, and dates back to when Lisp eq behaved
+ like C EQ does now. Nowadays Lisp eq is equivalent to the Lisp eql
+ and the C EQL. C EQ is meant for low-level C code, e.g., for
+ efficiency in places where at least one argument is a
+ non-float. */
INLINE bool
(EQ) (Lisp_Object x, Lisp_Object y)
@@ -1133,6 +1143,35 @@ INLINE bool
return lisp_h_EQ (x, y);
}
+enum { WORDS_PER_DOUBLE = (sizeof (double) / sizeof (EMACS_UINT)
+ + (sizeof (double) % sizeof (EMACS_UINT) != 0)) };
+union double_and_words
+{
+ double val;
+ EMACS_UINT word[WORDS_PER_DOUBLE];
+};
+
+/* Return true if X and Y are the same floating-point value.
+ This looks at X's and Y's representation, since (unlike '==')
+ it returns true if X and Y are the same NaN. */
+INLINE bool
+same_float (Lisp_Object x, Lisp_Object y)
+{
+ union double_and_words
+ xu = { .val = XFLOAT_DATA (x) },
+ yu = { .val = XFLOAT_DATA (y) };
+ EMACS_UINT neql = 0;
+ for (int i = 0; i < WORDS_PER_DOUBLE; i++)
+ neql |= xu.word[i] ^ yu.word[i];
+ return !neql;
+}
+
+INLINE bool
+EQL (Lisp_Object x, Lisp_Object y)
+{
+ return FLOATP (x) ? FLOATP (y) && same_float (x, y) : EQ (x, y);
+}
+
/* True if the possibly-unsigned integer I doesn't fit in a Lisp fixnum. */
#define FIXNUM_OVERFLOW_P(i) \
diff --git a/src/textprop.c b/src/textprop.c
index fe5b61e2dd..8ff2d625cc 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -237,11 +237,11 @@ interval_has_all_properties (Lisp_Object plist, INTERVAL i)
/* Go through I's plist, looking for sym1 */
for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
- if (EQ (sym1, XCAR (tail2)))
+ if (EQL (sym1, XCAR (tail2)))
{
/* Found the same property on both lists. If the
values are unequal, return false. */
- if (! EQ (Fcar (XCDR (tail1)), Fcar (XCDR (tail2))))
+ if (! EQL (Fcar (XCDR (tail1)), Fcar (XCDR (tail2))))
return false;
/* Property has same value on both lists; go to next one. */
@@ -271,7 +271,7 @@ interval_has_some_properties (Lisp_Object plist, INTERVAL i)
/* Go through i's plist, looking for tail1 */
for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
- if (EQ (sym, XCAR (tail2)))
+ if (EQL (sym, XCAR (tail2)))
return true;
}
@@ -293,7 +293,7 @@ interval_has_some_properties_list (Lisp_Object list, INTERVAL i)
/* Go through i's plist, looking for tail1 */
for (tail2 = i->plist; CONSP (tail2); tail2 = XCDR (XCDR (tail2)))
- if (EQ (sym, XCAR (tail2)))
+ if (EQL (sym, XCAR (tail2)))
return true;
}
@@ -310,7 +310,7 @@ property_value (Lisp_Object plist, Lisp_Object prop)
Lisp_Object value;
while (PLIST_ELT_P (plist, value))
- if (EQ (XCAR (plist), prop))
+ if (EQL (XCAR (plist), prop))
return XCAR (value);
else
plist = XCDR (value);
@@ -334,8 +334,8 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object)
for (sym = interval->plist;
PLIST_ELT_P (sym, value);
sym = XCDR (value))
- if (! EQ (property_value (properties, XCAR (sym)),
- XCAR (value)))
+ if (! EQL (property_value (properties, XCAR (sym)),
+ XCAR (value)))
{
record_property_change (interval->position, LENGTH (interval),
XCAR (sym), XCAR (value),
@@ -388,7 +388,7 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object,
/* Go through I's plist, looking for sym1 */
for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
- if (EQ (sym1, XCAR (tail2)))
+ if (EQL (sym1, XCAR (tail2)))
{
Lisp_Object this_cdr;
@@ -398,7 +398,7 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object,
/* The properties have the same value on both lists.
Continue to the next property. */
- if (EQ (val1, Fcar (this_cdr)))
+ if (EQL (val1, Fcar (this_cdr)))
break;
/* Record this change in the buffer, for undo purposes. */
@@ -473,7 +473,7 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object
Lisp_Object sym = XCAR (tail1);
/* First, remove the symbol if it's at the head of the list */
- while (CONSP (current_plist) && EQ (sym, XCAR (current_plist)))
+ while (CONSP (current_plist) && EQL (sym, XCAR (current_plist)))
{
if (BUFFERP (object))
record_property_change (i->position, LENGTH (i),
@@ -489,7 +489,7 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object
while (! NILP (tail2))
{
Lisp_Object this = XCDR (XCDR (tail2));
- if (CONSP (this) && EQ (sym, XCAR (this)))
+ if (CONSP (this) && EQL (sym, XCAR (this)))
{
if (BUFFERP (object))
record_property_change (i->position, LENGTH (i),
@@ -822,7 +822,7 @@ last valid position in OBJECT. */)
}
value = Fget_char_property (position, prop, object);
- if (!EQ (value, initial_value))
+ if (!EQL (value, initial_value))
break;
}
@@ -914,7 +914,7 @@ first valid position in OBJECT. */)
= Fget_char_property (make_number (XFASTINT (position) - 1),
prop, object);
- if (!EQ (value, initial_value))
+ if (!EQL (value, initial_value))
break;
}
}
@@ -1024,7 +1024,7 @@ past position LIMIT; return LIMIT if nothing is found before LIMIT. */)
here_val = textget (i->plist, prop);
next = next_interval (i);
while (next
- && EQ (here_val, textget (next->plist, prop))
+ && EQL (here_val, textget (next->plist, prop))
&& (NILP (limit) || next->position < XFASTINT (limit)))
next = next_interval (next);
@@ -1126,7 +1126,7 @@ back past position LIMIT; return LIMIT if nothing is found until LIMIT. */)
here_val = textget (i->plist, prop);
previous = previous_interval (i);
while (previous
- && EQ (here_val, textget (previous->plist, prop))
+ && EQL (here_val, textget (previous->plist, prop))
&& (NILP (limit)
|| (previous->position + LENGTH (previous) > XFASTINT (limit))))
previous = previous_interval (previous);
@@ -1752,7 +1752,7 @@ markers). If OBJECT is a string, START and END are 0-based indices into it. */
{
if (i->position >= e)
break;
- if (EQ (textget (i->plist, property), value))
+ if (EQL (textget (i->plist, property), value))
{
pos = i->position;
if (pos < XINT (start))
@@ -1789,7 +1789,7 @@ markers). If OBJECT is a string, START and END are 0-based indices into it. */
{
if (i->position >= e)
break;
- if (! EQ (textget (i->plist, property), value))
+ if (! EQL (textget (i->plist, property), value))
{
if (i->position > s)
s = i->position;
@@ -1922,7 +1922,7 @@ copy_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object src,
if (! NILP (prop))
while (! NILP (plist))
{
- if (EQ (Fcar (plist), prop))
+ if (EQL (Fcar (plist), prop))
{
plist = list2 (prop, Fcar (Fcdr (plist)));
break;
@@ -1992,7 +1992,7 @@ text_property_list (Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp
if (!NILP (prop))
for (; CONSP (plist); plist = Fcdr (XCDR (plist)))
- if (EQ (XCAR (plist), prop))
+ if (EQL (XCAR (plist), prop))
{
plist = list2 (prop, Fcar (XCDR (plist)));
break;
diff --git a/src/window.c b/src/window.c
index 422b06a49f..a220e61af8 100644
--- a/src/window.c
+++ b/src/window.c
@@ -4888,13 +4888,14 @@ window_wants_mode_line (struct window *w)
{
Lisp_Object window_mode_line_format =
window_parameter (w, Qmode_line_format);
+ Lisp_Object buf = WINDOW_BUFFER (w);
- return ((WINDOW_LEAF_P (w)
+ return ((!NILP (buf)
&& !MINI_WINDOW_P (w)
&& !WINDOW_PSEUDO_P (w)
&& !EQ (window_mode_line_format, Qnone)
&& (!NILP (window_mode_line_format)
- || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), mode_line_format)))
+ || !NILP (BVAR (XBUFFER (buf), mode_line_format)))
&& WINDOW_PIXEL_HEIGHT (w) > WINDOW_FRAME_LINE_HEIGHT (w))
? 1
: 0);
@@ -4919,13 +4920,14 @@ window_wants_header_line (struct window *w)
{
Lisp_Object window_header_line_format =
window_parameter (w, Qheader_line_format);
+ Lisp_Object buf = WINDOW_BUFFER (w);
- return ((WINDOW_LEAF_P (w)
+ return ((!NILP (buf)
&& !MINI_WINDOW_P (w)
&& !WINDOW_PSEUDO_P (w)
&& !EQ (window_header_line_format, Qnone)
&& (!NILP (window_header_line_format)
- || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
+ || !NILP (BVAR (XBUFFER (buf), header_line_format)))
&& (WINDOW_PIXEL_HEIGHT (w)
> (window_wants_mode_line (w)
? 2 * WINDOW_FRAME_LINE_HEIGHT (w)
--
2.17.1
^ permalink raw reply related [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-27 21:14 ` Making 'eq' == 'eql' in bignum branch Paul Eggert
@ 2018-07-28 14:26 ` Stefan Monnier
2018-07-29 3:34 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-07-28 14:26 UTC (permalink / raw)
To: emacs-devel
> suffers only a 2.3% slowdown, better than the 4% slowdown Stefan mentioned
> with his simpler patch.
I'm afraid you might be comparing apples and pears, since the relative
cost may vary substantially depending on the CPU's architecture.
Have you tried to measure the slowdown of my patch on your machine?
> Stefan, have you thought about hashing floating-point objects instead, so
> that comparing pointers suffices for eql, and eq becomes equivalent to eql
> in a different way?
No I have not considered this trade-off carefully. It's true that
floats aren't used very often, but it would make floats enormously more
expensive both in CPU and memory resources. Currently, they cost
8 bytes of allocated heap, and currently our hash-tables cost about
6 words per entry (i.e. 48 bytes per entry on 64bit systems).
Clearly we could cut that down for hash-consing uses (where key==value),
but it's still pretty bad.
> I still see a problem there in your simpler patch, since cmpfn_eql isn't
> used in the eq case, when hashing floating-point values.
Good spotting, thanks.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-28 14:26 ` Stefan Monnier
@ 2018-07-29 3:34 ` Paul Eggert
2018-07-29 4:09 ` Stefan Monnier
` (2 more replies)
0 siblings, 3 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-29 3:34 UTC (permalink / raw)
To: Stefan Monnier, emacs-devel
Stefan Monnier wrote:
> I'm afraid you might be comparing apples and pears, since the relative
> cost may vary substantially depending on the CPU's architecture.
> Have you tried to measure the slowdown of my patch on your machine?
It's definitely apples-to-pears, as your patch hashes incorrectly and that might
be a performance advantage.
For what it's worth I tried to do the measurement again, and this time got
different numbers. Again, this is Fedora 28 x86-64, AMD Phenom II X4 910e,
user+system time, average of 3 runs for "cd lisp; time make compile-always",
otherwise-idle system. However, this time I started with master commit
db80851a1f10d73f0b2c12299c3d77716bb8425a, and I did 4 runs and ignored the first
one to avoid any startup overheads involved. This time I got: master 460.587 s,
my patch 465.373 s (1% slower than master), your patch 469.619 s (2% slower than
master).
>> have you thought about hashing floating-point objects instead, so
>> that comparing pointers suffices for eql, and eq becomes equivalent to eql
>> in a different way?
>
> No I have not considered this trade-off carefully. It's true that
> floats aren't used very often, but it would make floats enormously more
> expensive both in CPU and memory resources. Currently, they cost
> 8 bytes of allocated heap, and currently our hash-tables cost about
> 6 words per entry (i.e. 48 bytes per entry on 64bit systems).
> Clearly we could cut that down for hash-consing uses (where key==value),
> but it's still pretty bad.
How about if we do to floats what fixnum+bignum would do to integers?
That is, on a 64-bit host, if the low-order 4 bits of the significand are all
zero, we encode the floating-point number directly in the Lisp_Object (with a
tag) so that the Lisp_Object need not be dereferenced and uses zero bytes of
floating-point heap. Otherwise, we put the floating-point value into a special
hash-consed table that should use about 16 bytes per entry (one for the double,
one for the pointer to it). I just checked 'make compile-always' and under this
proposal a full run would create 95694 Lisp floats of which 80048 (84%) would
use zero bytes and 15646 (16%) would use 16 bytes of floating-point heap. This
would mean a total floating-point heap usage of 15646*16 = 250 kB, as opposed to
current master which uses 95694*8 == 766 kB, i.e., we'd shrink floating-point
heap usage by about a factor of 3.
The tradeoff would be different on a 32-bit platform, since in the above
discussion we would replace '4 bits' with '36 bits', '15620 (16%)' with '16083
(17%)', and '16 bytes per entry' with '12 bytes per entry'. But it'd be an
even-bigger space win, as the total heap usage of 16083*12 = 193 kB of heap
would be even smaller than the 64-bit total, i.e., we'd shrink floating-point
heap usage by about a factor of 4.
We could of course use even less storage simply by lowering the precision of
Emacs Lisp floating-point, although that'd be a user-visible change, would be a
fairly drastic thing to do on 32-bit platforms, and wouldn't really address the
bignum eql issue. (Though it might be interesting to try anyway....)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-29 3:34 ` Paul Eggert
@ 2018-07-29 4:09 ` Stefan Monnier
2018-07-29 14:35 ` Eli Zaretskii
2018-08-20 0:04 ` Stefan Monnier
2 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-07-29 4:09 UTC (permalink / raw)
To: emacs-devel
> That is, on a 64-bit host, if the low-order 4 bits of the significand are
> all zero, we encode the floating-point number directly in the Lisp_Object
> (with a tag) so that the Lisp_Object need not be dereferenced and uses zero
> bytes of floating-point heap.
Sounds like an interesting optimization, yes.
> into a special hash-consed table that should use about 16 bytes per entry
> (one for the double, one for the pointer to it).
I assume by "one for the pointer to it" you meant "one for the pointer
to the next member of the same bucket".
> I just checked 'make
> compile-always' and under this proposal a full run would create 95694 Lisp
> floats of which 80048 (84%) would use zero bytes and 15646 (16%) would use
> 16 bytes of floating-point heap.
I'm not sure this is very relevant: for "make compile-always" the
resource cost of floats is irrelevant anyway (as evidenced by the fact
that only 95694 of them are created).
Similarly for bignums: if we only use them to slightly extend the reach
of integers past the 2^29 or 2^63 limit, then it's OK to hash-cons them,
but if/when someone comes around and uses them for computing with large
numbers he might be disappointed at the resulting performance.
Tho maybe it's not that bad: contrarily to operations of floats (which
are basically super-fast on nowadays CPUs) given the non-linear
algorithmic cost of many bignum operations, adding hash-consing to them
wouldn't slow them down that much
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-29 3:34 ` Paul Eggert
2018-07-29 4:09 ` Stefan Monnier
@ 2018-07-29 14:35 ` Eli Zaretskii
2018-07-30 17:07 ` Stefan Monnier
2018-08-20 0:04 ` Stefan Monnier
2 siblings, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-07-29 14:35 UTC (permalink / raw)
To: Paul Eggert; +Cc: monnier, emacs-devel
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sat, 28 Jul 2018 20:34:32 -0700
>
> How about if we do to floats what fixnum+bignum would do to integers?
>
> That is, on a 64-bit host, if the low-order 4 bits of the significand are all
> zero, we encode the floating-point number directly in the Lisp_Object (with a
> tag) so that the Lisp_Object need not be dereferenced and uses zero bytes of
> floating-point heap. Otherwise, we put the floating-point value into a special
> hash-consed table that should use about 16 bytes per entry (one for the double,
> one for the pointer to it).
How likely is it to see a floating-point number with 4 low-order bits
of mantissa zero?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-29 14:35 ` Eli Zaretskii
@ 2018-07-30 17:07 ` Stefan Monnier
2018-07-30 18:49 ` Eli Zaretskii
0 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-07-30 17:07 UTC (permalink / raw)
To: emacs-devel
> How likely is it to see a floating-point number with 4 low-order bits
> of mantissa zero?
For floating point values read from Elisp source code, the probability
is not bad at all. OTOH for code performing any non-trivial
calculation, of course, the probably should hover around 1/2^4, so
pretty low.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-30 17:07 ` Stefan Monnier
@ 2018-07-30 18:49 ` Eli Zaretskii
2018-07-30 20:10 ` Stefan Monnier
2018-07-30 21:58 ` Paul Eggert
0 siblings, 2 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-07-30 18:49 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Mon, 30 Jul 2018 13:07:35 -0400
>
> > How likely is it to see a floating-point number with 4 low-order bits
> > of mantissa zero?
>
> For floating point values read from Elisp source code, the probability
> is not bad at all. OTOH for code performing any non-trivial
> calculation, of course, the probably should hover around 1/2^4, so
> pretty low.
That's what I thought. So given this, aren't we optimizing a rare
situation, and OTOH making the code more complex and perhaps less
efficient for the majority of use cases?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-30 18:49 ` Eli Zaretskii
@ 2018-07-30 20:10 ` Stefan Monnier
2018-07-30 21:58 ` Paul Eggert
1 sibling, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-07-30 20:10 UTC (permalink / raw)
To: emacs-devel
> That's what I thought. So given this, aren't we optimizing a rare
> situation, and OTOH making the code more complex and perhaps less
> efficient for the majority of use cases?
I think we would be, yes (but I don't know if Paul really intended to
implement this suggestion).
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-30 18:49 ` Eli Zaretskii
2018-07-30 20:10 ` Stefan Monnier
@ 2018-07-30 21:58 ` Paul Eggert
2018-07-31 2:38 ` Eli Zaretskii
[not found] ` <<83d0v4p1si.fsf@gnu.org>
1 sibling, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-30 21:58 UTC (permalink / raw)
To: Eli Zaretskii, Stefan Monnier; +Cc: emacs-devel
Eli Zaretskii wrote:
> aren't we optimizing a rare situation,
Not at all. In practice, floating point computations favor values like 0.0 and
100.0 where the bottom 3 bits of the representation are zero. True, computations
involving random floating-point numbers will get such values only 1/8 of the
time; but Emacs computations are not typically random.
Any changes in this area should be aimed at typical Emacs usage. If we can get a
performance win when Emacs compiles itself, that'd be a good sign, though of
course not conclusive.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-30 21:58 ` Paul Eggert
@ 2018-07-31 2:38 ` Eli Zaretskii
2018-07-31 7:10 ` Paul Eggert
[not found] ` <<83d0v4p1si.fsf@gnu.org>
1 sibling, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-07-31 2:38 UTC (permalink / raw)
To: Paul Eggert; +Cc: monnier, emacs-devel
> Cc: emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Mon, 30 Jul 2018 14:58:15 -0700
>
> Not at all. In practice, floating point computations favor values like 0.0 and
> 100.0 where the bottom 3 bits of the representation are zero. True, computations
> involving random floating-point numbers will get such values only 1/8 of the
> time; but Emacs computations are not typically random.
>
> Any changes in this area should be aimed at typical Emacs usage. If we can get a
> performance win when Emacs compiles itself, that'd be a good sign, though of
> course not conclusive.
Emacs compiling itself is not a typical use of floats in Emacs, IMO.
It's a very specialized use case, which is very rare in normal usage
of Emacs. I typically build a production release of Emacs just once,
and then use it for many moons.
If we want to claim that typical usage of floats in Emacs favors
round values, we need to back that up by some data.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-31 2:38 ` Eli Zaretskii
@ 2018-07-31 7:10 ` Paul Eggert
2018-07-31 16:12 ` Eli Zaretskii
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-07-31 7:10 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
Eli Zaretskii wrote:
> Emacs compiling itself is not a typical use of floats in Emacs, IMO.
What would be a typical use, then? It'd be hard to evaluate alternatives without
any benchmarks at all, and in the meantime 'make compile-always', despite its
flaws, seems to be the best one we have. (It's certainly something I'd like to
go faster....)
^ permalink raw reply [flat|nested] 281+ messages in thread
* RE: Making 'eq' == 'eql' in bignum branch
[not found] ` <<83d0v4p1si.fsf@gnu.org>
@ 2018-07-31 15:08 ` Drew Adams
2018-07-31 16:24 ` Eli Zaretskii
2018-07-31 22:21 ` Paul Eggert
0 siblings, 2 replies; 281+ messages in thread
From: Drew Adams @ 2018-07-31 15:08 UTC (permalink / raw)
To: Eli Zaretskii, Paul Eggert; +Cc: monnier, emacs-devel
> If we want to claim that typical usage of floats in Emacs favors
> round values, we need to back that up by some data.
+1. I almost wrote something similar. A guess might be that many uses of floats in Emacs come from computations with floats, not from literal numerals. E.g., measurements/calculations involving window pixel sizes and such.
What indications are there that many uses of floats involve round numbers? I guess conversion of integers would be the main source. But do we have any quantitative info regarding relative frequency?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-31 7:10 ` Paul Eggert
@ 2018-07-31 16:12 ` Eli Zaretskii
2018-07-31 22:44 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-07-31 16:12 UTC (permalink / raw)
To: Paul Eggert; +Cc: monnier, emacs-devel
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Tue, 31 Jul 2018 00:10:35 -0700
>
> Eli Zaretskii wrote:
> > Emacs compiling itself is not a typical use of floats in Emacs, IMO.
>
> What would be a typical use, then? It'd be hard to evaluate alternatives without
> any benchmarks at all
I take it we agree that if someone writes a Lisp program which does FP
calculations, their chance of having a lot of such values would be
quite low, yes? So we should put such use cases aside.
One way of estimating what happens in the majority of uses is to find
Emacs APIs other than numerical calculations that can return floats,
and try to analyze what kind of floats will be the result. Like
file-system-info and file-attributes, for example.
> and in the meantime 'make compile-always', despite its flaws, seems
> to be the best one we have. (It's certainly something I'd like to go
> faster....)
How faster, in absolute numbers and in percents, will your build
finish with the proposed changes?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-31 15:08 ` Drew Adams
@ 2018-07-31 16:24 ` Eli Zaretskii
2018-07-31 22:21 ` Paul Eggert
1 sibling, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-07-31 16:24 UTC (permalink / raw)
To: Drew Adams; +Cc: eggert, monnier, emacs-devel
> Date: Tue, 31 Jul 2018 08:08:20 -0700 (PDT)
> From: Drew Adams <drew.adams@oracle.com>
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
>
> What indications are there that many uses of floats involve round numbers?
I think that's because most float values we have in our sources are
round (in their binary representation). Values like 1.0 and 0.5, for
example (but not 0.1).
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-31 15:08 ` Drew Adams
2018-07-31 16:24 ` Eli Zaretskii
@ 2018-07-31 22:21 ` Paul Eggert
1 sibling, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-31 22:21 UTC (permalink / raw)
To: Drew Adams, Eli Zaretskii; +Cc: monnier, emacs-devel
On 07/31/2018 08:08 AM, Drew Adams wrote:
> What indications are there that many uses of floats involve round numbers? I guess conversion of integers would be the main source. But do we have any quantitative info regarding relative frequency?
In the 'make compile-always' benchmark where Emacs compiles all its own
.el files, 85% of the floating-point objects that Emacs creates have the
low-order three bits zero. Of course this percentage is
benchmark-specific; still, for this benchmark most of Emacs's floating
point numbers come from things like hash-table parameters and suchlike;
that is, even though they may not be integers they are "round numbers"
in the sense that you mention.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-31 16:12 ` Eli Zaretskii
@ 2018-07-31 22:44 ` Paul Eggert
2018-08-01 5:51 ` Eli Zaretskii
2018-08-10 7:05 ` Elias Mårtenson
0 siblings, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-07-31 22:44 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
On 07/31/2018 09:12 AM, Eli Zaretskii wrote:
> I take it we agree that if someone writes a Lisp program which does FP
> calculations, their chance of having a lot of such values would be
> quite low, yes? So we should put such use cases aside.
Nobody should want to write such a program since Emacs is not intended
for and does not perform well with heavy-duty FP calculations. So I
agree that we shouldn't worry about such programs; we should focus on
"real-world Emacs", so to speak.
> One way of estimating what happens in the majority of uses is to find
> Emacs APIs other than numerical calculations that can return floats,
> and try to analyze what kind of floats will be the result. Like
> file-system-info and file-attributes, for example.
These should be fine on a 64-bit platform. file-system-info invariably
yields floating-point numbers with the bottom three bits zero, due to
how modern file systems are built (their sizes are multiples of powers
of two). file-attributes returns an exact value unless your file is
larger than 2**61 bytes (2 EiB), and once we get to the rare files
larger than that we should be using bignums anyway. (The same could be
said for file-system-info, of course.)
> How faster, in absolute numbers and in percents, will your build
> finish with the proposed changes?
I won't know unless I take the time to code it up.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-31 22:44 ` Paul Eggert
@ 2018-08-01 5:51 ` Eli Zaretskii
2018-08-01 6:43 ` Paul Eggert
2018-08-10 7:05 ` Elias Mårtenson
1 sibling, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-01 5:51 UTC (permalink / raw)
To: Paul Eggert; +Cc: monnier, emacs-devel
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Tue, 31 Jul 2018 15:44:24 -0700
>
> > One way of estimating what happens in the majority of uses is to find
> > Emacs APIs other than numerical calculations that can return floats,
> > and try to analyze what kind of floats will be the result. Like
> > file-system-info and file-attributes, for example.
>
> These should be fine on a 64-bit platform. file-system-info invariably
> yields floating-point numbers with the bottom three bits zero, due to
> how modern file systems are built (their sizes are multiples of powers
> of two). file-attributes returns an exact value unless your file is
> larger than 2**61 bytes (2 EiB), and once we get to the rare files
> larger than that we should be using bignums anyway. (The same could be
> said for file-system-info, of course.)
OK, but those were just examples, I didn't do an exhaustive search for
such APIs. Are there any others?
Then there are FP calculations in Lisp, e.g. in line-move-partial.
This gets executed many times in any Emacs, and I presume the values
there can be any FP number, so it's more akin to the use case of FP
programs we agreed not to consider. Searching for 'float', 'round',
and 'floor' through the lisp/ directory brings more than 2000 hits,
quite a few in Calc, but many unrelated to Calc. For example,
window.el seems to have many hits, as well as CC Mode, Org, and
calendar-related functions. Also image.el, Gnus, and timer.el.
> > How faster, in absolute numbers and in percents, will your build
> > finish with the proposed changes?
>
> I won't know unless I take the time to code it up.
OK, but do you have an estimate? If not, how do you know it will be
faster?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-01 5:51 ` Eli Zaretskii
@ 2018-08-01 6:43 ` Paul Eggert
2018-08-01 8:53 ` Eli Zaretskii
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-01 6:43 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
Eli Zaretskii wrote:
> OK, but those were just examples, I didn't do an exhaustive search for
> such APIs. Are there any others?
Sure, lots, but most of them are rarely used and so are not a big deal as far as
efficiency goes.
> Ohow do you know it will be faster?
I don't, I just have a suspicion. The only way to find out will be to try it.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-07-22 16:44 ` Paul Eggert
@ 2018-08-01 7:57 ` Paul Eggert
2018-08-01 11:59 ` Eli Zaretskii
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-01 7:57 UTC (permalink / raw)
To: Ken Raeburn; +Cc: Tom Tromey, Stefan Monnier, Richard Stallman, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1233 bytes --]
On July 22 I wrote:
> I see three ways to go here.
>
> 1. We change eql, memql, sxhash-eql, etc. to treat all NaNs alike, so that there
> is just one NaN value from the Lisp point of view. We also change 'format',
> 'copysign' etc. to ignore a NaN's sign, and look through any other use of
> floating-point values to make sure that NaN signs are ignored.
>
> 2. We change eql, memql, sxhash-eql, etc. so that only the sign (not the
> significand) of a NaN is looked at, so that there are just two NaN values from
> the Lisp point of view.
>
> 3. We alter 'read', 'format' etc. to read and generate NaN significands. For
> example, (format "%s" NaN) could return "0.1e+NaN" if the significand's
> low-order bit was set.
>
> (1) sounds too drastic, as the sign of a NaN can be useful in some cases and
> Emacs has long provided for obtaining the sign of a NaN. Although either (2) or
> (3) would be OK, I'm inclined to go for (3) as I expect it would be a bit
> cleaner and more useful.
No further comment on this, and I went with (3) and installed into master the
attached patch to do something along those lines on platforms that have
ieee754.h (mostly GNUish platforms, I expect). Other platforms are unaffected.
[-- Attachment #2: 0001-Read-and-print-NaN-significand-if-ieee754.h.patch --]
[-- Type: text/x-patch, Size: 4330 bytes --]
From 6e37d2fd05bea373c472af1c6e80238ace5e1c94 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 1 Aug 2018 00:49:39 -0700
Subject: [PATCH] Read and print NaN significand if <ieee754.h>
* configure.ac: Check for ieee754.h.
* doc/lispref/numbers.texi (Float Basics): Document
that NaN string representation digits are machine-dependent.
* etc/NEWS: Mention the change.
* src/lread.c, src/print.c [HAVE_IEEE754_H]: Include ieee754.h.
* src/lread.c (string_to_number) [HAVE_IEEE754_H]:
* src/print.c (float_to_string) [HAVE_IEEE754_H]:
Read and print NaN significand.
---
configure.ac | 1 +
doc/lispref/numbers.texi | 2 +-
etc/NEWS | 3 +++
src/lread.c | 11 +++++++++++
src/print.c | 11 +++++++++++
5 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index b691867..dbdcce7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1668,6 +1668,7 @@ AC_DEFUN
dnl checks for header files
AC_CHECK_HEADERS_ONCE(
+ ieee754.h
linux/fs.h
malloc.h
sys/systeminfo.h
diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index 14d5059..a3317c9 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -241,7 +241,7 @@ Float Basics
NaNs carry a sign and a significand, and non-numeric functions treat
two NaNs as equal when their
signs and significands agree. Significands of NaNs are
-machine-dependent and are not directly visible to Emacs Lisp.
+machine-dependent, as are the digits in their string representation.
When NaNs and signed zeros are involved, non-numeric functions like
@code{eql}, @code{equal}, @code{sxhash-eql}, @code{sxhash-equal} and
diff --git a/etc/NEWS b/etc/NEWS
index f1ea835..9e7a765 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -880,6 +880,9 @@ Formerly, some of these functions ignored signs and significands of
NaNs. Now, all these functions treat NaN signs and significands as
significant. For example, (eql 0.0e+NaN -0.0e+NaN) now returns nil
because the two NaNs have different signs; formerly it returned t.
+Also, on platforms that have <ieee754.h> Emacs now reads and prints
+NaN significands; e.g., if X is a NaN, (format "%s" X) now returns
+"0.0e+NaN", "1.0e+NaN", etc., depending on X's significand.
+++
** The function 'make-string' accepts an additional optional argument.
diff --git a/src/lread.c b/src/lread.c
index 50fc6ef..290b0f6 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -72,6 +72,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define file_tell ftell
#endif
+#if HAVE_IEEE754_H
+# include <ieee754.h>
+#endif
+
/* The objects or placeholders read with the #n=object form.
A hash table maps a number to either a placeholder (while the
@@ -3757,8 +3761,15 @@ string_to_number (char const *string, int base, int flags)
{
state |= E_EXP;
cp += 3;
+#if HAVE_IEEE754_H
+ union ieee754_double u
+ = { .ieee_nan = { .exponent = -1, .quiet_nan = 1,
+ .mantissa0 = n >> 31 >> 1, .mantissa1 = n }};
+ value = u.d;
+#else
/* NAN is a "positive" NaN on all known Emacs hosts. */
value = NAN;
+#endif
}
else
cp = ecp;
diff --git a/src/print.c b/src/print.c
index da6ec1a..add2160 100644
--- a/src/print.c
+++ b/src/print.c
@@ -40,6 +40,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <ftoastr.h>
#include <math.h>
+#if HAVE_IEEE754_H
+# include <ieee754.h>
+#endif
+
#ifdef WINDOWSNT
# include <sys/socket.h> /* for F_DUPFD_CLOEXEC */
#endif
@@ -1011,6 +1015,12 @@ float_to_string (char *buf, double data)
}
if (isnan (data))
{
+#if HAVE_IEEE754_H
+ union ieee754_double u = { .d = data };
+ uprintmax_t hi = u.ieee_nan.mantissa0;
+ return sprintf (buf, &"-%"pMu".0e+NaN"[!u.ieee_nan.negative],
+ (hi << 31 << 1) + u.ieee_nan.mantissa1);
+#else
/* Prepend "-" if the NaN's sign bit is negative.
The sign bit of a double is the bit that is 1 in -0.0. */
static char const NaN_string[] = "0.0e+NaN";
@@ -1029,6 +1039,7 @@ float_to_string (char *buf, double data)
strcpy (buf + negative, NaN_string);
return negative + sizeof NaN_string - 1;
+#endif
}
if (NILP (Vfloat_output_format)
--
2.7.4
^ permalink raw reply related [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-01 6:43 ` Paul Eggert
@ 2018-08-01 8:53 ` Eli Zaretskii
2018-08-03 7:40 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-01 8:53 UTC (permalink / raw)
To: Paul Eggert; +Cc: monnier, emacs-devel
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Tue, 31 Jul 2018 23:43:18 -0700
>
> Eli Zaretskii wrote:
>
> > OK, but those were just examples, I didn't do an exhaustive search for
> > such APIs. Are there any others?
>
> Sure, lots, but most of them are rarely used and so are not a big deal as far as
> efficiency goes.
Well, the FP calculations in Lisp are certainly in places that get
used a lot: the line-move stuff and window.el stuff.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-08-01 7:57 ` Paul Eggert
@ 2018-08-01 11:59 ` Eli Zaretskii
2018-08-02 2:06 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-01 11:59 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel, raeburn, tom, monnier, rms
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Wed, 1 Aug 2018 00:57:09 -0700
> Cc: Tom Tromey <tom@tromey.com>, Stefan Monnier <monnier@IRO.UMontreal.CA>,
> Richard Stallman <rms@gnu.org>, emacs-devel@gnu.org
>
> No further comment on this, and I went with (3) and installed into master the
> attached patch to do something along those lines on platforms that have
> ieee754.h (mostly GNUish platforms, I expect). Other platforms are unaffected.
Thanks, but isn't there a way to test whether a platform supports IEEE
FP representation except by looking for ieee754.h? AFAICS, that
header just defines a few data structures that any IEEE-compliant
platform should be able to work with. So limiting this to glibc
platforms is too restrictive, I think.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-08-01 11:59 ` Eli Zaretskii
@ 2018-08-02 2:06 ` Paul Eggert
2018-08-02 13:49 ` Eli Zaretskii
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-02 2:06 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel, raeburn, tom, monnier, rms
[-- Attachment #1: Type: text/plain, Size: 582 bytes --]
Eli Zaretskii wrote:
> isn't there a way to test whether a platform supports IEEE
> FP representation except by looking for ieee754.h? AFAICS, that
> header just defines a few data structures that any IEEE-compliant
> platform should be able to work with.
We can try using ieee754.h on non-GNU platforms and see what happens. In theory,
there could be weird platforms where it doesn't work (as no standard specifies
IEEE 754 layout); in practice, we'll probably be OK. So I created a Gnulib
module for ieee754.h, merged it in, and installed the attached into master.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Substitute-a-ieee754.h-on-hosts-lacking-it.patch --]
[-- Type: text/x-patch; name="0001-Substitute-a-ieee754.h-on-hosts-lacking-it.patch", Size: 16730 bytes --]
From d216d7d248199aa6c99cd642116717c5b301ae6d Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 1 Aug 2018 18:53:31 -0700
Subject: [PATCH] Substitute a <ieee754.h> on hosts lacking it
* .gitignore: Add lib/ieee754.h.
* admin/merge-gnulib (GNULIB_MODULES): Add ieee754-h.
* configure.ac: Remove ieee754.h check, as Gnulib now does that.
* etc/NEWS: Mention this.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* lib/ieee754.in.h, m4/ieee754-h.m4: New files, from Gnulib.
* src/lisp.h (IEEE_FLOATING_POINT): Now a macro so that it
can be used in #if.
* src/lread.c, src/print.c: Include <ieee754.h> if
IEEE_FLOATING_POINT, not if HAVE_IEEE754_H.
* src/lread.c (string_to_number):
* src/print.c (float_to_string):
Process NaNs only on IEEE hosts, and assume <ieee754.h>
in that case.
---
.gitignore | 1 +
admin/merge-gnulib | 2 +-
configure.ac | 1 -
etc/NEWS | 6 +-
lib/gnulib.mk.in | 29 +++++++
lib/ieee754.in.h | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++
m4/gnulib-comp.m4 | 4 +
m4/ieee754-h.m4 | 21 +++++
src/lisp.h | 11 +--
src/lread.c | 9 +--
src/print.c | 25 +-----
11 files changed, 291 insertions(+), 40 deletions(-)
create mode 100644 lib/ieee754.in.h
create mode 100644 m4/ieee754-h.m4
diff --git a/.gitignore b/.gitignore
index d3712b0..26fe4bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ lib/execinfo.h
lib/fcntl.h
lib/getopt.h
lib/getopt-cdefs.h
+lib/ieee754.h
lib/inttypes.h
lib/libgnu.a
lib/limits.h
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 39dfaee..1397ecf 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -35,7 +35,7 @@ GNULIB_MODULES=
fcntl fcntl-h fdatasync fdopendir
filemode filevercmp flexmember fpieee fstatat fsusage fsync
getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
- ignore-value intprops largefile lstat
+ ieee754-h ignore-value intprops largefile lstat
manywarnings memrchr minmax mkostemp mktime nstrftime
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
sig2str socklen stat-time std-gnu11 stdalign stddef stdio
diff --git a/configure.ac b/configure.ac
index dbdcce7..b691867 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1668,7 +1668,6 @@ AC_DEFUN
dnl checks for header files
AC_CHECK_HEADERS_ONCE(
- ieee754.h
linux/fs.h
malloc.h
sys/systeminfo.h
diff --git a/etc/NEWS b/etc/NEWS
index 9e7a765..6c79a46 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -880,9 +880,9 @@ Formerly, some of these functions ignored signs and significands of
NaNs. Now, all these functions treat NaN signs and significands as
significant. For example, (eql 0.0e+NaN -0.0e+NaN) now returns nil
because the two NaNs have different signs; formerly it returned t.
-Also, on platforms that have <ieee754.h> Emacs now reads and prints
-NaN significands; e.g., if X is a NaN, (format "%s" X) now returns
-"0.0e+NaN", "1.0e+NaN", etc., depending on X's significand.
+Also, Emacs now reads and prints NaN significands; e.g., if X is a
+NaN, (format "%s" X) now returns "0.0e+NaN", "1.0e+NaN", etc.,
+depending on X's significand.
+++
** The function 'make-string' accepts an additional optional argument.
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index e623921..7d28dcc 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -95,6 +95,7 @@
# gettime \
# gettimeofday \
# gitlog-to-changelog \
+# ieee754-h \
# ignore-value \
# intprops \
# largefile \
@@ -220,6 +221,7 @@ GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@
GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@
GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@
GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@
+GL_GENERATE_IEEE754_H = @GL_GENERATE_IEEE754_H@
GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@
GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@
GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@
@@ -646,6 +648,7 @@ HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@
HAVE_XSERVER = @HAVE_XSERVER@
HAVE__EXIT = @HAVE__EXIT@
HYBRID_MALLOC = @HYBRID_MALLOC@
+IEEE754_H = @IEEE754_H@
IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@
IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@
INCLUDE_NEXT = @INCLUDE_NEXT@
@@ -1787,6 +1790,32 @@ EXTRA_libgnu_a_SOURCES += group-member.c
endif
## end gnulib module group-member
+## begin gnulib module ieee754-h
+ifeq (,$(OMIT_GNULIB_MODULE_ieee754-h))
+
+BUILT_SOURCES += $(IEEE754_H)
+
+# We need the following in order to create <ieee754.h> when the system
+# doesn't have one that works with the given compiler.
+ifneq (,$(GL_GENERATE_IEEE754_H))
+ieee754.h: ieee754.in.h $(top_builddir)/config.status
+ $(AM_V_GEN)rm -f $@-t && \
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/ifndef _GL_GNULIB_HEADER/if 0/g' \
+ $(srcdir)/ieee754.in.h; \
+ } > $@-t && \
+ mv -f $@-t $@
+else
+ieee754.h: $(top_builddir)/config.status
+ rm -f $@
+endif
+MOSTLYCLEANFILES += ieee754.h ieee754.h-t
+
+EXTRA_DIST += ieee754.in.h
+
+endif
+## end gnulib module ieee754-h
+
## begin gnulib module ignore-value
ifeq (,$(OMIT_GNULIB_MODULE_ignore-value))
diff --git a/lib/ieee754.in.h b/lib/ieee754.in.h
new file mode 100644
index 0000000..316ac03
--- /dev/null
+++ b/lib/ieee754.in.h
@@ -0,0 +1,222 @@
+/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _IEEE754_H
+
+#define _IEEE754_H 1
+
+#ifndef _GL_GNULIB_HEADER
+/* Ordinary glibc usage. */
+# include <features.h>
+# include <endian.h>
+#else
+/* Gnulib usage. */
+# ifndef __BEGIN_DECLS
+# ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+# endif
+# ifndef __FLOAT_WORD_ORDER
+# define __LITTLE_ENDIAN 1234
+# define __BIG_ENDIAN 4321
+# ifdef WORDS_BIGENDIAN
+# define __BYTE_ORDER __BIG_ENDIAN
+# else
+# define __BYTE_ORDER __LITTLE_ENDIAN
+# endif
+# define __FLOAT_WORD_ORDER __BYTE_ORDER
+# endif
+#endif
+
+__BEGIN_DECLS
+
+union ieee754_float
+ {
+ float f;
+
+ /* This is the IEEE 754 single-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int mantissa:23;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:23;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa:22;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:22;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee_nan;
+ };
+
+#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
+
+
+union ieee754_double
+ {
+ double d;
+
+ /* This is the IEEE 754 double-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:20;
+ unsigned int mantissa1:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:19;
+ unsigned int mantissa1:32;
+#else
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
+
+
+union ieee854_long_double
+ {
+ long double d;
+
+ /* This is the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:32;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee;
+
+ /* This is for NaNs in the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int one:1;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa0:30;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
+
+__END_DECLS
+
+#endif /* ieee754.h */
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index a6e3be3..494c77c 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -101,6 +101,7 @@ AC_DEFUN
# Code from module gettimeofday:
# Code from module gitlog-to-changelog:
# Code from module group-member:
+ # Code from module ieee754-h:
# Code from module ignore-value:
# Code from module include_next:
# Code from module intprops:
@@ -295,6 +296,7 @@ AC_DEFUN
gl_PREREQ_GETTIMEOFDAY
fi
gl_SYS_TIME_MODULE_INDICATOR([gettimeofday])
+ gl_IEEE754_H
gl_INTTYPES_INCOMPLETE
AC_REQUIRE([gl_LARGEFILE])
gl_LIMITS_H
@@ -895,6 +897,7 @@ AC_DEFUN
lib/gettimeofday.c
lib/gl_openssl.h
lib/group-member.c
+ lib/ieee754.in.h
lib/ignore-value.h
lib/intprops.h
lib/inttypes.in.h
@@ -1017,6 +1020,7 @@ AC_DEFUN
m4/gl-openssl.m4
m4/gnulib-common.m4
m4/group-member.m4
+ m4/ieee754-h.m4
m4/include_next.m4
m4/inttypes.m4
m4/largefile.m4
diff --git a/m4/ieee754-h.m4 b/m4/ieee754-h.m4
new file mode 100644
index 0000000..bf7c332
--- /dev/null
+++ b/m4/ieee754-h.m4
@@ -0,0 +1,21 @@
+# Configure ieee754-h module
+
+dnl Copyright 2018 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_IEEE754_H],
+[
+ AC_REQUIRE([AC_C_BIGENDIAN])
+ AC_CHECK_HEADERS_ONCE([ieee754.h])
+ if test $ac_cv_header_ieee754_h = yes; then
+ IEEE754_H=
+ else
+ IEEE754_H=ieee754.h
+ AC_DEFINE([_GL_REPLACE_IEEE754_H], 1,
+ [Define to 1 if <ieee754.h> is missing.])
+ fi
+ AC_SUBST([IEEE754_H])
+ AM_CONDITIONAL([GL_GENERATE_IEEE754_H], [test -n "$IEEE754_H"])
+])
diff --git a/src/lisp.h b/src/lisp.h
index 96de60e..bdece81 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2670,17 +2670,14 @@ XFLOAT_DATA (Lisp_Object f)
/* Most hosts nowadays use IEEE floating point, so they use IEC 60559
representations, have infinities and NaNs, and do not trap on
- exceptions. Define IEEE_FLOATING_POINT if this host is one of the
+ exceptions. Define IEEE_FLOATING_POINT to 1 if this host is one of the
typical ones. The C11 macro __STDC_IEC_559__ is close to what is
wanted here, but is not quite right because Emacs does not require
all the features of C11 Annex F (and does not require C11 at all,
for that matter). */
-enum
- {
- IEEE_FLOATING_POINT
- = (FLT_RADIX == 2 && FLT_MANT_DIG == 24
- && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
- };
+
+#define IEEE_FLOATING_POINT (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
+ && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
/* A character, declared with the following typedef, is a member
of some character set associated with the current buffer. */
diff --git a/src/lread.c b/src/lread.c
index 290b0f6..9a025d8 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -72,7 +72,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define file_tell ftell
#endif
-#if HAVE_IEEE754_H
+#if IEEE_FLOATING_POINT
# include <ieee754.h>
#endif
@@ -3756,21 +3756,18 @@ string_to_number (char const *string, int base, int flags)
cp += 3;
value = INFINITY;
}
+#if IEEE_FLOATING_POINT
else if (cp[-1] == '+'
&& cp[0] == 'N' && cp[1] == 'a' && cp[2] == 'N')
{
state |= E_EXP;
cp += 3;
-#if HAVE_IEEE754_H
union ieee754_double u
= { .ieee_nan = { .exponent = -1, .quiet_nan = 1,
.mantissa0 = n >> 31 >> 1, .mantissa1 = n }};
value = u.d;
-#else
- /* NAN is a "positive" NaN on all known Emacs hosts. */
- value = NAN;
-#endif
}
+#endif
else
cp = ecp;
}
diff --git a/src/print.c b/src/print.c
index add2160..34c7fa1 100644
--- a/src/print.c
+++ b/src/print.c
@@ -40,7 +40,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <ftoastr.h>
#include <math.h>
-#if HAVE_IEEE754_H
+#if IEEE_FLOATING_POINT
# include <ieee754.h>
#endif
@@ -1013,34 +1013,15 @@ float_to_string (char *buf, double data)
strcpy (buf, minus_infinity_string + positive);
return sizeof minus_infinity_string - 1 - positive;
}
+#if IEEE_FLOATING_POINT
if (isnan (data))
{
-#if HAVE_IEEE754_H
union ieee754_double u = { .d = data };
uprintmax_t hi = u.ieee_nan.mantissa0;
return sprintf (buf, &"-%"pMu".0e+NaN"[!u.ieee_nan.negative],
(hi << 31 << 1) + u.ieee_nan.mantissa1);
-#else
- /* Prepend "-" if the NaN's sign bit is negative.
- The sign bit of a double is the bit that is 1 in -0.0. */
- static char const NaN_string[] = "0.0e+NaN";
- int i;
- union { double d; char c[sizeof (double)]; } u_data, u_minus_zero;
- bool negative = 0;
- u_data.d = data;
- u_minus_zero.d = - 0.0;
- for (i = 0; i < sizeof (double); i++)
- if (u_data.c[i] & u_minus_zero.c[i])
- {
- *buf = '-';
- negative = 1;
- break;
- }
-
- strcpy (buf + negative, NaN_string);
- return negative + sizeof NaN_string - 1;
-#endif
}
+#endif
if (NILP (Vfloat_output_format)
|| !STRINGP (Vfloat_output_format))
--
2.7.4
^ permalink raw reply related [flat|nested] 281+ messages in thread
* Re: Using the GNU GMP Library for Bignums in Emacs
2018-08-02 2:06 ` Paul Eggert
@ 2018-08-02 13:49 ` Eli Zaretskii
0 siblings, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-02 13:49 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel, raeburn, tom, monnier, rms
> Cc: raeburn@raeburn.org, tom@tromey.com, monnier@IRO.UMontreal.CA,
> rms@gnu.org, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Wed, 1 Aug 2018 19:06:49 -0700
>
> We can try using ieee754.h on non-GNU platforms and see what happens. In theory,
> there could be weird platforms where it doesn't work (as no standard specifies
> IEEE 754 layout); in practice, we'll probably be OK. So I created a Gnulib
> module for ieee754.h, merged it in, and installed the attached into master.
Thanks, works here on MS-Windows.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-01 8:53 ` Eli Zaretskii
@ 2018-08-03 7:40 ` Paul Eggert
2018-08-03 7:55 ` Eli Zaretskii
2018-08-10 11:12 ` Pip Cet
0 siblings, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-03 7:40 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 779 bytes --]
Eli Zaretskii wrote:
> Well, the FP calculations in Lisp are certainly in places that get
> used a lot: the line-move stuff and window.el stuff.
OK, I constructed a little benchmark based on some of the window.el stuff, and
timed it with immediate floats instead of the longstanding way of implementing
floats as pointers into the heap, and on this benchmark Emacs was 82% faster
with immediate floats, i.e., the CPU time on my usual 64-bit platform for (bench
1000000) shrank from 10.776 now to 5.914 seconds with immediate floats. So it
looks promising. This was the only benchmark I tried.
Patch to Emacs and benchmark source code attached. The benchmark was
byte-compiled. The Emacs patch is just a hack; it's not intended to be a real
implementation.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: flo.diff --]
[-- Type: text/x-patch; name="flo.diff", Size: 8268 bytes --]
diff --git a/configure.ac b/configure.ac
index b6918671e4..74200dd75b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1515,6 +1515,12 @@ AC_DEFUN
CPPFLAGS="$C_SWITCH_SYSTEM $C_SWITCH_MACHINE $CPPFLAGS"
fi
+AC_CHECK_SIZEOF([int])
+AC_CHECK_SIZEOF([long int])
+AC_CHECK_SIZEOF([long long int])
+AC_CHECK_SIZEOF([float])
+AC_CHECK_SIZEOF([double])
+
# Suppress obsolescent Autoconf test for size_t; Emacs assumes C99 or better.
AC_DEFUN([AC_TYPE_SIZE_T])
# Likewise for obsolescent test for uid_t, gid_t; Emacs assumes them.
diff --git a/src/alloc.c b/src/alloc.c
index ad716f543c..763df583ab 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -2643,12 +2643,14 @@ static int float_block_index = FLOAT_BLOCK_SIZE;
static struct Lisp_Float *float_free_list;
+#if FLOAT_REPR == FLOAT_TAGGED
+
/* Return a new float object with value FLOAT_VALUE. */
Lisp_Object
-make_float (double float_value)
+make_tagged_float (double float_value)
{
- register Lisp_Object val;
+ Lisp_Object val;
MALLOC_BLOCK_INPUT;
@@ -2685,6 +2687,7 @@ make_float (double float_value)
return val;
}
+#endif
\f
/***********************************************************************
@@ -5505,6 +5508,7 @@ static Lisp_Object
purecopy (Lisp_Object obj)
{
if (INTEGERP (obj)
+ || (FLOAT_REPR != FLOAT_TAGGED && FLOATP (obj))
|| (! SYMBOLP (obj) && PURE_P (XPNTR (obj)))
|| SUBRP (obj))
return obj; /* Already pure. */
@@ -6600,8 +6604,11 @@ mark_object (Lisp_Object arg)
}
case Lisp_Float:
- CHECK_ALLOCATED_AND_LIVE (live_float_p);
- FLOAT_MARK (XFLOAT (obj));
+ if (FLOAT_REPR == FLOAT_TAGGED)
+ {
+ CHECK_ALLOCATED_AND_LIVE (live_float_p);
+ FLOAT_MARK (XFLOAT (obj));
+ }
break;
case_Lisp_Int:
@@ -6673,7 +6680,7 @@ survives_gc_p (Lisp_Object obj)
break;
case Lisp_Float:
- survives_p = FLOAT_MARKED_P (XFLOAT (obj));
+ survives_p = FLOAT_REPR != FLOAT_TAGGED || FLOAT_MARKED_P (XFLOAT (obj));
break;
default:
diff --git a/src/lisp.h b/src/lisp.h
index bdece817bd..b4ee5656c7 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -81,18 +81,21 @@ DEFINE_GDB_SYMBOL_END (GCTYPEBITS)
typedef int EMACS_INT;
typedef unsigned int EMACS_UINT;
enum { EMACS_INT_WIDTH = INT_WIDTH, EMACS_UINT_WIDTH = UINT_WIDTH };
+# define SIZEOF_EMACS_INT SIZEOF_INT
# define EMACS_INT_MAX INT_MAX
# define pI ""
# elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT
typedef long int EMACS_INT;
typedef unsigned long EMACS_UINT;
enum { EMACS_INT_WIDTH = LONG_WIDTH, EMACS_UINT_WIDTH = ULONG_WIDTH };
+# define SIZEOF_EMACS_INT SIZEOF_LONG_INT
# define EMACS_INT_MAX LONG_MAX
# define pI "l"
# elif INTPTR_MAX <= LLONG_MAX
typedef long long int EMACS_INT;
typedef unsigned long long int EMACS_UINT;
enum { EMACS_INT_WIDTH = LLONG_WIDTH, EMACS_UINT_WIDTH = ULLONG_WIDTH };
+# define SIZEOF_EMACS_INT SIZEOF_LONG_LONG_INT
# define EMACS_INT_MAX LLONG_MAX
/* MinGW supports %lld only if __USE_MINGW_ANSI_STDIO is non-zero,
which is arranged by config.h, and (for mingw.org) if GCC is 6.0 or
@@ -618,6 +621,9 @@ enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false };
INLINE void set_sub_char_table_contents (Lisp_Object, ptrdiff_t,
Lisp_Object);
+/* Defined in alloc.c. */
+extern Lisp_Object make_tagged_float (double);
+
/* Defined in chartab.c. */
extern Lisp_Object char_table_ref (Lisp_Object, int);
extern void char_table_set (Lisp_Object, int, Lisp_Object);
@@ -2640,6 +2646,34 @@ XBUFFER_OBJFWD (union Lisp_Fwd *a)
}
\f
/* Lisp floating point type. */
+
+/* Most hosts nowadays use IEEE floating point, so they use IEC 60559
+ representations, have infinities and NaNs, and do not trap on
+ exceptions. Define IEEE_FLOATING_POINT to 1 if this host is one of the
+ typical ones. The C11 macro __STDC_IEC_559__ is close to what is
+ wanted here, but is not quite right because Emacs does not require
+ all the features of C11 Annex F (and does not require C11 at all,
+ for that matter). */
+
+#define IEEE_FLOATING_POINT (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
+ && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
+
+/* Whether Lisp floats are represented directly in Lisp_Object values,
+ as opposed to tagged pointers to storage. */
+#define FLOAT_TAGGED 0
+#define FLOAT_FLOAT 1
+#define FLOAT_DOUBLE 2
+#define FLOAT_REPR (! (USE_LSB_TAG && IEEE_FLOATING_POINT) ? FLOAT_TAGGED \
+ : SIZEOF_EMACS_INT == SIZEOF_FLOAT ? FLOAT_FLOAT \
+ : SIZEOF_EMACS_INT == SIZEOF_DOUBLE ? FLOAT_DOUBLE \
+ : FLOAT_TAGGED)
+#if FLOAT_REPR == FLOAT_FLOAT
+typedef float emacs_float;
+#elif FLOAT_REPR == FLOAT_DOUBLE
+typedef double emacs_float;
+#endif
+
+/* If Lisp floats are tagged pointers, they point to this. */
struct Lisp_Float
{
union
@@ -2655,9 +2689,21 @@ INLINE bool
return lisp_h_FLOATP (x);
}
+INLINE Lisp_Object
+make_float (double d)
+{
+#if FLOAT_REPR == FLOAT_TAGGED
+ return make_tagged_float (d);
+#else
+ return XIL (((union { emacs_float f; EMACS_INT i; }) {d} . i & VALMASK)
+ + Lisp_Float);
+#endif
+}
+
INLINE struct Lisp_Float *
XFLOAT (Lisp_Object a)
{
+ eassume (FLOAT_REPR == FLOAT_TAGGED);
eassert (FLOATP (a));
return XUNTAG (a, Lisp_Float, struct Lisp_Float);
}
@@ -2665,19 +2711,18 @@ XFLOAT (Lisp_Object a)
INLINE double
XFLOAT_DATA (Lisp_Object f)
{
- return XFLOAT (f)->u.data;
-}
-
-/* Most hosts nowadays use IEEE floating point, so they use IEC 60559
- representations, have infinities and NaNs, and do not trap on
- exceptions. Define IEEE_FLOATING_POINT to 1 if this host is one of the
- typical ones. The C11 macro __STDC_IEC_559__ is close to what is
- wanted here, but is not quite right because Emacs does not require
- all the features of C11 Annex F (and does not require C11 at all,
- for that matter). */
+ union { EMACS_INT i; float f; double d; } u = { .i = XLI (f) - Lisp_Float };
-#define IEEE_FLOATING_POINT (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
- && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
+ switch (FLOAT_REPR)
+ {
+ case FLOAT_FLOAT:
+ return u.f;
+ case FLOAT_DOUBLE:
+ return u.d;
+ default:
+ return XFLOAT (f)->u.data;
+ }
+}
/* A character, declared with the following typedef, is a member
of some character set associated with the current buffer. */
@@ -3696,7 +3741,6 @@ extern struct Lisp_Vector *allocate_pseudovector (int, int, int,
VECSIZE (type), tag))
extern bool gc_in_progress;
-extern Lisp_Object make_float (double);
extern void display_malloc_warning (void);
extern ptrdiff_t inhibit_garbage_collection (void);
extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);
diff --git a/src/print.c b/src/print.c
index 34c7fa12b6..c10bbc5ac2 100644
--- a/src/print.c
+++ b/src/print.c
@@ -39,6 +39,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <float.h>
#include <ftoastr.h>
#include <math.h>
+#include <stdlib.h>
#if IEEE_FLOATING_POINT
# include <ieee754.h>
@@ -1029,7 +1030,26 @@ float_to_string (char *buf, double data)
{
/* Generate the fewest number of digits that represent the
floating point value without losing information. */
- len = dtoastr (buf, FLOAT_TO_STRING_BUFSIZE - 2, 0, 0, data);
+ if (FLOAT_REPR == FLOAT_TAGGED)
+ len = dtoastr (buf, FLOAT_TO_STRING_BUFSIZE - 2, 0, 0, data);
+ else
+ for (int prec = ((fabs (data)
+ < (FLOAT_REPR == FLOAT_FLOAT
+ ? (double) FLT_MIN
+ : DBL_MIN))
+ ? 1
+ : ((FLOAT_REPR == FLOAT_FLOAT ? FLT_DIG : DBL_DIG)
+ - 1));
+ ; prec++)
+ {
+ len = snprintf (buf, FLOAT_TO_STRING_BUFSIZE - 2,
+ "%.*g", prec, data);
+ if (isnan (data))
+ break;
+ if (XFLOAT_DATA (make_float (strtod (buf, NULL))) == data)
+ break;
+ }
+
/* The decimal point must be printed, or the byte compiler can
get confused (Bug#8033). */
width = 1;
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: bench-float.el --]
[-- Type: text/x-emacs-lisp; name="bench-float.el", Size: 1661 bytes --]
;;; -*- lexical-binding:t -*-
;; Inspired by window--resize-child-windows-normal
(defvar this-delta 10)
(defvar window-height 50)
(defvar window-normal-size 0.5)
(defvar my-subs '(0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8))
(defvar my-tmp nil)
; (defun bench-nth (n l)
; (while (and l (not (zerop n)))
; (setq l (cdr l))
; (setq n (1- n)))
; (car l))
(defun bench-with (n)
(let ((start (float-time (get-internal-run-time)))
(i 0))
(while (< i n)
(let* ((delta-normal
(if (= (- this-delta) window-height)
(- window-normal-size)
(/ (float this-delta)
window-height)))
(parent-normal 0.0))
(dolist (sub my-subs)
(setq parent-normal
(+ parent-normal window-normal-size sub)))
(dolist (sub my-subs)
(let ((old-normal (+ sub window-normal-size)))
(setq my-tmp
(min 1.0 ; Don't get larger than 1.
(max (- old-normal
(* (/ old-normal parent-normal)
delta-normal))
;; Don't drop below 0.
0.0)))))
(let ((sum 0))
(dolist (sub my-subs)
(setq sum (+ sum window-normal-size sub))
(setq my-tmp (min 1.0 (max (- 1.0 sum) 0.0))))))
(setq i (1+ i)))
(- (float-time (get-internal-run-time)) start)))
(defun bench-without (n)
(let ((start (float-time (get-internal-run-time)))
(i 0))
(while (< i n)
(setq i (1+ i)))
(- (float-time (get-internal-run-time)) start)))
(defun bench (n)
(- (bench-with n)
(bench-without n)))
^ permalink raw reply related [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-03 7:40 ` Paul Eggert
@ 2018-08-03 7:55 ` Eli Zaretskii
2018-08-10 11:12 ` Pip Cet
1 sibling, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-03 7:55 UTC (permalink / raw)
To: Paul Eggert; +Cc: monnier, emacs-devel
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Fri, 3 Aug 2018 00:40:16 -0700
>
> Eli Zaretskii wrote:
> > Well, the FP calculations in Lisp are certainly in places that get
> > used a lot: the line-move stuff and window.el stuff.
>
> OK, I constructed a little benchmark based on some of the window.el stuff, and
> timed it with immediate floats instead of the longstanding way of implementing
> floats as pointers into the heap, and on this benchmark Emacs was 82% faster
> with immediate floats, i.e., the CPU time on my usual 64-bit platform for (bench
> 1000000) shrank from 10.776 now to 5.914 seconds with immediate floats. So it
> looks promising. This was the only benchmark I tried.
That does sound promising, thanks.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-31 22:44 ` Paul Eggert
2018-08-01 5:51 ` Eli Zaretskii
@ 2018-08-10 7:05 ` Elias Mårtenson
2018-08-10 8:02 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Elias Mårtenson @ 2018-08-10 7:05 UTC (permalink / raw)
To: Paul Eggert; +Cc: Eli Zaretskii, Stefan Monnier, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 956 bytes --]
On Wed, 1 Aug 2018, 06:45 Paul Eggert, <eggert@cs.ucla.edu> wrote:
>
> These should be fine on a 64-bit platform. file-system-info invariably
> yields floating-point numbers with the bottom three bits zero, due to
> how modern file systems are built (their sizes are multiples of powers
> of two). file-attributes returns an exact value unless your file is
> larger than 2**61 bytes (2 EiB), and once we get to the rare files
> larger than that we should be using bignums anyway. (The same could be
> said for file-system-info, of course.)
>
Sorry for butting in, but in reading this discussion I'm wondering why you
don't use the high order bits of the exponent instead of the low order bits
of the mantissa?
Sure, you'd need some bit fiddling (rotation and masking) to make it into a
proper floating point number, but now you'll find yourself in a situation
where almost 100% of floating point numbers will fit in a word with tags.
Regards,
Elias
>
[-- Attachment #2: Type: text/html, Size: 1581 bytes --]
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-10 7:05 ` Elias Mårtenson
@ 2018-08-10 8:02 ` Paul Eggert
0 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-10 8:02 UTC (permalink / raw)
To: Elias Mårtenson; +Cc: Eli Zaretskii, Stefan Monnier, emacs-devel
Elias Mårtenson wrote:
> I'm wondering why you
> don't use the high order bits of the exponent instead of the low order bits
> of the mantissa?
Because my benchmark was quick and dirty, and it was easier to mess with the low
order bits that the code is already messing with. I have been considering using
high order bits. (It's also possible to use some of each.)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-03 7:40 ` Paul Eggert
2018-08-03 7:55 ` Eli Zaretskii
@ 2018-08-10 11:12 ` Pip Cet
2018-08-10 15:15 ` Stefan Monnier
2018-08-10 20:48 ` Paul Eggert
1 sibling, 2 replies; 281+ messages in thread
From: Pip Cet @ 2018-08-10 11:12 UTC (permalink / raw)
To: eggert; +Cc: eliz, Stefan Monnier, emacs-devel
That sounds promising! However, I wonder whether NaN-boxing isn't the
right thing to do once we have bignums (on platforms that support it,
by limiting pointers to 48 bits like x86-64 does). I'm doing that in
my experimental code, and the only real disadvantage is Qnil is no
longer an all-zeroes pattern. I believe that's true for 61-bit float
"immediates" as well, though, because they need the all-zero tag bits.
(My current code is limited to 32-bit integers, which causes some
other problems, but hopefully those will go away once bignum support
is merged in.)
I also wonder how many of the non-immediate floats are infinities, or
other numbers that have all low-order mantissa bits set. We could
catch that by using two tags for floats, one for the all-zero case and
one for the all-ones case.
Note that NaN-boxing doesn't necessarily mean we treat integers as
floating-point values; integers get NaN-boxed, too, so floatp remains
meaningful for those places in our codebase that treat their fixnum
arguments differently from floats.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-10 11:12 ` Pip Cet
@ 2018-08-10 15:15 ` Stefan Monnier
2018-08-10 15:43 ` Pip Cet
2018-08-10 20:48 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-08-10 15:15 UTC (permalink / raw)
To: Pip Cet; +Cc: eliz, eggert, emacs-devel
> That sounds promising! However, I wonder whether NaN-boxing isn't the
> right thing to do once we have bignums (on platforms that support it,
> by limiting pointers to 48 bits like x86-64 does). I'm doing that in
NaN boxing implies 64bit boxes, which on 32bit platforms imposes
a non-negligible overhead. So, I think it'd end up costing
significantly more than the tentative patch with which Paul and I have
been playing.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-10 15:15 ` Stefan Monnier
@ 2018-08-10 15:43 ` Pip Cet
2018-08-10 15:55 ` Stefan Monnier
2018-08-10 16:52 ` John Yates
0 siblings, 2 replies; 281+ messages in thread
From: Pip Cet @ 2018-08-10 15:43 UTC (permalink / raw)
To: Stefan Monnier; +Cc: eliz, eggert, emacs-devel
On Fri, Aug 10, 2018 at 3:15 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> > That sounds promising! However, I wonder whether NaN-boxing isn't the
> > right thing to do once we have bignums (on platforms that support it,
> > by limiting pointers to 48 bits like x86-64 does). I'm doing that in
>
> NaN boxing implies 64bit boxes, which on 32bit platforms imposes
> a non-negligible overhead.
Sorry, I don't understand. I don't see how any of this applies to
32-bit platforms with 32-bit EMACS_INTs. On those, we cannot have
float immediates or NaN boxing.
> So, I think it'd end up costing
> significantly more than the tentative patch with which Paul and I have
> been playing.
I think we only have a benchmark for 61-bit floats, which would mean
giving up IEEE compliance and surprising the occasional user who wants
it. That's a very high price to pay for saving a few GCs.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-10 15:43 ` Pip Cet
@ 2018-08-10 15:55 ` Stefan Monnier
2018-08-10 16:52 ` John Yates
1 sibling, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-10 15:55 UTC (permalink / raw)
To: Pip Cet; +Cc: eliz, eggert, emacs-devel
>> NaN boxing implies 64bit boxes, which on 32bit platforms imposes
>> a non-negligible overhead.
> Sorry, I don't understand. I don't see how any of this applies to
> 32-bit platforms with 32-bit EMACS_INTs. On those, we cannot have
> float immediates or NaN boxing.
Indeed. But we want eq == eql on all platforms, including 32bit ones.
>> So, I think it'd end up costing
>> significantly more than the tentative patch with which Paul and I have
>> been playing.
> I think we only have a benchmark for 61-bit floats, which would mean
His idea was to use "immediate floats" when possible (e.g. with 4 zero
bits) and use hash-consed boxed floats for the rest, hence preserving
full 64bit float precision.
IOW the point was to reduce the proportion of floats we need to
hash-cons.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-10 15:43 ` Pip Cet
2018-08-10 15:55 ` Stefan Monnier
@ 2018-08-10 16:52 ` John Yates
2018-08-10 19:45 ` Eli Zaretskii
1 sibling, 1 reply; 281+ messages in thread
From: John Yates @ 2018-08-10 16:52 UTC (permalink / raw)
To: pipcet; +Cc: Eli Zaretskii, Paul Eggert, Stefan Monnier, Emacs developers
On Fri, Aug 10, 2018 at 11:44 AM Pip Cet <pipcet@gmail.com> wrote:
> giving up IEEE compliance and surprising the occasional user who wants it.
I have not been paying much attention to this thread so perhaps I am
preaching to the choir here...
In my day job one of my multi-year efforts has been to bring Mathwork's
MATLAB optimization and generated code into ever greater compliance
with the IEEE 754 standard. As such I have much exposure to both the
specifics of the standard and the (often erroneous) expectations of users.
The standard talks about values, not objects, and relationships between
values. NaN is a value just as much as 2 or pi.
More importantly the standard says that two NaN values (even if fetched
from the same container within a single expression) _always_ compare
not equal.
Were I that "occasional user who wants" IEEE compliance in my elisp
code I would expect comparisons of NaNs (whether via either eq or eql)
to return nil. My sense is that to achieve that effect one must _always_
compare floating point objects, even if they reside at the same address.
/john
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-10 16:52 ` John Yates
@ 2018-08-10 19:45 ` Eli Zaretskii
0 siblings, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-10 19:45 UTC (permalink / raw)
To: John Yates; +Cc: eggert, monnier, pipcet, emacs-devel
> From: John Yates <john@yates-sheets.org>
> Date: Fri, 10 Aug 2018 12:52:53 -0400
> Cc: Eli Zaretskii <eliz@gnu.org>, Paul Eggert <eggert@cs.ucla.edu>,
> Stefan Monnier <monnier@iro.umontreal.ca>,
> Emacs developers <emacs-devel@gnu.org>
>
> More importantly the standard says that two NaN values (even if fetched
> from the same container within a single expression) _always_ compare
> not equal.
>
> Were I that "occasional user who wants" IEEE compliance in my elisp
> code I would expect comparisons of NaNs (whether via either eq or eql)
> to return nil. My sense is that to achieve that effect one must _always_
> compare floating point objects, even if they reside at the same address.
We decided to follow IEEE for numerical comparisons ('='), but not for
object comparisons. I'm using IEEE fp calculations all the time on my
daytime job, and it still makes no sense to me to compare NaN
_objects_ not equal. IEEE only talks about comparing numerical
values.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-10 11:12 ` Pip Cet
2018-08-10 15:15 ` Stefan Monnier
@ 2018-08-10 20:48 ` Paul Eggert
1 sibling, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-10 20:48 UTC (permalink / raw)
To: Pip Cet; +Cc: eliz, Stefan Monnier, emacs-devel
Pip Cet wrote:
> That sounds promising! However, I wonder whether NaN-boxing isn't the
> right thing to do once we have bignums (on platforms that support it,
> by limiting pointers to 48 bits like x86-64 does).
I worry that NaN-boxing is less portable. Won't it have problems, for example,
on a system that uses ASLR and where randomized virtual addresses exceed the
2**52 limit?
I suppose, though, that if all the Javascript guys are doing NaN boxing then we
can live in their shadow.
> the only real disadvantage is Qnil is no
> longer an all-zeroes pattern. I believe that's true for 61-bit float
> "immediates" as well, though, because they need the all-zero tag bits.
Actually, Qnil is still all-zeroes with my patch. XFLOAT removes the Lisp_Float
tag bits before treating the resulting Lisp_Object value as a double. I expect
this costs an instruction with XFLOAT, and that it's worth it to keep NILP fast.
We can play a similar trick with NaN boxing, so that Qnil is all-zeros there
too. For example, we could complement all the bits in a Lisp_Object value before
treating it as a double. So I don't view this as being a major advantage for the
approach I suggested.
> I also wonder how many of the non-immediate floats are infinities, or
> other numbers that have all low-order mantissa bits set.
Infinities have the significand bits all zero, no? I'm skeptical that this is a
profitable way to explore.
> I don't see how any of this applies to
> 32-bit platforms with 32-bit EMACS_INTs. On those, we cannot have
> float immediates or NaN boxing.
We can if we're willing to limit ourselves to 'float' precision for Emacs floats
and at most 2**22-or-so distinct non-numeric objects. That might be doable.
However I would rather not spend a lot of time worrying about tuning 32-bit
EMACS_INT platforms.
> 61-bit floats would mean
> giving up IEEE compliance and surprising the occasional user who wants
> it. That's a very high price to pay for saving a few GCs.
RMS had a different opinion; he didn't think full IEEE compliance was worth all
that much trouble <https://debbugs.gnu.org/32405#47>. Although I was originally
striving for IEEE compliance, I'm becoming more inclined to try things along
those lines as it should indeed be faster and I doubt whether Emacs users care
all that much about full IEEE.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-07-29 3:34 ` Paul Eggert
2018-07-29 4:09 ` Stefan Monnier
2018-07-29 14:35 ` Eli Zaretskii
@ 2018-08-20 0:04 ` Stefan Monnier
2018-08-20 1:33 ` Paul Eggert
2018-08-20 6:35 ` Pip Cet
2 siblings, 2 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-20 0:04 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel
Regarding `eq` for bignums, there seems to be some reluctance to
just defining `eq` to be an alias of the current `eql` and I think
I agree because my current approach is more costly now with the new
bignum code: `eql` used to just do
FLOATP (x) ? costly_eql (x, y) : EQ (x, y)
where FLOATP would just check the 3 low bits of `x`. But now we have to do
(FLOATP (x) || BIGNUMP (x)) ? costly_eql (x, y) : EQ (x, y)
where BIGNUMP not only checks the low order bits of `x` but also looks at
the pseudovector_header of `x` if x is a pseudovector (to see if it's
a bignum), so the cost in CPU time is larger and the cost in code size is
even larger yet.
So I think hash-consing bignums makes sense. It will bring us back the
equivalence between `eq` and `eql` for integers (hence bringing us
closer to making `eq == eql` which I think is a very worthy goal), and
I think its cost should not be too high in practice: the time to lookup
up a GMP number in a hash table basically should never be longer than
the time it took to construct this number in the first place, so that's
a worst-case slowdown factor of 2 which I think is perfectly acceptable.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 0:04 ` Stefan Monnier
@ 2018-08-20 1:33 ` Paul Eggert
2018-08-20 15:20 ` Stefan Monnier
2018-08-20 6:35 ` Pip Cet
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-20 1:33 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier wrote:
> the time to lookup
> up a GMP number in a hash table basically should never be longer than
> the time it took to construct this number in the first place
Doesn't a similar argument apply to the cost of construcing an Lisp float
(including memory allocation)? If we hashed floats as well as bignums, eq==eql
would be trivial.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 0:04 ` Stefan Monnier
2018-08-20 1:33 ` Paul Eggert
@ 2018-08-20 6:35 ` Pip Cet
2018-08-20 7:05 ` Paul Eggert
2018-08-20 14:02 ` Stefan Monnier
1 sibling, 2 replies; 281+ messages in thread
From: Pip Cet @ 2018-08-20 6:35 UTC (permalink / raw)
To: Stefan Monnier; +Cc: eggert, emacs-devel
On Mon, Aug 20, 2018 at 12:05 AM Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
> I think its cost should not be too high in practice: the time to lookup
> up a GMP number in a hash table basically should never be longer than
> the time it took to construct this number in the first place, so that's
> a worst-case slowdown factor of 2 which I think is perfectly acceptable.
Can you explain why you think that's the case?
I think it's currently true, but only because make_number always
creates a copy of its argument (at which point we might as well hash
it), and it sounded like Paul was going to fix that soon.
It sounds to me like a good implementation of this would require GMP
support, keeping a hash of each mpz_t in the memory allocated for it.
Perhaps we should make a wishlist of GMP features, which would
currently include three items:
- make long-running integer operations interruptible (so C-g works)
- don't abort() when overflowing the 16 GB limit (and/or remove that
limit entirely)
- hash numbers as you create them, at least for the fast single-pass
operations (addition, left shift, negation).
Do we need to worry about algorithmic complexity attacks? Or about
integers created accidentally that collide in the hash?
I think 64-bit integers, at least, ought to be fast and small. Maybe
we could use our free tag value for that special case.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 6:35 ` Pip Cet
@ 2018-08-20 7:05 ` Paul Eggert
2018-08-20 7:19 ` Pip Cet
2018-08-20 14:02 ` Stefan Monnier
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-20 7:05 UTC (permalink / raw)
To: Pip Cet, Stefan Monnier; +Cc: emacs-devel
Pip Cet wrote:
> I think it's currently true, but only because make_number always
> creates a copy of its argument (at which point we might as well hash
> it), and it sounded like Paul was going to fix that soon.
It's on my list of things to look at, though I can't guarantee I'll fix it (much
less "soon").
> It sounds to me like a good implementation of this would require GMP
> support, keeping a hash of each mpz_t in the memory allocated for it.
> Perhaps we should make a wishlist of GMP features, which would
> currently include three items:
>
> - make long-running integer operations interruptible (so C-g works)
We can approximate this by checking for C-g in the GMP-specific memory allocator
hooks. Perhaps all we need is some sort of guarantee that unbounded computation
won't occur without some memory allocation action.
> - don't abort() when overflowing the 16 GB limit (and/or remove that
> limit entirely)
Yes, that reeally needs to be fixed. I think I have a handle on avoiding that
glitch in the meantime (still polishing it).
> - hash numbers as you create them, at least for the fast single-pass
> operations (addition, left shift, negation).
Could well be a win, yes. Not sure how much of a win it would be for typical
use, though. Usually bignums are pretty small.
> Do we need to worry about algorithmic complexity attacks? Or about
> integers created accidentally that collide in the hash?
Both, I'd think.
> I think 64-bit integers, at least, ought to be fast and small. Maybe
> we could use our free tag value for that special case.
Hold on, let's not spend that valuable tag so casually! Perhaps bignums or
floats are a better use for a tag than 64-bit ints.
One other thing: we can pry another tag free. Now that we have bignums we no
longer need to give fixnums two tags.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 7:05 ` Paul Eggert
@ 2018-08-20 7:19 ` Pip Cet
2018-08-20 7:27 ` Paul Eggert
2018-08-20 15:12 ` Eli Zaretskii
0 siblings, 2 replies; 281+ messages in thread
From: Pip Cet @ 2018-08-20 7:19 UTC (permalink / raw)
To: eggert; +Cc: Stefan Monnier, emacs-devel
On Mon, Aug 20, 2018 at 7:06 AM Paul Eggert <eggert@cs.ucla.edu> wrote:
> Hold on, let's not spend that valuable tag so casually! Perhaps bignums or
> floats are a better use for a tag than 64-bit ints.
Considering it's only those 64-bit ints that don't fit into 61 (or 62,
or 30, or 29) bits already, I'm no longer convinced this is a good
idea at all. At the very least, it would make our interpreter code
harder to read.
> One other thing: we can pry another tag free. Now that we have bignums we no
> longer need to give fixnums two tags.
I think too many places might still assume that most-positive-fixnum
is precisely either one of its current values (OTOH, I'm running with
most-positive-fixnum = 0x7fffffff and things appear to work).
I think references to most-positive-fixnum (and implicit ones, like
using Frandom without an argument) should be eliminated. Fixnum range
is now an implementation detail.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 7:19 ` Pip Cet
@ 2018-08-20 7:27 ` Paul Eggert
2018-08-20 8:49 ` Andy Moreton
` (2 more replies)
2018-08-20 15:12 ` Eli Zaretskii
1 sibling, 3 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-20 7:27 UTC (permalink / raw)
To: Pip Cet; +Cc: Stefan Monnier, emacs-devel
Pip Cet wrote:
> I think too many places might still assume that most-positive-fixnum
> is precisely either one of its current values (OTOH, I'm running with
> most-positive-fixnum = 0x7fffffff and things appear to work).
Older Emacs used different values, and we survived OK when we changed them.
Plus, xemacs's values differ from both old and current Emacs, and people port
scripts among these implementations. So I think we'd be all right if we changed
these values again.
> I think references to most-positive-fixnum (and implicit ones, like
> using Frandom without an argument) should be eliminated. Fixnum range
> is now an implementation detail.
I tend to agree. Also, we should remove the fixnump and bignump functions; these
functions certainly don't need to be in C code and I don't see why they even
need to be present at all. We shouldn't be giving users the impression that the
distinction between fixnums and bignums is important.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 7:27 ` Paul Eggert
@ 2018-08-20 8:49 ` Andy Moreton
2018-08-20 16:03 ` Paul Eggert
2018-08-20 15:13 ` Eli Zaretskii
2018-08-21 3:37 ` Richard Stallman
2 siblings, 1 reply; 281+ messages in thread
From: Andy Moreton @ 2018-08-20 8:49 UTC (permalink / raw)
To: emacs-devel
On Mon 20 Aug 2018, Paul Eggert wrote:
> Pip Cet wrote:
>> I think references to most-positive-fixnum (and implicit ones, like
>> using Frandom without an argument) should be eliminated. Fixnum range
>> is now an implementation detail.
There will always be a performance diffrence between fixnum and bignum
values, and it may be useful for performance tuning to have a simple way
to discover where that boundary lies.
> I tend to agree. Also, we should remove the fixnump and bignump functions;
> these functions certainly don't need to be in C code and I don't see why they
> even need to be present at all. We shouldn't be giving users the impression
> that the distinction between fixnums and bignums is important.
These are used in the tests to ensure that implementation is correct,
and that values in fixnum range are always represented as fixnums, not
bignums. How do you propose to test that without these predicates ?
AndyM
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 6:35 ` Pip Cet
2018-08-20 7:05 ` Paul Eggert
@ 2018-08-20 14:02 ` Stefan Monnier
1 sibling, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-20 14:02 UTC (permalink / raw)
To: Pip Cet; +Cc: eggert, emacs-devel
> I think it's currently true, but only because make_number always
> creates a copy of its argument (at which point we might as well hash
> it), and it sounded like Paul was going to fix that soon.
Two options:
1- the operation does not create a new number. Since Elisp's
side only sees immutable bignum numbers if the number is not new we
indeed shouldn't create a new number and can reuse the existing
bignum without any need for hash-consing either: so hash-consing
doesn't make this case any slower.
2- the operation does create a new number. In that case the
creation of the number almost inevitably will have to touch every
"limb" of the number (it has a complexity of O(N) in the best case),
so computing the hash shouldn't take noticeably more time.
> It sounds to me like a good implementation of this would require GMP
> support, keeping a hash of each mpz_t in the memory allocated for it.
We can keep the hash in the hash-table.
> Do we need to worry about algorithmic complexity attacks? Or about
> integers created accidentally that collide in the hash?
Emacs already offers so many other attack vectors that I don't think
it's worth worrying about this one at this point.
> I think 64-bit integers, at least, ought to be fast and small.
Indeed, it's for those small bignums that hash-consing will be most
expensive, but I'm not sure it'll be a significant problem.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 7:19 ` Pip Cet
2018-08-20 7:27 ` Paul Eggert
@ 2018-08-20 15:12 ` Eli Zaretskii
2018-08-20 15:26 ` Lars Ingebrigtsen
` (2 more replies)
1 sibling, 3 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-20 15:12 UTC (permalink / raw)
To: Pip Cet; +Cc: eggert, monnier, emacs-devel
> From: Pip Cet <pipcet@gmail.com>
> Date: Mon, 20 Aug 2018 07:19:39 +0000
> Cc: Stefan Monnier <monnier@iro.umontreal.ca>, emacs-devel@gnu.org
>
> I think references to most-positive-fixnum (and implicit ones, like
> using Frandom without an argument) should be eliminated. Fixnum range
> is now an implementation detail.
That is too radical, IMO. Having bignums _allows_ us to write
programs that are oblivious to most-positive-fixnum's value, but it
doesn't _require_ it. It is perfectly legitimate to want to write a
program that is sensitive to that value, e.g., because using bignums
makes some program significantly slow, and so you'd like to ask the
users whether they want to proceed regardless. Or maybe even refuse
to do something (e.g., buffers and strings generally cannot be larger
than that).
We have other system dependent variables and constants (e.g.,
shell-file-name), and for a good reason. Sometimes you need those so
you could actually implement a portable program.
So I don't think we want to argue for a total elimination of
most-positive-fixnum from our code.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 7:27 ` Paul Eggert
2018-08-20 8:49 ` Andy Moreton
@ 2018-08-20 15:13 ` Eli Zaretskii
2018-08-20 15:26 ` Stefan Monnier
2018-08-20 16:01 ` Paul Eggert
2018-08-21 3:37 ` Richard Stallman
2 siblings, 2 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-20 15:13 UTC (permalink / raw)
To: Paul Eggert; +Cc: monnier, pipcet, emacs-devel
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Mon, 20 Aug 2018 00:27:39 -0700
> Cc: Stefan Monnier <monnier@iro.umontreal.ca>, emacs-devel@gnu.org
>
> I tend to agree. Also, we should remove the fixnump and bignump functions; these
> functions certainly don't need to be in C code and I don't see why they even
> need to be present at all. We shouldn't be giving users the impression that the
> distinction between fixnums and bignums is important.
I don't think we should go as far as removing these functions, as they
can still be useful in some situations. Let's not rush.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 1:33 ` Paul Eggert
@ 2018-08-20 15:20 ` Stefan Monnier
0 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-20 15:20 UTC (permalink / raw)
To: emacs-devel
>> the time to lookup up a GMP number in a hash table basically should
>> never be longer than the time it took to construct this number in the
>> first place
> Doesn't a similar argument apply to the cost of construcing an Lisp float
> (including memory allocation)? If we hashed floats as well as bignums,
> eq==eql would be trivial.
Float operations are fundamentally much faster than a hash-lookup.
The fact that we heap-allocate them makes the relative cost of
hash-consing lower, but I think it's still likely to increase run-time
by a factor higher than 2x.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:13 ` Eli Zaretskii
@ 2018-08-20 15:26 ` Stefan Monnier
2018-08-20 16:19 ` Eli Zaretskii
2018-08-21 15:01 ` Robert Pluim
2018-08-20 16:01 ` Paul Eggert
1 sibling, 2 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-20 15:26 UTC (permalink / raw)
To: emacs-devel
> I don't think we should go as far as removing these functions, as they
> can still be useful in some situations. Let's not rush.
Agreed. How 'bout we first try to actually make use of bignums?
E.g. changing Calc to use them instead of its own implementation of bignums?
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:12 ` Eli Zaretskii
@ 2018-08-20 15:26 ` Lars Ingebrigtsen
2018-08-20 16:18 ` Eli Zaretskii
2018-08-21 3:38 ` Richard Stallman
2018-08-20 15:37 ` Stefan Monnier
2018-08-20 16:12 ` Paul Eggert
2 siblings, 2 replies; 281+ messages in thread
From: Lars Ingebrigtsen @ 2018-08-20 15:26 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: eggert, monnier, Pip Cet, emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
> So I don't think we want to argue for a total elimination of
> most-positive-fixnum from our code.
I agree, but its usage in Emacsen with larger numbers present can be
problematic.
I'm pretty sure that I've written code that's essentially along the
lines of
(when list-of-numbers
(let ((i most-positive-fixnum))
(dolist (a list-of-numbers)
(setq i (min i a)))
i))
to get the smallest number in a set. (Not exactly like that, of course,
but using `most-positive-fixnum' as a guard value, knowing that none of
numbers in list-of-numbers can be larger than that guard value.)
So perhaps a warning might be warranted?
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:12 ` Eli Zaretskii
2018-08-20 15:26 ` Lars Ingebrigtsen
@ 2018-08-20 15:37 ` Stefan Monnier
2018-08-20 16:23 ` Eli Zaretskii
2018-08-20 16:12 ` Paul Eggert
2 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-08-20 15:37 UTC (permalink / raw)
To: emacs-devel
>> I think references to most-positive-fixnum (and implicit ones, like
>> using Frandom without an argument) should be eliminated. Fixnum range
>> is now an implementation detail.
> That is too radical, IMO.
I think what Pip is saying is that we should review all *uses* of
most-positive-fixnum, because it's very likely that many/most of them
are now wrong or suboptimal.
That doesn't mean we should remove most-positive-fixnum itself.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:13 ` Eli Zaretskii
2018-08-20 15:26 ` Stefan Monnier
@ 2018-08-20 16:01 ` Paul Eggert
2018-08-20 16:26 ` Eli Zaretskii
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-20 16:01 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, pipcet, emacs-devel
Eli Zaretskii wrote:
> I don't think we should go as far as removing these functions, as they
> can still be useful in some situations.
'still'? They were just introduced a week ago. No user code is using them. Why
push them onto users? It's a step in the wrong direction.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 8:49 ` Andy Moreton
@ 2018-08-20 16:03 ` Paul Eggert
2018-08-20 16:41 ` Andy Moreton
2018-08-20 17:23 ` Eli Zaretskii
0 siblings, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-20 16:03 UTC (permalink / raw)
To: Andy Moreton, emacs-devel
Andy Moreton wrote:
> There will always be a performance diffrence between fixnum and bignum
> values, and it may be useful for performance tuning to have a simple way
> to discover where that boundary lies.
Performance nerds can use 'most-positive-fixnum' and 'most-negative-fixnum' for
that sort of thing. These constants have been there for some time and are not
going away. My objection is to 'bignump' and 'fixnump', which are no more
necessary as primitives than 'negativep' would be.
> These are used in the tests to ensure that implementation is correct,
> and that values in fixnum range are always represented as fixnums, not
> bignums. How do you propose to test that without these predicates ?
Tests can use 'most-positive-fixnum' and 'most-negative-fixnum', constants that
tests need to use anyway in order to generate values like (1+
most-positive-fixnum). So they can survive quite well without 'bignump' and
'fixnump' as primitives.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:12 ` Eli Zaretskii
2018-08-20 15:26 ` Lars Ingebrigtsen
2018-08-20 15:37 ` Stefan Monnier
@ 2018-08-20 16:12 ` Paul Eggert
2018-08-20 17:21 ` Helmut Eller
2 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-20 16:12 UTC (permalink / raw)
To: Eli Zaretskii, Pip Cet; +Cc: monnier, emacs-devel
Eli Zaretskii wrote:
> I don't think we want to argue for a total elimination of
> most-positive-fixnum from our code.
I agree. Software like 'calc' springs to mind: quite possibly it will want to do
some arithmetic in fixnums, and will want to know the fixnum range to do that,
and most-negative-fixnum and most-positive-fixnum are how it can do that.
As I recall, Gerd introduced most-positive-fixnum and most-negative-fixnum to
Emacs Lisp in 2001, as it was a good idea taken from Common Lisp. However,
fixnump and bignump are not in Common Lisp, and we don't need them in Emacs Lisp
either. When we're reinventing the wheel why add unnecessary gizmos?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:26 ` Lars Ingebrigtsen
@ 2018-08-20 16:18 ` Eli Zaretskii
2018-08-22 19:59 ` Stefan Monnier
2018-08-21 3:38 ` Richard Stallman
1 sibling, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-20 16:18 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: eggert, monnier, pipcet, emacs-devel
> From: Lars Ingebrigtsen <larsi@gnus.org>
> Cc: Pip Cet <pipcet@gmail.com>, eggert@cs.ucla.edu, monnier@iro.umontreal.ca, emacs-devel@gnu.org
> Date: Mon, 20 Aug 2018 17:26:18 +0200
>
> So perhaps a warning might be warranted?
Too annoying, IMO. Instead, we should keep this in mind while
reviewing patches.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:26 ` Stefan Monnier
@ 2018-08-20 16:19 ` Eli Zaretskii
2018-08-21 15:01 ` Robert Pluim
1 sibling, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-20 16:19 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Mon, 20 Aug 2018 11:26:14 -0400
>
> > I don't think we should go as far as removing these functions, as they
> > can still be useful in some situations. Let's not rush.
>
> Agreed. How 'bout we first try to actually make use of bignums?
> E.g. changing Calc to use them instead of its own implementation of bignums?
Yes, collecting actual experience with bignums is a good way of
figuring out what is important and what's less so.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:37 ` Stefan Monnier
@ 2018-08-20 16:23 ` Eli Zaretskii
0 siblings, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-20 16:23 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Mon, 20 Aug 2018 11:37:01 -0400
>
> >> I think references to most-positive-fixnum (and implicit ones, like
> >> using Frandom without an argument) should be eliminated. Fixnum range
> >> is now an implementation detail.
> > That is too radical, IMO.
>
> I think what Pip is saying is that we should review all *uses* of
> most-positive-fixnum, because it's very likely that many/most of them
> are now wrong or suboptimal.
>
> That doesn't mean we should remove most-positive-fixnum itself.
I didn't think he meant to remove it. But the goal of eliminating
references to it can only go so far, because there are legitimate use
cases for referencing it. References that are no longer needed should
be removed, but this is a case by case decision, and sometimes a
judgment call, not an absolute requirement that Pip's wording hinted
at.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 16:01 ` Paul Eggert
@ 2018-08-20 16:26 ` Eli Zaretskii
0 siblings, 0 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-20 16:26 UTC (permalink / raw)
To: Paul Eggert; +Cc: monnier, pipcet, emacs-devel
> Cc: pipcet@gmail.com, monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Mon, 20 Aug 2018 09:01:23 -0700
>
> It's a step in the wrong direction.
I don't think we know that yet. We should collect hands-on experience
first.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 16:03 ` Paul Eggert
@ 2018-08-20 16:41 ` Andy Moreton
2018-08-20 16:51 ` Paul Eggert
2018-08-20 19:50 ` Pip Cet
2018-08-20 17:23 ` Eli Zaretskii
1 sibling, 2 replies; 281+ messages in thread
From: Andy Moreton @ 2018-08-20 16:41 UTC (permalink / raw)
To: emacs-devel
On Mon 20 Aug 2018, Paul Eggert wrote:
> Andy Moreton wrote:
>
>> There will always be a performance diffrence between fixnum and bignum
>> values, and it may be useful for performance tuning to have a simple way
>> to discover where that boundary lies.
>
> Performance nerds can use 'most-positive-fixnum' and 'most-negative-fixnum'
> for that sort of thing. These constants have been there for some time and are
> not going away. My objection is to 'bignump' and 'fixnump', which are no more
> necessary as primitives than 'negativep' would be.
Pip Cet was advocating removal of most-positive-fixnum, and that is what
I was objecting to as being too severe. We do not need negativep as we
already have other prmitives for testing that property.
>> These are used in the tests to ensure that implementation is correct,
>> and that values in fixnum range are always represented as fixnums, not
>> bignums. How do you propose to test that without these predicates ?
>
> Tests can use 'most-positive-fixnum' and 'most-negative-fixnum', constants
> that tests need to use anyway in order to generate values like (1+
> most-positive-fixnum). So they can survive quite well without 'bignump' and
> 'fixnump' as primitives.
You have avoided the question.
The current codebase assumes that lisp bignum objects only exist for
values outside fixnum range. Without fixnump how can tests check that
values within fixnum range actually have a fixnum representation ? How
can test check that no bignum object is created for a fixnum value ?
AndyM
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 16:41 ` Andy Moreton
@ 2018-08-20 16:51 ` Paul Eggert
2018-08-20 16:58 ` Andy Moreton
2018-08-20 19:50 ` Pip Cet
1 sibling, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-20 16:51 UTC (permalink / raw)
To: Andy Moreton, emacs-devel
Andy Moreton wrote:
> The current codebase assumes that lisp bignum objects only exist for
> values outside fixnum range. Without fixnump how can tests check that
> values within fixnum range actually have a fixnum representation
Tests cannot possibly check that, because 'fixnump' itself might simply return t
for any integer in fixnum range, even if the integer is internally represented
as a bignum.
Besides, the current codebase is not actually assuming that Lisp bignum objects
exist only for values outside fixnum range (the current codebase is not assuming
that bignums exist at all, for that matter). What the current codebase is
assuming is alluded to in the "Subject:" line of this email, i.e., it is
assuming that eq is equivalent to eql on fixnums. And this assumption can be
tested directly, by doing some computations and checking that eq works as
expected when results are in fixnum range. The test code doesn't need fixnump or
bignump to do this sort of test.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 16:51 ` Paul Eggert
@ 2018-08-20 16:58 ` Andy Moreton
0 siblings, 0 replies; 281+ messages in thread
From: Andy Moreton @ 2018-08-20 16:58 UTC (permalink / raw)
To: emacs-devel
On Mon 20 Aug 2018, Paul Eggert wrote:
> Andy Moreton wrote:
>> The current codebase assumes that lisp bignum objects only exist for
>> values outside fixnum range. Without fixnump how can tests check that
>> values within fixnum range actually have a fixnum representation
>
> Tests cannot possibly check that, because 'fixnump' itself might simply return
> t for any integer in fixnum range, even if the integer is internally
> represented as a bignum.
Only true if the tests can make no assumptions about the implementation.
As the tests and the codebase are developed together that need not be
the case.
> Besides, the current codebase is not actually assuming that Lisp bignum
> objects exist only for values outside fixnum range (the current codebase is
> not assuming that bignums exist at all, for that matter).
The C code most certainly does assume this. The lisp code does not care
about representation (other than tripping over various bignum bugs that
need fixing).
AndyM
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 16:12 ` Paul Eggert
@ 2018-08-20 17:21 ` Helmut Eller
0 siblings, 0 replies; 281+ messages in thread
From: Helmut Eller @ 2018-08-20 17:21 UTC (permalink / raw)
To: emacs-devel
On Mon, Aug 20 2018, Paul Eggert wrote:
> As I recall, Gerd introduced most-positive-fixnum and
> most-negative-fixnum to Emacs Lisp in 2001, as it was a good idea
> taken from Common Lisp. However, fixnump and bignump are not in Common
> Lisp, and we don't need them in Emacs Lisp either. When we're
> reinventing the wheel why add unnecessary gizmos?
Common Lisp doesn't have so many type predicates because it has TYPEP.
Both FIXNUM and BIGNUM are standard types in Common Lisp. The BIGNUM
type is actually defined as (AND INTEGER (NOT FIXNUM)). So if you
remove fixnump then at least make typep (and typecase etc.) work with
'fixnum and 'bignum type specifiers.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 16:03 ` Paul Eggert
2018-08-20 16:41 ` Andy Moreton
@ 2018-08-20 17:23 ` Eli Zaretskii
2018-08-20 17:35 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-20 17:23 UTC (permalink / raw)
To: Paul Eggert; +Cc: andrewjmoreton, emacs-devel
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Mon, 20 Aug 2018 09:03:17 -0700
>
> My objection is to 'bignump' and 'fixnump', which are no more
> necessary as primitives than 'negativep' would be.
We do have natnump, though, so bignump is not as outlandish as it
might sound.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 17:23 ` Eli Zaretskii
@ 2018-08-20 17:35 ` Paul Eggert
0 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-20 17:35 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: andrewjmoreton, emacs-devel
Eli Zaretskii wrote:
>> My objection is to 'bignump' and 'fixnump', which are no more
>> necessary as primitives than 'negativep' would be.
> We do have natnump, though, so bignump is not as outlandish as it
> might sound.
You're right that bignump is not outlandish. However, it's not at all necessary,
and we should try to keep the core interpreter as simple and clean as possible.
There is a longstanding tradition in mathematics to talk about "natural numbers"
and so there is a genuine need in applications for natnump that comes outside of
Emacs. bignump is nowhere near to natnump in importance. Emacs apps don't need
bignump, and even our test cases' use of it is unnecessary.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 16:41 ` Andy Moreton
2018-08-20 16:51 ` Paul Eggert
@ 2018-08-20 19:50 ` Pip Cet
2018-08-20 21:54 ` Andy Moreton
2018-08-21 3:38 ` Richard Stallman
1 sibling, 2 replies; 281+ messages in thread
From: Pip Cet @ 2018-08-20 19:50 UTC (permalink / raw)
To: andrewjmoreton; +Cc: emacs-devel
On Mon, Aug 20, 2018 at 4:43 PM Andy Moreton <andrewjmoreton@gmail.com> wrote:
> On Mon 20 Aug 2018, Paul Eggert wrote:
>
> > Andy Moreton wrote:
> >
> >> There will always be a performance diffrence between fixnum and bignum
> >> values, and it may be useful for performance tuning to have a simple way
> >> to discover where that boundary lies.
> >
> > Performance nerds can use 'most-positive-fixnum' and 'most-negative-fixnum'
> > for that sort of thing. These constants have been there for some time and are
> > not going away. My objection is to 'bignump' and 'fixnump', which are no more
> > necessary as primitives than 'negativep' would be.
>
> Pip Cet was advocating removal of most-positive-fixnum, and that is what
> I was objecting to as being too severe. We do not need negativep as we
> already have other prmitives for testing that property.
I'm sorry for the sloppy wording. `most-positive-fixnum' should stay:
it's an important implementation detail. All the references to it in
lisp/, though, look to me like they should be removed.
The references in test/ should stay, for example, and I think a good
case can be made that the fixnum range should be included in Emacs bug
reports, which would be a legitimate use in the lisp/ directory.
> >> These are used in the tests to ensure that implementation is correct,
> >> and that values in fixnum range are always represented as fixnums, not
> >> bignums. How do you propose to test that without these predicates ?
> >
> > Tests can use 'most-positive-fixnum' and 'most-negative-fixnum', constants
> > that tests need to use anyway in order to generate values like (1+
> > most-positive-fixnum). So they can survive quite well without 'bignump' and
> > 'fixnump' as primitives.
>
> You have avoided the question.
>
> The current codebase assumes that lisp bignum objects only exist for
> values outside fixnum range. Without fixnump how can tests check that
> values within fixnum range actually have a fixnum representation ? How
> can test check that no bignum object is created for a fixnum value ?
I think keeping a Lisp function around for the sole purpose of testing
C code from Lisp is wrong. The right thing to do in this case is to
test the C code from C; I believe GCC does so extensively, and it
would be easy enough to add a test function that eassert()s that
FIXNUMP(Fsub1(Fadd1(MOST_POSITIVE_FIXNUM))), for example.
Again, I think important implementation details, like what a good
range for fast integer arithmetic is ([most-negative-fixnum,
most-positive-fixnum]) and how floats are encoded and whether IEEE
rules are being followed (IEEE_FLOATING_POINT), should be exposed to
Lisp. (For example, I'm playing around with big rational numbers, and
one possible implementation is for them to replace floats, but that
almost naturally requires a ratio-to-nearby-simple-ratio function to
avoid building up huge representations; whether to use such a function
and what it does would be an implementation detail, but one that code
might want to optimize for...)
Does bignump serve a purpose other than testing C code? My impression
is that it doesn't in the current implementation, and the symbol
should be left unbound, but considered reserved. While there is
hypothetical code that wants to know whether a number is currently
encoded as a bignum (I'm thinking of benchmarking code that's run in a
future Emacs with contrarily bignum-encoded fixnum-range integers), I
think it's exotic enough that it can just test (if (fboundp 'fixnump)
(fixnump x) (<= most-negative-fixnum x most-positive-fixnum)). Leaving
bignump in will lead to people thinking it's synonymous to "is this
number outside the fixnum range", and such code will then break if
it's suddenly possible for (bignump 0) to be false.
Perhaps a good analogy is that (bignump x) is on a level with "what C
address is x stored at": it's a question only very curious Lisp
programs would ask, and the answer is subject to change and dangerous
to rely on.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 19:50 ` Pip Cet
@ 2018-08-20 21:54 ` Andy Moreton
2018-08-21 3:38 ` Richard Stallman
1 sibling, 0 replies; 281+ messages in thread
From: Andy Moreton @ 2018-08-20 21:54 UTC (permalink / raw)
To: emacs-devel
On Mon 20 Aug 2018, Pip Cet wrote:
> On Mon, Aug 20, 2018 at 4:43 PM Andy Moreton <andrewjmoreton@gmail.com> wrote:
>> On Mon 20 Aug 2018, Paul Eggert wrote:
>>
>> > Andy Moreton wrote:
>> >
>> >> There will always be a performance diffrence between fixnum and bignum
>> >> values, and it may be useful for performance tuning to have a simple way
>> >> to discover where that boundary lies.
>> >
>> > Performance nerds can use 'most-positive-fixnum' and 'most-negative-fixnum'
>> > for that sort of thing. These constants have been there for some time and are
>> > not going away. My objection is to 'bignump' and 'fixnump', which are no more
>> > necessary as primitives than 'negativep' would be.
>>
>> Pip Cet was advocating removal of most-positive-fixnum, and that is what
>> I was objecting to as being too severe. We do not need negativep as we
>> already have other prmitives for testing that property.
>
> I'm sorry for the sloppy wording. `most-positive-fixnum' should stay:
> it's an important implementation detail. All the references to it in
> lisp/, though, look to me like they should be removed.
Agreed, Apologies for misunderstanding your original message.
>
> I think keeping a Lisp function around for the sole purpose of testing
> C code from Lisp is wrong. The right thing to do in this case is to
> test the C code from C; I believe GCC does so extensively, and it
> would be easy enough to add a test function that eassert()s that
> FIXNUMP(Fsub1(Fadd1(MOST_POSITIVE_FIXNUM))), for example.
A good point.
> Again, I think important implementation details, like what a good
> range for fast integer arithmetic is ([most-negative-fixnum,
> most-positive-fixnum]) and how floats are encoded and whether IEEE
> rules are being followed (IEEE_FLOATING_POINT), should be exposed to
> Lisp. (For example, I'm playing around with big rational numbers, and
> one possible implementation is for them to replace floats, but that
> almost naturally requires a ratio-to-nearby-simple-ratio function to
> avoid building up huge representations; whether to use such a function
> and what it does would be an implementation detail, but one that code
> might want to optimize for...)
Perhaps these implementation details should also be added to bug reports ?
AndyM
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 7:27 ` Paul Eggert
2018-08-20 8:49 ` Andy Moreton
2018-08-20 15:13 ` Eli Zaretskii
@ 2018-08-21 3:37 ` Richard Stallman
2 siblings, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-08-21 3:37 UTC (permalink / raw)
To: Paul Eggert; +Cc: monnier, pipcet, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Also, we should remove the fixnump and bignump functions; these
> functions certainly don't need to be in C code and I don't see why
> they even need to be present at all. We shouldn't be giving users
> the impression that the distinction between fixnums and bignums is
> important.
Since it does affect behavior in some cases, we should have those
functions. We can also ask people to write to emacs-devel to report
any time that they find it necessary for code to call them. We might
find out about reasons that didn't occur to us, and then maybe then
we could make them unnecessary.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 19:50 ` Pip Cet
2018-08-20 21:54 ` Andy Moreton
@ 2018-08-21 3:38 ` Richard Stallman
1 sibling, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-08-21 3:38 UTC (permalink / raw)
To: Pip Cet; +Cc: andrewjmoreton, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
To reject fixnump and bignump seems to me like pushing our luck.
It would be wiser to define them and urge people to try to avoid them.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:26 ` Lars Ingebrigtsen
2018-08-20 16:18 ` Eli Zaretskii
@ 2018-08-21 3:38 ` Richard Stallman
2018-08-25 23:27 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-08-21 3:38 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: eliz, eggert, monnier, pipcet, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> I'm pretty sure that I've written code that's essentially along the
> lines of
> (when list-of-numbers
> (let ((i most-positive-fixnum))
> (dolist (a list-of-numbers)
> (setq i (min i a)))
> i))
> to get the smallest number in a set.
This seems to be a real problem.
I wonder -- do most of these instances involve binding
a variable to most-positive-fixnum? If so, that could be a
way to warn about cases that are likely to be wrong, while
skipping other cases.
How many problem cases is this likely to miss?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 15:26 ` Stefan Monnier
2018-08-20 16:19 ` Eli Zaretskii
@ 2018-08-21 15:01 ` Robert Pluim
2018-08-21 19:09 ` Robert Pluim
2018-08-22 20:01 ` Stefan Monnier
1 sibling, 2 replies; 281+ messages in thread
From: Robert Pluim @ 2018-08-21 15:01 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> I don't think we should go as far as removing these functions, as they
>> can still be useful in some situations. Let's not rush.
>
> Agreed. How 'bout we first try to actually make use of bignums?
> E.g. changing Calc to use them instead of its own implementation of bignums?
That probably wouldn't be too hard. Any suggestions for what kind of
tests you'd want of the result?
Robert
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-21 15:01 ` Robert Pluim
@ 2018-08-21 19:09 ` Robert Pluim
2018-08-21 19:35 ` Paul Eggert
2018-08-22 20:01 ` Stefan Monnier
1 sibling, 1 reply; 281+ messages in thread
From: Robert Pluim @ 2018-08-21 19:09 UTC (permalink / raw)
To: emacs-devel
Robert Pluim <rpluim@gmail.com> writes:
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>>> I don't think we should go as far as removing these functions, as they
>>> can still be useful in some situations. Let's not rush.
>>
>> Agreed. How 'bout we first try to actually make use of bignums?
>> E.g. changing Calc to use them instead of its own implementation of bignums?
>
> That probably wouldn't be too hard. Any suggestions for what kind of
> tests you'd want of the result?
First rough cut attached. It works for basic arithmetic stuff, but
still has bugs, eg when using trigonometric functions. I assume itʼs
faster, but havenʼt measured it.
diff --git i/lisp/calc/calc-aent.el w/lisp/calc/calc-aent.el
index 93aacac8cb..4e58ce8ec2 100644
--- i/lisp/calc/calc-aent.el
+++ w/lisp/calc/calc-aent.el
@@ -82,7 +82,7 @@ calc-do-quick-calc
" ")
shortbuf buf)
(if (and (= (length alg-exp) 1)
- (memq (car-safe (car alg-exp)) '(nil bigpos bigneg))
+; (memq (car-safe (car alg-exp)) '(nil bigpos bigneg))
(< (length buf) 20)
(= calc-number-radix 10))
(setq buf (concat buf " ("
diff --git i/lisp/calc/calc-alg.el w/lisp/calc/calc-alg.el
index 7a448d20ec..2440155ae5 100644
--- i/lisp/calc/calc-alg.el
+++ w/lisp/calc/calc-alg.el
@@ -258,9 +258,9 @@ math-beforep
(and (eq comp 0)
(not (equal a b))
(> (length (memq (car-safe a)
- '(bigneg nil bigpos frac float)))
+ '(nil frac float)))
(length (memq (car-safe b)
- '(bigneg nil bigpos frac float))))))))
+ '(nil frac float))))))))
((equal b '(neg (var inf var-inf))) nil)
((equal a '(neg (var inf var-inf))) t)
((equal a '(var inf var-inf)) nil)
diff --git i/lisp/calc/calc-bin.el w/lisp/calc/calc-bin.el
index c05a71a2d7..253e632dee 100644
--- i/lisp/calc/calc-bin.el
+++ w/lisp/calc/calc-bin.el
@@ -273,14 +273,6 @@ calcFunc-and
(math-binary-arg b w)))
w))))
-(defun math-binary-arg (a w)
- (if (not (Math-integerp a))
- (setq a (math-trunc a)))
- (if (Math-integer-negp a)
- (math-not-bignum (cdr (math-bignum-test (math-sub -1 a)))
- (math-abs (if w (math-trunc w) calc-word-size)))
- (cdr (Math-bignum-test a))))
-
(defun math-binary-modulo-args (f a b w)
(let (mod)
(if (eq (car-safe a) 'mod)
@@ -310,14 +302,6 @@ math-binary-modulo-args
(funcall f a w))
mod))))
-(defun math-and-bignum (a b) ; [l l l]
- (and a b
- (let ((qa (math-div-bignum-digit a math-bignum-digit-power-of-two))
- (qb (math-div-bignum-digit b math-bignum-digit-power-of-two)))
- (math-mul-bignum-digit (math-and-bignum (math-norm-bignum (car qa))
- (math-norm-bignum (car qb)))
- math-bignum-digit-power-of-two
- (logand (cdr qa) (cdr qb))))))
(defun calcFunc-or (a b &optional w) ; [I I I] [Public]
(cond ((Math-messy-integerp w)
@@ -337,14 +321,6 @@ calcFunc-or
(math-binary-arg b w)))
w))))
-(defun math-or-bignum (a b) ; [l l l]
- (and (or a b)
- (let ((qa (math-div-bignum-digit a math-bignum-digit-power-of-two))
- (qb (math-div-bignum-digit b math-bignum-digit-power-of-two)))
- (math-mul-bignum-digit (math-or-bignum (math-norm-bignum (car qa))
- (math-norm-bignum (car qb)))
- math-bignum-digit-power-of-two
- (logior (cdr qa) (cdr qb))))))
(defun calcFunc-xor (a b &optional w) ; [I I I] [Public]
(cond ((Math-messy-integerp w)
@@ -364,14 +340,6 @@ calcFunc-xor
(math-binary-arg b w)))
w))))
-(defun math-xor-bignum (a b) ; [l l l]
- (and (or a b)
- (let ((qa (math-div-bignum-digit a math-bignum-digit-power-of-two))
- (qb (math-div-bignum-digit b math-bignum-digit-power-of-two)))
- (math-mul-bignum-digit (math-xor-bignum (math-norm-bignum (car qa))
- (math-norm-bignum (car qb)))
- math-bignum-digit-power-of-two
- (logxor (cdr qa) (cdr qb))))))
(defun calcFunc-diff (a b &optional w) ; [I I I] [Public]
(cond ((Math-messy-integerp w)
@@ -391,14 +359,6 @@ calcFunc-diff
(math-binary-arg b w)))
w))))
-(defun math-diff-bignum (a b) ; [l l l]
- (and a
- (let ((qa (math-div-bignum-digit a math-bignum-digit-power-of-two))
- (qb (math-div-bignum-digit b math-bignum-digit-power-of-two)))
- (math-mul-bignum-digit (math-diff-bignum (math-norm-bignum (car qa))
- (math-norm-bignum (car qb)))
- math-bignum-digit-power-of-two
- (logand (cdr qa) (lognot (cdr qb)))))))
(defun calcFunc-not (a &optional w) ; [I I] [Public]
(cond ((Math-messy-integerp w)
@@ -416,16 +376,6 @@ calcFunc-not
(math-not-bignum (math-binary-arg a w)
w))))))
-(defun math-not-bignum (a w) ; [l l]
- (let ((q (math-div-bignum-digit a math-bignum-digit-power-of-two)))
- (if (<= w math-bignum-logb-digit-size)
- (list (logand (lognot (cdr q))
- (1- (lsh 1 w))))
- (math-mul-bignum-digit (math-not-bignum (math-norm-bignum (car q))
- (- w math-bignum-logb-digit-size))
- math-bignum-digit-power-of-two
- (logxor (cdr q)
- (1- math-bignum-digit-power-of-two))))))
(defun calcFunc-lsh (a &optional n w) ; [I I] [Public]
(setq a (math-trunc a)
diff --git i/lisp/calc/calc-ext.el w/lisp/calc/calc-ext.el
index 5feff23f72..5922ce0acf 100644
--- i/lisp/calc/calc-ext.el
+++ w/lisp/calc/calc-ext.el
@@ -2116,45 +2116,40 @@ math-expand-formulas
;;; True if A is an odd integer. [P R R] [Public]
(defun math-oddp (a)
- (if (consp a)
- (and (memq (car a) '(bigpos bigneg))
- (= (% (nth 1 a) 2) 1))
- (/= (% a 2) 0)))
+ (/= (% a 2) 0))
;;; True if A is a small or big integer. [P x] [Public]
(defun math-integerp (a)
- (or (integerp a)
- (memq (car-safe a) '(bigpos bigneg))))
+ (integerp a))
;;; True if A is (numerically) a non-negative integer. [P N] [Public]
(defun math-natnump (a)
- (or (natnump a)
- (eq (car-safe a) 'bigpos)))
+ (natnump a))
;;; True if A is a rational (or integer). [P x] [Public]
(defun math-ratp (a)
(or (integerp a)
- (memq (car-safe a) '(bigpos bigneg frac))))
+ (eq (car-safe a) 'frac)))
;;; True if A is a real (or rational). [P x] [Public]
(defun math-realp (a)
(or (integerp a)
- (memq (car-safe a) '(bigpos bigneg frac float))))
+ (memq (car-safe a) '(frac float))))
;;; True if A is a real or HMS form. [P x] [Public]
(defun math-anglep (a)
(or (integerp a)
- (memq (car-safe a) '(bigpos bigneg frac float hms))))
+ (memq (car-safe a) '(frac float hms))))
;;; True if A is a number of any kind. [P x] [Public]
(defun math-numberp (a)
(or (integerp a)
- (memq (car-safe a) '(bigpos bigneg frac float cplx polar))))
+ (memq (car-safe a) '(frac float cplx polar))))
;;; True if A is a complex number or angle. [P x] [Public]
(defun math-scalarp (a)
(or (integerp a)
- (memq (car-safe a) '(bigpos bigneg frac float cplx polar hms))))
+ (memq (car-safe a) '(frac float cplx polar hms))))
;;; True if A is a vector. [P x] [Public]
(defun math-vectorp (a)
@@ -2163,13 +2158,13 @@ math-vectorp
;;; True if A is any vector or scalar data object. [P x]
(defun math-objvecp (a) ; [Public]
(or (integerp a)
- (memq (car-safe a) '(bigpos bigneg frac float cplx polar
+ (memq (car-safe a) '(frac float cplx polar
hms date sdev intv mod vec incomplete))))
;;; True if A is an object not composed of sub-formulas . [P x] [Public]
(defun math-primp (a)
(or (integerp a)
- (memq (car-safe a) '(bigpos bigneg frac float cplx polar
+ (memq (car-safe a) '(frac float cplx polar
hms date mod var))))
;;; True if A is numerically (but not literally) an integer. [P x] [Public]
@@ -2186,7 +2181,6 @@ math-num-integerp
;;; True if A is (numerically) a non-negative integer. [P N] [Public]
(defun math-num-natnump (a)
(or (natnump a)
- (eq (car-safe a) 'bigpos)
(and (eq (car-safe a) 'float)
(Math-natnump (nth 1 a))
(>= (nth 2 a) 0))))
@@ -2276,7 +2270,7 @@ math-ident-row-p
;;; True if A is any scalar data object. [P x]
(defun math-objectp (a) ; [Public]
(or (integerp a)
- (memq (car-safe a) '(bigpos bigneg frac float cplx
+ (memq (car-safe a) '(frac float cplx
polar hms date sdev intv mod))))
;;; Verify that A is an integer and return A in integer form. [I N; - x]
@@ -2348,13 +2342,7 @@ math-contains-sdev-p
;;; Coerce integer A to be a small integer. [S I]
(defun math-fixnum (a)
- (if (consp a)
- (if (cdr a)
- (if (eq (car a) 'bigneg)
- (- (math-fixnum-big (cdr a)))
- (math-fixnum-big (cdr a)))
- 0)
- a))
+ a)
(defun math-fixnum-big (a)
(if (cdr a)
@@ -2469,12 +2457,6 @@ math-norm-bignum
(setcdr last nil)
a))))
-(defun math-bignum-test (a) ; [B N; B s; b b]
- (if (consp a)
- a
- (math-bignum a)))
-
-
;;; Return 0 for zero, -1 for negative, 1 for positive. [S n] [Public]
(defun calcFunc-sign (a &optional x)
(let ((signs (math-possible-signs a)))
diff --git i/lisp/calc/calc-macs.el w/lisp/calc/calc-macs.el
index 0a1f552840..8c68e30e6b 100644
--- i/lisp/calc/calc-macs.el
+++ w/lisp/calc/calc-macs.el
@@ -29,9 +29,6 @@
(declare-function math-looks-negp "calc-misc" (a))
(declare-function math-posp "calc-misc" (a))
(declare-function math-compare "calc-ext" (a b))
-(declare-function math-bignum "calc" (a))
-(declare-function math-compare-bignum "calc-ext" (a b))
-
(defmacro calc-wrapper (&rest body)
`(calc-do (function (lambda ()
@@ -70,29 +67,22 @@ calc-with-trail-buffer
;;; Faster in-line version zerop, normalized values only.
(defsubst Math-zerop (a) ; [P N]
(if (consp a)
- (and (not (memq (car a) '(bigpos bigneg)))
- (if (eq (car a) 'float)
- (eq (nth 1 a) 0)
- (math-zerop a)))
+ (if (eq (car a) 'float)
+ (eq (nth 1 a) 0)
+ (math-zerop a))
(eq a 0)))
(defsubst Math-integer-negp (a)
- (if (consp a)
- (eq (car a) 'bigneg)
- (< a 0)))
+ (< a 0))
(defsubst Math-integer-posp (a)
- (if (consp a)
- (eq (car a) 'bigpos)
- (> a 0)))
+ (> a 0))
(defsubst Math-negp (a)
(if (consp a)
- (or (eq (car a) 'bigneg)
- (and (not (eq (car a) 'bigpos))
- (if (memq (car a) '(frac float))
- (Math-integer-negp (nth 1 a))
- (math-negp a))))
+ (if (memq (car a) '(frac float))
+ (Math-integer-negp (nth 1 a))
+ (math-negp a))
(< a 0)))
(defsubst Math-looks-negp (a) ; [P x] [Public]
@@ -104,41 +94,38 @@ Math-looks-negp
(defsubst Math-posp (a)
(if (consp a)
- (or (eq (car a) 'bigpos)
- (and (not (eq (car a) 'bigneg))
- (if (memq (car a) '(frac float))
- (Math-integer-posp (nth 1 a))
- (math-posp a))))
+ (if (memq (car a) '(frac float))
+ (Math-integer-posp (nth 1 a))
+ (math-posp a))
(> a 0)))
(defsubst Math-integerp (a)
- (or (not (consp a))
- (memq (car a) '(bigpos bigneg))))
+ (not (consp a)))
(defsubst Math-natnump (a)
(if (consp a)
- (eq (car a) 'bigpos)
+ nil
(>= a 0)))
(defsubst Math-ratp (a)
(or (not (consp a))
- (memq (car a) '(bigpos bigneg frac))))
+ (eq (car a) 'frac)))
(defsubst Math-realp (a)
(or (not (consp a))
- (memq (car a) '(bigpos bigneg frac float))))
+ (memq (car a) '(frac float))))
(defsubst Math-anglep (a)
(or (not (consp a))
- (memq (car a) '(bigpos bigneg frac float hms))))
+ (memq (car a) '(frac float hms))))
(defsubst Math-numberp (a)
(or (not (consp a))
- (memq (car a) '(bigpos bigneg frac float cplx polar))))
+ (memq (car a) '(frac float cplx polar))))
(defsubst Math-scalarp (a)
(or (not (consp a))
- (memq (car a) '(bigpos bigneg frac float cplx polar hms))))
+ (memq (car a) '(frac float cplx polar hms))))
(defsubst Math-vectorp (a)
(and (consp a) (eq (car a) 'vec)))
@@ -151,21 +138,17 @@ Math-messy-integerp
(defsubst Math-objectp (a) ; [Public]
(or (not (consp a))
(memq (car a)
- '(bigpos bigneg frac float cplx polar hms date sdev intv mod))))
+ '(frac float cplx polar hms date sdev intv mod))))
(defsubst Math-objvecp (a) ; [Public]
(or (not (consp a))
(memq (car a)
- '(bigpos bigneg frac float cplx polar hms date
+ '(frac float cplx polar hms date
sdev intv mod vec))))
;;; Compute the negative of A. [O O; o o] [Public]
(defsubst Math-integer-neg (a)
- (if (consp a)
- (if (eq (car a) 'bigpos)
- (cons 'bigneg (cdr a))
- (cons 'bigpos (cdr a)))
- (- a)))
+ (- a))
(defsubst Math-equal (a b)
(= (math-compare a b) 0))
@@ -175,19 +158,14 @@ Math-lessp
(defsubst Math-primp (a)
(or (not (consp a))
- (memq (car a) '(bigpos bigneg frac float cplx polar
+ (memq (car a) '(frac float cplx polar
hms date mod var))))
(defsubst Math-num-integerp (a)
(or (not (consp a))
- (memq (car a) '(bigpos bigneg))
(and (eq (car a) 'float)
(>= (nth 2 a) 0))))
-(defsubst Math-bignum-test (a) ; [B N; B s; b b]
- (if (consp a)
- a
- (math-bignum a)))
(defsubst Math-equal-int (a b)
(or (eq a b)
diff --git i/lisp/calc/calc-misc.el w/lisp/calc/calc-misc.el
index 29e8510413..eebfe3834b 100644
--- i/lisp/calc/calc-misc.el
+++ w/lisp/calc/calc-misc.el
@@ -658,10 +658,7 @@ math-concat
;;;###autoload
(defun math-zerop (a)
(if (consp a)
- (cond ((memq (car a) '(bigpos bigneg))
- (while (eq (car (setq a (cdr a))) 0))
- (null a))
- ((memq (car a) '(frac float polar mod))
+ (cond ((memq (car a) '(frac float polar mod))
(math-zerop (nth 1 a)))
((eq (car a) 'cplx)
(and (math-zerop (nth 1 a)) (math-zerop (nth 2 a))))
@@ -677,9 +674,7 @@ math-zerop
;;;###autoload
(defun math-negp (a)
(if (consp a)
- (cond ((eq (car a) 'bigpos) nil)
- ((eq (car a) 'bigneg) (cdr a))
- ((memq (car a) '(float frac))
+ (cond ((memq (car a) '(float frac))
(Math-integer-negp (nth 1 a)))
((eq (car a) 'hms)
(if (math-zerop (nth 1 a))
@@ -712,9 +707,7 @@ math-looks-negp
;;;###autoload
(defun math-posp (a)
(if (consp a)
- (cond ((eq (car a) 'bigpos) (cdr a))
- ((eq (car a) 'bigneg) nil)
- ((memq (car a) '(float frac))
+ (cond ((memq (car a) '(float frac))
(Math-integer-posp (nth 1 a)))
((eq (car a) 'hms)
(if (math-zerop (nth 1 a))
@@ -742,20 +735,13 @@ 'math-fixnatnump
;; True if A is an even integer. [P R R] [Public]
;;;###autoload
(defun math-evenp (a)
- (if (consp a)
- (and (memq (car a) '(bigpos bigneg))
- (= (% (nth 1 a) 2) 0))
- (= (% a 2) 0)))
+ (= (% a 2) 0))
;; Compute A / 2, for small or big integer A. [I i]
;; If A is negative, type of truncation is undefined.
;;;###autoload
(defun math-div2 (a)
- (if (consp a)
- (if (cdr a)
- (math-normalize (cons (car a) (math-div2-bignum (cdr a))))
- 0)
- (/ a 2)))
+ (/ a 2))
;;;###autoload
(defun math-div2-bignum (a) ; [l l]
diff --git i/lisp/calc/calc.el w/lisp/calc/calc.el
index 4bebd5f47b..cdf4580dde 100644
--- i/lisp/calc/calc.el
+++ w/lisp/calc/calc.el
@@ -2627,42 +2627,7 @@ math-normalize
(setq math-normalize-error nil)
(cond
((not (consp math-normalize-a))
- (if (integerp math-normalize-a)
- (if (or (>= math-normalize-a math-small-integer-size)
- (<= math-normalize-a (- math-small-integer-size)))
- (math-bignum math-normalize-a)
- math-normalize-a)
- math-normalize-a))
- ((eq (car math-normalize-a) 'bigpos)
- (if (eq (nth (1- (length math-normalize-a)) math-normalize-a) 0)
- (let* ((last (setq math-normalize-a
- (copy-sequence math-normalize-a))) (digs math-normalize-a))
- (while (setq digs (cdr digs))
- (or (eq (car digs) 0) (setq last digs)))
- (setcdr last nil)))
- (if (cdr (cdr (cdr math-normalize-a)))
- math-normalize-a
- (cond
- ((cdr (cdr math-normalize-a)) (+ (nth 1 math-normalize-a)
- (* (nth 2 math-normalize-a)
- math-bignum-digit-size)))
- ((cdr math-normalize-a) (nth 1 math-normalize-a))
- (t 0))))
- ((eq (car math-normalize-a) 'bigneg)
- (if (eq (nth (1- (length math-normalize-a)) math-normalize-a) 0)
- (let* ((last (setq math-normalize-a (copy-sequence math-normalize-a)))
- (digs math-normalize-a))
- (while (setq digs (cdr digs))
- (or (eq (car digs) 0) (setq last digs)))
- (setcdr last nil)))
- (if (cdr (cdr (cdr math-normalize-a)))
- math-normalize-a
- (cond
- ((cdr (cdr math-normalize-a)) (- (+ (nth 1 math-normalize-a)
- (* (nth 2 math-normalize-a)
- math-bignum-digit-size))))
- ((cdr math-normalize-a) (- (nth 1 math-normalize-a)))
- (t 0))))
+ math-normalize-a)
((eq (car math-normalize-a) 'float)
(math-make-float (math-normalize (nth 1 math-normalize-a))
(nth 2 math-normalize-a)))
@@ -2774,30 +2739,6 @@ math-check-complete
((consp a) a)
(t (error "Invalid data object encountered"))))
-
-
-;; Coerce integer A to be a bignum. [B S]
-(defun math-bignum (a)
- (cond
- ((>= a 0)
- (cons 'bigpos (math-bignum-big a)))
- ((= a most-negative-fixnum)
- ;; Note: cannot get the negation directly because
- ;; (- most-negative-fixnum) is most-negative-fixnum.
- ;;
- ;; most-negative-fixnum := -most-positive-fixnum - 1
- (math-sub (cons 'bigneg (math-bignum-big most-positive-fixnum))
- 1))
- (t
- (cons 'bigneg (math-bignum-big (- a))))))
-
-(defun math-bignum-big (a) ; [L s]
- (if (= a 0)
- nil
- (cons (% a math-bignum-digit-size)
- (math-bignum-big (/ a math-bignum-digit-size)))))
-
-
;; Build a normalized floating-point number. [F I S]
(defun math-make-float (mant exp)
(if (eq mant 0)
@@ -2847,8 +2788,6 @@ math-float
(defun math-neg (a)
(cond ((not (consp a)) (- a))
- ((eq (car a) 'bigpos) (cons 'bigneg (cdr a)))
- ((eq (car a) 'bigneg) (cons 'bigpos (cdr a)))
((memq (car a) '(frac float))
(list (car a) (Math-integer-neg (nth 1 a)) (nth 2 a)))
((memq (car a) '(cplx vec hms date calcFunc-idn))
@@ -2881,76 +2820,23 @@ math-scale-int
(defun math-scale-left (a n) ; [I I S]
(if (= n 0)
a
- (if (consp a)
- (cons (car a) (math-scale-left-bignum (cdr a) n))
- (if (>= n math-bignum-digit-length)
- (if (or (>= a math-bignum-digit-size)
- (<= a (- math-bignum-digit-size)))
- (math-scale-left (math-bignum a) n)
- (math-scale-left (* a math-bignum-digit-size)
- (- n math-bignum-digit-length)))
- (let ((sz (expt 10 (- (* 2 math-bignum-digit-length) n))))
- (if (or (>= a sz) (<= a (- sz)))
- (math-scale-left (math-bignum a) n)
- (* a (expt 10 n))))))))
-
-(defun math-scale-left-bignum (a n)
- (if (>= n math-bignum-digit-length)
- (while (>= (setq a (cons 0 a)
- n (- n math-bignum-digit-length))
- math-bignum-digit-length)))
- (if (> n 0)
- (math-mul-bignum-digit a (expt 10 n) 0)
- a))
+ (* a (expt 10 n))))
(defun math-scale-right (a n) ; [i i S]
(if (= n 0)
a
- (if (consp a)
- (cons (car a) (math-scale-right-bignum (cdr a) n))
- (if (<= a 0)
- (if (= a 0)
- 0
- (- (math-scale-right (- a) n)))
- (if (>= n math-bignum-digit-length)
- (while (and (> (setq a (/ a math-bignum-digit-size)) 0)
- (>= (setq n (- n math-bignum-digit-length))
- math-bignum-digit-length))))
- (if (> n 0)
- (/ a (expt 10 n))
- a)))))
-
-(defun math-scale-right-bignum (a n) ; [L L S; l l S]
- (if (>= n math-bignum-digit-length)
- (setq a (nthcdr (/ n math-bignum-digit-length) a)
- n (% n math-bignum-digit-length)))
- (if (> n 0)
- (cdr (math-mul-bignum-digit a (expt 10 (- math-bignum-digit-length n)) 0))
- a))
+ (if (<= a 0)
+ (if (= a 0)
+ 0
+ (- (math-scale-right (- a) n)))
+ (if (> n 0)
+ (/ a (expt 10 n))
+ a))))
;;; Multiply (with rounding) the integer A by 10^N. [I i S]
(defun math-scale-rounding (a n)
(cond ((>= n 0)
(math-scale-left a n))
- ((consp a)
- (math-normalize
- (cons (car a)
- (let ((val (if (< n (- math-bignum-digit-length))
- (math-scale-right-bignum
- (cdr a)
- (- (- math-bignum-digit-length) n))
- (if (< n 0)
- (math-mul-bignum-digit
- (cdr a)
- (expt 10 (+ math-bignum-digit-length n)) 0)
- (cdr a))))) ; n = -math-bignum-digit-length
- (if (and val (>= (car val) (/ math-bignum-digit-size 2)))
- (if (cdr val)
- (if (eq (car (cdr val)) (1- math-bignum-digit-size))
- (math-add-bignum (cdr val) '(1))
- (cons (1+ (car (cdr val))) (cdr (cdr val))))
- '(1))
- (cdr val))))))
(t
(if (< a 0)
(- (math-scale-rounding (- a) n))
@@ -2963,36 +2849,13 @@ math-scale-rounding
(defun math-add (a b)
(or
(and (not (or (consp a) (consp b)))
- (progn
- (setq a (+ a b))
- (if (or (<= a (- math-small-integer-size)) (>= a math-small-integer-size))
- (math-bignum a)
- a)))
+ (+ a b))
(and (Math-zerop a) (not (eq (car-safe a) 'mod))
(if (and (math-floatp a) (Math-ratp b)) (math-float b) b))
(and (Math-zerop b) (not (eq (car-safe b) 'mod))
(if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
(and (Math-objvecp a) (Math-objvecp b)
(or
- (and (Math-integerp a) (Math-integerp b)
- (progn
- (or (consp a) (setq a (math-bignum a)))
- (or (consp b) (setq b (math-bignum b)))
- (if (eq (car a) 'bigneg)
- (if (eq (car b) 'bigneg)
- (cons 'bigneg (math-add-bignum (cdr a) (cdr b)))
- (math-normalize
- (let ((diff (math-sub-bignum (cdr b) (cdr a))))
- (if (eq diff 'neg)
- (cons 'bigneg (math-sub-bignum (cdr a) (cdr b)))
- (cons 'bigpos diff)))))
- (if (eq (car b) 'bigneg)
- (math-normalize
- (let ((diff (math-sub-bignum (cdr a) (cdr b))))
- (if (eq diff 'neg)
- (cons 'bigneg (math-sub-bignum (cdr b) (cdr a)))
- (cons 'bigpos diff))))
- (cons 'bigpos (math-add-bignum (cdr a) (cdr b)))))))
(and (Math-ratp a) (Math-ratp b)
(require 'calc-ext)
(calc-add-fractions a b))
@@ -3008,78 +2871,6 @@ math-add
(and (require 'calc-ext)
(math-add-symb-fancy a b))))
-(defun math-add-bignum (a b) ; [L L L; l l l]
- (if a
- (if b
- (let* ((a (copy-sequence a)) (aa a) (carry nil) sum)
- (while (and aa b)
- (if carry
- (if (< (setq sum (+ (car aa) (car b)))
- (1- math-bignum-digit-size))
- (progn
- (setcar aa (1+ sum))
- (setq carry nil))
- (setcar aa (- sum (1- math-bignum-digit-size))))
- (if (< (setq sum (+ (car aa) (car b))) math-bignum-digit-size)
- (setcar aa sum)
- (setcar aa (- sum math-bignum-digit-size))
- (setq carry t)))
- (setq aa (cdr aa)
- b (cdr b)))
- (if carry
- (if b
- (nconc a (math-add-bignum b '(1)))
- (while (eq (car aa) (1- math-bignum-digit-size))
- (setcar aa 0)
- (setq aa (cdr aa)))
- (if aa
- (progn
- (setcar aa (1+ (car aa)))
- a)
- (nconc a '(1))))
- (if b
- (nconc a b)
- a)))
- a)
- b))
-
-(defun math-sub-bignum (a b) ; [l l l]
- (if b
- (if a
- (let* ((a (copy-sequence a)) (aa a) (borrow nil) diff)
- (while (and aa b)
- (if borrow
- (if (>= (setq diff (- (car aa) (car b))) 1)
- (progn
- (setcar aa (1- diff))
- (setq borrow nil))
- (setcar aa (+ diff (1- math-bignum-digit-size))))
- (if (>= (setq diff (- (car aa) (car b))) 0)
- (setcar aa diff)
- (setcar aa (+ diff math-bignum-digit-size))
- (setq borrow t)))
- (setq aa (cdr aa)
- b (cdr b)))
- (if borrow
- (progn
- (while (eq (car aa) 0)
- (setcar aa (1- math-bignum-digit-size))
- (setq aa (cdr aa)))
- (if aa
- (progn
- (setcar aa (1- (car aa)))
- a)
- 'neg))
- (while (eq (car b) 0)
- (setq b (cdr b)))
- (if b
- 'neg
- a)))
- (while (eq (car b) 0)
- (setq b (cdr b)))
- (and b
- 'neg))
- a))
(defun math-add-float (a b) ; [F F F]
(let ((ediff (- (nth 2 a) (nth 2 b))))
@@ -3100,12 +2891,7 @@ math-add-float
;;; Compute the difference of A and B. [O O O] [Public]
(defun math-sub (a b)
- (if (or (consp a) (consp b))
- (math-add a (math-neg b))
- (setq a (- a b))
- (if (or (<= a (- math-small-integer-size)) (>= a math-small-integer-size))
- (math-bignum a)
- a)))
+ (- a b))
(defun math-sub-float (a b) ; [F F F]
(let ((ediff (- (nth 2 a) (nth 2 b))))
@@ -3130,8 +2916,6 @@ math-sub-float
(defun math-mul (a b)
(or
(and (not (consp a)) (not (consp b))
- (< a math-bignum-digit-size) (> a (- math-bignum-digit-size))
- (< b math-bignum-digit-size) (> b (- math-bignum-digit-size))
(* a b))
(and (Math-zerop a) (not (eq (car-safe b) 'mod))
(if (Math-scalarp b)
@@ -3145,17 +2929,6 @@ math-mul
(math-mul-zero b a)))
(and (Math-objvecp a) (Math-objvecp b)
(or
- (and (Math-integerp a) (Math-integerp b)
- (progn
- (or (consp a) (setq a (math-bignum a)))
- (or (consp b) (setq b (math-bignum b)))
- (math-normalize
- (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
- (if (cdr (cdr a))
- (if (cdr (cdr b))
- (math-mul-bignum (cdr a) (cdr b))
- (math-mul-bignum-digit (cdr a) (nth 1 b) 0))
- (math-mul-bignum-digit (cdr b) (nth 1 a) 0))))))
(and (Math-ratp a) (Math-ratp b)
(require 'calc-ext)
(calc-mul-fractions a b))
@@ -3184,51 +2957,6 @@ math-infinitep
'(var uinf var-uinf)
a)))
-;;; Multiply digit lists A and B. [L L L; l l l]
-(defun math-mul-bignum (a b)
- (and a b
- (let* ((sum (if (<= (car b) 1)
- (if (= (car b) 0)
- (list 0)
- (copy-sequence a))
- (math-mul-bignum-digit a (car b) 0)))
- (sump sum) c d aa ss prod)
- (while (setq b (cdr b))
- (setq ss (setq sump (or (cdr sump) (setcdr sump (list 0))))
- d (car b)
- c 0
- aa a)
- (while (progn
- (setcar ss (% (setq prod (+ (+ (car ss) (* (car aa) d))
- c))
- math-bignum-digit-size))
- (setq aa (cdr aa)))
- (setq c (/ prod math-bignum-digit-size)
- ss (or (cdr ss) (setcdr ss (list 0)))))
- (if (>= prod math-bignum-digit-size)
- (if (cdr ss)
- (setcar (cdr ss) (+ (/ prod math-bignum-digit-size) (car (cdr ss))))
- (setcdr ss (list (/ prod math-bignum-digit-size))))))
- sum)))
-
-;;; Multiply digit list A by digit D. [L L D D; l l D D]
-(defun math-mul-bignum-digit (a d c)
- (if a
- (if (<= d 1)
- (and (= d 1) a)
- (let* ((a (copy-sequence a)) (aa a) prod)
- (while (progn
- (setcar aa
- (% (setq prod (+ (* (car aa) d) c))
- math-bignum-digit-size))
- (cdr aa))
- (setq aa (cdr aa)
- c (/ prod math-bignum-digit-size)))
- (if (>= prod math-bignum-digit-size)
- (setcdr aa (list (/ prod math-bignum-digit-size))))
- a))
- (and (> c 0)
- (list c))))
;;; Compute the integer (quotient . remainder) of A and B, which may be
@@ -3237,93 +2965,12 @@ math-mul-bignum-digit
(defun math-idivmod (a b)
(if (eq b 0)
(math-reject-arg a "*Division by zero"))
- (if (or (consp a) (consp b))
- (if (and (natnump b) (< b math-bignum-digit-size))
- (let ((res (math-div-bignum-digit (cdr a) b)))
- (cons
- (math-normalize (cons (car a) (car res)))
- (cdr res)))
- (or (consp a) (setq a (math-bignum a)))
- (or (consp b) (setq b (math-bignum b)))
- (let ((res (math-div-bignum (cdr a) (cdr b))))
- (cons
- (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
- (car res)))
- (math-normalize (cons (car a) (cdr res))))))
- (cons (/ a b) (% a b))))
+ (cons (/ a b) (% a b)))
(defun math-quotient (a b) ; [I I I] [Public]
- (if (and (not (consp a)) (not (consp b)))
- (if (= b 0)
- (math-reject-arg a "*Division by zero")
- (/ a b))
- (if (and (natnump b) (< b math-bignum-digit-size))
- (if (= b 0)
- (math-reject-arg a "*Division by zero")
- (math-normalize (cons (car a)
- (car (math-div-bignum-digit (cdr a) b)))))
- (or (consp a) (setq a (math-bignum a)))
- (or (consp b) (setq b (math-bignum b)))
- (let* ((alen (1- (length a)))
- (blen (1- (length b)))
- (d (/ math-bignum-digit-size (1+ (nth (1- blen) (cdr b)))))
- (res (math-div-bignum-big (math-mul-bignum-digit (cdr a) d 0)
- (math-mul-bignum-digit (cdr b) d 0)
- alen blen)))
- (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
- (car res)))))))
-
-
-;;; Divide a bignum digit list by another. [l.l l L]
-;;; The following division algorithm is borrowed from Knuth vol. II, sec. 4.3.1
-(defun math-div-bignum (a b)
- (if (cdr b)
- (let* ((alen (length a))
- (blen (length b))
- (d (/ math-bignum-digit-size (1+ (nth (1- blen) b))))
- (res (math-div-bignum-big (math-mul-bignum-digit a d 0)
- (math-mul-bignum-digit b d 0)
- alen blen)))
- (if (= d 1)
- res
- (cons (car res)
- (car (math-div-bignum-digit (cdr res) d)))))
- (let ((res (math-div-bignum-digit a (car b))))
- (cons (car res) (list (cdr res))))))
-
-;;; Divide a bignum digit list by a digit. [l.D l D]
-(defun math-div-bignum-digit (a b)
- (if a
- (let* ((res (math-div-bignum-digit (cdr a) b))
- (num (+ (* (cdr res) math-bignum-digit-size) (car a))))
- (cons
- (cons (/ num b) (car res))
- (% num b)))
- '(nil . 0)))
-
-(defun math-div-bignum-big (a b alen blen) ; [l.l l L]
- (if (< alen blen)
- (cons nil a)
- (let* ((res (math-div-bignum-big (cdr a) b (1- alen) blen))
- (num (cons (car a) (cdr res)))
- (res2 (math-div-bignum-part num b blen)))
- (cons
- (cons (car res2) (car res))
- (cdr res2)))))
-
-(defun math-div-bignum-part (a b blen) ; a < b*math-bignum-digit-size [D.l l L]
- (let* ((num (+ (* (or (nth blen a) 0) math-bignum-digit-size)
- (or (nth (1- blen) a) 0)))
- (den (nth (1- blen) b))
- (guess (min (/ num den) (1- math-bignum-digit-size))))
- (math-div-bignum-try a b (math-mul-bignum-digit b guess 0) guess)))
-
-(defun math-div-bignum-try (a b c guess) ; [D.l l l D]
- (let ((rem (math-sub-bignum a c)))
- (if (eq rem 'neg)
- (math-div-bignum-try a b (math-sub-bignum c b) (1- guess))
- (cons guess rem))))
-
+ (if (= b 0)
+ (math-reject-arg a "*Division by zero")
+ (/ a b)))
;;; Compute the quotient of A and B. [O O N] [Public]
(defun math-div (a b)
@@ -3548,11 +3195,11 @@ math-format-number
(math-format-binary a)
(math-format-radix a))))
(math-format-radix a))))
- (math-format-number (math-bignum a))))
+ (math-format-bignum a)))
((stringp a) a)
((not (consp a)) (prin1-to-string a))
- ((eq (car a) 'bigpos) (math-format-bignum (cdr a)))
- ((eq (car a) 'bigneg) (concat "-" (math-format-bignum (cdr a))))
+ ((eq (car a) 'bigpos) (error "bignum found"))
+ ((eq (car a) 'bigneg) (error "bignum found"))
((and (eq (car a) 'float) (= calc-number-radix 10))
(if (Math-integer-negp (nth 1 a))
(concat "-" (math-format-number (math-neg a)))
@@ -3642,21 +3289,7 @@ math-format-bignum
(math-format-bignum-fancy a)))
(defun math-format-bignum-decimal (a) ; [X L]
- (if a
- (let ((s ""))
- (while (cdr (cdr a))
- (setq s (concat
- (format
- (concat "%0"
- (number-to-string (* 2 math-bignum-digit-length))
- "d")
- (+ (* (nth 1 a) math-bignum-digit-size) (car a))) s)
- a (cdr (cdr a))))
- (concat (int-to-string
- (+ (* (or (nth 1 a) 0) math-bignum-digit-size) (car a))) s))
- "0"))
-
-
+ (number-to-string a))
;;; Parse a simple number in string form. [N X] [Public]
(defun math-read-number (s &optional decimal)
@@ -3673,9 +3306,7 @@ math-read-number
(eq (aref digs 0) ?0)
(null decimal))
(math-read-number (concat "8#" digs))
- (if (<= (length digs) (* 2 math-bignum-digit-length))
- (string-to-number digs)
- (cons 'bigpos (math-read-bignum digs))))))
+ (string-to-number digs))))
;; Clean up the string if necessary
((string-match "\\`\\(.*\\)[ \t\n]+\\([^\001]*\\)\\'" s)
@@ -3730,14 +3361,10 @@ math-read-number-simple
((string-match "^[0-9]+$" s)
(if (string-match "^\\(0+\\)" s)
(setq s (substring s (match-end 0))))
- (if (<= (length s) (* 2 math-bignum-digit-length))
- (string-to-number s)
- (cons 'bigpos (math-read-bignum s))))
+ (string-to-number s))
;; Minus sign
((string-match "^-[0-9]+$" s)
- (if (<= (length s) (1+ (* 2 math-bignum-digit-length)))
- (string-to-number s)
- (cons 'bigneg (math-read-bignum (substring s 1)))))
+ (string-to-number s))
;; Decimal point
((string-match "^\\(-?[0-9]*\\)\\.\\([0-9]*\\)$" s)
(let ((int (math-match-substring s 1))
diff --git i/test/lisp/calc/calc-tests.el w/test/lisp/calc/calc-tests.el
index fbd5f0e3a1..6f17ed3691 100644
--- i/test/lisp/calc/calc-tests.el
+++ w/test/lisp/calc/calc-tests.el
@@ -62,12 +62,6 @@ calc-tests-simple
(calc-top-n 1))
(calc-pop 0)))
-(ert-deftest test-math-bignum ()
- ;; bug#17556
- (let ((n (math-bignum most-negative-fixnum)))
- (should (math-negp n))
- (should (cl-notany #'cl-minusp (cdr n)))))
-
(ert-deftest test-calc-remove-units ()
(should (calc-tests-equal (calc-tests-simple #'calc-remove-units "-1 m") -1)))
^ permalink raw reply related [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-21 19:09 ` Robert Pluim
@ 2018-08-21 19:35 ` Paul Eggert
2018-08-22 8:26 ` Lars Ingebrigtsen
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-21 19:35 UTC (permalink / raw)
To: emacs-devel
Robert Pluim wrote:
> First rough cut attached. It works for basic arithmetic stuff, but
> still has bugs, eg when using trigonometric functions. I assume itʼs
> faster, but havenʼt measured it.
This looks promising; thanks for looking into it.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-21 19:35 ` Paul Eggert
@ 2018-08-22 8:26 ` Lars Ingebrigtsen
2018-08-22 13:22 ` Herring, Davis
0 siblings, 1 reply; 281+ messages in thread
From: Lars Ingebrigtsen @ 2018-08-22 8:26 UTC (permalink / raw)
To: emacs-devel
Slightly off-topic, but I thought it was amusing:
I was reading a blog post on C over/underruns, and I got to this bit:
Note that there is no value than can hold 2147483648, so if you
negate (int)0x80000000, you get (int)0x80000000 again. That is
something to look out for, because it means abs() returns a
negative value when fed -2147483648.
I didn't know that, and indeed in Emacs until a few weeks ago:
(abs most-negative-fixnum) => -2305843009213693952
Now, of course, with bignum support, we get a more correct result:
(abs most-negative-fixnum) => 2305843009213693952
(bignump (abs most-negative-fixnum)) => t
So now we don't have to fix the documentation of `abs':
---
abs is a built-in function in ‘C source code’.
(abs ARG)
Return the absolute value of ARG.
---
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-22 8:26 ` Lars Ingebrigtsen
@ 2018-08-22 13:22 ` Herring, Davis
2018-08-22 13:28 ` Lars Ingebrigtsen
2018-08-22 13:55 ` Paul Eggert
0 siblings, 2 replies; 281+ messages in thread
From: Herring, Davis @ 2018-08-22 13:22 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: emacs-devel@gnu.org
> I was reading a blog post on C over/underruns, and I got to this bit:
>
> Note that there is no value than can hold 2147483648, so if you
> negate (int)0x80000000, you get (int)0x80000000 again. That is
> something to look out for, because it means abs() returns a
> negative value when fed -2147483648.
>
> I didn't know that, [...]
You still don't, because C doesn't work that way. Even writing (int)0x80000000 (on a system with suitably-sized ints) is implementation-defined <https://en.cppreference.com/w/c/language/conversion#Integer_conversions>. Applying - to it (on almost any system) is overflow and hence undefined behavior <https://en.cppreference.com/w/c/language/operator_arithmetic#Unary_arithmetic>.
Of course, you have observed the "correctness" of this statement, but that's because it has well-defined (if surprising) behavior in (at least) x86 assembly <https://stackoverflow.com/questions/26440463/does-neg-instruction-in-assembly-language-sets-the-overflow-flag> and, formally, that _happened_ to be the manifestation of the undefined behavior (in the C implementation of Emacs).
On the gripping hand, when the compiler can't prove anything about an integer argument, it is reasonable for us to assume that this will be the behavior; this is far from the only place in Emacs where what is formally undefined behavior is expected to "do the obvious thing". But it's wrong for "a blog post on C" to say that is unconditionally the behavior.
Davis
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-22 13:22 ` Herring, Davis
@ 2018-08-22 13:28 ` Lars Ingebrigtsen
2018-08-22 13:55 ` Paul Eggert
1 sibling, 0 replies; 281+ messages in thread
From: Lars Ingebrigtsen @ 2018-08-22 13:28 UTC (permalink / raw)
To: Herring, Davis; +Cc: emacs-devel@gnu.org
"Herring, Davis" <herring@lanl.gov> writes:
> But it's wrong for "a blog post on C" to say that is unconditionally
> the behavior.
It doesn't. There are caveats galore, but including them all
(ones-complement machines and other obscure things, other word sizes
etc) didn't seem very interesting to me in an Emacs bignum context.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-22 13:22 ` Herring, Davis
2018-08-22 13:28 ` Lars Ingebrigtsen
@ 2018-08-22 13:55 ` Paul Eggert
1 sibling, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-22 13:55 UTC (permalink / raw)
To: Herring, Davis, Lars Ingebrigtsen; +Cc: emacs-devel@gnu.org
Herring, Davis wrote:
> this is far from the only place in Emacs where what is formally undefined behavior is expected to "do the obvious thing"
Emacs does not rely on undefined behavior for integer arithmetic. Even in Emacs
26, (abs most-negative-fixnum) yields most-negative-fixnum without doing
anything undefined at the C level, because (- most-negative-fixnum) fits within
machine limits and the tagging operation does not overflow.
Although there may be a few places left in Emacs that rely on undefined integer
behavior, these are now considered bugs and occasionally I try to stamp them out
by building with gcc -fsanitize=undefined. For example, in Emacs 26 (*
most-positive-fixnum most-positive-fixnum) returns 1 (the overflowed value)
without overflowing at the C level.
Emacs *does* rely on undefined behavior when it tags pointers, but that's a
different kettle of fish.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-20 16:18 ` Eli Zaretskii
@ 2018-08-22 19:59 ` Stefan Monnier
0 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-22 19:59 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Lars Ingebrigtsen, eggert, pipcet, emacs-devel
>> So perhaps a warning might be warranted?
> Too annoying, IMO.
Agreed. I think for now a "grep" is more appropriate,
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-21 15:01 ` Robert Pluim
2018-08-21 19:09 ` Robert Pluim
@ 2018-08-22 20:01 ` Stefan Monnier
2018-08-23 8:13 ` Robert Pluim
1 sibling, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-08-22 20:01 UTC (permalink / raw)
To: emacs-devel
>>> I don't think we should go as far as removing these functions, as they
>>> can still be useful in some situations. Let's not rush.
>> Agreed. How 'bout we first try to actually make use of bignums?
>> E.g. changing Calc to use them instead of its own implementation of bignums?
> That probably wouldn't be too hard.
IIUC, such changes have already been applied to the Calc that's
distributed with SXEmacs (where Calc's former maintainer moved), so it's
probably worth looking at that code (and associated doc).
> Any suggestions for what kind of tests you'd want of the result?
Fast and exhaustive tests, of course ;-)
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-22 20:01 ` Stefan Monnier
@ 2018-08-23 8:13 ` Robert Pluim
2018-08-23 13:45 ` Eli Zaretskii
2018-08-23 18:43 ` Stefan Monnier
0 siblings, 2 replies; 281+ messages in thread
From: Robert Pluim @ 2018-08-23 8:13 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
>>>> I don't think we should go as far as removing these functions, as they
>>>> can still be useful in some situations. Let's not rush.
>>> Agreed. How 'bout we first try to actually make use of bignums?
>>> E.g. changing Calc to use them instead of its own implementation of bignums?
>> That probably wouldn't be too hard.
>
> IIUC, such changes have already been applied to the Calc that's
> distributed with SXEmacs (where Calc's former maintainer moved), so it's
> probably worth looking at that code (and associated doc).
I didnʼt know about that. Would there be any issue with merging such
changes back to emacs? I assume itʼs all GPL, but there might be
copyright assignment issues.
>> Any suggestions for what kind of tests you'd want of the result?
>
> Fast and exhaustive tests, of course ;-)
It passes the test-suite, which has 5 tests :-)
In terms of speed:
(require 'calc-units)
(dotimes (i 10)
(benchmark 1
'(dotimes (i 10000)
(calcFunc-mul 230584300921369395100000000
10000000000000000000000000000000000000000
234287928374298347289374298347234782937428934723489729374823
7492837429837))))
master:
Elapsed time: 0.687519s (0.114858s in 15 GCs)
Elapsed time: 0.683179s (0.122283s in 14 GCs)
Elapsed time: 0.688424s (0.125096s in 15 GCs)
Elapsed time: 0.683192s (0.117345s in 14 GCs)
Elapsed time: 0.691941s (0.127961s in 15 GCs)
Elapsed time: 0.692849s (0.126826s in 15 GCs)
Elapsed time: 0.679750s (0.116932s in 14 GCs)
Elapsed time: 0.682929s (0.122974s in 15 GCs)
Elapsed time: 0.689449s (0.125723s in 15 GCs)
Elapsed time: 0.707762s (0.114604s in 14 GCs)
master using native bignums:
Elapsed time: 0.074445s (0.028334s in 4 GCs)
Elapsed time: 0.057261s (0.022541s in 3 GCs)
Elapsed time: 0.063773s (0.030844s in 4 GCs)
Elapsed time: 0.056425s (0.023070s in 3 GCs)
Elapsed time: 0.065788s (0.031533s in 4 GCs)
Elapsed time: 0.065265s (0.031403s in 4 GCs)
Elapsed time: 0.056984s (0.022835s in 3 GCs)
Elapsed time: 0.064079s (0.030197s in 4 GCs)
Elapsed time: 0.057158s (0.023442s in 3 GCs)
Elapsed time: 0.071579s (0.035323s in 4 GCs)
so using native bignums appears to be ~10x faster that calc's bignums,
and create less garbage.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-23 8:13 ` Robert Pluim
@ 2018-08-23 13:45 ` Eli Zaretskii
2018-08-23 14:48 ` Robert Pluim
2018-08-23 18:43 ` Stefan Monnier
1 sibling, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-23 13:45 UTC (permalink / raw)
To: Robert Pluim; +Cc: emacs-devel
> From: Robert Pluim <rpluim@gmail.com>
> Date: Thu, 23 Aug 2018 10:13:38 +0200
> Cc: emacs-devel@gnu.org
>
> > IIUC, such changes have already been applied to the Calc that's
> > distributed with SXEmacs (where Calc's former maintainer moved), so it's
> > probably worth looking at that code (and associated doc).
>
> I didnʼt know about that. Would there be any issue with merging such
> changes back to emacs? I assume itʼs all GPL, but there might be
> copyright assignment issues.
I presume the changes are beyond the dozen or so lines which we are
allowed to accept without copyright assignment, in which case this
will require legal paperwork as a prerequisite.
> so using native bignums appears to be ~10x faster that calc's bignums,
> and create less garbage.
Sounds great, thanks for working on this.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-23 13:45 ` Eli Zaretskii
@ 2018-08-23 14:48 ` Robert Pluim
0 siblings, 0 replies; 281+ messages in thread
From: Robert Pluim @ 2018-08-23 14:48 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
>> From: Robert Pluim <rpluim@gmail.com>
>> Date: Thu, 23 Aug 2018 10:13:38 +0200
>> Cc: emacs-devel@gnu.org
>>
>> > IIUC, such changes have already been applied to the Calc that's
>> > distributed with SXEmacs (where Calc's former maintainer moved), so it's
>> > probably worth looking at that code (and associated doc).
>>
>> I didnʼt know about that. Would there be any issue with merging such
>> changes back to emacs? I assume itʼs all GPL, but there might be
>> copyright assignment issues.
>
> I presume the changes are beyond the dozen or so lines which we are
> allowed to accept without copyright assignment, in which case this
> will require legal paperwork as a prerequisite.
My current patch is ~1200 lines, and incomplete, so yes. Although
given that I can't locate those calc changes on the SXEmacs website,
the point is kind of moot anyway.
Robert
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-23 8:13 ` Robert Pluim
2018-08-23 13:45 ` Eli Zaretskii
@ 2018-08-23 18:43 ` Stefan Monnier
2018-08-24 9:51 ` Robert Pluim
1 sibling, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-08-23 18:43 UTC (permalink / raw)
To: emacs-devel
> I didnʼt know about that. Would there be any issue with merging such
> changes back to emacs? I assume itʼs all GPL, but there might be
> copyright assignment issues.
He signed the paperwork (back when he was maintaining Emacs's Calc), so
there shouldn't be any issue in this respect.
It'd be good to tell him about this change in Emacs, tho. He may be
convinced to come back to Emacs now ;-)
>> Fast and exhaustive tests, of course ;-)
> It passes the test-suite, which has 5 tests :-)
All the tests? That sounds like "exhaustive" to me!
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-23 18:43 ` Stefan Monnier
@ 2018-08-24 9:51 ` Robert Pluim
2018-08-25 17:59 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Robert Pluim @ 2018-08-24 9:51 UTC (permalink / raw)
To: emacs-devel
Robert Pluim <rpluim@gmail.com> writes:
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>>> I didnʼt know about that. Would there be any issue with merging such
>>> changes back to emacs? I assume itʼs all GPL, but there might be
>>> copyright assignment issues.
>>
>> He signed the paperwork (back when he was maintaining Emacs's Calc), so
>> there shouldn't be any issue in this respect.
>> It'd be good to tell him about this change in Emacs, tho. He may be
>> convinced to come back to Emacs now ;-)
>>
Well, the calc in the SXEmacs git repo still uses its own bignum
implementation, and their email archives are offline, so Iʼm no
wiser. Could you point me in the direction of the author (privately if
you think thatʼs necessary)?
>>>> Fast and exhaustive tests, of course ;-)
>>> It passes the test-suite, which has 5 tests :-)
>>
>> All the tests? That sounds like "exhaustive" to me!
None of them directly test bignums though. Iʼll have to write some
more.
Robert
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-24 9:51 ` Robert Pluim
@ 2018-08-25 17:59 ` Stefan Monnier
0 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-25 17:59 UTC (permalink / raw)
To: emacs-devel
> Well, the calc in the SXEmacs git repo still uses its own bignum
> implementation, and their email archives are offline, so Iʼm no
> wiser. Could you point me in the direction of the author (privately if
> you think thatʼs necessary)?
Hmm... I remember seeing the discussion on the sxemacs-devel
mailing-list (via Gmane). His name is Jay Belanger.
IIRC he didn't add just support for GMP numbers but also for GNU mpfr
(which we don't have).
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-21 3:38 ` Richard Stallman
@ 2018-08-25 23:27 ` Paul Eggert
2018-08-26 12:45 ` Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch) Michael Albinus
` (3 more replies)
0 siblings, 4 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-25 23:27 UTC (permalink / raw)
To: rms, Lars Ingebrigtsen; +Cc: eliz, monnier, pipcet, emacs-devel
> > I'm pretty sure that I've written code that's essentially along the
> > lines of
>
> > (when list-of-numbers
> > (let ((i most-positive-fixnum))
> > (dolist (a list-of-numbers)
> > (setq i (min i a)))
> > i))
>
> > to get the smallest number in a set.
>
> This seems to be a real problem.
It is a real problem, but not a serious one.
A few days ago I audited Emacs master for all uses of most-positive-fixnum and
most-negative-fixnum, and in commit a4a3c92e9de59bd0251f36326375cce898919edc I
fixed five instances of problems like the one mentioned above. After doing this
exercise, my impression is that although this problem is real it is not serious.
The unfixed code was already broken on Emacs 26, as integers that exceeded
most-positive-fixnum wrapped around silently, breaking the min calculations in a
different way. With bignums in place the unfixed code was still broken, but
bignums did not introduce a bug that wasn't there already.
Also, many of these calculations involve things like column counts or window
positions, for which it's extremely unlikely that users will go beyond fixnum
limits, and which can help to explain why the dubious code in question has
remained unfixed in Emacs for so long. Although we should fix such limitations,
misbehavior is so unlikely here that it's not high priority.
In case you're curious, here are the remaining dubious instances of
most-negative-fixnum and most-positive-fixnum in the Emacs master source, and
what they mean in terms of correctness. This should give you a deeper feel for
thie issue.
* Several modules assumes that buffer sizes fits into fixnums. This assumption
is correct for Emacs master, though it will become dubious if we change Emacs to
support buffer sizes greater than most-positive-fixnum. The affected modules are
emacs-lisp/syntax.el, org/org-list.el, progmodes/cc-engine.el, progmodes/js.el,
and simple.el.
* net/tramp-sh.el contains some assumptions that file sizes and other attributes
that don't fit into fixnums are converted to floats by the underlying drivers.
This assumption won't be true of list-attributes, and presumably shouldn't be
true of tramp's other drivers (though I don't know the details here; I'm
handwaving a bit).
* gnus/gnus-registry.el and registry.el assume entry counts fit in fixnums.
* net/eww.el assumes readability scores are never less than most-negative-fixnum.
* org/org-element.el assumes that element keys are fixnums.
* subr.el assumes that undo counts fit in fixnum.
* xterm.el assumes that Emacs will never run for more than most-positive-fixnum
seconds.
Some of these assumptions are quite safe, others are a bit more dubious, none
seem to represent serious bugs.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch)
2018-08-25 23:27 ` Paul Eggert
@ 2018-08-26 12:45 ` Michael Albinus
2018-08-26 15:34 ` Paul Eggert
2018-08-26 16:34 ` Making 'eq' == 'eql' in bignum branch Tom Tromey
` (2 subsequent siblings)
3 siblings, 1 reply; 281+ messages in thread
From: Michael Albinus @ 2018-08-26 12:45 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel
Paul Eggert <eggert@cs.ucla.edu> writes:
Hi Paul,
> * net/tramp-sh.el contains some assumptions that file sizes and other
> attributes that don't fit into fixnums are converted to floats by the
> underlying drivers. This assumption won't be true of list-attributes,
> and presumably shouldn't be true of tramp's other drivers (though I
> don't know the details here; I'm handwaving a bit).
Could you pls explain in more detail what you believe is wrong? A
pointer to a suspicious code snippet would help.
What do you mean with `list-attributes'? Maybe `file-attributes'?
Best regards, Michael.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch)
2018-08-26 12:45 ` Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch) Michael Albinus
@ 2018-08-26 15:34 ` Paul Eggert
2018-08-26 16:06 ` Eli Zaretskii
2018-08-26 16:49 ` Tramp and fixnum Michael Albinus
0 siblings, 2 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-26 15:34 UTC (permalink / raw)
To: Michael Albinus; +Cc: emacs-devel
Michael Albinus wrote:
>> * net/tramp-sh.el contains some assumptions that file sizes and other
>> attributes that don't fit into fixnums are converted to floats by the
>> underlying drivers. This assumption won't be true of list-attributes,
>> and presumably shouldn't be true of tramp's other drivers (though I
>> don't know the details here; I'm handwaving a bit).
>
> Could you pls explain in more detail what you believe is wrong? A
> pointer to a suspicious code snippet would help.
>
> What do you mean with `list-attributes'? Maybe `file-attributes'?
Yes, sorry, I meant 'file-attributes'. The fishy-looking code is in
tramp-convert-file-attributes. Here's one snippet:
(when (and (floatp (nth 2 attr))
(<= (nth 2 attr) most-positive-fixnum))
(setcar (nthcdr 2 attr) (round (nth 2 attr))))
Although this snippet shouldn't hurt, it should be unnecessary once
file-attributes is fixed to not return floats. And in the meantime, the "(<=
(nth 2 attr) most-positive-fixnum)" is unnecessary since file-attributes never
returns a float less than or equal to most-positive-fixnum. There are three
snippets like this.
The main offender is the inode converter in that function, which splits integers
into three parts, whereas it should simply keep the integers as-is since they
don't overflow any more.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch)
2018-08-26 15:34 ` Paul Eggert
@ 2018-08-26 16:06 ` Eli Zaretskii
2018-08-26 16:44 ` Tramp and fixnum Michael Albinus
2018-08-28 4:47 ` Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch) Paul Eggert
2018-08-26 16:49 ` Tramp and fixnum Michael Albinus
1 sibling, 2 replies; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-26 16:06 UTC (permalink / raw)
To: Paul Eggert; +Cc: michael.albinus, emacs-devel
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 26 Aug 2018 08:34:25 -0700
> Cc: emacs-devel@gnu.org
>
> > What do you mean with `list-attributes'? Maybe `file-attributes'?
>
> Yes, sorry, I meant 'file-attributes'. The fishy-looking code is in
> tramp-convert-file-attributes. Here's one snippet:
>
> (when (and (floatp (nth 2 attr))
> (<= (nth 2 attr) most-positive-fixnum))
> (setcar (nthcdr 2 attr) (round (nth 2 attr))))
>
> Although this snippet shouldn't hurt, it should be unnecessary once
> file-attributes is fixed to not return floats.
Fixed in what version of Emacs? Tramp wants to support more than just
the latest master version.
> The main offender is the inode converter in that function, which splits integers
> into three parts, whereas it should simply keep the integers as-is since they
> don't overflow any more.
They do in older Emacs versions, AFAIR.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-25 23:27 ` Paul Eggert
2018-08-26 12:45 ` Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch) Michael Albinus
@ 2018-08-26 16:34 ` Tom Tromey
2018-08-26 16:59 ` Stefan Monnier
2018-08-26 20:19 ` Alan Mackenzie
2018-08-26 20:45 ` Richard Stallman
3 siblings, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-08-26 16:34 UTC (permalink / raw)
To: Paul Eggert; +Cc: rms, emacs-devel, monnier, pipcet, Lars Ingebrigtsen, eliz
>>>>> "Paul" == Paul Eggert <eggert@cs.ucla.edu> writes:
Paul> * Several modules assumes that buffer sizes fits into fixnums. This
Paul> assumption is correct for Emacs master, though it will become dubious
Paul> if we change Emacs to support buffer sizes greater than
Paul> most-positive-fixnum. The affected modules are emacs-lisp/syntax.el,
Paul> org/org-list.el, progmodes/cc-engine.el, progmodes/js.el, and
Paul> simple.el.
The js.el uses fall into 2 categories.
One, assuming the maximum paren depth is most-positive-fixnum:
(defconst js--initial-pitem
(make-js--pitem
:paren-depth most-negative-fixnum
:type 'toplevel))
This seems reasonably safe. You'd need a truly absurd .js file to break
this.
Two, as an argument to forward-comment: (forward-comment most-positive-fixnum).
This also seems safe, as the argument is a comment count, not a buffer position.
That said these could perhaps be changed to (forward-comment (point-max)).
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum
2018-08-26 16:06 ` Eli Zaretskii
@ 2018-08-26 16:44 ` Michael Albinus
2018-08-28 4:47 ` Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch) Paul Eggert
1 sibling, 0 replies; 281+ messages in thread
From: Michael Albinus @ 2018-08-26 16:44 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Paul Eggert, emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
>> Yes, sorry, I meant 'file-attributes'. The fishy-looking code is in
>> tramp-convert-file-attributes. Here's one snippet:
>>
>> (when (and (floatp (nth 2 attr))
>> (<= (nth 2 attr) most-positive-fixnum))
>> (setcar (nthcdr 2 attr) (round (nth 2 attr))))
>>
>> Although this snippet shouldn't hurt, it should be unnecessary once
>> file-attributes is fixed to not return floats.
>
> Fixed in what version of Emacs? Tramp wants to support more than just
> the latest master version.
Yes, back to Emacs 24.
>> The main offender is the inode converter in that function, which
>> splits integers
>> into three parts, whereas it should simply keep the integers as-is since they
>> don't overflow any more.
>
> They do in older Emacs versions, AFAIR.
Yes. See Bug#25854, which triggered this code. It was reported towards
Emacs 26.0.50.
Best regards, Michael.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum
2018-08-26 15:34 ` Paul Eggert
2018-08-26 16:06 ` Eli Zaretskii
@ 2018-08-26 16:49 ` Michael Albinus
2018-08-28 4:48 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Michael Albinus @ 2018-08-26 16:49 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel
Paul Eggert <eggert@cs.ucla.edu> writes:
Hi Paul,
> And in the meantime, the "(<= (nth 2 attr) most-positive-fixnum)" is
> unnecessary since file-attributes never returns a float less than or
> equal to most-positive-fixnum.
It still does for older Emacsen. But maybe I'll write compatibility
functions like the other ones in tramp-compat.el. Using floats in
file-attributes shall be reduced to Emacs versions they still need.
Next days, likely.
Best regards, Michael.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-26 16:34 ` Making 'eq' == 'eql' in bignum branch Tom Tromey
@ 2018-08-26 16:59 ` Stefan Monnier
0 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-26 16:59 UTC (permalink / raw)
To: Tom Tromey; +Cc: Paul Eggert, rms, emacs-devel, pipcet, Lars Ingebrigtsen, eliz
> Two, as an argument to forward-comment: (forward-comment
> most-positive-fixnum). This also seems safe, as the argument is
> a comment count, not a buffer position. That said these could perhaps
> be changed to (forward-comment (point-max)).
Yes, point-max is better. Same seems to apply to the cases in
syntax.el.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-25 23:27 ` Paul Eggert
2018-08-26 12:45 ` Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch) Michael Albinus
2018-08-26 16:34 ` Making 'eq' == 'eql' in bignum branch Tom Tromey
@ 2018-08-26 20:19 ` Alan Mackenzie
2018-08-26 20:31 ` Stefan Monnier
2018-08-27 2:31 ` Eli Zaretskii
2018-08-26 20:45 ` Richard Stallman
3 siblings, 2 replies; 281+ messages in thread
From: Alan Mackenzie @ 2018-08-26 20:19 UTC (permalink / raw)
To: Paul Eggert; +Cc: rms, emacs-devel, monnier, pipcet, Lars Ingebrigtsen, eliz
Hello, Paul.
On Sat, Aug 25, 2018 at 16:27:20 -0700, Paul Eggert wrote:
[ .... ]
> * Several modules assumes that buffer sizes fits into fixnums. This
> assumption is correct for Emacs master, though it will become dubious
> if we change Emacs to support buffer sizes greater than
> most-positive-fixnum. The affected modules are emacs-lisp/syntax.el,
> org/org-list.el, progmodes/cc-engine.el, progmodes/js.el, and
> simple.el.
I'm trying to imagine a buffer whose size won't fit into a fixnum, on a
64-bit machine. most-positive-fixnum is close to 2^61. Imagine
scrolling through a 2^61 byte buffer.
Let's imagine it has an average line length of 64 bytes, in a window 64
lines deep, and auto-repeat is at 16 screens per second. That's 2^(6+6+4)
characters per second scroll rate, i.e. 2^16.
So the number of seconds it would take would be 2^(61 - 16) = 2^45.
2^45 seconds = 2^45 / 86400 / 365.25 years, this being a little over 1.1
million years. Holding the PageDown key down for this length of time
would get a little tedious.
Surely, at least for 64-bit systems, expecting buffer sizes ever to
exceed fixnums, is somewhat unrealistic. Is anybody seriously going to
be editing a 540 Mbyte buffer on a 32-bit system nowadays?
Surely the assumption of buffer sizes being fixnums is realistic and
harmless.
--
Alan Mackenzie (Nuremberg, Germany).
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-26 20:19 ` Alan Mackenzie
@ 2018-08-26 20:31 ` Stefan Monnier
2018-08-27 2:31 ` Eli Zaretskii
1 sibling, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-26 20:31 UTC (permalink / raw)
To: Alan Mackenzie
Cc: Paul Eggert, rms, emacs-devel, pipcet, Lars Ingebrigtsen, eliz
> I'm trying to imagine a buffer whose size won't fit into a fixnum, on a
> 64-bit machine.
Unlikely (at least in the foreseeable future), indeed.
But for 32bit builds, this was deemed important enough to
introduce --with-wide-int.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-25 23:27 ` Paul Eggert
` (2 preceding siblings ...)
2018-08-26 20:19 ` Alan Mackenzie
@ 2018-08-26 20:45 ` Richard Stallman
2018-08-26 22:10 ` Clément Pit-Claudel
3 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-08-26 20:45 UTC (permalink / raw)
To: Paul Eggert; +Cc: larsi, emacs-devel, eliz, pipcet, monnier
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
I'm glad this wasn't hard.
Should we add something in the Emacs Lisp manual to give advice
about cases like this?
How about if we make min and max accept, and ignore, nil as argument?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-26 20:45 ` Richard Stallman
@ 2018-08-26 22:10 ` Clément Pit-Claudel
2018-08-27 0:23 ` Paul Eggert
` (3 more replies)
0 siblings, 4 replies; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-08-26 22:10 UTC (permalink / raw)
To: emacs-devel
On 2018-08-26 16:45, Richard Stallman wrote:
> How about if we make min and max accept, and ignore, nil as argument?
I usually use 1.0e+INF and -1.0e+INF when I need a neutral element for min and max respectively, rather than most-positive-fixnum. Is there anything wrong with that? If not, I think we don't even need to change min and max at all.
Clément.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-26 22:10 ` Clément Pit-Claudel
@ 2018-08-27 0:23 ` Paul Eggert
2018-08-27 22:50 ` Richard Stallman
` (2 subsequent siblings)
3 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-27 0:23 UTC (permalink / raw)
To: Clément Pit-Claudel, emacs-devel
Clément Pit-Claudel wrote:
> I usually use 1.0e+INF and -1.0e+INF when I need a neutral element for min and max respectively, rather than most-positive-fixnum. Is there anything wrong with that?
That should work, yes.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-26 20:19 ` Alan Mackenzie
2018-08-26 20:31 ` Stefan Monnier
@ 2018-08-27 2:31 ` Eli Zaretskii
2018-08-27 4:45 ` Stefan Monnier
1 sibling, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-27 2:31 UTC (permalink / raw)
To: Alan Mackenzie; +Cc: eggert, rms, emacs-devel, monnier, pipcet, larsi
> Date: Sun, 26 Aug 2018 20:19:47 +0000
> Cc: rms@gnu.org, Lars Ingebrigtsen <larsi@gnus.org>, eliz@gnu.org,
> monnier@iro.umontreal.ca, pipcet@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
>
> Is anybody seriously going to be editing a 540 Mbyte buffer on a
> 32-bit system nowadays?
I do. But such buffers are not larger than most-positive-fixnum,
because I use a build --with-wide-int, where an Emacs integer is a
64-bit type.
The actual problem is to exceed SIZE_T_MAX, i.e. have a buffer that
cannot be referenced by a single 'char *' pointer.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 2:31 ` Eli Zaretskii
@ 2018-08-27 4:45 ` Stefan Monnier
2018-08-27 5:10 ` Paul Eggert
2018-08-27 14:59 ` Eli Zaretskii
0 siblings, 2 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-27 4:45 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: eggert, rms, emacs-devel, pipcet, Alan Mackenzie, larsi
> I do. But such buffers are not larger than most-positive-fixnum,
> because I use a build --with-wide-int, where an Emacs integer is a
> 64-bit type.
BTW, anyone interested in adding support for buffers larger than
most-positive-fixnum (using bignums) so that it can also be
done --without-wide-int?
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 4:45 ` Stefan Monnier
@ 2018-08-27 5:10 ` Paul Eggert
2018-08-27 14:59 ` Eli Zaretskii
1 sibling, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-27 5:10 UTC (permalink / raw)
To: Stefan Monnier, Eli Zaretskii
Cc: Alan Mackenzie, larsi, rms, pipcet, emacs-devel
Stefan Monnier wrote:
> BTW, anyone interested in adding support for buffers larger than
> most-positive-fixnum (using bignums) so that it can also be
> done --without-wide-int?
It's on my list of things to do, yes. I have an abnormally fond liking for
obsolescent hardware.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 4:45 ` Stefan Monnier
2018-08-27 5:10 ` Paul Eggert
@ 2018-08-27 14:59 ` Eli Zaretskii
2018-08-27 15:18 ` Stefan Monnier
1 sibling, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-27 14:59 UTC (permalink / raw)
To: Stefan Monnier; +Cc: eggert, rms, emacs-devel, pipcet, acm, larsi
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: Alan Mackenzie <acm@muc.de>, eggert@cs.ucla.edu, rms@gnu.org, larsi@gnus.org, pipcet@gmail.com, emacs-devel@gnu.org
> Date: Mon, 27 Aug 2018 00:45:33 -0400
>
> > I do. But such buffers are not larger than most-positive-fixnum,
> > because I use a build --with-wide-int, where an Emacs integer is a
> > 64-bit type.
>
> BTW, anyone interested in adding support for buffers larger than
> most-positive-fixnum (using bignums) so that it can also be
> done --without-wide-int?
Wouldn't that be much slower than --with-wide-int? Instead of a
couple of machine instructions we will have a function call.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 14:59 ` Eli Zaretskii
@ 2018-08-27 15:18 ` Stefan Monnier
2018-08-27 15:37 ` Eli Zaretskii
0 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-08-27 15:18 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: eggert, rms, emacs-devel, pipcet, acm, larsi
>> BTW, anyone interested in adding support for buffers larger than
>> most-positive-fixnum (using bignums) so that it can also be
>> done --without-wide-int?
> Wouldn't that be much slower than --with-wide-int?
I don't want to pay for --with-wide-int in my builds because I almost
never look at such large files. But I'd be happy to be able to look at
such large files every once in a while.
Whether it'd be significantly slower depends a lot on whether we keep
most buffer positions as C integers or as Lisp integers and how often we
convert from one to the other. I don't have a clear enough idea about
that to venture a guess.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 15:18 ` Stefan Monnier
@ 2018-08-27 15:37 ` Eli Zaretskii
2018-08-27 15:47 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Eli Zaretskii @ 2018-08-27 15:37 UTC (permalink / raw)
To: Stefan Monnier; +Cc: eggert, rms, emacs-devel, pipcet, acm, larsi
> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
> Cc: acm@muc.de, eggert@cs.ucla.edu, rms@gnu.org, larsi@gnus.org,
> pipcet@gmail.com, emacs-devel@gnu.org
> Date: Mon, 27 Aug 2018 11:18:21 -0400
>
> >> BTW, anyone interested in adding support for buffers larger than
> >> most-positive-fixnum (using bignums) so that it can also be
> >> done --without-wide-int?
> > Wouldn't that be much slower than --with-wide-int?
>
> I don't want to pay for --with-wide-int in my builds because I almost
> never look at such large files.
How can you not pay for that? If you are saying that operating on
buffers and strings will only use GMP when we exceed the C limits, it
would mean an addition of a lot of tests where we currently just do
simple arithmetics on buffer/string positions. Or am I missing
something?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 15:37 ` Eli Zaretskii
@ 2018-08-27 15:47 ` Stefan Monnier
2018-08-27 18:57 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-08-27 15:47 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: eggert, rms, emacs-devel, pipcet, acm, larsi
> How can you not pay for that?
There might be a cost to supporting bignum buffer positions (even when
only fixnum positions are being used), indeed.
Like the case where bignums are used, I don't have a clear enough idea
of whether it'll end up too costly or not.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 15:47 ` Stefan Monnier
@ 2018-08-27 18:57 ` Paul Eggert
0 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-27 18:57 UTC (permalink / raw)
To: Stefan Monnier, Eli Zaretskii; +Cc: acm, larsi, rms, pipcet, emacs-devel
Stefan Monnier wrote:
> Like the case where bignums are used, I don't have a clear enough idea
> of whether it'll end up too costly or not.
Yes, the only way to find out whether the cost will be acceptable is to try it.
My intuition is that it'll be OK, in the sense that large buffers are already so
slow for other other reasons that the cost of testing for bignums will be not
noticed by users.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-26 22:10 ` Clément Pit-Claudel
2018-08-27 0:23 ` Paul Eggert
@ 2018-08-27 22:50 ` Richard Stallman
2018-08-28 1:44 ` Paul Eggert
` (2 more replies)
2018-08-28 1:33 ` Lars Ingebrigtsen
2018-08-30 19:13 ` Johan Bockgård
3 siblings, 3 replies; 281+ messages in thread
From: Richard Stallman @ 2018-08-27 22:50 UTC (permalink / raw)
To: Clément Pit-Claudel; +Cc: emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> I usually use 1.0e+INF and -1.0e+INF when I need a neutral element
> for min and max respectively, rather than most-positive-fixnum.
> Is there anything wrong with that?
Only that it is a magic sequence that most programmers won't remember.
We could put it in the doc strings and manual.
But perhaps nil is better.
If not, I think we don't even
> need to change min and max at all.
Why NOT make nil work here? It would be useful in a number of ways,
I think. For instance, you could run mapcar with a function
that would produce a number or nil, and nil would mean "ignore this one",
then apply max or min.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-26 22:10 ` Clément Pit-Claudel
2018-08-27 0:23 ` Paul Eggert
2018-08-27 22:50 ` Richard Stallman
@ 2018-08-28 1:33 ` Lars Ingebrigtsen
2018-08-28 2:25 ` Pip Cet
2018-08-30 19:13 ` Johan Bockgård
3 siblings, 1 reply; 281+ messages in thread
From: Lars Ingebrigtsen @ 2018-08-28 1:33 UTC (permalink / raw)
To: Clément Pit-Claudel; +Cc: emacs-devel
Clément Pit-Claudel <cpitclaudel@gmail.com> writes:
> I usually use 1.0e+INF and -1.0e+INF when I need a neutral element for
> min and max respectively, rather than most-positive-fixnum.
Hey, nice tip. I hadn't even considered those (well, I didn't know they
had a read syntax -- is that new?). And I've already started using them
where I would previously have used most-positive-fixnum, like in this
code I just found myself typing:
(cl-sort films '<
:key (lambda (e)
(or (getf e :year) 1.0e+INF)))
This sorts a list of films by year, and sorts the ones with unknown
(nil) years to the end. This would obviously previously have been a
problem in the year 2305843009213693951 CE on legacy 64-bit machines,
but my code is now future proof.
But anyway, as Richard implies, it's a read syntax that's strangely
difficult to remember. Would it make sense to have a variable like
`positive-infinity' (etc) or `math-positive-infinity'? Or perhaps we'll
all start remembering it after seeing it sprinkled throughout the source
code after a while.
Hm... Probably the latter.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 22:50 ` Richard Stallman
@ 2018-08-28 1:44 ` Paul Eggert
2018-08-28 14:12 ` Tom Tromey
2018-08-28 18:03 ` Clément Pit-Claudel
2 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-28 1:44 UTC (permalink / raw)
To: rms, Clément Pit-Claudel; +Cc: emacs-devel
Richard Stallman wrote:
> For instance, you could run mapcar with a function
> that would produce a number or nil, and nil would mean "ignore this one",
> then apply max or min.
Infinities serve the same function, so I'm not seeing the benefit of adding nil
as another special case.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 1:33 ` Lars Ingebrigtsen
@ 2018-08-28 2:25 ` Pip Cet
2018-08-28 3:45 ` Paul Eggert
` (2 more replies)
0 siblings, 3 replies; 281+ messages in thread
From: Pip Cet @ 2018-08-28 2:25 UTC (permalink / raw)
To: larsi; +Cc: cpitclaudel, emacs-devel
On Tue, Aug 28, 2018 at 1:50 AM Lars Ingebrigtsen <larsi@gnus.org> wrote:
> But anyway, as Richard implies, it's a read syntax that's strangely
> difficult to remember. Would it make sense to have a variable like
> `positive-infinity' (etc) or `math-positive-infinity'? Or perhaps we'll
> all start remembering it after seeing it sprinkled throughout the source
> code after a while.
How about making (min) = 1.0e+INF and (max) = -1.0e+INF? That would be
easier to type, and it's mathematically correct. We could even
optimize it in the bytecode compiler.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 2:25 ` Pip Cet
@ 2018-08-28 3:45 ` Paul Eggert
2018-08-28 7:34 ` Ken Raeburn
2018-08-28 21:25 ` Richard Stallman
2 siblings, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-28 3:45 UTC (permalink / raw)
To: Pip Cet, larsi; +Cc: cpitclaudel, emacs-devel
Pip Cet wrote:
> How about making (min) = 1.0e+INF and (max) = -1.0e+INF? That would be
> easier to type, and it's mathematically correct. We could even
> optimize it in the bytecode compiler.
Makes sense to me.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch)
2018-08-26 16:06 ` Eli Zaretskii
2018-08-26 16:44 ` Tramp and fixnum Michael Albinus
@ 2018-08-28 4:47 ` Paul Eggert
1 sibling, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-28 4:47 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: michael.albinus, emacs-devel
Eli Zaretskii wrote:
>> From: Paul Eggert <eggert@cs.ucla.edu>
>> (when (and (floatp (nth 2 attr))
>> (<= (nth 2 attr) most-positive-fixnum))
>> (setcar (nthcdr 2 attr) (round (nth 2 attr))))
>>
>> Although this snippet shouldn't hurt, it should be unnecessary once
>> file-attributes is fixed to not return floats.
>
> Fixed in what version of Emacs? Tramp wants to support more than just
> the latest master version.
Good point, I keep forgetting. In that case, that snippet won't hurt.
I just now installed patches into Emacs to fix file-attributes as mentioned
above, along with a bunch of other functions dealing with system types like
ino_t and pid_t.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum
2018-08-26 16:49 ` Tramp and fixnum Michael Albinus
@ 2018-08-28 4:48 ` Paul Eggert
2018-08-28 11:50 ` Michael Albinus
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-28 4:48 UTC (permalink / raw)
To: Michael Albinus; +Cc: emacs-devel
Michael Albinus wrote:
> It still does for older Emacsen. But maybe I'll write compatibility
> functions like the other ones in tramp-compat.el. Using floats in
> file-attributes shall be reduced to Emacs versions they still need.
Please give the latest master a try, since its file-attributes now generates
bignums instead of floats when the file attribute integers don't fix into fixnums.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 2:25 ` Pip Cet
2018-08-28 3:45 ` Paul Eggert
@ 2018-08-28 7:34 ` Ken Raeburn
2018-08-28 9:11 ` Helmut Eller
2018-08-28 12:15 ` Stefan Monnier
2018-08-28 21:25 ` Richard Stallman
2 siblings, 2 replies; 281+ messages in thread
From: Ken Raeburn @ 2018-08-28 7:34 UTC (permalink / raw)
To: Pip Cet; +Cc: larsi, cpitclaudel, emacs-devel
On Aug 27, 2018, at 22:25, Pip Cet <pipcet@gmail.com> wrote:
>
> On Tue, Aug 28, 2018 at 1:50 AM Lars Ingebrigtsen <larsi@gnus.org> wrote:
>> But anyway, as Richard implies, it's a read syntax that's strangely
>> difficult to remember. Would it make sense to have a variable like
>> `positive-infinity' (etc) or `math-positive-infinity'? Or perhaps we'll
>> all start remembering it after seeing it sprinkled throughout the source
>> code after a while.
>
> How about making (min) = 1.0e+INF and (max) = -1.0e+INF? That would be
> easier to type, and it's mathematically correct. We could even
> optimize it in the bytecode compiler.
That’s great if you’re applying max or min to a possibly-empty collection of values. But if you’ve got a loop where you’re tracking a minimum/maximum value along with doing other stuff (possibly including computing the values you’re looking for the minimum of), this may not help much.
If “1.0e+INF” is hard to remember, how about defining symbols “+inifinity” and “-inifinity” (and if you want to get fancy with the Unicode, +∞ and -∞) with the appropriate numeric values? I kind of like the nil idea too.
There’s no reason we couldn’t do some or all of the above. Only question is, should “(min nil)” return nil or infinity?
Ken
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 7:34 ` Ken Raeburn
@ 2018-08-28 9:11 ` Helmut Eller
2018-08-28 12:15 ` Stefan Monnier
1 sibling, 0 replies; 281+ messages in thread
From: Helmut Eller @ 2018-08-28 9:11 UTC (permalink / raw)
To: emacs-devel
On Tue, Aug 28 2018, Ken Raeburn wrote:
> If “1.0e+INF” is hard to remember, how about defining symbols
> “+inifinity” and “-inifinity” (and if you want to get fancy with the
> Unicode, +∞ and -∞) with the appropriate numeric values? I kind of
> like the nil idea too.
There is already most-positive-float. To bad that those "constants"
need to be set with cl-float-limits.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum
2018-08-28 4:48 ` Paul Eggert
@ 2018-08-28 11:50 ` Michael Albinus
2018-08-28 14:33 ` Michael Albinus
0 siblings, 1 reply; 281+ messages in thread
From: Michael Albinus @ 2018-08-28 11:50 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel
Paul Eggert <eggert@cs.ucla.edu> writes:
Hi Paul,
>> It still does for older Emacsen. But maybe I'll write compatibility
>> functions like the other ones in tramp-compat.el. Using floats in
>> file-attributes shall be reduced to Emacs versions they still need.
>
> Please give the latest master a try, since its file-attributes now
> generates bignums instead of floats when the file attribute integers
> don't fix into fixnums.
Will do next days.
Best regards, Michael.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 7:34 ` Ken Raeburn
2018-08-28 9:11 ` Helmut Eller
@ 2018-08-28 12:15 ` Stefan Monnier
2018-08-28 18:00 ` Clément Pit-Claudel
1 sibling, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-08-28 12:15 UTC (permalink / raw)
To: emacs-devel
> That’s great if you’re applying max or min to a possibly-empty collection of
> values. But if you’ve got a loop where you’re tracking a minimum/maximum
> value along with doing other stuff (possibly including computing the values
> you’re looking for the minimum of), this may not help much.
It helps because you can use (min) or (max) as your starting value.
> If “1.0e+INF” is hard to remember, how about defining symbols “+inifinity”
Pip's suggestion is to use (max) for that.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 22:50 ` Richard Stallman
2018-08-28 1:44 ` Paul Eggert
@ 2018-08-28 14:12 ` Tom Tromey
2018-08-28 21:30 ` Richard Stallman
2018-08-28 18:03 ` Clément Pit-Claudel
2 siblings, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-08-28 14:12 UTC (permalink / raw)
To: Richard Stallman; +Cc: Clément Pit-Claudel, emacs-devel
>>>>> "RMS" == Richard Stallman <rms@gnu.org> writes:
RMS> [[[ To any NSA and FBI agents reading my email: please consider ]]]
RMS> [[[ whether defending the US Constitution against all enemies, ]]]
RMS> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>> I usually use 1.0e+INF and -1.0e+INF when I need a neutral element
>> for min and max respectively, rather than most-positive-fixnum.
>> Is there anything wrong with that?
RMS> Only that it is a magic sequence that most programmers won't remember.
RMS> We could put it in the doc strings and manual.
How about adding (defconst Infinity 1.0e+INF) to subr.el?
That would be easier to remember.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum
2018-08-28 11:50 ` Michael Albinus
@ 2018-08-28 14:33 ` Michael Albinus
2018-08-28 15:18 ` Paul Eggert
0 siblings, 1 reply; 281+ messages in thread
From: Michael Albinus @ 2018-08-28 14:33 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel
Michael Albinus <michael.albinus@gmx.de> writes:
Hi Paul,
>>> It still does for older Emacsen. But maybe I'll write compatibility
>>> functions like the other ones in tramp-compat.el. Using floats in
>>> file-attributes shall be reduced to Emacs versions they still need.
>>
>> Please give the latest master a try, since its file-attributes now
>> generates bignums instead of floats when the file attribute integers
>> don't fix into fixnums.
>
> Will do next days.
This was more simple as expected. Tramp supports Emacsen 24+, and all of
them convert integer to floats automatically when needed. So I could get
rid of the "e0" hack.
And for the inode number conversion, I check whether function `bignump'
is available. If yes, I don't convert.
See commit adcf904b3a.
Best regards, Michael.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum
2018-08-28 14:33 ` Michael Albinus
@ 2018-08-28 15:18 ` Paul Eggert
2018-08-29 8:09 ` Michael Albinus
0 siblings, 1 reply; 281+ messages in thread
From: Paul Eggert @ 2018-08-28 15:18 UTC (permalink / raw)
To: Michael Albinus; +Cc: emacs-devel
Michael Albinus wrote:
> And for the inode number conversion, I check whether function `bignump'
> is available. If yes, I don't convert.
I must be slow this morning, but I don't see why that test needs to know whether
bignums are supported. That is, for this change:
- ;; Convert inode.
- (unless (listp (nth 10 attr))
+ ;; Convert inode. Big numbers have been added to Emacs 27.
+ (unless (or (fboundp 'bignump) (listp (nth 10 attr)))
How about changing to the following instead?
(let ((inode (nth 10 attr)))
(unless (or (integerp inode) (listp inode))
...
That is, if the inode number is already an integer, leave it alone. This should
work regardless of whether bignums are supported.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 12:15 ` Stefan Monnier
@ 2018-08-28 18:00 ` Clément Pit-Claudel
2018-08-28 22:57 ` Pip Cet
2018-08-29 3:22 ` Elias Mårtenson
0 siblings, 2 replies; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-08-28 18:00 UTC (permalink / raw)
To: emacs-devel
On 2018-08-28 08:15, Stefan Monnier wrote:
>> If “1.0e+INF” is hard to remember, how about defining symbols “+inifinity”
> Pip's suggestion is to use (max) for that.
I think you read Pip's suggestion backward: (max) would return -infinity, not +infinity. (Which makes sense, since you want max to distribute over list concatenation)
FWIW, I'm not a fan of using either (min) or (max) to represent minus infinity; it looks a bit odd. Many other languages have an infinity constant already, so that pattern is well established; making (max) an alias for either of the infinities is prone to introducing confusion.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-27 22:50 ` Richard Stallman
2018-08-28 1:44 ` Paul Eggert
2018-08-28 14:12 ` Tom Tromey
@ 2018-08-28 18:03 ` Clément Pit-Claudel
2018-08-29 3:53 ` Stefan Monnier
2 siblings, 1 reply; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-08-28 18:03 UTC (permalink / raw)
To: rms; +Cc: emacs-devel
On 2018-08-27 18:50, Richard Stallman wrote:
> Only that it is a magic sequence that most programmers won't remember.
> We could put it in the doc strings and manual.
Python spells it float("+inf"), and I see it used fairly often there.
I'd expect anyone who can remember most-positive-fixnum to quickly memorize 1.0e+INF :) (when I forget, I just eval (exp 9999999999999) and get 1.0e+INF as a reminder.)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 2:25 ` Pip Cet
2018-08-28 3:45 ` Paul Eggert
2018-08-28 7:34 ` Ken Raeburn
@ 2018-08-28 21:25 ` Richard Stallman
2 siblings, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-08-28 21:25 UTC (permalink / raw)
To: Pip Cet; +Cc: larsi, cpitclaudel, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> How about making (min) = 1.0e+INF and (max) = -1.0e+INF? That would be
> easier to type, and it's mathematically correct.
I think that is a good idea. However, I still think it would be
a convenience to make max and min ignore nil as argument.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 14:12 ` Tom Tromey
@ 2018-08-28 21:30 ` Richard Stallman
2018-08-28 22:03 ` Clément Pit-Claudel
0 siblings, 1 reply; 281+ messages in thread
From: Richard Stallman @ 2018-08-28 21:30 UTC (permalink / raw)
To: Tom Tromey; +Cc: cpitclaudel, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> How about adding (defconst Infinity 1.0e+INF) to subr.el?
(max) is easier to remember. Also, the capital initial makes the name
strange.
However, I think that making max and min allow nil
would be a good change for other reasons.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 21:30 ` Richard Stallman
@ 2018-08-28 22:03 ` Clément Pit-Claudel
2018-08-29 22:10 ` Richard Stallman
0 siblings, 1 reply; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-08-28 22:03 UTC (permalink / raw)
To: rms, Tom Tromey; +Cc: emacs-devel
On 2018-08-28 17:30, Richard Stallman wrote:
> (max) is easier to remember.
Really, even though (max) will be *minus* infinity?
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 18:00 ` Clément Pit-Claudel
@ 2018-08-28 22:57 ` Pip Cet
2018-08-29 3:42 ` Herring, Davis
2018-08-29 3:22 ` Elias Mårtenson
1 sibling, 1 reply; 281+ messages in thread
From: Pip Cet @ 2018-08-28 22:57 UTC (permalink / raw)
To: cpitclaudel; +Cc: emacs-devel
On Tue, Aug 28, 2018 at 6:19 PM Clément Pit-Claudel
<cpitclaudel@gmail.com> wrote:
>
> On 2018-08-28 08:15, Stefan Monnier wrote:
> >> If “1.0e+INF” is hard to remember, how about defining symbols “+inifinity”
> > Pip's suggestion is to use (max) for that.
>
> I think you read Pip's suggestion backward: (max) would return -infinity, not +infinity. (Which makes sense, since you want max to distribute over list concatenation)
>
> FWIW, I'm not a fan of using either (min) or (max) to represent minus infinity; it looks a bit odd. Many other languages have an infinity constant already, so that pattern is well established; making (max) an alias for either of the infinities is prone to introducing confusion.
It's more natural in code than it sounds at first: you use (min) when
finding a minimum, (max) when finding a maximum. However, if there is
a good name for it, an infinity constant is perfectly fine. Such a
name should make clear that we're talking about a signed infinity, not
one that makes 1/x continuous by adding a point at infinity to the
real line.
Signed infinities are convenient symbols, but they're not numbers; I
recall the horrified reaction of a mathematician when I told her about
IEEE infinities (she thought I was making it up about NaNs).
I think it's all so confusing that it would be best to accept the
slight performance cost of having a function like
(defun minpair (alist)
"Return an element of ALIST for which (cdr X) is minimal."
...)
and using it consistently, in addition to defining (min), (max),
defining a pair of infinity constants, making `min' and `max' ignore
nil arguments, and changing `eq' to work on infinities. And maybe
changing the read and print syntax for infinities.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 18:00 ` Clément Pit-Claudel
2018-08-28 22:57 ` Pip Cet
@ 2018-08-29 3:22 ` Elias Mårtenson
2018-08-29 18:56 ` Clément Pit-Claudel
1 sibling, 1 reply; 281+ messages in thread
From: Elias Mårtenson @ 2018-08-29 3:22 UTC (permalink / raw)
To: cpitclaudel; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 578 bytes --]
On Wed, 29 Aug 2018 at 02:19, Clément Pit-Claudel <cpitclaudel@gmail.com>
wrote:
> FWIW, I'm not a fan of using either (min) or (max) to represent minus
> infinity; it looks a bit odd. Many other languages have an infinity
> constant already, so that pattern is well established; making (max) an
> alias for either of the infinities is prone to introducing confusion.
>
For anyone curious, the way to do it in APL is ⌈/⍬ and ⌊/⍬, which literally
means take the max and min values of an empty list, so it's not completely
unheard of.
Regards,
Elias
[-- Attachment #2: Type: text/html, Size: 881 bytes --]
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 22:57 ` Pip Cet
@ 2018-08-29 3:42 ` Herring, Davis
2018-08-29 5:40 ` Helmut Eller
` (2 more replies)
0 siblings, 3 replies; 281+ messages in thread
From: Herring, Davis @ 2018-08-29 3:42 UTC (permalink / raw)
To: Pip Cet; +Cc: cpitclaudel@gmail.com, emacs-devel@gnu.org
> Such a name should make clear that we're talking about a signed
> infinity, not one that makes 1/x continuous by adding a point at
> infinity to the real line.
Sure: the extended reals <https://en.wikipedia.org/wiki/Extended_real_number_line>, not the projective reals <https://en.wikipedia.org/wiki/Projectively_extended_real_line>.
> Signed infinities are convenient symbols, but they're not numbers; I
> recall the horrified reaction of a mathematician when I told her about
> IEEE infinities (she thought I was making it up about NaNs).
Of course +/-inf are numbers. They're not real numbers, but neither are complex numbers, split-complex numbers, dual numbers, p-adic numbers, quaternions, octonions, sedenions, hyperreal numbers, or (please no) surreal numbers. With all due respect to your mathematician friend, she has no exclusive claim over the definition (such as it is) of "number" (and I'm a bit surprised if she hadn't heard of at least one of the extended real lines I linked).
NaN, on the other hand, is of course a floating-point value that explicitly claims not to be a number. I'm not sure whether to believe it; it seems very useful that the operations on floating-point "numbers" are closed, but that depends on NaN being one of them...
Davis
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 18:03 ` Clément Pit-Claudel
@ 2018-08-29 3:53 ` Stefan Monnier
2018-08-29 18:49 ` Clément Pit-Claudel
0 siblings, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-08-29 3:53 UTC (permalink / raw)
To: emacs-devel
> I'd expect anyone who can remember most-positive-fixnum to quickly memorize
> 1.0e+INF
TAB completion is pretty useful to fill the holes of my memory w.r.t
most-positive-fixnum, whereas I'm afraid it will be of not help with
1.0e+INF.
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-29 3:42 ` Herring, Davis
@ 2018-08-29 5:40 ` Helmut Eller
2018-08-29 13:15 ` Pip Cet
2018-08-31 19:59 ` Alan Mackenzie
2 siblings, 0 replies; 281+ messages in thread
From: Helmut Eller @ 2018-08-29 5:40 UTC (permalink / raw)
To: emacs-devel
On Wed, Aug 29 2018, Herring, Davis wrote:
> Of course +/-inf are numbers. They're not real numbers, but neither
> are complex numbers, split-complex numbers, dual numbers, p-adic
> numbers, quaternions, octonions, sedenions, hyperreal numbers, or
> (please no) surreal numbers. With all due respect to your
> mathematician friend, she has no exclusive claim over the definition
> (such as it is) of "number" (and I'm a bit surprised if she hadn't
> heard of at least one of the extended real lines I linked).
Also, it seems quite common to define max/min so that +/-inf are the
neutral elements <https://en.wikipedia.org/wiki/Identity_element>.
In Lisp, many associative operations return the neutral element if
called with zero arguments, e.g. (*) => 1. So I think it's quite nice
that (max) returns -infinity.
In Scheme, the syntax +inf.0 and -inf.0 is used for infinities. Emacs
Lisp could use the same as +inf.0 is just an ordinary symbol. At least
Schemers could remember that.
One could also write (/ 1 0.0) for +infinity; the easiest to remember
IMO.
Helmut
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Tramp and fixnum
2018-08-28 15:18 ` Paul Eggert
@ 2018-08-29 8:09 ` Michael Albinus
0 siblings, 0 replies; 281+ messages in thread
From: Michael Albinus @ 2018-08-29 8:09 UTC (permalink / raw)
To: Paul Eggert; +Cc: emacs-devel
Paul Eggert <eggert@cs.ucla.edu> writes:
Hi Paul,
> + ;; Convert inode. Big numbers have been added to Emacs 27.
> + (unless (or (fboundp 'bignump) (listp (nth 10 attr)))
>
> How about changing to the following instead?
>
> (let ((inode (nth 10 attr)))
> (unless (or (integerp inode) (listp inode))
> ...
>
> That is, if the inode number is already an integer, leave it
> alone. This should work regardless of whether bignums are supported.
Indeed, that's better. Finally, it just needs
(when (floatp (nth 10 attr))
Pushed to the repositories.
Best regards, Michael.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-29 3:42 ` Herring, Davis
2018-08-29 5:40 ` Helmut Eller
@ 2018-08-29 13:15 ` Pip Cet
2018-08-31 19:59 ` Alan Mackenzie
2 siblings, 0 replies; 281+ messages in thread
From: Pip Cet @ 2018-08-29 13:15 UTC (permalink / raw)
To: herring; +Cc: cpitclaudel, emacs-devel
On Wed, Aug 29, 2018 at 3:42 AM Herring, Davis <herring@lanl.gov> wrote:
> > Signed infinities are convenient symbols, but they're not numbers; I
> > recall the horrified reaction of a mathematician when I told her about
> > IEEE infinities (she thought I was making it up about NaNs).
>
> Of course +/-inf are numbers.
I'm sorry I made a tangential mathematical statement; while I think
it's correct that the usual definition of "number" excludes infinities
(but not numbers that happen to be infinite), you are perfectly
correct that it's okay to redefine the term as you see fit. To get
this back to Emacs matters, `numberp' is fine as it is.
> They're not real numbers, but neither are complex numbers, split-complex numbers, dual numbers, p-adic numbers, quaternions, octonions, sedenions, hyperreal numbers, or (please no) surreal numbers. With all due respect to your mathematician friend, she has no exclusive claim over the definition (such as it is) of "number" (and I'm a bit surprised if she hadn't heard of at least one of the extended real lines I linked).
She has; she simply has a different definition of "number" (and no
doubt the three of us have three different definitions of the term).
> NaN, on the other hand, is of course a floating-point value that explicitly claims not to be a number. I'm not sure whether to believe it; it seems very useful that the operations on floating-point "numbers" are closed, but that depends on NaN being one of them...
Four definitions!
For those not familiar with APL, JavaScript is a popular language that
has Math.min() = Infinity.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-29 3:53 ` Stefan Monnier
@ 2018-08-29 18:49 ` Clément Pit-Claudel
0 siblings, 0 replies; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-08-29 18:49 UTC (permalink / raw)
To: emacs-devel
On 2018-08-28 23:53, Stefan Monnier wrote:
>> I'd expect anyone who can remember most-positive-fixnum to quickly memorize
>> 1.0e+INF
>
> TAB completion is pretty useful to fill the holes of my memory w.r.t
> most-positive-fixnum, whereas I'm afraid it will be of not help with
> 1.0e+INF.
(defvar 1\.0e+INF 1.0e+INF) ? :)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-29 3:22 ` Elias Mårtenson
@ 2018-08-29 18:56 ` Clément Pit-Claudel
2018-08-29 19:30 ` Stefan Monnier
0 siblings, 1 reply; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-08-29 18:56 UTC (permalink / raw)
To: Elias Mårtenson; +Cc: emacs-devel
On 2018-08-28 23:22, Elias Mårtenson wrote:
> On Wed, 29 Aug 2018 at 02:19, Clément Pit-Claudel <cpitclaudel@gmail.com <mailto:cpitclaudel@gmail.com>> wrote:
>
>
> FWIW, I'm not a fan of using either (min) or (max) to represent minus infinity; it looks a bit odd. Many other languages have an infinity constant already, so that pattern is well established; making (max) an alias for either of the infinities is prone to introducing confusion.
>
>
> For anyone curious, the way to do it in APL is ⌈/⍬ and ⌊/⍬, which literally means take the max and min values of an empty list, so it's not completely unheard of.
Let me amend what I wrote above. I'm not excited about (max) becoming the common spelling for negative infinity, but I'm fine with changing max to accept zero arguments and return -infinity in that case (and, indeed, that's the only value that makes sense to me).
I'd simply prefer to have a more explicit spelling for both infinities, and if 1.0e+INF if too hard to remember, a new read syntax or a new defconst would have my preference over (max) and (min).
Clément.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-29 18:56 ` Clément Pit-Claudel
@ 2018-08-29 19:30 ` Stefan Monnier
2018-08-31 0:09 ` Stefan Monnier
2018-08-31 16:41 ` Paul Eggert
0 siblings, 2 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-29 19:30 UTC (permalink / raw)
To: emacs-devel
> Let me amend what I wrote above. I'm not excited about (max) becoming the
> common spelling for negative infinity, but I'm fine with changing max to
> accept zero arguments and return -infinity in that case (and, indeed, that's
> the only value that makes sense to me).
Same here, except rather than "I'm fine with" I'd say that I'm in favor
of it (for the same reason that I made `apply` work when called with
a single argument).
> I'd simply prefer to have a more explicit spelling for both infinities, and
> if 1.0e+INF if too hard to remember, a new read syntax or a new defconst
> would have my preference over (max) and (min).
(aol-mode 1)
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-28 22:03 ` Clément Pit-Claudel
@ 2018-08-29 22:10 ` Richard Stallman
0 siblings, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-08-29 22:10 UTC (permalink / raw)
To: Clément Pit-Claudel; +Cc: tom, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> > (max) is easier to remember.
> Really, even though (max) will be *minus* infinity?
Maybe you are right.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-26 22:10 ` Clément Pit-Claudel
` (2 preceding siblings ...)
2018-08-28 1:33 ` Lars Ingebrigtsen
@ 2018-08-30 19:13 ` Johan Bockgård
2018-08-30 21:14 ` Clément Pit-Claudel
3 siblings, 1 reply; 281+ messages in thread
From: Johan Bockgård @ 2018-08-30 19:13 UTC (permalink / raw)
To: Clément Pit-Claudel; +Cc: emacs-devel
Clément Pit-Claudel <cpitclaudel@gmail.com> writes:
> On 2018-08-26 16:45, Richard Stallman wrote:
>> How about if we make min and max accept, and ignore, nil as argument?
>
> I usually use 1.0e+INF and -1.0e+INF when I need a neutral element for
> min and max respectively, rather than most-positive-fixnum. Is there
> anything wrong with that? If not, I think we don't even need to change
> min and max at all.
It doesn't preserve integerness; (min 1 NEUTRAL-ELEMENT) should be 1,
but (min 1 1e+INF) is 1.0.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-30 19:13 ` Johan Bockgård
@ 2018-08-30 21:14 ` Clément Pit-Claudel
2018-08-30 21:35 ` Tom Tromey
0 siblings, 1 reply; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-08-30 21:14 UTC (permalink / raw)
To: Johan Bockgård; +Cc: emacs-devel
On 2018-08-30 15:13, Johan Bockgård wrote:
> Clément Pit-Claudel <cpitclaudel@gmail.com> writes:
>
>> On 2018-08-26 16:45, Richard Stallman wrote:
>>> How about if we make min and max accept, and ignore, nil as argument?
>>
>> I usually use 1.0e+INF and -1.0e+INF when I need a neutral element for
>> min and max respectively, rather than most-positive-fixnum. Is there
>> anything wrong with that? If not, I think we don't even need to change
>> min and max at all.
>
> It doesn't preserve integerness; (min 1 NEUTRAL-ELEMENT) should be 1,
> but (min 1 1e+INF) is 1.0.
What platform are you on? On my machine (x86_64-pc-linux-gnu) it returns 1, not 1.0.
And, AFAICT, the implementation always returns one of its arguments:
static Lisp_Object
minmax_driver (ptrdiff_t nargs, Lisp_Object *args,
enum Arith_Comparison comparison)
{
Lisp_Object accum = args[0];
CHECK_NUMBER_COERCE_MARKER (accum);
for (ptrdiff_t argnum = 1; argnum < nargs; argnum++)
{
Lisp_Object val = args[argnum];
CHECK_NUMBER_COERCE_MARKER (val);
if (!NILP (arithcompare (val, accum, comparison)))
accum = val;
else if (FLOATP (val) && isnan (XFLOAT_DATA (val)))
return val;
}
return accum;
}
Clément.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-30 21:14 ` Clément Pit-Claudel
@ 2018-08-30 21:35 ` Tom Tromey
2018-08-30 21:56 ` Clément Pit-Claudel
0 siblings, 1 reply; 281+ messages in thread
From: Tom Tromey @ 2018-08-30 21:35 UTC (permalink / raw)
To: Clément Pit-Claudel; +Cc: Johan Bockgård, emacs-devel
>>>>> "Clément" == Clément Pit-Claudel <cpitclaudel@gmail.com> writes:
>> It doesn't preserve integerness; (min 1 NEUTRAL-ELEMENT) should be 1,
>> but (min 1 1e+INF) is 1.0.
Clément> What platform are you on? On my machine (x86_64-pc-linux-gnu)
Clément> it returns 1, not 1.0.
Clément> And, AFAICT, the implementation always returns one of its arguments:
This changed in recent history, min/max used to do float promotion.
Tom
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-30 21:35 ` Tom Tromey
@ 2018-08-30 21:56 ` Clément Pit-Claudel
0 siblings, 0 replies; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-08-30 21:56 UTC (permalink / raw)
To: Tom Tromey; +Cc: Johan Bockgård, emacs-devel
On 2018-08-30 17:35, Tom Tromey wrote:
> Clément> What platform are you on? On my machine (x86_64-pc-linux-gnu)
> Clément> it returns 1, not 1.0.
>
> This changed in recent history, min/max used to do float promotion.
Neat, that explains it :) Thanks!
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-29 19:30 ` Stefan Monnier
@ 2018-08-31 0:09 ` Stefan Monnier
2018-09-01 2:32 ` Richard Stallman
2018-08-31 16:41 ` Paul Eggert
1 sibling, 1 reply; 281+ messages in thread
From: Stefan Monnier @ 2018-08-31 0:09 UTC (permalink / raw)
To: emacs-devel
>> I'd simply prefer to have a more explicit spelling for both infinities, and
>> if 1.0e+INF if too hard to remember, a new read syntax or a new defconst
>> would have my preference over (max) and (min).
(defconst +∞ 1.0e+INF)
(defconst -∞ -1.0e+INF)
Stefan
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-29 19:30 ` Stefan Monnier
2018-08-31 0:09 ` Stefan Monnier
@ 2018-08-31 16:41 ` Paul Eggert
1 sibling, 0 replies; 281+ messages in thread
From: Paul Eggert @ 2018-08-31 16:41 UTC (permalink / raw)
To: Stefan Monnier, emacs-devel
Stefan Monnier wrote:
> Same here, except rather than "I'm fine with" I'd say that I'm in favor
> of it (for the same reason that I made `apply` work when called with
> a single argument).
I looked into implementing something along those lines and ran into a problem:
the C standard does not require support for floating-point infinity, and a few
mildly-plausible Emacs targets lack it. The most significant is IBM z/OS when
compiled in default mode. There is also the Unisys Clearpath (formerly
Burroughs) and Dorado (formerly Univac) lines. These environments are still
supported, and help explain why the C standard does not require support for a
working INFINITY macro in <math.h>, and why Common Lisp does not require
infinity constants.
That being said, I now see that the Emacs source code has been using <math.h>'s
INFINITY macro since Emacs 25.1. Although this was just an oversight (and I just
now fixed it on master), nobody has complained.
With that in mind we could simply be upfront about it and explicitly require
IEEE floating point, excluding old mainframe environments and some embedded
platforms. Then we could change 'min' and 'max' to return infinity, and we can
also simplify the C code a bit by assuming IEEE_FLOATING_POINT. On the other
hand perhaps it's better to leave sleeping dogs lie, and not jump completely
into the IEEE bed, and wait for the next C standard to revamp the floating point
API again (which it looks like it will) before worrying about this.
As for a named constant, I now see a problem with it: it wouldn't work in
expressions like (let ((gamow '(1 2 3 infinity))) ...). So perhaps we should
just ask people to remember to use 1e+INF instead, as it doesn't have this
syntactic glitch.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-29 3:42 ` Herring, Davis
2018-08-29 5:40 ` Helmut Eller
2018-08-29 13:15 ` Pip Cet
@ 2018-08-31 19:59 ` Alan Mackenzie
2018-08-31 20:30 ` Clément Pit-Claudel
` (3 more replies)
2 siblings, 4 replies; 281+ messages in thread
From: Alan Mackenzie @ 2018-08-31 19:59 UTC (permalink / raw)
To: Herring, Davis; +Cc: cpitclaudel@gmail.com, Pip Cet, emacs-devel@gnu.org
Hello, Davis.
On Wed, Aug 29, 2018 at 03:42:26 +0000, Herring, Davis wrote:
> > Such a name should make clear that we're talking about a signed
> > infinity, not one that makes 1/x continuous by adding a point at
> > infinity to the real line.
> Sure: the extended reals
> <https://en.wikipedia.org/wiki/Extended_real_number_line>, not the
> projective reals
> <https://en.wikipedia.org/wiki/Projectively_extended_real_line>.
> > Signed infinities are convenient symbols, but they're not numbers; I
> > recall the horrified reaction of a mathematician when I told her
> > about IEEE infinities (she thought I was making it up about NaNs).
> Of course +/-inf are numbers.
I'm speaking not as a mathematician, but as somebody with a degree in
maths.
+/-infinity are not numbers. They do not satisfy the axioms which
define numbers. For example they do not satisfy
(x + y) + z = x + (y + z)
. They cannot be made to satisfy these axioms.
> They're not real numbers, but neither are complex numbers,
> split-complex numbers, dual numbers, p-adic numbers, quaternions,
> octonions, sedenions, hyperreal numbers, or (please no) surreal
> numbers.
That's a strawman. The issue being discussed here is numbers, not
arbitrary algebraic structures.
> With all due respect to your mathematician friend, ....
That is offensive in the extreme.
> .... she has no exclusive claim over the definition (such as it is) of
> "number"
That's analagous to saying that climate scientists don't have the
exclusive say-so about climate change. Ha ha, who needs experts?
Mathematicians are _experts_ on numbers, with a deep understanding of
their definitions, properties, and limitations. I would have expected,
in this mailing list (as contrasted with lesser forums) to see respect
for expertise, not disparagement.
> (and I'm a bit surprised if she hadn't heard of at least one of the
> extended real lines I linked).
Again, offensive. "Infinity", with or without a sign, might be classed
as an "extended number", but as noted above, is not a number.
> NaN, on the other hand, is of course a floating-point value that
> explicitly claims not to be a number. I'm not sure whether to believe
> it; it seems very useful that the operations on floating-point
> "numbers" are closed, but that depends on NaN being one of them...
NaN is not a number, either, for much the same reasons. If you actually
attempt to do anything numerical with NaN you will run into trouble.
There have been discussions about the Lisp functions max and min being
called without arguments. Some people have advocated that non-numbers
be returned in such cases. I request most earnestly that this is not
done. Callers of these functions have a right to assume that returned
results are mathematically correct and that they can do arithmetic with
them.
Currently, max and min throw errors if called with no arguments. This
is surely the right thing to do, and we should carry on doing it.
> Davis
--
Alan Mackenzie (Nuremberg, Germany).
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-31 19:59 ` Alan Mackenzie
@ 2018-08-31 20:30 ` Clément Pit-Claudel
2018-08-31 21:58 ` Alan Mackenzie
2018-09-01 1:26 ` Herring, Davis
2018-08-31 21:15 ` Stefan Monnier
` (2 subsequent siblings)
3 siblings, 2 replies; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-08-31 20:30 UTC (permalink / raw)
To: Alan Mackenzie, Herring, Davis; +Cc: Pip Cet, emacs-devel@gnu.org
Hey Alan,
On 2018-08-31 15:59, Alan Mackenzie wrote:
> I'm speaking not as a mathematician, but as somebody with a degree in
> maths.
I'm speaking as someone who didn't expect a conversation like this one to spark such a strong-worded discussion :) The whole debate rings odd to me (I agree with https://math.stackexchange.com/questions/36289/is-infinity-a-number: It comes down to the definition of "number," as well as the definition of "infinity")
> +/-infinity are not numbers. They do not satisfy the axioms which
> define numbers. For example they do not satisfy
>
> (x + y) + z = x + (y + z)
>
> . They cannot be made to satisfy these axioms.
I see the point, but… floating point numbers are not associative either, and it doesn't seem to controversial to call them "numbers".
>> They're not real numbers, but neither are complex numbers,
>> split-complex numbers, dual numbers, p-adic numbers, quaternions,
>> octonions, sedenions, hyperreal numbers, or (please no) surreal
>> numbers.
>
> That's a strawman. The issue being discussed here is numbers, not
> arbitrary algebraic structures.
I read this as an example of the many meanings that the word "number" can take, depending on the context. It sounded pretty convincing.
>> .... she has no exclusive claim over the definition (such as it is) of
>> "number"
>
> That's analagous to saying that climate scientists don't have the
> exclusive say-so about climate change. Ha ha, who needs experts?
This is a very strongly worded charge. The original formulation could have been better, but to me it didn't look like a rejection of expertise… rather, I took it as a statement that the word "number" gets assigned different meanings across fields.
>> (and I'm a bit surprised if she hadn't heard of at least one of the
>> extended real lines I linked).
>
> Again, offensive. "Infinity", with or without a sign, might be classed
> as an "extended number", but as noted above, is not a number.
I don't understand this part. Does the word "number" on its own even have a strict definition, beyond something vague like Wikipedia's "mathematical object used to count, measure and also label"?
Cheers,
Clément.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-31 19:59 ` Alan Mackenzie
2018-08-31 20:30 ` Clément Pit-Claudel
@ 2018-08-31 21:15 ` Stefan Monnier
2018-09-01 1:05 ` Herring, Davis
2018-09-01 4:47 ` Clément Pit-Claudel
3 siblings, 0 replies; 281+ messages in thread
From: Stefan Monnier @ 2018-08-31 21:15 UTC (permalink / raw)
To: emacs-devel
I don't have any opinion on whether infinities should be called numbers
or not, but regarding:
> There have been discussions about the Lisp functions max and min being
> called without arguments. Some people have advocated that non-numbers
> be returned in such cases. I request most earnestly that this is not
> done. Callers of these functions have a right to assume that returned
> results are mathematically correct and that they can do arithmetic with
> them.
Currently many arithmetic functions, when called with "non-numbers" do
not signal an error, but instead return another such "non-number".
E.g. (+ 1.0e+INF 1) returns 1.0e+INF.
This is considered normal according to the IEEE practice.
So, from that point of view, I think it's fairly normal for min/max to
follow the same practice and return some kind of non-number when called
with another non-number, and by extension when not called with a number.
This non-number result (e.g. 1.0e+INF for `min`) can very be considered
as "returning an error" (just not using Elisp's error handling system,
but using IEEE's NaNs instead).
Stefan
PS: I prefer to stay away from anything past the Z set of numbers, and
I think anything involving floats will inevitably suck in corner cases,
so any behavior you choose in that case is OK AFAIC ;-)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-31 20:30 ` Clément Pit-Claudel
@ 2018-08-31 21:58 ` Alan Mackenzie
2018-09-01 1:26 ` Herring, Davis
1 sibling, 0 replies; 281+ messages in thread
From: Alan Mackenzie @ 2018-08-31 21:58 UTC (permalink / raw)
To: Clément Pit-Claudel; +Cc: Pip Cet, emacs-devel@gnu.org
Hello, Clément.
On Fri, Aug 31, 2018 at 16:30:46 -0400, Clément Pit-Claudel wrote:
> Hey Alan,
> On 2018-08-31 15:59, Alan Mackenzie wrote:
> > I'm speaking not as a mathematician, but as somebody with a degree in
> > maths.
> I'm speaking as someone who didn't expect a conversation like this one
> to spark such a strong-worded discussion :) The whole debate rings
> odd to me (I agree with
> https://math.stackexchange.com/questions/36289/is-infinity-a-number:
> It comes down to the definition of "number," as well as the definition
> of "infinity")
"Number" is defined in maths (of course, it's not simple, with many
different types of number), "infinity" is not, except in special
restricted contexts.
> > +/-infinity are not numbers. They do not satisfy the axioms which
> > define numbers. For example they do not satisfy
> >
> > (x + y) + z = x + (y + z)
> >
> > . They cannot be made to satisfy these axioms.
> I see the point, but… floating point numbers are not associative
> either, and it doesn't seem to controversial to call them "numbers".
Addition on real numbers is associative. It is also, almost, on
floating points, but not quite, because floating point is only a
practical approximation to real numbers. In practice, it means you've
got to be careful with floating point calculations, and what order you
do them in.
> >> They're not real numbers, but neither are complex numbers,
> >> split-complex numbers, dual numbers, p-adic numbers, quaternions,
> >> octonions, sedenions, hyperreal numbers, or (please no) surreal
> >> numbers.
> > That's a strawman. The issue being discussed here is numbers, not
> > arbitrary algebraic structures.
> I read this as an example of the many meanings that the word "number"
> can take, depending on the context. It sounded pretty convincing.
To me, it sounded like a diversion from the concept of numbers we have
in Emacs.
> >> .... she has no exclusive claim over the definition (such as it is)
> >> of "number"
> > That's analagous to saying that climate scientists don't have the
> > exclusive say-so about climate change. Ha ha, who needs experts?
> This is a very strongly worded charge. The original formulation could
> have been better, but to me it didn't look like a rejection of
> expertise… rather, I took it as a statement that the word "number"
> gets assigned different meanings across fields.
Yes, it may. But which meaning should we stick to in Emacs? I say the
mathematicians' meaning. It's the most likely to be consistent and the
least likely to cause untoward side-effects.
> >> (and I'm a bit surprised if she hadn't heard of at least one of the
> >> extended real lines I linked).
> > Again, offensive. "Infinity", with or without a sign, might be
> > classed as an "extended number", but as noted above, is not a
> > number.
> I don't understand this part. Does the word "number" on its own even
> have a strict definition, beyond something vague like Wikipedia's
> "mathematical object used to count, measure and also label"?
There are many different types (grades, if you like) of number. In
Emacs, we have computer approximations of Integers and real numbers.
Both of these concepts are rigorously defined in maths, in several
different ways (which can be shown to be equivalent). Other types of
number include rationals (aka fractions), algebraic numbers (solutions
of polynomial equations with integer coefficients), and complex numbers
(which cannot appear as arguments to min or max, since the relation <
cannot be defined on complex numbers without creating contradictions).
> Cheers,
> Clément.
--
Alan Mackenzie (Nuremberg, Germany).
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-31 19:59 ` Alan Mackenzie
2018-08-31 20:30 ` Clément Pit-Claudel
2018-08-31 21:15 ` Stefan Monnier
@ 2018-09-01 1:05 ` Herring, Davis
2018-09-02 10:57 ` Alan Mackenzie
2018-09-01 4:47 ` Clément Pit-Claudel
3 siblings, 1 reply; 281+ messages in thread
From: Herring, Davis @ 2018-09-01 1:05 UTC (permalink / raw)
To: Alan Mackenzie; +Cc: cpitclaudel@gmail.com, Pip Cet, emacs-devel@gnu.org
> +/-infinity are not numbers. They do not satisfy the axioms which
> define numbers. For example they do not satisfy
>
> (x + y) + z = x + (y + z)
What is the list of such axioms? If it includes the existence of an additive identity, you lose the natural numbers; if it includes the trichotomy property, you lose the complex numbers; if it includes commutativity of addition, you lose the ordinal numbers. Of course we can decide that any or all of those "aren't really numbers", but why?
While addition is one of the operations with the broadest applicability (but see the supernatural numbers) and associativity is one of the properties most widely required of a binary operation (but see the octonions), even associativity of addition is sometimes violated (consider the example of infinite series <https://en.wikipedia.org/wiki/Associative_property#Non-associative_operation>).
>> They're not real numbers, but neither are complex numbers,
>> split-complex numbers, dual numbers, p-adic numbers, quaternions,
>> octonions, sedenions, hyperreal numbers, or (please no) surreal
>> numbers.
>
> That's a strawman. The issue being discussed here is numbers, not
> arbitrary algebraic structures.
Which of those sets aren't sets of numbers? No one said anything about vector spaces, Lie groups, Sobolev spaces, tangent bundles, etc.
>> With all due respect to your mathematician friend, ....
>
> That is offensive in the extreme.
I'm sorry, but I don't understand how. I _meant_ the "due respect" that I wrote. Perhaps I should not presume that any two people are friends, but the broad use of that term was meant to be generous, not condescending.
>> .... she has no exclusive claim over the definition (such as it is) of
>> "number"
>
> That's analagous to saying that climate scientists don't have the
> exclusive say-so about climate change. Ha ha, who needs experts?
I don't follow the analogy. Outside of trivial misconceptions (like "weather" vs. "climate"), I don't know of a situation where the _definition_ of "climate change" is unclear. On the other hand, I don't know of any rigorous definition for "number" (thus my request for axioms above).
> I would have expected,
> in this mailing list (as contrasted with lesser forums) to see respect
> for expertise, not disparagement.
No one is disparaging expertise, certainly not in general. Experts routinely disagree, without any disrespect, about the more philosophical topics in their field. Given (what I consider to be) such a weakness of definition, I remain uncertain why a mathematical expert would so flatly reject a widely-used category of "number".
>> (and I'm a bit surprised if she hadn't heard of at least one of the
>> extended real lines I linked).
>
> Again, offensive.
Again, I'm afraid you'll have to explain. I stated that I considered it unlikely that a mathematician would be unfamiliar with the extended reals (considering that they are used as a notational device even in Calculus I). I said so because I don't know what other explanation to offer for such surprise at the IEEE rules, based so closely as they are on the extended reals.
Davis
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-31 20:30 ` Clément Pit-Claudel
2018-08-31 21:58 ` Alan Mackenzie
@ 2018-09-01 1:26 ` Herring, Davis
1 sibling, 0 replies; 281+ messages in thread
From: Herring, Davis @ 2018-09-01 1:26 UTC (permalink / raw)
To: Clément Pit-Claudel, Alan Mackenzie; +Cc: Pip Cet, emacs-devel@gnu.org
> The original formulation could have been better, but to me
> it didn't look like a rejection of expertise… rather, I took it
> as a statement that the word "number" gets assigned
> different meanings across fields.
You're definitely right that it could have been better: I now realize that I made a poor assumption. Re-quoting:
> Signed infinities are convenient symbols, but they're not numbers; I
> recall the horrified reaction of a mathematician when I told her about
> IEEE infinities
From context, I took this to mean that the mathematician in question objected to IEEE infinities _because +/-inf "aren't numbers"_, when her opinion could easily have been something rather more nuanced like "the utility of floating-point arithmetic is reduced by the inclusion of values that are not real numbers". There are legitimate issues with IEEE arithmetic, like the fact that infinities are produced despite the general rule that results are supposed to be rounded to the nearest representable value (which can't ever be infinity).
My apologies for presuming to know the reasoning of someone not even party to the conversation!
Davis
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-31 0:09 ` Stefan Monnier
@ 2018-09-01 2:32 ` Richard Stallman
0 siblings, 0 replies; 281+ messages in thread
From: Richard Stallman @ 2018-09-01 2:32 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> (defconst +∞ 1.0e+INF)
To start using non-ASCII characters in the names of Emacs Lisp
constructs is a fundamental change in practices. It is not
something to be done lightly.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-08-31 19:59 ` Alan Mackenzie
` (2 preceding siblings ...)
2018-09-01 1:05 ` Herring, Davis
@ 2018-09-01 4:47 ` Clément Pit-Claudel
3 siblings, 0 replies; 281+ messages in thread
From: Clément Pit-Claudel @ 2018-09-01 4:47 UTC (permalink / raw)
To: Alan Mackenzie, Herring, Davis; +Cc: Pip Cet, emacs-devel@gnu.org
Hi again Alan,
Thanks for your thoughtful response!
On 2018-08-31 15:59, Alan Mackenzie wrote:
> There have been discussions about the Lisp functions max and min being
> called without arguments. Some people have advocated that non-numbers
> be returned in such cases. I request most earnestly that this is not
> done. Callers of these functions have a right to assume that returned
> results are mathematically correct and that they can do arithmetic with
> them.
>
> Currently, max and min throw errors if called with no arguments. This
> is surely the right thing to do, and we should carry on doing it.
Thinking more about your message, I'm not sure I agree with this point, either. I don't know about the US or Germany, but at least in France it is common to define inf and sup as functions from ℝ into ℝ ∪ {–∞, +∞}, the extended real number line. With these definitions, inf(∅) is customarily set to +∞, and sup(∅) is set to +∞.
https://en.wikipedia.org/wiki/Empty_set#Extended_real_numbers says:
Since the empty set has no members, when it is considered as a subset of any ordered set, then every member of that set will be an upper bound and lower bound for the empty set. For example, when considered as a subset of the real numbers, with its usual ordering, represented by the real number line, every real number is both an upper and lower bound for the empty set. When considered as a subset of the extended reals formed by adding two "numbers" or "points" to the real numbers, namely negative infinity, denoted −∞, which is defined to be less than every other extended real number, and positive infinity, denoted +∞, which is defined to be greater than every other extended real number, then:
sup ∅ = min({−∞, +∞} ∪ R) = −∞
and
inf ∅ = max({−∞, +∞} ∪ R) = +∞
That is, the least upper bound (sup or supremum) of the empty set is negative infinity, while the greatest lower bound (inf or infimum) is positive infinity. By analogy with the above, in the domain of the extended reals, negative infinity is the identity element for the maximum and supremum operators, while positive infinity is the identity element for minimum and infimum.
I could be convinced that returning −∞ and +∞ is wrong based on the fact that inf and sup are not min and max, and that the outputs of min and max should be elements of the sets they operate on; conversely, I'm also receptive to the convenience aspect or min and max returning infinities; but all in all I don't find the "numberness" argument particularly compelling, based on the reasoning outlined above.
Clément.
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-09-01 1:05 ` Herring, Davis
@ 2018-09-02 10:57 ` Alan Mackenzie
2018-09-04 6:14 ` Herring, Davis
0 siblings, 1 reply; 281+ messages in thread
From: Alan Mackenzie @ 2018-09-02 10:57 UTC (permalink / raw)
To: Herring, Davis; +Cc: cpitclaudel@gmail.com, Pip Cet, emacs-devel@gnu.org
Hello, Davis.
On Sat, Sep 01, 2018 at 01:05:33 +0000, Herring, Davis wrote:
> > +/-infinity are not numbers. They do not satisfy the axioms which
> > define numbers. For example they do not satisfy
> > (x + y) + z = x + (y + z)
> What is the list of such axioms?
Obviously different for different sorts of number. For the real numbers,
briefly, numbers form a field (loosely speaking, a structure in which one
can do +, -, *, / (except by 0, of course)), they are ordered (loosely
speaking, for any pair of numbers, they are either equal or one is less
than the other, together with axioms for manipulating <), and the
completeness axiom aplies (if a non-empty set of reals is bounded above,
there exists a real number which is a least upper bound).
> If it includes the existence of an additive identity, you lose the
> natural numbers; if it includes the trichotomy property, you lose the
> complex numbers; if it includes commutativity of addition, you lose the
> ordinal numbers. Of course we can decide that any or all of those
> "aren't really numbers", but why?
Because this is an emacs groups, and we have to use "number" in that
context. We have integers (of various sorts) and floating point numbers.
I believe SXEmacs has more categories of "number" than Emacs, but I don't
know what (if anything) they get used for.
[ .... ]
> >> They're not real numbers, but neither are complex numbers,
> >> split-complex numbers, dual numbers, p-adic numbers, quaternions,
> >> octonions, sedenions, hyperreal numbers, or (please no) surreal
> >> numbers.
> > That's a strawman. The issue being discussed here is numbers, not
> > arbitrary algebraic structures.
> Which of those sets aren't sets of numbers? No one said anything
> about vector spaces, Lie groups, Sobolev spaces, tangent bundles, etc.
See above.
> >> With all due respect to your mathematician friend, ....
> > That is offensive in the extreme.
> I'm sorry, but I don't understand how. I _meant_ the "due respect"
> that I wrote. Perhaps I should not presume that any two people are
> friends, but the broad use of that term was meant to be generous, not
> condescending.
"With all due respect, ....., I am ignoring your expert judgment" is how
it came over to me.
> >> .... she has no exclusive claim over the definition (such as it is)
> >> of "number"
> > That's analagous to saying that climate scientists don't have the
> > exclusive say-so about climate change. Ha ha, who needs experts?
> I don't follow the analogy. Outside of trivial misconceptions (like
> "weather" vs. "climate"), I don't know of a situation where the
> _definition_ of "climate change" is unclear.
The analogy was about respect and contempt for expertise, not
definitions.
> On the other hand, I don't know of any rigorous definition for "number"
> (thus my request for axioms above).
Note that these two "infinities" are being proposed as members of
(Emacs's) real numbers, so it is reasonable to focus on real numbers. I
hope my summary of the axioms above has helped.
> > I would have expected, in this mailing list (as contrasted with
> > lesser forums) to see respect for expertise, not disparagement.
> No one is disparaging expertise, certainly not in general. Experts
> routinely disagree, without any disrespect, about the more
> philosophical topics in their field. Given (what I consider to be)
> such a weakness of definition, I remain uncertain why a mathematical
> expert would so flatly reject a widely-used category of "number".
I've explained already. Because extending the real numbers with
"infinity" means they no longer satisfy the field axioms, or the ordering
axioms; they're no longer real numbers.
[ .... ]
> Davis
--
Alan Mackenzie (Nuremberg, Germany).
^ permalink raw reply [flat|nested] 281+ messages in thread
* Re: Making 'eq' == 'eql' in bignum branch
2018-09-02 10:57 ` Alan Mackenzie
@ 2018-09-04 6:14 ` Herring, Davis
0 siblings, 0 replies; 281+ messages in thread
From: Herring, Davis @ 2018-09-04 6:14 UTC (permalink / raw)
To: Alan Mackenzie; +Cc: cpitclaudel@gmail.com, Pip Cet, emacs-devel@gnu.org
> Because this is an emacs groups, and we have to use "number" in that
> context.
I think we've finally found the root of our miscommunication: I took the discussion to be about numbers in general, from which we might draw useful conclusions for Emacs, rather than to (already) be about Emacs' model for the real numbers.
>> What is the list of such axioms?
>
> Obviously different for different sorts of number.
Certainly: that was the entire point of my most recent message -- and of my first in this thread.
> For the real numbers, [...]
...And conversely I was never asking for the axioms for real numbers, although it's good to remember those every once in a while (I usually think only of Cauchy completeness, but that allows interlopers like the Levi-Civita field).
> Note that these two "infinities" are being proposed as members of
> (Emacs's) real numbers, so it is reasonable to focus on real numbers.
They're not being proposed -- they're already there (if not in C, then at least on all machines in common use), since IEEE 754 is in fact based on the (affinely) extended reals. It's begging the question to call Emacs' numbers real and then object to the inclusion of infinities based on that, but you're right that it's reasonable to _focus_ on the cofinite real subset when trying to engineer a usable system we can reason about.
Davis
^ permalink raw reply [flat|nested] 281+ messages in thread
end of thread, other threads:[~2018-09-04 6:14 UTC | newest]
Thread overview: 281+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-04-21 14:15 Using the GNU GMP Library for Bignums in Emacs Siraphob (Ben) Phipathananunth
2018-04-21 14:34 ` Eli Zaretskii
2018-04-21 15:01 ` Siraphob (Ben) Phipathananunth
2018-04-21 15:23 ` Paul Eggert
2018-04-21 15:36 ` Eli Zaretskii
2018-04-21 15:40 ` Siraphob (Ben) Phipathananunth
2018-04-21 15:54 ` Eli Zaretskii
2018-04-21 16:08 ` Paul Eggert
2018-04-26 3:17 ` Tom Tromey
2018-04-26 3:33 ` Stefan Monnier
2018-04-27 15:56 ` Richard Stallman
2018-04-27 16:08 ` Stefan Monnier
2018-04-21 22:42 ` Richard Stallman
2018-04-22 2:48 ` dancol
2018-04-22 13:00 ` Philipp Stephani
2018-04-22 17:43 ` Paul Eggert
2018-04-22 18:04 ` Daniel Colascione
2018-04-22 18:34 ` Clément Pit-Claudel
2018-04-23 3:39 ` Richard Stallman
2018-04-22 8:00 ` Siraphob (Ben) Phipathananunth
2018-04-22 9:06 ` Paul Eggert
2018-04-23 5:19 ` Helmut Eller
2018-04-23 8:39 ` Andreas Schwab
2018-04-23 14:36 ` Paul Eggert
2018-04-23 19:22 ` Helmut Eller
2018-04-23 20:26 ` Paul Eggert
2018-04-23 3:36 ` Richard Stallman
2018-04-22 12:43 ` Helmut Eller
2018-04-22 17:47 ` Paul Eggert
2018-04-23 3:39 ` Richard Stallman
2018-04-23 4:41 ` Paul Eggert
2018-04-24 2:54 ` Richard Stallman
2018-04-24 2:54 ` Richard Stallman
2018-04-24 4:35 ` Paul Eggert
2018-04-24 5:45 ` Helmut Eller
2018-06-03 23:44 ` Jefferson Carpenter
2018-04-25 1:05 ` Richard Stallman
2018-04-25 1:19 ` Paul Eggert
2018-04-25 22:40 ` Richard Stallman
2018-04-25 23:29 ` Paul Eggert
2018-04-30 3:07 ` Richard Stallman
2018-04-30 5:00 ` Michael Welsh Duggan
2018-04-30 12:34 ` Stefan Monnier
2018-05-01 3:01 ` Richard Stallman
2018-04-30 7:04 ` Paul Eggert
2018-05-01 3:01 ` Richard Stallman
2018-05-01 21:45 ` Paul Eggert
2018-05-03 3:34 ` Richard Stallman
2018-05-03 5:53 ` Paul Eggert
2018-05-03 6:26 ` Helmut Eller
2018-05-03 17:49 ` Eli Zaretskii
2018-05-03 18:26 ` Paul Eggert
2018-05-04 4:26 ` Richard Stallman
2018-05-05 5:03 ` Ken Raeburn
2018-05-06 3:12 ` Richard Stallman
2018-05-07 17:24 ` Ken Raeburn
2018-05-08 1:55 ` Richard Stallman
2018-05-07 18:40 ` Andreas Schwab
2018-05-03 18:51 ` Helmut Eller
[not found] ` <83sh78o6af.fsf@gnu.org>
2018-05-03 20:30 ` Helmut Eller
2018-05-03 21:48 ` Paul Eggert
2018-05-04 4:22 ` Richard Stallman
2018-04-23 3:03 ` Stefan Monnier
2018-07-05 21:29 ` Tom Tromey
2018-07-05 21:53 ` John Wiegley
2018-07-06 20:43 ` Tom Tromey
2018-07-06 21:00 ` Paul Eggert
2018-07-07 4:27 ` Tom Tromey
2018-07-07 4:53 ` Paul Eggert
2018-07-07 6:20 ` Tom Tromey
2018-07-07 6:38 ` Paul Eggert
2018-07-09 5:37 ` Tom Tromey
2018-07-09 16:22 ` Paul Eggert
2018-07-09 22:56 ` Tom Tromey
2018-07-09 23:02 ` Paul Eggert
2018-07-09 23:13 ` Tom Tromey
2018-07-10 4:01 ` Tom Tromey
2018-07-10 13:46 ` Tom Tromey
2018-07-08 15:59 ` Tom Tromey
2018-07-09 5:43 ` Tom Tromey
2018-07-10 4:10 ` Stefan Monnier
2018-07-07 23:43 ` Richard Stallman
2018-07-08 4:58 ` Paul Eggert
2018-07-08 22:55 ` Richard Stallman
2018-07-08 5:01 ` Tom Tromey
2018-07-08 22:55 ` Richard Stallman
2018-07-09 5:39 ` Tom Tromey
2018-07-09 20:15 ` Stefan Monnier
2018-07-09 23:25 ` Paul Eggert
2018-07-10 3:41 ` Stefan Monnier
2018-07-10 5:32 ` Helmut Eller
2018-07-10 13:54 ` Stefan Monnier
2018-07-10 16:01 ` Paul Eggert
2018-07-10 16:48 ` Helmut Eller
2018-07-10 17:45 ` Paul Eggert
2018-07-10 19:14 ` Helmut Eller
2018-07-11 1:31 ` Stefan Monnier
2018-07-11 5:59 ` Helmut Eller
2018-07-11 14:23 ` Stefan Monnier
2018-07-11 2:04 ` Tom Tromey
2018-07-11 2:36 ` Paul Eggert
2018-07-10 20:33 ` Stefan Monnier
2018-07-11 1:52 ` Tom Tromey
2018-07-11 2:35 ` Paul Eggert
2018-07-11 3:16 ` Stefan Monnier
2018-07-11 3:30 ` Paul Eggert
2018-07-11 3:42 ` Stefan Monnier
2018-07-11 22:48 ` Richard Stallman
2018-07-12 4:51 ` Tom Tromey
2018-07-12 23:35 ` Richard Stallman
2018-07-15 15:02 ` Stefan Monnier
2018-07-18 10:20 ` Paul Eggert
2018-07-18 13:17 ` Stefan Monnier
2018-07-27 21:14 ` Making 'eq' == 'eql' in bignum branch Paul Eggert
2018-07-28 14:26 ` Stefan Monnier
2018-07-29 3:34 ` Paul Eggert
2018-07-29 4:09 ` Stefan Monnier
2018-07-29 14:35 ` Eli Zaretskii
2018-07-30 17:07 ` Stefan Monnier
2018-07-30 18:49 ` Eli Zaretskii
2018-07-30 20:10 ` Stefan Monnier
2018-07-30 21:58 ` Paul Eggert
2018-07-31 2:38 ` Eli Zaretskii
2018-07-31 7:10 ` Paul Eggert
2018-07-31 16:12 ` Eli Zaretskii
2018-07-31 22:44 ` Paul Eggert
2018-08-01 5:51 ` Eli Zaretskii
2018-08-01 6:43 ` Paul Eggert
2018-08-01 8:53 ` Eli Zaretskii
2018-08-03 7:40 ` Paul Eggert
2018-08-03 7:55 ` Eli Zaretskii
2018-08-10 11:12 ` Pip Cet
2018-08-10 15:15 ` Stefan Monnier
2018-08-10 15:43 ` Pip Cet
2018-08-10 15:55 ` Stefan Monnier
2018-08-10 16:52 ` John Yates
2018-08-10 19:45 ` Eli Zaretskii
2018-08-10 20:48 ` Paul Eggert
2018-08-10 7:05 ` Elias Mårtenson
2018-08-10 8:02 ` Paul Eggert
[not found] ` <<83d0v4p1si.fsf@gnu.org>
2018-07-31 15:08 ` Drew Adams
2018-07-31 16:24 ` Eli Zaretskii
2018-07-31 22:21 ` Paul Eggert
2018-08-20 0:04 ` Stefan Monnier
2018-08-20 1:33 ` Paul Eggert
2018-08-20 15:20 ` Stefan Monnier
2018-08-20 6:35 ` Pip Cet
2018-08-20 7:05 ` Paul Eggert
2018-08-20 7:19 ` Pip Cet
2018-08-20 7:27 ` Paul Eggert
2018-08-20 8:49 ` Andy Moreton
2018-08-20 16:03 ` Paul Eggert
2018-08-20 16:41 ` Andy Moreton
2018-08-20 16:51 ` Paul Eggert
2018-08-20 16:58 ` Andy Moreton
2018-08-20 19:50 ` Pip Cet
2018-08-20 21:54 ` Andy Moreton
2018-08-21 3:38 ` Richard Stallman
2018-08-20 17:23 ` Eli Zaretskii
2018-08-20 17:35 ` Paul Eggert
2018-08-20 15:13 ` Eli Zaretskii
2018-08-20 15:26 ` Stefan Monnier
2018-08-20 16:19 ` Eli Zaretskii
2018-08-21 15:01 ` Robert Pluim
2018-08-21 19:09 ` Robert Pluim
2018-08-21 19:35 ` Paul Eggert
2018-08-22 8:26 ` Lars Ingebrigtsen
2018-08-22 13:22 ` Herring, Davis
2018-08-22 13:28 ` Lars Ingebrigtsen
2018-08-22 13:55 ` Paul Eggert
2018-08-22 20:01 ` Stefan Monnier
2018-08-23 8:13 ` Robert Pluim
2018-08-23 13:45 ` Eli Zaretskii
2018-08-23 14:48 ` Robert Pluim
2018-08-23 18:43 ` Stefan Monnier
2018-08-24 9:51 ` Robert Pluim
2018-08-25 17:59 ` Stefan Monnier
2018-08-20 16:01 ` Paul Eggert
2018-08-20 16:26 ` Eli Zaretskii
2018-08-21 3:37 ` Richard Stallman
2018-08-20 15:12 ` Eli Zaretskii
2018-08-20 15:26 ` Lars Ingebrigtsen
2018-08-20 16:18 ` Eli Zaretskii
2018-08-22 19:59 ` Stefan Monnier
2018-08-21 3:38 ` Richard Stallman
2018-08-25 23:27 ` Paul Eggert
2018-08-26 12:45 ` Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch) Michael Albinus
2018-08-26 15:34 ` Paul Eggert
2018-08-26 16:06 ` Eli Zaretskii
2018-08-26 16:44 ` Tramp and fixnum Michael Albinus
2018-08-28 4:47 ` Tramp and fixnum (was: Making 'eq' == 'eql' in bignum branch) Paul Eggert
2018-08-26 16:49 ` Tramp and fixnum Michael Albinus
2018-08-28 4:48 ` Paul Eggert
2018-08-28 11:50 ` Michael Albinus
2018-08-28 14:33 ` Michael Albinus
2018-08-28 15:18 ` Paul Eggert
2018-08-29 8:09 ` Michael Albinus
2018-08-26 16:34 ` Making 'eq' == 'eql' in bignum branch Tom Tromey
2018-08-26 16:59 ` Stefan Monnier
2018-08-26 20:19 ` Alan Mackenzie
2018-08-26 20:31 ` Stefan Monnier
2018-08-27 2:31 ` Eli Zaretskii
2018-08-27 4:45 ` Stefan Monnier
2018-08-27 5:10 ` Paul Eggert
2018-08-27 14:59 ` Eli Zaretskii
2018-08-27 15:18 ` Stefan Monnier
2018-08-27 15:37 ` Eli Zaretskii
2018-08-27 15:47 ` Stefan Monnier
2018-08-27 18:57 ` Paul Eggert
2018-08-26 20:45 ` Richard Stallman
2018-08-26 22:10 ` Clément Pit-Claudel
2018-08-27 0:23 ` Paul Eggert
2018-08-27 22:50 ` Richard Stallman
2018-08-28 1:44 ` Paul Eggert
2018-08-28 14:12 ` Tom Tromey
2018-08-28 21:30 ` Richard Stallman
2018-08-28 22:03 ` Clément Pit-Claudel
2018-08-29 22:10 ` Richard Stallman
2018-08-28 18:03 ` Clément Pit-Claudel
2018-08-29 3:53 ` Stefan Monnier
2018-08-29 18:49 ` Clément Pit-Claudel
2018-08-28 1:33 ` Lars Ingebrigtsen
2018-08-28 2:25 ` Pip Cet
2018-08-28 3:45 ` Paul Eggert
2018-08-28 7:34 ` Ken Raeburn
2018-08-28 9:11 ` Helmut Eller
2018-08-28 12:15 ` Stefan Monnier
2018-08-28 18:00 ` Clément Pit-Claudel
2018-08-28 22:57 ` Pip Cet
2018-08-29 3:42 ` Herring, Davis
2018-08-29 5:40 ` Helmut Eller
2018-08-29 13:15 ` Pip Cet
2018-08-31 19:59 ` Alan Mackenzie
2018-08-31 20:30 ` Clément Pit-Claudel
2018-08-31 21:58 ` Alan Mackenzie
2018-09-01 1:26 ` Herring, Davis
2018-08-31 21:15 ` Stefan Monnier
2018-09-01 1:05 ` Herring, Davis
2018-09-02 10:57 ` Alan Mackenzie
2018-09-04 6:14 ` Herring, Davis
2018-09-01 4:47 ` Clément Pit-Claudel
2018-08-29 3:22 ` Elias Mårtenson
2018-08-29 18:56 ` Clément Pit-Claudel
2018-08-29 19:30 ` Stefan Monnier
2018-08-31 0:09 ` Stefan Monnier
2018-09-01 2:32 ` Richard Stallman
2018-08-31 16:41 ` Paul Eggert
2018-08-28 21:25 ` Richard Stallman
2018-08-30 19:13 ` Johan Bockgård
2018-08-30 21:14 ` Clément Pit-Claudel
2018-08-30 21:35 ` Tom Tromey
2018-08-30 21:56 ` Clément Pit-Claudel
2018-08-20 15:37 ` Stefan Monnier
2018-08-20 16:23 ` Eli Zaretskii
2018-08-20 16:12 ` Paul Eggert
2018-08-20 17:21 ` Helmut Eller
2018-08-20 14:02 ` Stefan Monnier
2018-07-18 15:55 ` Using the GNU GMP Library for Bignums in Emacs Eli Zaretskii
2018-07-18 21:42 ` Paul Eggert
2018-07-22 12:06 ` Ken Raeburn
2018-07-22 16:44 ` Paul Eggert
2018-08-01 7:57 ` Paul Eggert
2018-08-01 11:59 ` Eli Zaretskii
2018-08-02 2:06 ` Paul Eggert
2018-08-02 13:49 ` Eli Zaretskii
2018-07-22 19:57 ` Achim Gratz
2018-04-21 16:46 ` Markus Triska
2018-04-21 17:09 ` Eli Zaretskii
2018-04-21 17:27 ` Markus Triska
2018-04-21 18:37 ` Paul Eggert
2018-04-21 22:42 ` Richard Stallman
2018-04-22 2:43 ` Eli Zaretskii
2018-04-23 3:34 ` Richard Stallman
2018-04-23 4:21 ` Paul Eggert
2018-04-23 13:13 ` Stefan Monnier
2018-04-24 2:54 ` Richard Stallman
2018-04-24 4:34 ` Paul Eggert
2018-04-25 1:05 ` Richard Stallman
2018-04-23 15:18 ` Eli Zaretskii
2018-04-24 18:56 ` Emanuele Santoro
2018-04-26 15:52 ` Glenn Morris
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).