From: <don...@is...> - 2015-10-16 07:21:45
|
[1]> (lisp-implementation-version) ; built from current source "2.49+ (2010-07-17) (built 3653902709) (memory 3653902846)" [2]> (constantp 'pi) ; I think this should return T NIL [3]> (defconstant pi2 pi) PI2 [4]> (constantp 'pi2) T [5]> |
From: Pascal J. B. <pj...@in...> - 2015-10-16 13:58:19
|
On 16/10/15 09:21, Don Cohen wrote: > [1]> (lisp-implementation-version) ; built from current source > "2.49+ (2010-07-17) (built 3653902709) (memory 3653902846)" > [2]> (constantp 'pi) ; I think this should return T > NIL > [3]> (defconstant pi2 pi) > PI2 > [4]> (constantp 'pi2) > T > [5]> > The problem is that in clisp, CL:PI is not constant [1]> pi 3.1415926535897932385L0 [2]> (setf (ext:long-float-digits) 1000) 1000 [3]> pi 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587L0 [4]> Conformity could be restored by having CL:PI defined as a constant variable bound to double-float π, and to have another variable EXT:PI bound to the changing long-float π value. -- __Pascal J. Bourguignon__ http://www.informatimago.com/ |
From: Pierpaolo B. <olo...@gm...> - 2015-10-16 14:10:20
|
On Fri, Oct 16, 2015 at 3:38 PM, Pascal J. Bourguignon <pj...@in...> wrote: > Conformity could be restored by having CL:PI defined as a constant > variable bound to double-float π, and to have another variable EXT:PI > bound to the changing long-float π value. Would still be not conforming. ==== Constant Variable PI Value: an implementation-dependent long float. Description: The best long float approximation to the mathematical constant <PI>. ==== To be pedantically conformant, one must excise variable-precision long-floats. (I'll keep them, thank you very much :) |
From: <don...@is...> - 2015-10-18 16:13:43
|
I should have remembered about pi being recomputed. > Conformity could be restored by having CL:PI defined as a constant > variable bound to double-float, and to have another variable EXT:PI > bound to the changing long-float value. Would still be not conforming. Although the suggestion above would not be strictly conforming, I think it would be an improvement in that (let (pi)) would signal an error and constantp would return the expected result. I was also wondering about (constantp '(+ 1 pi2)) returning t but (constantp '(sin pi2)) returning nil. But I recognize this is conforming. |
From: Pierpaolo B. <olo...@gm...> - 2015-10-18 16:35:42
|
On Sun, Oct 18, 2015 at 6:13 PM, Don Cohen <don...@is...> wrote: > > Conformity could be restored by having CL:PI defined as a constant > > variable bound to double-float, and to have another variable EXT:PI > > bound to the changing long-float value. > > Would still be not conforming. > > Although the suggestion above would not be strictly conforming, I > think it would be an improvement in that (let (pi)) would signal an > error and constantp would return the expected result. At the cost of every computation involving pi and long floats returning wrong answers! |
From: <don...@is...> - 2015-10-18 18:02:21
|
Pierpaolo Bernardi writes: > On Sun, Oct 18, 2015 at 6:13 PM, Don Cohen > <don...@is...> wrote: > > > > Conformity could be restored by having CL:PI defined as a constant > > > variable bound to double-float, and to have another variable EXT:PI > > > bound to the changing long-float value. > > > > Would still be not conforming. > > > > Although the suggestion above would not be strictly conforming, I > > think it would be an improvement in that (let (pi)) would signal an > > error and constantp would return the expected result. > > At the cost of every computation involving pi and long floats > returning wrong answers! Why do you think they're wrong? |
From: Pierpaolo B. <olo...@gm...> - 2015-10-18 18:29:14
|
On Sun, Oct 18, 2015 at 8:02 PM, Don Cohen <don...@is...> wrote: > Pierpaolo Bernardi writes: > > At the cost of every computation involving pi and long floats > > returning wrong answers! > > Why do you think they're wrong? They would be wrong if PI had not the required long float precision. PI not being a constant is a much more benign non conformity. Surely you can work around it? |
From: <don...@is...> - 2015-10-18 18:57:33
|
Pierpaolo Bernardi writes: > On Sun, Oct 18, 2015 at 8:02 PM, Don Cohen > <don...@is...> wrote: > > Pierpaolo Bernardi writes: > > > > At the cost of every computation involving pi and long floats > > > returning wrong answers! > > > > Why do you think they're wrong? > > They would be wrong if PI had not the required long float precision. Wrong in what sense? I think that "wrong" means different from intended. (setf (EXT:LONG-FLOAT-DIGITS) 128) (setf s2 (sqrt 2l0)) (setf (EXT:LONG-FLOAT-DIGITS) 64) (* 2 s2) Is this now wrong because s2 was computed with higher precision? If this is what I intended then I think it's right. > PI not being a constant is a much more benign non conformity. Surely > you can work around it? I think you could use ext:pi for the cases where you want it to change. In fact, it occurs to me that it would make more sense to use (pi &optional precision) to compute pi (values could still be cached), and allow special binding of *ext:long-float-digits* to control default precision. BTW, it now occurs to be that things like MOST-POSITIVE-LONG-FLOAT have to be reinterpreted compared to other lisp implementations: (setf (EXT:LONG-FLOAT-DIGITS) 128) (setf mp128 MOST-POSITIVE-LONG-FLOAT) (setf (EXT:LONG-FLOAT-DIGITS) 64) (> mp128 MOST-POSITIVE-LONG-FLOAT) => T It would make sense to me to treat these other "constants" in the same way I now propose to treat pi. |
From: Pierpaolo B. <olo...@gm...> - 2015-10-18 19:51:53
|
On Sun, Oct 18, 2015 at 8:57 PM, Don Cohen <don...@is...> wrote: > Pierpaolo Bernardi writes: > > On Sun, Oct 18, 2015 at 8:02 PM, Don Cohen > > <don...@is...> wrote: > > > Pierpaolo Bernardi writes: > > > > > > At the cost of every computation involving pi and long floats > > > > returning wrong answers! > > > > > > Why do you think they're wrong? > > > > They would be wrong if PI had not the required long float precision. > > Wrong in what sense? PI is required to be the best long float approximation to pi. If it wasn't then it would be wrong. Also, PI is required to be a constant variable. It isn't and so it's wrong. But i think this "wrong" is a very small price to pay in exchange for having adjustable precision long floats. > (setf (EXT:LONG-FLOAT-DIGITS) 128) > (setf s2 (sqrt 2l0)) > (setf (EXT:LONG-FLOAT-DIGITS) 64) > (* 2 s2) > Is this now wrong because s2 was computed with higher precision? > If this is what I intended then I think it's right. In this case you are using a Clisp extension and you are getting what Clisp promises to deliver. So it is right. > > PI not being a constant is a much more benign non conformity. Surely > > you can work around it? > > I think you could use ext:pi for the cases where you want it to > change. The problem then is the value of CL:PI. What do you propose it should be? > In fact, it occurs to me that it would make more sense to use > (pi &optional precision) to compute pi (values could still be cached), > and allow special binding of *ext:long-float-digits* to control > default precision. The problem of what should be the value of CL:PI remains. > BTW, it now occurs to be that things like MOST-POSITIVE-LONG-FLOAT > have to be reinterpreted compared to other lisp implementations: > (setf (EXT:MOST-POSITIVE-LONG-FLOAT) > (setf (EXT:LONG-FLOAT-DIGITS) 64) > (> mp128 MOST-POSITIVE-LONG-FLOAT) > => > T > > It would make sense to me to treat these other "constants" in the same > way I now propose to treat pi. If you use EXT:LONG-FLOAT-DIGITS then you are outside of portable CL, and you should take into account your uses of this function in your coding. If you don't use EXT:LONG-FLOAT-DIGITS then the only non-confomance is that some things that should be constant variables are variables instead (but they won't in fact vary). |
From: <don...@is...> - 2015-10-18 20:14:00
|
> PI is required to be the best long float approximation to pi. If it > wasn't then it would be wrong. But that is already long unless long float digits is at its maximal value. **** -- sorry, "long" should be "wrong" > Also, PI is required to be a constant variable. It isn't and so it's > wrong. But i think this "wrong" is a very small price to pay in > exchange for having adjustable precision long floats. I'm not proposing to keep LONG-FLOAT-DIGITS at its maximal value, so I'm satisfied allowing PI not to be the best available approximation. > In this case you are using a Clisp extension and you are getting what > Clisp promises to deliver. So it is right. Setting LONG-FLOAT-DIGITS is also using a clisp extension. By using that you accept whatever non-conformance it causes. > The problem then is the value of CL:PI. What do you propose it should be? I propose it should be the default value before changing LONG-FLOAT-DIGITS. > If you use EXT:LONG-FLOAT-DIGITS then you are outside of portable CL, > and you should take into account your uses of this function in your > coding. Exactly. So PI should be the constant value that it would be without using that. > If you don't use EXT:LONG-FLOAT-DIGITS then the only non-confomance is > that some things that should be constant variables are variables > instead (but they won't in fact vary). In my solution, if you don't use long-float-digits one might reasonably argue that everything is compliant - there are no better approximations of pi available without using long-float-digits. |
From: <don...@is...> - 2015-10-18 20:10:37
|
> PI is required to be the best long float approximation to pi. If it > wasn't then it would be wrong. But that is already long unless long float digits is at its maximal value. > Also, PI is required to be a constant variable. It isn't and so it's > wrong. But i think this "wrong" is a very small price to pay in > exchange for having adjustable precision long floats. I'm not proposing to keep LONG-FLOAT-DIGITS at its maximal value, so I'm satisfied allowing PI not to be the best available approximation. > In this case you are using a Clisp extension and you are getting what > Clisp promises to deliver. So it is right. Setting LONG-FLOAT-DIGITS is also using a clisp extension. By using that you accept whatever non-conformance it causes. > The problem then is the value of CL:PI. What do you propose it should be? I propose it should be the default value before changing LONG-FLOAT-DIGITS. > If you use EXT:LONG-FLOAT-DIGITS then you are outside of portable CL, > and you should take into account your uses of this function in your > coding. Exactly. So PI should be the constant value that it would be without using that. > If you don't use EXT:LONG-FLOAT-DIGITS then the only non-confomance is > that some things that should be constant variables are variables > instead (but they won't in fact vary). In my solution, if you don't use long-float-digits one might reasonably argue that everything is compliant - there are no better approximations of pi available without using long-float-digits. |
From: Pascal J. B. <pj...@in...> - 2015-10-19 00:24:53
|
On 18/10/15 18:13, Don Cohen wrote: > I should have remembered about pi being recomputed. > > > Conformity could be restored by having CL:PI defined as a constant > > variable bound to double-float, and to have another variable EXT:PI > > bound to the changing long-float value. > > Would still be not conforming. > > Although the suggestion above would not be strictly conforming, I > think it would be an improvement in that (let (pi)) would signal an > error and constantp would return the expected result. It seems to me that (typep cl:pi 'long-float) is more important to maintain than (constantp 'cl:pi). Either case would introduce a small non-conformity of clisp. The only way we could restore conformity would be to keep long-float fixed size (and therefore the value of cl:pi identical), and to rename extended long floats ext:variable-precision-long-float (or something else) and have that distinct ext:pi variable. (subtypep 'ext:variable-precision-long-float 'float) AFAIK, introducing a new floating point subtype would be an acceptable extension that wouldn't introduce any obvious non-conformity. But I would note that already programs can have difficulties dealing conformingly with the existing subtypes of float, eg. in a typedef: (declare (type float v)) (typedef v (short-float 1) (single-float 2) (double-float 3) (long-float 4)) This form compiles with duplicate types warnings on implementations that coalesce some float subtypes. It would also miss the case where v would be of a fifth float subtype. Using etypedef is not the point. Granted, one could argue that a conforming program probably should not expect to have only at most 4 subtypes of float. In practice, it means that IMO more code would break if we introduced a fifth float subtype. (That said, if a maintained wanted to do that, it would be trivial enough to scan all the quicklisp libraries and a few major applications (eg. maxima), to check if it'd really be a problem). So, we have to consider the complexity involved in introducing this fifth floating point type. After all, most applications (and conforming code definitely) never set ext:long-float-digits, so for conforming applications, cl:pi never changes. Furthermore, while clhs constantp seems to imply a specified list of constant values including cl:pi, I would argue that constantp can be considered more like an introspection operator telling the truth (as known by the implementation) rather than telling what's specified. The point here is that a conforming library would work correctly when processing an expression containing cl:pi with constantp returning NIL (and therefore, not "inlining" cl:pi, in the case of clisp, if some other code non-conforming changes the long-float-digits. But it would break if constantp lied and returned T. Therefore in my opinion, it's better to have constantp return nil for a non-constant cl:pi, since while it's nominaly non-conforming, allows more conforming programs to continue working correctly, and since it's much less complex than adding a fifth float subtype. -- __Pascal J. Bourguignon__ http://www.informatimago.com/ |
From: <don...@is...> - 2015-10-19 06:33:14
|
Pascal J. Bourguignon writes: > It seems to me that (typep cl:pi 'long-float) > is more important to maintain than (constantp 'cl:pi). If you leave pi with its original value this remains true: (defconstant pi2 pi) (setf (ext:long-float-digits) 128) (typep pi2 'long-float) => T > Either case would introduce a small non-conformity of clisp. > > The only way we could restore conformity would be to keep long-float > fixed size (and therefore the value of cl:pi identical), and to rename > extended long floats ext:variable-precision-long-float (or something > else) and have that distinct ext:pi variable. I think the previous argument was that conformity requires pi to be the best available approximation, which would require the highest possible precision, which I don't think anyone wants to do. So we have to reinterpret that as the best available without using the extension that changes the amount of precision. > a conforming library would work correctly when > processing an expression containing cl:pi with constantp returning NIL > (and therefore, not "inlining" cl:pi, That's not the only use of constantp. Don't you think a conforming library might count on constantp to tell it what symbols not to accept as variables to be bound? And if pi were allowed to be bound, say, to some non-number, don't you think some sort of non-conforming behavior might result? > Therefore in my opinion, it's better to have constantp return nil for a > non-constant cl:pi, since while it's nominaly non-conforming, allows > more conforming programs to continue working correctly, and since it's > much less complex than adding a fifth float subtype. I don't see why any such additional subtype is needed. Perhaps I'm missing something. Other than recomputing a lot of constants that I don't think should be changed, what does setting ext:long-float-digits do? My impression was that it affected the result of READing a long float. Once the value is read, its precision is fixed, right? Changing long-float-digits doesn't affect it. So continuing my previous example, now that we have 64 bit pi2 and 128 bit pi, I get (+ 1 pi) => 4.14159265358979323846264338327950288418L0 (+ 1 pi2) => 4.1415926535897932383L0 You might view these as values of two different subtypes of long-float, namely 64-bit and 128-bit long floats, but type-of returns long-float in both cases. |
From: Pascal J. B. <pj...@in...> - 2015-10-19 07:21:50
|
On 19/10/15 08:33, Don Cohen wrote: > Pascal J. Bourguignon writes: > > > It seems to me that (typep cl:pi 'long-float) > > is more important to maintain than (constantp 'cl:pi). > > If you leave pi with its original value this remains true: > (defconstant pi2 pi) > (setf (ext:long-float-digits) 128) > (typep pi2 'long-float) => T Yes, and this is what I mean; the opposite option being ext:variable-precision-long-float as subtype of float distinct from the other subtypes, and (typep cl:pi 'ext:variable-precision-long-float) and therefore (not (typep cl:pi 'long-float)). This would be bad. > > > a conforming library would work correctly when > > processing an expression containing cl:pi with constantp returning NIL > > (and therefore, not "inlining" cl:pi, > That's not the only use of constantp. Sure, this is what it means. Read clhs constantp. > Don't you think a conforming library might count on constantp to tell > it what symbols not to accept as variables to be bound? And if pi > were allowed to be bound, say, to some non-number, don't you think > some sort of non-conforming behavior might result? Nope, constantp applies on a form, not a symbol denoting a variable. It is useless to call it before a let, because let is source code that would detect the error at compilation time, while constantp is a run-time function. (if (constantp 'cl:pi) (let ((mypi 3)) (f mypi)) (let ((cl:pi 3)) (f cl:pi))) is dumb. (And using #. wouldn't make it less dumb). > > > Therefore in my opinion, it's better to have constantp return nil for a > > non-constant cl:pi, since while it's nominaly non-conforming, allows > > more conforming programs to continue working correctly, and since it's > > much less complex than adding a fifth float subtype. > > I don't see why any such additional subtype is needed. Because that would allow us to leave cl:pi alone, binding it as a defconstant to a value that wouldn't change. > Perhaps I'm missing something. Other than recomputing a lot of > constants that I don't think should be changed, what does setting > ext:long-float-digits do? My impression was that it affected the > result of READing a long float. Once the value is read, its precision > is fixed, right? Changing long-float-digits doesn't affect it. Yes. But you could re-read it. > > So continuing my previous example, now that we have 64 bit pi2 and > 128 bit pi, I get > (+ 1 pi) => 4.14159265358979323846264338327950288418L0 > (+ 1 pi2) => 4.1415926535897932383L0 > You might view these as values of two different subtypes of > long-float, namely 64-bit and 128-bit long floats, but type-of > returns long-float in both cases. > > That's a good way to see them, but it doesn't help with the constant long-float pi problem. But this gives me an idea for another solution: cl:pi --> #.ext:π (typep ext:π) --> long-float ext:π --> #.ext:π That is, bind cl:pi to a symbolic object of type long-float, which, when *used* in arithmetic operations would evaluate to the value of π in the current subtype of long-float. cl:pi --> #.ext:π ext:π --> #.ext:π (+ 1 pi) --> 4.1415926535897932383L0 (setf (ext:long-float-digits) 128) (+ 1 pi) --> 4.14159265358979323846264338327950288418L0 -- __Pascal J. Bourguignon__ http://www.informatimago.com/ |
From: <don...@is...> - 2015-10-19 07:57:13
|
On 19/10/15 08:33, Don Cohen wrote: > Pascal J. Bourguignon writes: > > > It seems to me that (typep cl:pi 'long-float) > > is more important to maintain than (constantp 'cl:pi). Since we can have both, we don't have to argue about that. > > a conforming library would work correctly when > > processing an expression containing cl:pi with constantp returning NIL > > (and therefore, not "inlining" cl:pi, > That's not the only use of constantp. Sure, this is what it means. Read clhs constantp. I've read clhs. I don't see where it says this is the only use. > Don't you think a conforming library might count on constantp to tell > it what symbols not to accept as variables to be bound? And if pi > were allowed to be bound, say, to some non-number, don't you think > some sort of non-conforming behavior might result? Nope, constantp applies on a form, not a symbol denoting a variable. A symbol denoting a variable IS a form. It is useless to call it before a let, because let is source code that would detect the error at compilation time, while constantp is a run-time function. First, let is not the only binding form - how about progv. Second, you can view what I'm doing as compile time. I'm planning to tell the user I don't understand his input cause I don't recognize pi as a variable. And finally, there won't be an error at run time unless 'pi is constantp. > > Therefore in my opinion, it's better to have constantp return nil for a > > non-constant cl:pi, since while it's nominaly non-conforming, allows > > more conforming programs to continue working correctly, and since it's > > much less complex than adding a fifth float subtype. > I don't see why any such additional subtype is needed. Because that would allow us to leave cl:pi alone, binding it as a defconstant to a value that wouldn't change. But no subtype is needed in order to do that. Just declare pi as defconstant as it is. It will always be the same long float. When you want a different precision pi you can use (ext:pi) for the current long-float-digits or (ext:pi ndigits) for some other precision. > Perhaps I'm missing something. Other than recomputing a lot of > constants that I don't think should be changed, what does setting > ext:long-float-digits do? My impression was that it affected the > result of READing a long float. Once the value is read, its precision > is fixed, right? Changing long-float-digits doesn't affect it. Yes. But you could re-read it. Right, (read-from-string "2.1l0") would not be constantp. However pi would be. > So continuing my previous example, now that we have 64 bit pi2 and > 128 bit pi, I get > (+ 1 pi) => 4.14159265358979323846264338327950288418L0 > (+ 1 pi2) => 4.1415926535897932383L0 > You might view these as values of two different subtypes of > long-float, namely 64-bit and 128-bit long floats, but type-of > returns long-float in both cases. That's a good way to see them, but it doesn't help with the constant long-float pi problem. What exactly is this problem? I see no problem if pi is a defconstant with the value that it would have before long-float-digits ever changes. |
From: Pierpaolo B. <olo...@gm...> - 2015-10-19 15:34:09
|
On Sun, Oct 18, 2015 at 10:10 PM, Don Cohen <don...@is...> wrote: > > The problem then is the value of CL:PI. What do you propose it should be? > > I propose it should be the default value before changing > LONG-FLOAT-DIGITS. > > > If you use EXT:LONG-FLOAT-DIGITS then you are outside of portable CL, > > and you should take into account your uses of this function in your > > coding. > Exactly. So PI should be the constant value that it would be without > using that. > > > If you don't use EXT:LONG-FLOAT-DIGITS then the only non-confomance is > > that some things that should be constant variables are variables > > instead (but they won't in fact vary). > > In my solution, if you don't use long-float-digits one might > reasonably argue that everything is compliant - there are no better > approximations of pi available without using long-float-digits. Yes, now it is a sound proposal. But, if implemented in plain Clisp it would make variable precision floats a PITA to use, in addition to invalidating all previously written Clisp programs using variable precision floats. One solution could be for the ansi mode to transform all these variables in constant variables, and remove the EXT:LONG-FLOAT-DIGITS function from the image. Still, I don't get the need to do this work, supposing someone is willing to do it (It seems I haven't got all the emails in this thread and I may have missed some clarifying explanation of this point) |
From: <don...@is...> - 2015-10-19 18:46:49
|
> Yes, now it is a sound proposal. But, if implemented in plain Clisp it > would make variable precision floats a PITA to use, in addition to I don't see how it makes variable precision any worse than before. > invalidating all previously written Clisp programs using variable > precision floats. Actually, only those using variable precision float CONSTANTS, and I'm not so sure that all those would be invalidated. Some might actually be fixed, if their authors didn't have in mind that those values should change. However, I agree that it would (or at least could) be necessary to change various occurrences of pi to (pi) and similarly for the other constants. I wonder how many such things would have to be changed. I bet not many. What's the view of the clisp authors/community on the relative value of backward compatibility compared to conformance and other priorities? I've occasionally found that code that worked in an earlier version stopped working in a later one. But I doubt I could enumerate those cases. > One solution could be for the ansi mode to transform all these > variables in constant variables, and remove the EXT:LONG-FLOAT-DIGITS > function from the image. I don't see that removing EXT:LONG-FLOAT-DIGITS is really necessary. It's an extension, and if you don't use it then everything seems to conform. As long as we interpret "best long float approximation" to mean best without using the extension. > Still, I don't get the need to do this work, supposing someone is > willing to do it (It seems I haven't got all the emails in this thread > and I may have missed some clarifying explanation of this point) I don't claim it's necessary, only an improvement. A small one, but also, I think, requiring a small amount of work. |
From: Raymond T. <toy...@gm...> - 2015-10-19 19:55:44
|
>>>>> "Pierpaolo" == Pierpaolo Bernardi <olo...@gm...> writes: Pierpaolo> On Sun, Oct 18, 2015 at 10:10 PM, Don Cohen Pierpaolo> <don...@is...> wrote: >> > The problem then is the value of CL:PI. What do you propose it should be? >> >> I propose it should be the default value before changing >> LONG-FLOAT-DIGITS. >> >> > If you use EXT:LONG-FLOAT-DIGITS then you are outside of portable CL, >> > and you should take into account your uses of this function in your >> > coding. >> Exactly. So PI should be the constant value that it would be without >> using that. >> >> > If you don't use EXT:LONG-FLOAT-DIGITS then the only non-confomance is >> > that some things that should be constant variables are variables >> > instead (but they won't in fact vary). >> >> In my solution, if you don't use long-float-digits one might >> reasonably argue that everything is compliant - there are no better >> approximations of pi available without using long-float-digits. Pierpaolo> Yes, now it is a sound proposal. But, if implemented in plain Clisp it Pierpaolo> would make variable precision floats a PITA to use, in addition to Pierpaolo> invalidating all previously written Clisp programs using variable Pierpaolo> precision floats. Pierpaolo> One solution could be for the ansi mode to transform all these Pierpaolo> variables in constant variables, and remove the EXT:LONG-FLOAT-DIGITS Pierpaolo> function from the image. As a user (not developer), I rather like that if I (setf (long-float-digits)), pi does change. That clisp is the only lisp I use where long-float and double-float are different has allowed to find and fix erroneous assumptions in my code where I had assumed pi was a double-float. -- Ray |
From: Pierpaolo B. <olo...@gm...> - 2015-10-19 21:55:45
|
On Mon, Oct 19, 2015 at 8:46 PM, Don Cohen <don...@is...> wrote: > > > Yes, now it is a sound proposal. But, if implemented in plain Clisp it > > would make variable precision floats a PITA to use, in addition to > > I don't see how it makes variable precision any worse than before. A typical use case for adjustable precision floats is the following: (setf (ext:long-float-digits) some-appropriate-number-of-bits) (large-body-of-standard-portable-cl-code-using-long-floats) If long-float-digits is changed and the "constants" are not adjusted then STANDARD PORTABLE CL code will break. > > invalidating all previously written Clisp programs using variable > > precision floats. > > Actually, only those using variable precision float CONSTANTS, All of them will be broken until someone audits them and proves that they are not. > > One solution could be for the ansi mode to transform all these > > variables in constant variables, and remove the EXT:LONG-FLOAT-DIGITS > > function from the image. > > I don't see that removing EXT:LONG-FLOAT-DIGITS is really necessary. > It's an extension, and if you don't use it then everything seems to > conform. And if you use it then everything breaks. So removing it will avoid troubles. > > Still, I don't get the need to do this work, supposing someone is > > willing to do it (It seems I haven't got all the emails in this thread > > and I may have missed some clarifying explanation of this point) > > I don't claim it's necessary, only an improvement. A small one, but > also, I think, requiring a small amount of work. Maybe a simpler solution could be to replace CL:CONSTANTP with something similar to (setf (symbol-function 'cl::system-constantp) (symbol-function 'cl:constantp) (defun cl:constantp (x) (case s ((CL:PI CL:MOST-POSITIVE-LONG-FLOAT ...) t) (otherwise (cl::system-constantp x)))) when compliance wrt this issue is desired. Would this break something? |
From: <don...@is...> - 2015-10-19 22:28:17
|
Pierpaolo Bernardi writes: > A typical use case for adjustable precision floats is the following: > > (setf (ext:long-float-digits) some-appropriate-number-of-bits) > (large-body-of-standard-portable-cl-code-using-long-floats) > > If long-float-digits is changed and the "constants" are not adjusted > then STANDARD PORTABLE CL code will break. I don't understand what you think will go wrong. Please specify. > And if you use it then everything breaks. So removing it will > avoid troubles. I don't accept that everything breaks if you use it. However if you remove it and still use it then clearly it does break. Given that nothing goes wrong if you DON'T use it, and you're guaranteeing to break code that DOES use it, removing it can only make things worse. > Maybe a simpler solution could be to replace CL:CONSTANTP with > something similar to > > (setf (symbol-function 'cl::system-constantp) (symbol-function 'cl:constantp) > > (defun cl:constantp (x) > (case s > ((CL:PI CL:MOST-POSITIVE-LONG-FLOAT ...) t) > (otherwise (cl::system-constantp x)))) > > when compliance wrt this issue is desired. > > Would this break something? In other words would it break something to change things that are declared (or at least recognized as) constants (presumably the compiler and the rest of the system use cl:constantp and not system-constantp)? I would certinly expect so. Unless constantp is not used at all. |
From: Pierpaolo B. <olo...@gm...> - 2015-10-19 22:57:29
|
On Tue, Oct 20, 2015 at 12:28 AM, Don Cohen <don...@is...> wrote: > Pierpaolo Bernardi writes: > > A typical use case for adjustable precision floats is the following: > > > > (setf (ext:long-float-digits) some-appropriate-number-of-bits) > > (large-body-of-standard-portable-cl-code-using-long-floats) > > > > If long-float-digits is changed and the "constants" are not adjusted > > then STANDARD PORTABLE CL code will break. > > I don't understand what you think will go wrong. > Please specify. Portable, standard, CL code expects the value of MOST-POSITIVE-LONG-FLOAT to be the most positive long float value. With your proposal, the example case I described above won't work. Since I think the above case is an important one, I wouldn't be happy if Clisp changed in this way. OK, portable, standard, CL code expects also MOST-POSITIVE-LONG-FLOAT to be a constant, but, for some reason, this does not worry me. > > And if you use it then everything breaks. So removing it will > > avoid troubles. > I don't accept that everything breaks if you use it. However if > you remove it and still use it then clearly it does break. > Given that nothing goes wrong if you DON'T use it, and you're > guaranteeing to break code that DOES use it, removing it can only > make things worse. OK, I agree. In fact I think that, if one wants to retain adjustable precision long floats, then any change to the status quo will make things worse. |
From: <don...@is...> - 2015-10-19 23:25:55
|
Pierpaolo Bernardi writes: > On Tue, Oct 20, 2015 at 12:28 AM, Don Cohen > <don...@is...> wrote: > > Pierpaolo Bernardi writes: > > > A typical use case for adjustable precision floats is the following: > > > > > > (setf (ext:long-float-digits) some-appropriate-number-of-bits) > > > (large-body-of-standard-portable-cl-code-using-long-floats) > > > > > > If long-float-digits is changed and the "constants" are not adjusted > > > then STANDARD PORTABLE CL code will break. > > > > I don't understand what you think will go wrong. > > Please specify. > > Portable, standard, CL code expects the value of > MOST-POSITIVE-LONG-FLOAT to be the most positive long float value. I already demonstrated that this expectation is violated in clisp as things are right now. I didn't actually propose to "fix" that. I'd rather "fix" the expectations of users/programmers who set long-float-digits. > With your proposal, the example case I described above won't work. Your code above does not demonstrate this. I was asking for such a demonstration. How about a demonstration of some code that might be useful for something other than demonstrating non-compliance? > Since I think the above case is an important one, I wouldn't be happy > if Clisp changed in this way. Again I want to see more detail on this important case. > OK, I agree. In fact I think that, if one wants to retain adjustable > precision long floats, then any change to the status quo will make > things worse. I'm still waiting to see how my proposed change makes things worse. |
From: Pierpaolo B. <olo...@gm...> - 2015-10-19 23:54:04
|
On Tue, Oct 20, 2015 at 1:25 AM, Don Cohen <don...@is...> wrote: > Pierpaolo Bernardi writes: > > On Tue, Oct 20, 2015 at 12:28 AM, Don Cohen > > <don...@is...> wrote: > > > Pierpaolo Bernardi writes: > > > > A typical use case for adjustable precision floats is the following: > > > > > > > > (setf (ext:long-float-digits) some-appropriate-number-of-bits) > > > > (large-body-of-standard-portable-cl-code-using-long-floats) > > > > > > > > If long-float-digits is changed and the "constants" are not adjusted > > > > then STANDARD PORTABLE CL code will break. > > > > > > I don't understand what you think will go wrong. > > > Please specify. > > > > Portable, standard, CL code expects the value of > > MOST-POSITIVE-LONG-FLOAT to be the most positive long float value. > > I already demonstrated that this expectation is violated in clisp > as things are right now. > > I didn't actually propose to "fix" that. > I'd rather "fix" the expectations of users/programmers who set > long-float-digits. > > > With your proposal, the example case I described above won't work. > > Your code above does not demonstrate this. I was asking for such a > demonstration. How about a demonstration of some code that might > be useful for something other than demonstrating non-compliance? Here it is: ;; portable CL code library (defun circle-area (radius) (* radius radius pi)) currently in Clisp I can use the above code in this way: (setf (ext:long-float-digits) 1000) ;; print area with 1000 bits precision (print (circle-area 42l0)) This will break under your proposal. I think this is an important use case and I will be unhappy if this stopped working. If you don't agree that this is a useful feature of Clisp, then we will have to agree to disagree. Cheers P. |
From: <don...@is...> - 2015-10-20 01:01:26
|
> ;; portable CL code library > (defun circle-area (radius) > (* radius radius pi)) Note that your portable code could have also been (* radius radius #.pi) which is supposed to mean the same thing. In clisp it doesn't, but under my proposal it would. > currently in Clisp I can use the above code in this way: > (setf (ext:long-float-digits) 1000) > ;; print area with 1000 bits precision > (print (circle-area 42l0)) Note that you are now asking for your "portable" code to exhibit non portable behavior. What you get from clisp under my proposal would be the same as you'd get from code in other lisps (after the break when you try to change precision). That seems more "portable" to me. In order to get this non portable behavior I think you should write instead (defun circle-area (radius) (* radius radius (pi))) and if you want that to work in other lisp implementations, #-clisp (defun pi() pi) > This will break under your proposal. I think this is an important > use case and I will be unhappy if this stopped working. The terms "break" and "stop working" seem out of place here. To me the code seems to be working in the standard and portable way. Admittedly that's not what you want. You want it to work in some way outside the standard. I think you should expect to write something outside of the standard in order to get that to happen. (Even something in addition to setting the precision.) |
From: Pascal J. B. <pj...@in...> - 2015-10-20 03:32:51
|
On 19/10/15 23:55, Pierpaolo Bernardi wrote: > On Mon, Oct 19, 2015 at 8:46 PM, Don Cohen > <don...@is...> wrote: >> > Yes, now it is a sound proposal. But, if implemented in plain Clisp it >> > would make variable precision floats a PITA to use, in addition to >> >> I don't see how it makes variable precision any worse than before. > A typical use case for adjustable precision floats is the following: > > (setf (ext:long-float-digits) some-appropriate-number-of-bits) > (large-body-of-standard-portable-cl-code-using-long-floats) > > If long-float-digits is changed and the "constants" are not adjusted > then STANDARD PORTABLE CL code will break. This is incomplete: Not only the constants should be adjusted, but all the standard portable CL code that has been compiled so far needs to be compiled again, because defconstant constants can be inlined. This is to avoid having to recompile and reload everything each time you set ext:long-float-digits, that cl:pi is not a constant. > >> > Still, I don't get the need to do this work, supposing someone is >> > willing to do it (It seems I haven't got all the emails in this thread >> > and I may have missed some clarifying explanation of this point) >> >> I don't claim it's necessary, only an improvement. A small one, but >> also, I think, requiring a small amount of work. > Maybe a simpler solution could be to replace CL:CONSTANTP with > something similar to > > (setf (symbol-function 'cl::system-constantp) (symbol-function 'cl:constantp) > > (defun cl:constantp (x) > (case s > ((CL:PI CL:MOST-POSITIVE-LONG-FLOAT ...) t) > (otherwise (cl::system-constantp x)))) > > when compliance wrt this issue is desired. > > Would this break something? Yes. It would break code that has been compiled before you set long-float-digits, and that would use the old value instead of the new one. On the other hand, if you have long-float literals in the source code, then you would have to re-read this source code too, to take into account the new precision. And it should be noted, that if you keep modifying long-float-digits, you can have in the image, and still use and combine in expressions, long-float values of different precisions. The user shall know what he's doing. But for values like π or e, you definitely want to provide the value in the new (or best) precision. In the case of e, it's simple, since there's no such constant, but a function (exp 1L0). In the case of π, CL:PI is redundant, we could as well use (* 4L0 (atan 1L0)). -- __Pascal J. Bourguignon__ http://www.informatimago.com/ |