From: <don...@is...> - 2015-10-20 22:55:47
|
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 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. 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. > 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. |