From: Pascal J. B. <pj...@in...> - 2015-10-21 13:39:40
|
On 21/10/15 00:55, Don Cohen wrote: > > The current state is not conforming but it's better than a conforming > solution that would have to be much more complex. > I think most people so far agree that clisp cannot conform to spec > without discarding variable precision long floats. > Nobody so far wants that. > The current issue is which of the proposed nonconforming solutions > is best. > > > This doesn't solve the larger problem of constants in code. > > You probably don't want to replace 1l0 in your code with > > (read-from-string "1l0"), at leat if that code is to run many times. > > It's possible to write a macro (adjust-precision "1l0") that generates > > code that checks whether precision has been changed since it was last > > run (I hope that's cheap) and if so rereads the constant. It could > > even keep a cache of values of different precisions. > > 1L0 is always 1L0, whatever the long-float-digits. > However not all 1L0's are the same. > (/ 1L0 3) > 0.33333333333333333334L0 > (setf (ext:long-float-digits) 128) > (/ 1L0 3) > 0.333333333333333333333333333333333333334L0 [1]> (defparameter *one-def* 1L0) *ONE-DEF* [2]> (setf (ext:long-float-digits) 100) 100 [5]> (defparameter *one-100* 1L0) *ONE-100* [6]> (eql *one-def* *one-100*) NIL [7]> (= *one-def* *one-100*) T [8]> (type-of *one-def*) LONG-FLOAT [9]> (type-of *one-100*) LONG-FLOAT [10]> This is another non-conformity. clhs eql: The value of eql is true of two objects, x and y, in the folowing cases: 1. If x and y are eq. 2. If x and y are both numbers of the same type and the same value. 3. If they are both characters that represent the same character. Otherwise the value of eql is false. So we have here two numbers that have the same value (=), and the same type (type-of), but they are not EQL. As mentionned before, when we change the long-float-digits, we start using values of a different subtype of long-float. Unfortunately, TYPE-OF doesn't return that subtype, and it looks like those numbers are of the same type, which is not the case (as demonstrated by EQL returning false). > > > when you change long-float-digit, the long float value that should > represent pi or e (or any of the other transcendental numbers), is > not the same anymore. > I don't understand why you think pi should be the best approximation > available with long-float-digits digits. > The spec says the best long approximation. > This is only satisfied by whatever is the maximum allowed value of > long-float-digits and nobody (in his right mind) wants to use that. But you cannot guess in advance what will be the maximum used by a program! The maximum allowed propably fills the RAM. > > Given that the image contains values of aribtrarily many different > precisions, why should pi contain this one rather than any of the > others? I think it should contain the original one and that should > simply be the local clisp definition of pi. Because CL:PI is meant to represent π and any value with less precision than the maximum allowed will be a DIFFERENT value, not representing π, but a DECIMAL number different to π. The only DECIMAL number that represents π is the one with the maximum allowed precision. > > >> While we're at it, I suggest that it would be a lot more convenient >> to programmatically control precision if there were a function to >> read long floats of precision n, e.g., (read-long "1l0" n), which >> returns the rough equivalent (I hope much more efficiently) of >> (let ((p (ext:long-float-digits))) >> (setf (ext:long-float-digits) n) >> (prog1 (read-from-string "1l0") (setf (ext:long-float-digits) p))) > There it is: > > (defun read-long (string n) > (let ((p (ext:long-float-digits))) > (setf (ext:long-float-digits) n) > (prog1 (read-from-string "1l0") (setf (ext:long-float-digits) p)))) > > I guess you didn't notice the remark about efficiency. > It ought to be a whole lot faster to create a 1L0 of precision > 1000000 than to compute pi to that precision. > > > It would also be nice if different threads could work in different > > default precisions. For this purpose it seems better to make > > long-float-digits a regular special variable that can be rebound > > by any code and only affect the reads that are done with that binding. > > Of course, I don't propose that pi be changed or even rebound when > > long-float-digits is rebound. But the rebinding will affect the value > > of (pi). > > The binding of cl:pi could be thread-local. > > Is this really what you propose? > So when you set long-float-digits you do what, exactly? > > > So now I'm proposing somewhat larger changes, but I think they > > make the resulting system quite a bit more useful. > > The underlying clisp seems perfectly well adapted to using different > > precisions under program control, but this facility is made > > unnecessarily inconvenient to use, in my opinion, by the current > > mechanism of (setf long-float-digits) and its adjustments, along with > > the lack of the read-long function and the functions like > > (pi &optional precision). > > Notice that if you set long-float-digits, and save a bunch of > long-float values computed with that precision, then you change > long-float-digits, and use the saved values to further compute, then > the resulting long-float will have the original precision. Therefore > you can already have threads performing computations with different > long-float precisions! (only take care of not reading new long > floats or not using cl:pi or otherwise poluting your computing with > long-float of a different precision). > > I agree that you CAN do these things but they're very inconvenient and > very innefficient compared to simply binding a special variable. > If my threads want their own precision (or at least don't want to just > use whatever precision some other thread decided to use), they all > have to lock this single resource, which is also very expensive to > pass from one to another. > I don't know what YOU want either. Introducing variable precision long-float as it's done is clearly bringing a lot of non-conformities, and having (not (constantp 'pi)) is the most benign of them. Do you want to change that? It'll be worse. Do you want to change something else? It'll be worser. Before considering any change on clisp long-float, I would advise you to study realib and a few alternative (to implement "infinite" precision numbers), and try to think about how we could add such types to the CL numeric tower in an extension that doesn't introduce non-conformities. -- __Pascal J. Bourguignon__ http://www.informatimago.com/ |