You can subscribe to this list here.
2000 
_{Jan}
(16) 
_{Feb}
(21) 
_{Mar}
(49) 
_{Apr}
(35) 
_{May}
(25) 
_{Jun}
(15) 
_{Jul}
(17) 
_{Aug}
(15) 
_{Sep}
(12) 
_{Oct}
(18) 
_{Nov}
(42) 
_{Dec}
(31) 

2001 
_{Jan}
(35) 
_{Feb}
(24) 
_{Mar}
(53) 
_{Apr}
(59) 
_{May}
(124) 
_{Jun}
(134) 
_{Jul}
(92) 
_{Aug}
(74) 
_{Sep}
(75) 
_{Oct}
(95) 
_{Nov}
(47) 
_{Dec}
(32) 
2002 
_{Jan}
(191) 
_{Feb}
(143) 
_{Mar}
(279) 
_{Apr}
(287) 
_{May}
(106) 
_{Jun}
(96) 
_{Jul}
(95) 
_{Aug}
(126) 
_{Sep}
(184) 
_{Oct}
(152) 
_{Nov}
(84) 
_{Dec}
(136) 
2003 
_{Jan}
(170) 
_{Feb}
(64) 
_{Mar}
(202) 
_{Apr}
(142) 
_{May}
(103) 
_{Jun}
(145) 
_{Jul}
(56) 
_{Aug}
(204) 
_{Sep}
(130) 
_{Oct}
(91) 
_{Nov}
(32) 
_{Dec}
(130) 
2004 
_{Jan}
(89) 
_{Feb}
(208) 
_{Mar}
(190) 
_{Apr}
(61) 
_{May}
(111) 
_{Jun}
(126) 
_{Jul}
(121) 
_{Aug}
(90) 
_{Sep}
(65) 
_{Oct}
(80) 
_{Nov}
(90) 
_{Dec}
(95) 
2005 
_{Jan}
(63) 
_{Feb}
(106) 
_{Mar}
(105) 
_{Apr}
(90) 
_{May}
(99) 
_{Jun}
(96) 
_{Jul}
(197) 
_{Aug}
(144) 
_{Sep}
(128) 
_{Oct}
(123) 
_{Nov}
(232) 
_{Dec}
(153) 
2006 
_{Jan}
(210) 
_{Feb}
(69) 
_{Mar}
(37) 
_{Apr}
(74) 
_{May}
(123) 
_{Jun}
(51) 
_{Jul}
(91) 
_{Aug}
(25) 
_{Sep}
(98) 
_{Oct}
(98) 
_{Nov}
(87) 
_{Dec}
(33) 
2007 
_{Jan}
(43) 
_{Feb}
(41) 
_{Mar}
(27) 
_{Apr}
(18) 
_{May}
(20) 
_{Jun}
(18) 
_{Jul}
(35) 
_{Aug}
(35) 
_{Sep}
(21) 
_{Oct}
(75) 
_{Nov}
(41) 
_{Dec}
(28) 
2008 
_{Jan}
(34) 
_{Feb}
(28) 
_{Mar}
(33) 
_{Apr}
(26) 
_{May}
(45) 
_{Jun}
(35) 
_{Jul}
(36) 
_{Aug}
(32) 
_{Sep}
(87) 
_{Oct}
(70) 
_{Nov}
(98) 
_{Dec}
(96) 
2009 
_{Jan}
(94) 
_{Feb}
(79) 
_{Mar}
(9) 
_{Apr}
(10) 
_{May}
(5) 
_{Jun}
(54) 
_{Jul}
(49) 
_{Aug}
(65) 
_{Sep}
(61) 
_{Oct}
(16) 
_{Nov}
(61) 
_{Dec}
(70) 
2010 
_{Jan}
(2) 
_{Feb}
(67) 
_{Mar}
(8) 
_{Apr}
(30) 
_{May}
(19) 
_{Jun}
(2) 
_{Jul}
(17) 
_{Aug}
(30) 
_{Sep}
(23) 
_{Oct}
(20) 
_{Nov}
(47) 
_{Dec}
(12) 
2011 
_{Jan}
(44) 
_{Feb}
(46) 
_{Mar}
(20) 
_{Apr}
(74) 
_{May}
(35) 
_{Jun}
(37) 
_{Jul}
(5) 
_{Aug}
(14) 
_{Sep}

_{Oct}
(8) 
_{Nov}
(6) 
_{Dec}
(1) 
2012 
_{Jan}
(18) 
_{Feb}
(12) 
_{Mar}
(22) 
_{Apr}
(6) 
_{May}
(16) 
_{Jun}
(17) 
_{Jul}
(10) 
_{Aug}
(13) 
_{Sep}
(2) 
_{Oct}
(8) 
_{Nov}
(10) 
_{Dec}
(1) 
2013 
_{Jan}
(19) 
_{Feb}
(14) 
_{Mar}
(12) 
_{Apr}
(3) 
_{May}
(33) 
_{Jun}
(12) 
_{Jul}
(20) 
_{Aug}
(5) 
_{Sep}
(5) 
_{Oct}
(17) 
_{Nov}
(15) 
_{Dec}
(4) 
2014 
_{Jan}
(8) 
_{Feb}
(4) 
_{Mar}
(17) 
_{Apr}

_{May}
(16) 
_{Jun}
(10) 
_{Jul}
(7) 
_{Aug}

_{Sep}
(1) 
_{Oct}
(25) 
_{Nov}
(6) 
_{Dec}
(1) 
2015 
_{Jan}
(1) 
_{Feb}
(3) 
_{Mar}
(9) 
_{Apr}
(1) 
_{May}
(8) 
_{Jun}

_{Jul}
(16) 
_{Aug}
(13) 
_{Sep}

_{Oct}
(44) 
_{Nov}
(1) 
_{Dec}
(4) 
2016 
_{Jan}
(1) 
_{Feb}
(1) 
_{Mar}

_{Apr}
(3) 
_{May}

_{Jun}
(8) 
_{Jul}

_{Aug}
(2) 
_{Sep}
(2) 
_{Oct}

_{Nov}

_{Dec}

From: Pascal Bourguignon <pjb@in...>  20151022 15:37:33

You are right, see 12.1.2.1.1. Sent from my iPhone > On 22 Oct 2015, at 16:19, <JoergCyril.Hoehle@...> <JoergCyril.Hoehle@...> wrote: > > Don, > >> #clisp (defun pi() pi) > There's a weakness in your proposal, I believe, because IIRC conforming > implementations are not allowed to add other definitions to symbols known > from the CL package. IOW, a bound (symbolfunction 'CL:PI) is not conforming. > You'd have to use anoyther symbol, e.g. EXT:PI. > > I'm surprised that I saw nobody raise that argument. Maybe I'm wrong. > > Regards, > Jörg Höhle >  > _______________________________________________ > clisplist mailing list > clisplist@... > https://lists.sourceforge.net/lists/listinfo/clisplist 
From: <JoergCyril.H<oehle@t...>  20151022 14:36:40

Hi, > 1L0 is always 1L0, whatever the longfloatdigits. >However not all 1L0's are the same. >(/ 1L0 3) >0.33333333333333333334L0 >(setf (ext:longfloatdigits) 128) >(/ 1L0 3) >0.333333333333333333333333333333333333334L0 It just occurred to me that one could, in theory, blame CLISP for not implementing *printreadably* correctly, since the output does not mention the number of longfloatdigits, does it? Looking closer upon the notion of "similarity" in CLHS http://www.lispworks.com/documentation/lw51/CLHS/Body/03_bdbb.htm it appears that what CLISP does is ok, isn't it? "Two numbers S and C are similar if they are of the same type and represent the same mathematical value." Or one argues that the above values are not the same? Regards, Jörg Höhle 
From: <JoergCyril.H<oehle@t...>  20151022 14:19:37

Don, >#clisp (defun pi() pi) There's a weakness in your proposal, I believe, because IIRC conforming implementations are not allowed to add other definitions to symbols known from the CL package. IOW, a bound (symbolfunction 'CL:PI) is not conforming. You'd have to use anoyther symbol, e.g. EXT:PI. I'm surprised that I saw nobody raise that argument. Maybe I'm wrong. Regards, Jörg Höhle 
From: Pascal J. Bourguignon <pjb@in...>  20151022 06:48:05

On 21/10/15 21:16, Don Cohen wrote: > > But this argument is the one that requires us to fill RAM with that > one best approximation. > Clearly we have to give up compliance on the point of pi being the > best approximation the implementation can provide. Not necessarily. I gave you a way to do it without losing compliance. > > I don't know what YOU want either. > Introducing variable precision longfloat as it's done is clearly > bringing a lot of nonconformities, and having (not (constantp > 'pi)) is the most benign of them. > >  I want the special variable *longfloatdigits* to control the > precision of long floats created by READ. > (BTW (let ((*longfloatdigits* n))(readfromstring "1l0")) > would now be the way to get constants of precision n) or as you suggested, (coerce 1l0 `(longfloat ,n)). >  I want (pi &optional precision) and similar functions for other > constants to compute values of the given precision, with the > default value of precision being *longfloatdigits* agreed. >  I want to remove (longfloatdigits) and its setf We may keep it for legacy compatibility. >  I want pi and the other similar constants to be defconstant > keeping their initial values. Then you need an abstract value ext:π that provides a different precision depending on *longfloatdigits* It's not a symbol macro, because: (defconstant cl:pi #S(ext:π)) cl:pi > #S(ext:π) (+ 0 cl:pi) > 3.141592l0 Actually, #S(ext:π) might print as #S(ext:π) only when *printreadably* is true, and could print as the current approximation of π when *printreadably* is false. (then we can't use ext:π since that's the syntax for a symbol, or #<ext:π> since that's an unreadable syntax, hence #S(ext:π)). >  I'd now add to my wish list the type spec (longfloat precision) > with typeof returning those types for long floats and subtypep > recognizing those types as subtype of longfloat. yes. > I think my proposal makes it much more practical to use different > precisions in different pieces of code, including in different > threads. > (BTW I consider this much more valuable than (constantp 'pi).) > I think my proposal reduces nonconformance without introducing > any more nonconformance. > In fact the only remaining nonconformance I see is that >  pi is not (and never was!) the best available approximation >  mostpositivelongfloat is not (and never was) the most positive > long float > etc. for other defconstants. We could introduce similarly #S(ext:mostpositivelongfloat) etc, ie. symbolic numbers. > However all of this nonconformance at least appears only in > programs that change *longfloatdigits*. > > I admit this will be incompatible with some existing code. > Perhaps some accomodation can be made to support such code.  __Pascal J. Bourguignon__ http://www.informatimago.com/ 
From: <donsourceforgex2012@is...>  20151021 22:15:44

> Don> It seems the best solution to this problem would be to > Don> add to clisp the typespec (longfloat precision) which would be a > I think that's not a valid float specifier. Actually I now notice that (longfloat 64) already is used to mean long floats >=64 and (longfloat 64 128) means those also <= 128. I was thinking the implementation is allowed to extend these  is that correct? If so, I'd suggest (longfloat 64 128 256) to mean a long float between 64 and 128 having precision 256, and that typeof return something like (longfloat * * 256) Or maybe (longfloat 64 128 256 512) should mean a long float between 64 and 128 with precision between 256 and 512 and typeof should return (longfloat * * 256 256) (or it could return (longfloat 99 99 256 256) > Is it conforming that cl:pi be a function? I admit I've not paid enough attention to what things the implementation is allowed to add to the standard. If not cl:pi then perhaps ext:pi or some other name > And sorry to be pessimistic, but unless a maintainer steps up nothing > is going to happen. I recognize all that. Someone does occasionally volunteer for this sort of duty. The next person who works on MT or the next person who wants to really make use of variable precision floats might want to do this. Someone who wants to add variable precision to some other system might also find this discussion useful. 
From: Raymond Toy <toy.raymond@gm...>  20151021 19:52:26

>>>>> "Don" == Don Cohen <donsourceforgex2012@...> writes: Don> [8]> (typeof *onedef*) Don> LONGFLOAT Don> [9]> (typeof *one100*) Don> LONGFLOAT Don> [10]> Don> This is another nonconformity. clhs eql: Don> The value of eql is true of two objects, x and y, in the folowing cases: Don> 1. If x and y are eq. Don> 2. If x and y are both numbers of the same type and the same value. Don> 3. If they are both characters that represent the same character. Don> Otherwise the value of eql is false. Don> It seems the best solution to this problem would be to Don> add to clisp the typespec (longfloat precision) which would be a I think that's not a valid float specifier. It seems to me that if you want cl:pi to be fixed and never changes independent of setting longfloatdigits, you are pretty much stuck with cl:pi having a precision of 64 (?) since that is the default value of longfloatdigits. Don>  I want (pi &optional precision) and similar functions for other Don> constants to compute values of the given precision, with the Don> default value of precision being *longfloatdigits* Is it conforming that cl:pi be a function? Don>  I want to remove (longfloatdigits) and its setf Don>  I want pi and the other similar constants to be defconstant Don> keeping their initial values. I would hate that because it breaks (the little) clisp code I have. Don>  I'd now add to my wish list the type spec (longfloat precision) Don> with typeof returning those types for long floats and subtypep Don> recognizing those types as subtype of longfloat. Don> I think my proposal makes it much more practical to use different Don> precisions in different pieces of code, including in different Don> threads. Don> (BTW I consider this much more valuable than (constantp 'pi).) I've never really had a need for constantp, so the fact that pi isn't doesn't bother me. I want pi to change when I change longfloatdigits. I would accept allowing (pi) return the a longfloat approx to pi. And sorry to be pessimistic, but unless a maintainer steps up nothing is going to happen. Unless you create your own fork at which point you can do whatever you want.  Ray 
From: <donsourceforgex2012@is...>  20151021 19:16:30

[8]> (typeof *onedef*) LONGFLOAT [9]> (typeof *one100*) LONGFLOAT [10]> This is another nonconformity. 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. It seems the best solution to this problem would be to add to clisp the typespec (longfloat precision) which would be a recognizable subtype of longfloat, and have typeof return that. I suspect this is not very difficult. This is independent of all other discussions in this thread. It's purely a fix of current clisp which increases conformity and also is useful for more accurately finding the type of a value. (You agree?) > I don't understand why you think pi should be the best approximation > available with longfloatdigits digits. > The spec says the best long approximation. > This is only satisfied by whatever is the maximum allowed value of > longfloatdigits and nobody (in his right mind) wants to use that. But you cannot guess in advance what will be the maximum used by a I don't see what the maximum used by a program has to do with this. program! The maximum allowed propably fills the RAM. That's why nobody would want to use it. > 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 <pi> and any value with less precision than the maximum allowed will be a DIFFERENT value, not representing <pi> But this argument is the one that requires us to fill RAM with that one best approximation. Clearly we have to give up compliance on the point of pi being the best approximation the implementation can provide. Once that is recognized, why would you consider one noncompliant approximation to be better than any other ? If we just leave it at the initial value and make that defconstant then at least one point of compliance is restored, without introducing any others. I don't know what YOU want either. Introducing variable precision longfloat as it's done is clearly bringing a lot of nonconformities, and having (not (constantp 'pi)) is the most benign of them.  I want the special variable *longfloatdigits* to control the precision of long floats created by READ. (BTW (let ((*longfloatdigits* n))(readfromstring "1l0")) would now be the way to get constants of precision n)  I want (pi &optional precision) and similar functions for other constants to compute values of the given precision, with the default value of precision being *longfloatdigits*  I want to remove (longfloatdigits) and its setf  I want pi and the other similar constants to be defconstant keeping their initial values.  I'd now add to my wish list the type spec (longfloat precision) with typeof returning those types for long floats and subtypep recognizing those types as subtype of longfloat. I think my proposal makes it much more practical to use different precisions in different pieces of code, including in different threads. (BTW I consider this much more valuable than (constantp 'pi).) I think my proposal reduces nonconformance without introducing any more nonconformance. In fact the only remaining nonconformance I see is that  pi is not (and never was!) the best available approximation  mostpositivelongfloat is not (and never was) the most positive long float etc. for other defconstants. However all of this nonconformance at least appears only in programs that change *longfloatdigits*. I admit this will be incompatible with some existing code. Perhaps some accomodation can be made to support such code. 
From: Pascal J. Bourguignon <pjb@in...>  20151021 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 > > (readfromstring "1l0"), at leat if that code is to run many times. > > It's possible to write a macro (adjustprecision "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 longfloatdigits. > However not all 1L0's are the same. > (/ 1L0 3) > 0.33333333333333333334L0 > (setf (ext:longfloatdigits) 128) > (/ 1L0 3) > 0.333333333333333333333333333333333333334L0 [1]> (defparameter *onedef* 1L0) *ONEDEF* [2]> (setf (ext:longfloatdigits) 100) 100 [5]> (defparameter *one100* 1L0) *ONE100* [6]> (eql *onedef* *one100*) NIL [7]> (= *onedef* *one100*) T [8]> (typeof *onedef*) LONGFLOAT [9]> (typeof *one100*) LONGFLOAT [10]> This is another nonconformity. 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 (typeof), but they are not EQL. As mentionned before, when we change the longfloatdigits, we start using values of a different subtype of longfloat. Unfortunately, TYPEOF 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 longfloatdigit, 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 longfloatdigits digits. > The spec says the best long approximation. > This is only satisfied by whatever is the maximum allowed value of > longfloatdigits 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., (readlong "1l0" n), which >> returns the rough equivalent (I hope much more efficiently) of >> (let ((p (ext:longfloatdigits))) >> (setf (ext:longfloatdigits) n) >> (prog1 (readfromstring "1l0") (setf (ext:longfloatdigits) p))) > There it is: > > (defun readlong (string n) > (let ((p (ext:longfloatdigits))) > (setf (ext:longfloatdigits) n) > (prog1 (readfromstring "1l0") (setf (ext:longfloatdigits) 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 > > longfloatdigits 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 > > longfloatdigits is rebound. But the rebinding will affect the value > > of (pi). > > The binding of cl:pi could be threadlocal. > > Is this really what you propose? > So when you set longfloatdigits 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 longfloatdigits) and its adjustments, along with > > the lack of the readlong function and the functions like > > (pi &optional precision). > > Notice that if you set longfloatdigits, and save a bunch of > longfloat values computed with that precision, then you change > longfloatdigits, and use the saved values to further compute, then > the resulting longfloat will have the original precision. Therefore > you can already have threads performing computations with different > longfloat precisions! (only take care of not reading new long > floats or not using cl:pi or otherwise poluting your computing with > longfloat 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 longfloat as it's done is clearly bringing a lot of nonconformities, 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 longfloat, 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 nonconformities.  __Pascal J. Bourguignon__ http://www.informatimago.com/ 
From: <donsourceforgex2012@is...>  20151020 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 > (readfromstring "1l0"), at leat if that code is to run many times. > It's possible to write a macro (adjustprecision "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 longfloatdigits. However not all 1L0's are the same. (/ 1L0 3) 0.33333333333333333334L0 (setf (ext:longfloatdigits) 128) (/ 1L0 3) 0.333333333333333333333333333333333333334L0 when you change longfloatdigit, 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 longfloatdigits digits. The spec says the best long approximation. This is only satisfied by whatever is the maximum allowed value of longfloatdigits 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., (readlong "1l0" n), which > returns the rough equivalent (I hope much more efficiently) of > (let ((p (ext:longfloatdigits))) > (setf (ext:longfloatdigits) n) > (prog1 (readfromstring "1l0") (setf (ext:longfloatdigits) p))) There it is: (defun readlong (string n) (let ((p (ext:longfloatdigits))) (setf (ext:longfloatdigits) n) (prog1 (readfromstring "1l0") (setf (ext:longfloatdigits) 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 > longfloatdigits 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 > longfloatdigits is rebound. But the rebinding will affect the value > of (pi). The binding of cl:pi could be threadlocal. Is this really what you propose? So when you set longfloatdigits 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 longfloatdigits) and its adjustments, along with > the lack of the readlong function and the functions like > (pi &optional precision). Notice that if you set longfloatdigits, and save a bunch of longfloat values computed with that precision, then you change longfloatdigits, and use the saved values to further compute, then the resulting longfloat will have the original precision. Therefore you can already have threads performing computations with different longfloat precisions! (only take care of not reading new long floats or not using cl:pi or otherwise poluting your computing with longfloat 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. 
From: Pascal J. Bourguignon <pjb@in...>  20151020 20:24:34

On 20/10/15 21:29, Don Cohen wrote: > > If longfloatdigits 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:longfloatdigits, that cl:pi is not a constant. > > If I understand correctly, you are saying that > *If* pi, etc. were declared defconstant and changing precision changed > it, then everything using pi would have to be recompiled. > And depending on what you think it means to change precision, you > might also want to reread and recompile all the code containing long > constants. > > I think you agree with me that it's a bad idea to change the values of > things that are declared defconstant. Yes. Or to declare with defconstant variables that can change. Also, remember that defconstant defines constant VARIABLES. > I can't tell whether you think pi should not be defconstant because of > this, or whether you agree with me that it should be declared > defconstant and then not changed. Read again the discussion. The current state is not conforming but it's better than a conforming solution that would have to be much more complex. > This doesn't solve the larger problem of constants in code. > You probably don't want to replace 1l0 in your code with > (readfromstring "1l0"), at leat if that code is to run many times. > It's possible to write a macro (adjustprecision "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 longfloatdigits. 1234567890123456789012345678901234567890123456789012345678901234567890L0 may be read as different values when read with a different longfloatdigits, but this remains conforming, since this is a behavior that already exists for the other floating point types and on all the implementations, and since the application knows when it changes the longfloatdigits, so it may decide what to do about it. In any case, the point is that in both cases, the precision of the concerned number is finite. On the other hand, for π or e, the precision is infinite. Therefore when you change longfloatdigit, the long float value that should represent π or e (or any of the other transcendental numbers), is not the same anymore. Again, in the case of e or other values, the implementation can deal with it, since it knows that it changed longfloatdigits, it can recompute a new approximation of its trancendantals with the new precision. But the standard has a defect, in that it specifies PI to be a constant variable instead of being a function. For a strict pedantic conformity, this means you would have to keep the precision of longfloat fixed, and we'd have to provide a fifth subtype of longfloat for variable precision. This would lead to complexities (and problems of conformity with programs that don't expect a fifth subtype of float!). Therefore it's better to make CL:PI a non constant variable, and to rebind it when we change the precision. We could also provide functions in EXT to provide values of transcendantals such as PI and E at the current or other precisions. > 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., (readlong "1l0" n), which > returns the rough equivalent (I hope much more efficiently) of > (let ((p (ext:longfloatdigits))) > (setf (ext:longfloatdigits) n) > (prog1 (readfromstring "1l0") (setf (ext:longfloatdigits) p))) There it is: (defun readlong (string n) (let ((p (ext:longfloatdigits))) (setf (ext:longfloatdigits) n) (prog1 (readfromstring "1l0") (setf (ext:longfloatdigits) p)))) > It would also be nice if different threads could work in different > default precisions. For this purpose it seems better to make > longfloatdigits 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 > longfloatdigits is rebound. But the rebinding will affect the value > of (pi). The binding of cl:pi could be threadlocal. > 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 longfloatdigits) and its adjustments, along with > the lack of the readlong function and the functions like > (pi &optional precision). Notice that if you set longfloatdigits, and save a bunch of longfloat values computed with that precision, then you change longfloatdigits, and use the saved values to further compute, then the resulting longfloat will have the original precision. Therefore you can already have threads performing computations with different longfloat precisions! (only take care of not reading new long floats or not using cl:pi or otherwise poluting your computing with longfloat of a different precision).  __Pascal J. Bourguignon__ http://www.informatimago.com/ 
From: <donsourceforgex2012@is...>  20151020 19:30:06

> If longfloatdigits 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:longfloatdigits, that cl:pi is not a constant. If I understand correctly, you are saying that *If* pi, etc. were declared defconstant and changing precision changed it, then everything using pi would have to be recompiled. And depending on what you think it means to change precision, you might also want to reread and recompile all the code containing long constants. I think you agree with me that it's a bad idea to change the values of things that are declared defconstant. I can't tell whether you think pi should not be defconstant because of this, or whether you agree with me that it should be declared defconstant and then not changed. And it should be noted, that if you keep modifying longfloatdigits, you can have in the image, and still use and combine in expressions, longfloat values of different precisions. The user shall know what he's doing. But for values like pi or e, you definitely want to provide the value in the new (or best) precision. This sounds like you want to change the value of pi. But maybe you're willing to accept my version of "provide the value in the new (or best) precision", which is that (pi) returns the value in the current precision and (pi n) returns the value in precision n, and similar functions are supplied for all the other defconstants. Then you can write code that changes its behavior in response to changing precision. This doesn't solve the larger problem of constants in code. You probably don't want to replace 1l0 in your code with (readfromstring "1l0"), at leat if that code is to run many times. It's possible to write a macro (adjustprecision "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. 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., (readlong "1l0" n), which returns the rough equivalent (I hope much more efficiently) of (let ((p (ext:longfloatdigits))) (setf (ext:longfloatdigits) n) (prog1 (readfromstring "1l0") (setf (ext:longfloatdigits) p))) It would also be nice if different threads could work in different default precisions. For this purpose it seems better to make longfloatdigits 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 longfloatdigits is rebound. But the rebinding will affect the value of (pi). 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 longfloatdigits) and its adjustments, along with the lack of the readlong function and the functions like (pi &optional precision). 
From: Pascal J. Bourguignon <pjb@in...>  20151020 03:32:51

On 19/10/15 23:55, Pierpaolo Bernardi wrote: > On Mon, Oct 19, 2015 at 8:46 PM, Don Cohen > <donsourceforgex2012@...> 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:longfloatdigits) someappropriatenumberofbits) > (largebodyofstandardportableclcodeusinglongfloats) > > If longfloatdigits 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:longfloatdigits, 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 (symbolfunction 'cl::systemconstantp) (symbolfunction 'cl:constantp) > > (defun cl:constantp (x) > (case s > ((CL:PI CL:MOSTPOSITIVELONGFLOAT ...) t) > (otherwise (cl::systemconstantp x)))) > > when compliance wrt this issue is desired. > > Would this break something? Yes. It would break code that has been compiled before you set longfloatdigits, and that would use the old value instead of the new one. On the other hand, if you have longfloat literals in the source code, then you would have to reread this source code too, to take into account the new precision. And it should be noted, that if you keep modifying longfloatdigits, you can have in the image, and still use and combine in expressions, longfloat 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/ 
From: <donsourceforgex2012@is...>  20151020 01:01:26

> ;; portable CL code library > (defun circlearea (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:longfloatdigits) 1000) > ;; print area with 1000 bits precision > (print (circlearea 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 circlearea (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: Pierpaolo Bernardi <olopierpa@gm...>  20151019 23:54:04

On Tue, Oct 20, 2015 at 1:25 AM, Don Cohen <donsourceforgex2012@...> wrote: > Pierpaolo Bernardi writes: > > On Tue, Oct 20, 2015 at 12:28 AM, Don Cohen > > <donsourceforgex2012@...> wrote: > > > Pierpaolo Bernardi writes: > > > > A typical use case for adjustable precision floats is the following: > > > > > > > > (setf (ext:longfloatdigits) someappropriatenumberofbits) > > > > (largebodyofstandardportableclcodeusinglongfloats) > > > > > > > > If longfloatdigits 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 > > MOSTPOSITIVELONGFLOAT 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 > longfloatdigits. > > > 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 noncompliance? Here it is: ;; portable CL code library (defun circlearea (radius) (* radius radius pi)) currently in Clisp I can use the above code in this way: (setf (ext:longfloatdigits) 1000) ;; print area with 1000 bits precision (print (circlearea 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: <donsourceforgex2012@is...>  20151019 23:25:55

Pierpaolo Bernardi writes: > On Tue, Oct 20, 2015 at 12:28 AM, Don Cohen > <donsourceforgex2012@...> wrote: > > Pierpaolo Bernardi writes: > > > A typical use case for adjustable precision floats is the following: > > > > > > (setf (ext:longfloatdigits) someappropriatenumberofbits) > > > (largebodyofstandardportableclcodeusinglongfloats) > > > > > > If longfloatdigits 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 > MOSTPOSITIVELONGFLOAT 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 longfloatdigits. > 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 noncompliance? > 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 Bernardi <olopierpa@gm...>  20151019 22:57:29

On Tue, Oct 20, 2015 at 12:28 AM, Don Cohen <donsourceforgex2012@...> wrote: > Pierpaolo Bernardi writes: > > A typical use case for adjustable precision floats is the following: > > > > (setf (ext:longfloatdigits) someappropriatenumberofbits) > > (largebodyofstandardportableclcodeusinglongfloats) > > > > If longfloatdigits 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 MOSTPOSITIVELONGFLOAT 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 MOSTPOSITIVELONGFLOAT 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: <donsourceforgex2012@is...>  20151019 22:28:17

Pierpaolo Bernardi writes: > A typical use case for adjustable precision floats is the following: > > (setf (ext:longfloatdigits) someappropriatenumberofbits) > (largebodyofstandardportableclcodeusinglongfloats) > > If longfloatdigits 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 (symbolfunction 'cl::systemconstantp) (symbolfunction 'cl:constantp) > > (defun cl:constantp (x) > (case s > ((CL:PI CL:MOSTPOSITIVELONGFLOAT ...) t) > (otherwise (cl::systemconstantp 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 systemconstantp)? I would certinly expect so. Unless constantp is not used at all. 
From: Pierpaolo Bernardi <olopierpa@gm...>  20151019 21:55:45

On Mon, Oct 19, 2015 at 8:46 PM, Don Cohen <donsourceforgex2012@...> 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:longfloatdigits) someappropriatenumberofbits) (largebodyofstandardportableclcodeusinglongfloats) If longfloatdigits 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:LONGFLOATDIGITS > > function from the image. > > I don't see that removing EXT:LONGFLOATDIGITS 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 (symbolfunction 'cl::systemconstantp) (symbolfunction 'cl:constantp) (defun cl:constantp (x) (case s ((CL:PI CL:MOSTPOSITIVELONGFLOAT ...) t) (otherwise (cl::systemconstantp x)))) when compliance wrt this issue is desired. Would this break something? 
From: Raymond Toy <toy.raymond@gm...>  20151019 19:55:44

>>>>> "Pierpaolo" == Pierpaolo Bernardi <olopierpa@...> writes: Pierpaolo> On Sun, Oct 18, 2015 at 10:10 PM, Don Cohen Pierpaolo> <donsourceforgex2012@...> 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 >> LONGFLOATDIGITS. >> >> > If you use EXT:LONGFLOATDIGITS 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:LONGFLOATDIGITS then the only nonconfomance 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 longfloatdigits one might >> reasonably argue that everything is compliant  there are no better >> approximations of pi available without using longfloatdigits. 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:LONGFLOATDIGITS Pierpaolo> function from the image. As a user (not developer), I rather like that if I (setf (longfloatdigits)), pi does change. That clisp is the only lisp I use where longfloat and doublefloat are different has allowed to find and fix erroneous assumptions in my code where I had assumed pi was a doublefloat.  Ray 
From: <donsourceforgex2012@is...>  20151019 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:LONGFLOATDIGITS > function from the image. I don't see that removing EXT:LONGFLOATDIGITS 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: Pierpaolo Bernardi <olopierpa@gm...>  20151019 15:34:09

On Sun, Oct 18, 2015 at 10:10 PM, Don Cohen <donsourceforgex2012@...> 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 > LONGFLOATDIGITS. > > > If you use EXT:LONGFLOATDIGITS 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:LONGFLOATDIGITS then the only nonconfomance 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 longfloatdigits one might > reasonably argue that everything is compliant  there are no better > approximations of pi available without using longfloatdigits. 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:LONGFLOATDIGITS 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: <donsourceforgex2012@is...>  20151019 07:57:13

On 19/10/15 08:33, Don Cohen wrote: > Pascal J. Bourguignon writes: > > > It seems to me that (typep cl:pi 'longfloat) > > 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 nonnumber, don't you think > some sort of nonconforming 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 runtime 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 > > nonconstant cl:pi, since while it's nominaly nonconforming, 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 longfloatdigits 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:longfloatdigits 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 longfloatdigits doesn't affect it. Yes. But you could reread it. Right, (readfromstring "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 > longfloat, namely 64bit and 128bit long floats, but typeof > returns longfloat in both cases. That's a good way to see them, but it doesn't help with the constant longfloat pi problem. What exactly is this problem? I see no problem if pi is a defconstant with the value that it would have before longfloatdigits ever changes. 
From: Pascal J. Bourguignon <pjb@in...>  20151019 07:21:50

On 19/10/15 08:33, Don Cohen wrote: > Pascal J. Bourguignon writes: > > > It seems to me that (typep cl:pi 'longfloat) > > 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:longfloatdigits) 128) > (typep pi2 'longfloat) => T Yes, and this is what I mean; the opposite option being ext:variableprecisionlongfloat as subtype of float distinct from the other subtypes, and (typep cl:pi 'ext:variableprecisionlongfloat) and therefore (not (typep cl:pi 'longfloat)). 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 nonnumber, don't you think > some sort of nonconforming 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 runtime 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 > > nonconstant cl:pi, since while it's nominaly nonconforming, 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:longfloatdigits 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 longfloatdigits doesn't affect it. Yes. But you could reread 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 > longfloat, namely 64bit and 128bit long floats, but typeof > returns longfloat in both cases. > > That's a good way to see them, but it doesn't help with the constant longfloat pi problem. But this gives me an idea for another solution: cl:pi > #.ext:π (typep ext:π) > longfloat ext:π > #.ext:π That is, bind cl:pi to a symbolic object of type longfloat, which, when *used* in arithmetic operations would evaluate to the value of π in the current subtype of longfloat. cl:pi > #.ext:π ext:π > #.ext:π (+ 1 pi) > 4.1415926535897932383L0 (setf (ext:longfloatdigits) 128) (+ 1 pi) > 4.14159265358979323846264338327950288418L0  __Pascal J. Bourguignon__ http://www.informatimago.com/ 
From: <donsourceforgex2012@is...>  20151019 06:33:14

Pascal J. Bourguignon writes: > It seems to me that (typep cl:pi 'longfloat) > 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:longfloatdigits) 128) (typep pi2 'longfloat) => T > Either case would introduce a small nonconformity of clisp. > > The only way we could restore conformity would be to keep longfloat > fixed size (and therefore the value of cl:pi identical), and to rename > extended long floats ext:variableprecisionlongfloat (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 nonnumber, don't you think some sort of nonconforming behavior might result? > Therefore in my opinion, it's better to have constantp return nil for a > nonconstant cl:pi, since while it's nominaly nonconforming, 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:longfloatdigits 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 longfloatdigits 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 longfloat, namely 64bit and 128bit long floats, but typeof returns longfloat in both cases. 
From: Pascal J. Bourguignon <pjb@in...>  20151019 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 doublefloat, and to have another variable EXT:PI > > bound to the changing longfloat 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 'longfloat) is more important to maintain than (constantp 'cl:pi). Either case would introduce a small nonconformity of clisp. The only way we could restore conformity would be to keep longfloat fixed size (and therefore the value of cl:pi identical), and to rename extended long floats ext:variableprecisionlongfloat (or something else) and have that distinct ext:pi variable. (subtypep 'ext:variableprecisionlongfloat 'float) AFAIK, introducing a new floating point subtype would be an acceptable extension that wouldn't introduce any obvious nonconformity. 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 (shortfloat 1) (singlefloat 2) (doublefloat 3) (longfloat 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:longfloatdigits, 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 nonconforming changes the longfloatdigits. But it would break if constantp lied and returned T. Therefore in my opinion, it's better to have constantp return nil for a nonconstant cl:pi, since while it's nominaly nonconforming, 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/ 