Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Nov 28 2021, Paul Smith wrote: >> The C standard defines the largest unsigned long long value >> as 18446744073709551615, the largest signed long long value >> as 9223372036854775807, and the smallest signed long long value as - >> 9223372036854775808. So, the definition cannot be wrong in any >> standards-conforming implementation of C. Andreas Schwab (6 December 2021 12:30) replied: > This is wrong. These are *minimum* limits. For reference: the number of bytes needed for the ASCII decimal representation (including terminating '\0') of an integral type is bounded (fairly tightly) above by 53 * sizeof(type) / 22 + (3 if type is signed else 2) When I need a compile-time constant for an array buffer size, this is what I use. Fuller explanation here: https://github.com/ediosyncratic/study.py/blob/master/maths/buffersize.py Eddy.
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Nov 28 2021, Paul Smith wrote: > The C standard defines the largest unsigned long long value > as 18446744073709551615, the largest signed long long value > as 9223372036854775807, and the smallest signed long long value as - > 9223372036854775808. So, the definition cannot be wrong in any > standards-conforming implementation of C. This is wrong. These are *minimum* limits. Andreas. -- Andreas Schwab, SUSE Labs, sch...@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different."
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, 2021-11-28 at 15:49 +0100, Jouke Witteveen wrote: > I fully agree, but was not aware of the robustness of INTSTR_LENGTH. > It felt a bit fragile when I spotted its definition in makeint.h. The C standard defines the largest unsigned long long value as 18446744073709551615, the largest signed long long value as 9223372036854775807, and the smallest signed long long value as - 9223372036854775808. So, the definition cannot be wrong in any standards-conforming implementation of C. > File sizes are an interesting application indeed. If you want me to > change the patches to use strtoll, I would need some help since I am > not sure how to set things up so that we get a fallback > implementation on platforms where it is missing. I already did it locally, thanks for the offer. I enhanced the tests to check that the above (signed) values are parsed correctly. I just changed the gnulib import of "strtol" to "strtoll". strtoll() is required by the C99 standard (which we were forced to require in GNU make as well, since gnulib requires it) so it's pretty much everywhere these days. There are a few older platforms where it has incorrect implementations that gnulib will take care of for us. Cheers!
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, Nov 28, 2021 at 3:20 PM Paul Smith wrote: > > On Sun, 2021-11-28 at 14:57 +0100, Jouke Witteveen wrote: > > > Since the two arguments are equal, it doesn't matter which of LHS > > > or RHS we return. > > > > They could differ for instance when one of them contains a '+'-sign. > > My reason for using LHS is that we already have a string for it. > > I don't think that it's necessary return the exact string. If the user > wanted a string match they can do that other ways. Returning the > "absolute value" (stripping leading +/-, leading 0's, etc.) seems more > useful to me. I fully agree, but was not aware of the robustness of INTSTR_LENGTH. It felt a bit fragile when I spotted its definition in makeint.h. > > > However, now that I think about it I need to change the code more: we > > > need to be using "long long" here not just "long". While on Linux etc. > > > a "long" is 8 bytes, on Windows "long" is only 4 bytes. > > > > I was hoping this would not be necessary, and I cannot think of a > > typical use case where make is a good fit for dealing with large > > integers. The benefit of "long" is that strtol is more widely > > available than strtoll. > > I see what you mean, but I _really_ don't like the idea of GNU make > working differently on different platforms, even if such use cases are > rare. I can imagine a situation where, for example, someone wants to > compare the sizes of files and if one of the files is >4G then it will > work on Linux and fail on Windows. File sizes are an interesting application indeed. If you want me to change the patches to use strtoll, I would need some help since I am not sure how to set things up so that we get a fallback implementation on platforms where it is missing.
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, Nov 28, 2021 at 3:33 PM Paul Smith wrote: > > On Sun, 2021-11-28 at 08:24 +0100, Jouke Witteveen wrote: > > On the user side, strcmp could now probably be defined something like > > $(and $(intcmp $(words $1),$(words $2)),$(findstring x $1 x,x $2 x)) > > I don't think this is equivalent since a putative strcmp would also do > greater / less than comparison (like intcmp does). Of course that > leads into all sorts of i18n / locale issues, but likely we'd just punt > (like C's strcmp does) and use ASCII ordering; we've already taken that > route elsewhere. This was only intended as a demonstration of how the two-argument strcmp function could be implemented already (I initially forgot the spaces around the 'x's). This would serve as a test for exact string-wise equality. If anything, this could mean that there is no reason to spend time on adding strcmp now. It's all a digression and I agree with everything you said about it.
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, 2021-11-28 at 08:24 +0100, Jouke Witteveen wrote: > On the user side, strcmp could now probably be defined something like > $(and $(intcmp $(words $1),$(words $2)),$(findstring x$1x,x$2x)) I don't think this is equivalent since a putative strcmp would also do greater / less than comparison (like intcmp does). Of course that leads into all sorts of i18n / locale issues, but likely we'd just punt (like C's strcmp does) and use ASCII ordering; we've already taken that route elsewhere. You can probably gin up something that works using $(sort ...) but it seems tricky. Anyway I'm not suggesting this be added right now but just keeping options open for the future.
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, 2021-11-28 at 14:57 +0100, Jouke Witteveen wrote: > > Since the two arguments are equal, it doesn't matter which of LHS > > or RHS we return. > > They could differ for instance when one of them contains a '+'-sign. > My reason for using LHS is that we already have a string for it. I don't think that it's necessary return the exact string. If the user wanted a string match they can do that other ways. Returning the "absolute value" (stripping leading +/-, leading 0's, etc.) seems more useful to me. > By using sprintf, we need to make the buffer big enough, which in > turn requires INTSTR_LENGTH to be fitting for whatever width a long > has on the current platform. That's already the case; GNU make defines this constant to be large enough to hold the largest possible (8-byte) integer value, regardless of platform. This is used in various places when showing output etc. > > However, now that I think about it I need to change the code more: we > > need to be using "long long" here not just "long". While on Linux etc. > > a "long" is 8 bytes, on Windows "long" is only 4 bytes. > > I was hoping this would not be necessary, and I cannot think of a > typical use case where make is a good fit for dealing with large > integers. The benefit of "long" is that strtol is more widely > available than strtoll. I see what you mean, but I _really_ don't like the idea of GNU make working differently on different platforms, even if such use cases are rare. I can imagine a situation where, for example, someone wants to compare the sizes of files and if one of the files is >4G then it will work on Linux and fail on Windows.
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, Nov 28, 2021 at 2:45 PM Paul Smith wrote: > > On Sun, 2021-11-28 at 08:24 +0100, Jouke Witteveen wrote: > > Thanks for sending this message, I would have otherwise prepared and > > sent an updated patch series today. My plan was to expand to RHS in > > the two-argument case if both values are equal. I assume you also > > updated the documentation where needed? If so, there's nothing I have > > to add and I'm looking forward to the new functionality. > > Yes, I updated the docs. > > Since the two arguments are equal, it doesn't matter which of LHS or > RHS we return. They could differ for instance when one of them contains a '+'-sign. My reason for using LHS is that we already have a string for it. By using sprintf, we need to make the buffer big enough, which in turn requires INTSTR_LENGTH to be fitting for whatever width a long has on the current platform. > The change I made was: > > argv += 2; > > if (*argv == NULL) > { > if (lhs == rhs) > { > char buf[INTSTR_LENGTH+1]; > sprintf (buf, "%ld", lhs); > o = variable_buffer_output(o, buf, strlen (buf)); > } > return o; > } > > However, now that I think about it I need to change the code more: we > need to be using "long long" here not just "long". While on Linux etc. > a "long" is 8 bytes, on Windows "long" is only 4 bytes. I was hoping this would not be necessary, and I cannot think of a typical use case where make is a good fit for dealing with large integers. The benefit of "long" is that strtol is more widely available than strtoll. Regards, - Jouke
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, 2021-11-28 at 08:24 +0100, Jouke Witteveen wrote: > Thanks for sending this message, I would have otherwise prepared and > sent an updated patch series today. My plan was to expand to RHS in > the two-argument case if both values are equal. I assume you also > updated the documentation where needed? If so, there's nothing I have > to add and I'm looking forward to the new functionality. Yes, I updated the docs. Since the two arguments are equal, it doesn't matter which of LHS or RHS we return. The change I made was: argv += 2; if (*argv == NULL) { if (lhs == rhs) { char buf[INTSTR_LENGTH+1]; sprintf (buf, "%ld", lhs); o = variable_buffer_output(o, buf, strlen (buf)); } return o; } However, now that I think about it I need to change the code more: we need to be using "long long" here not just "long". While on Linux etc. a "long" is 8 bytes, on Windows "long" is only 4 bytes.
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, Nov 28, 2021 at 5:02 AM Paul Smith wrote: > > On Mon, 2021-11-15 at 20:49 +0100, Jouke Witteveen wrote: > > It may be obscure, but how about we implement this as well? Sure, the > > two-argument form of $(compare) will be a little inconsistent, but it > > may be useful. > > I applied this three-patch set. > > I left the argument order as you originally specified it, and I added > support for a 2-argument form that provides a trivial equality as > above. Maybe it's weird but I think it might be useful. > > The one change I made is changing the name of the function from > "compare" to "intcmp": I felt "compare" was too generic. Sometime we > may want to introduce other types of comparison such as "strcmp" etc. > > Let me know what you think about this: I've only applied it to my local > Git repository but not pushed it yet. > Hi Paul, Thanks for sending this message, I would have otherwise prepared and sent an updated patch series today. My plan was to expand to RHS in the two-argument case if both values are equal. I assume you also updated the documentation where needed? If so, there's nothing I have to add and I'm looking forward to the new functionality. On the user side, strcmp could now probably be defined something like $(and $(intcmp $(words $1),$(words $2)),$(findstring x$1x,x$2x)) Thanks, - Jouke
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Mon, 2021-11-15 at 20:49 +0100, Jouke Witteveen wrote: > It may be obscure, but how about we implement this as well? Sure, the > two-argument form of $(compare) will be a little inconsistent, but it > may be useful. I applied this three-patch set. I left the argument order as you originally specified it, and I added support for a 2-argument form that provides a trivial equality as above. Maybe it's weird but I think it might be useful. The one change I made is changing the name of the function from "compare" to "intcmp": I felt "compare" was too generic. Sometime we may want to introduce other types of comparison such as "strcmp" etc. Let me know what you think about this: I've only applied it to my local Git repository but not pushed it yet.
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Tue, Nov 16, 2021 at 10:28 AM Edward Welbourne wrote: > > On Sun, Nov 14, 2021 at 8:42 PM Paul Smith wrote: > > It's even possible to allow $(compare ,) with no other > > arguments and say that if they are equal then it expands to the value, > > else it expands to the empty string, to give a very short-circuited > > equality statement. > > I should point out one bug in that: if the two parameters are equal > *but empty* you're going to mistake that for them being different. Empty strings will not be accepted as or , since those arguments are parsed as numbers. A case like $(compare +0,-0) would expand to "0" (without quotes), which is how the value would be formatted by the standard C routines. I don't think there is a bug here. Regards, - Jouke
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, Nov 14, 2021 at 8:42 PM Paul Smith wrote: > It's even possible to allow $(compare ,) with no other > arguments and say that if they are equal then it expands to the value, > else it expands to the empty string, to give a very short-circuited > equality statement. I should point out one bug in that: if the two parameters are equal *but empty* you're going to mistake that for them being different. Eddy.
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Sun, Nov 14, 2021 at 8:42 PM Paul Smith wrote: > > On Wed, 2021-11-10 at 18:19 +0100, Jouke Witteveen wrote: > > On Mon, Nov 8, 2021 at 4:08 PM Paul Smith wrote: > > > > > On Fri, 2021-07-16 at 14:04 +0200, Jouke Witteveen wrote: > > > > $(compare > > > > @var{lhs},@var{rhs},@var{lt-part}[,@var{eq-part}[,@var{gt-part}]]) > > > Let me ask this: would it be better to use a format of: > > >$(compare , , [, [, ]]) > > > > $(if $(compare ,,,they_are_equal,),,) > > > > In fact, in the original design you could get away with just the > > three-argument version of $(compare) in combination with $(if), > > $(and) and $(or). This is not the case for the alternative design. > > Can you explain this, perhaps with an example or two? I don't quite > follow. It seems that: > > $(if $(compare ,,equal),,) > > works fine with the alternative syntax. What I was trying to say is that the two versions differ only in the abilities provided by their thee-argument forms. It's not much of a reason to favor one over the other, but the three-argument form of the original proposal (less-than) is 'complete' in the sense that all of <, >, =, and their negations can be expressed as boolean combinations of it. The same is not true of the three-argument form of the alternative design (e.g. less-than cannot be expressed using the three-argument version of that design alone). > It's even possible to allow $(compare ,) with no other > arguments and say that if they are equal then it expands to the value, > else it expands to the empty string, to give a very short-circuited > equality statement. It may be obscure, but how about we implement this as well? Sure, the two-argument form of $(compare) will be a little inconsistent, but it may be useful. > > I also took a look at other languages. Nearly everywhere I could find > > three-way comparisons, the possible outcomes are listed as LT, EQ, > > GT, in that order. > > I'm certainly willing to be convinced that the original idea is better, > but this argument doesn't hold much water for me. I don't think that > changing the order of the extra arguments will cause much cognitive > dissonance for people. Interesting. The fact that I saw the mental model of the LT, EQ, GT ordering of outcomes reflected so often was convincing for me that this would be the more unsurprising design. I'm not saying the alternative will cause cognitive dissonance, just that the occasional user of make might not need to consult the reference documentation as much trying to recall how the compare function works. Admittedly, the difference, if any, will likely be negligible. Regards, - Jouke P.S. I started this series saying that I see no merit in discussing possible extensions and alternatives. Regarding version comparison (a minefield if you ask me), I'd just like to point out that you can do basic parsing of a version with $(let major minor patch, $(subst ., ,$(version)),)
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Wed, 2021-11-10 at 18:19 +0100, Jouke Witteveen wrote: > On Mon, Nov 8, 2021 at 4:08 PM Paul Smith wrote: > > > On Fri, 2021-07-16 at 14:04 +0200, Jouke Witteveen wrote: > > > $(compare > > > @var{lhs},@var{rhs},@var{lt-part}[,@var{eq-part}[,@var{gt-part}]]) > > Let me ask this: would it be better to use a format of: > >$(compare , , [, [, ]]) > > $(if $(compare ,,,they_are_equal,),,) > > In fact, in the original design you could get away with just the > three-argument version of $(compare) in combination with $(if), > $(and) and $(or). This is not the case for the alternative design. Can you explain this, perhaps with an example or two? I don't quite follow. It seems that: $(if $(compare ,,equal),,) works fine with the alternative syntax. It's even possible to allow $(compare ,) with no other arguments and say that if they are equal then it expands to the value, else it expands to the empty string, to give a very short-circuited equality statement. I do agree, though, that we already have a way to test equality (via filter-out) and although it will treat "1" and "01" as different this is probably a rare problem. > I also took a look at other languages. Nearly everywhere I could find > three-way comparisons, the possible outcomes are listed as LT, EQ, > GT, in that order. I'm certainly willing to be convinced that the original idea is better, but this argument doesn't hold much water for me. I don't think that changing the order of the extra arguments will cause much cognitive dissonance for people.
RE: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On November 10, 2021 12:19 PM, Jouke Witteveen wrote: > To: psm...@gnu.org > Cc: bug-make > Subject: Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison > > On Mon, Nov 8, 2021 at 4:08 PM Paul Smith wrote: > > > > On Fri, 2021-07-16 at 14:04 +0200, Jouke Witteveen wrote: > > > +@item $(compare > > > +@var{lhs},@var{rhs},@var{lt-part}[,@var{eq-part}[,@var{gt-part}]]) > > > > Let me ask this: would it be better to use a format of: > > > > $(compare , , [, [, ]]) > > > > Then the rule is, if the values are equal we get the part, if lhs > > is less than rhs we get , and if lhs is greater than rhs we get > > . > > > > If is not present then the invocation devolves to: > > > > $(compare , , , ) > > > > that is, the fourth arg is used for not equal. > > > > If is also not present then is used if the value is equal > > else it expands to the empty string. > > > > Cool, an alternative design that has something to go for it! Here is why I > like > the original design better. > > The only real difference is in four-argument usage. This alternative trades > the > 'ordered' nature of the arguments for favoring equality testing. To some > degree, equality testing is already possible through string-based equality > testing, and even if you really want to do a numerical equality check, the > original design allows you to do > > $(if $(compare ,,,they_are_equal,),,) > > In fact, in the original design you could get away with just the three- > argument version of $(compare) in combination with $(if), $(and) and $(or). > This is not the case for the alternative design. > > I also took a look at other languages. Nearly everywhere I could find three- > way comparisons, the possible outcomes are listed as LT, EQ, GT, in that > order. Fortran apparently had an "Arithmetic IF", that was also ordered as in > the original design of $(compare). I have a similar function in my own fork called $(vcompare), which is similar, but does comparison of version-like strings. It does not have the additional arguments, which I would think are better separated off into a control function like $(if) instead of having then and else built into the $(compare). Randall
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Fri, 2021-07-16 at 14:04 +0200, Jouke Witteveen wrote: > +@item $(compare > @var{lhs},@var{rhs},@var{lt-part}[,@var{eq-part}[,@var{gt-part}]]) Let me ask this: would it be better to use a format of: $(compare , , [, [, ]]) Then the rule is, if the values are equal we get the part, if lhs is less than rhs we get , and if lhs is greater than rhs we get . If is not present then the invocation devolves to: $(compare , , , ) that is, the fourth arg is used for not equal. If is also not present then is used if the value is equal else it expands to the empty string.
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
Also perhaps the more general mathematical function On Mon, Sep 13, 2021 at 10:04 PM Randall S. Becker wrote: > On September 13, 2021 2:40 PM, Jouke Witteveen wrote: > >On Fri, Jul 16, 2021 at 2:04 PM Jouke Witteveen > wrote: > >> > >> Numbers can come from $(words ...), automatic variables such as > >> $(MAKELEVEL), from environment variables, or from shell output such as > >> through $(shell expr ...). The $(compare ...) function allows > >> conditional evaluation controlled by numerical variables. > >> > >> * NEWS: Announce this feature. > >> * doc/make.texi (Functions for Conditionals): Document 'compare'. > >> * src/function.c (func_compare): Create the 'compare' built-in function. > >> * tests/scripts/functions/compare: Test the 'compare' built-in function. > >> --- > >> > >> This is a cleaned-up and documented version of a proposal submitted a > >> year ago. The interface was conceived by Edward Welbourne and myself. > >> Personally, I would not introduce mathematical operators to make, but > >> given that numbers are a thing and they do pop up in variables, a > >> comparison function makes sense to me. > >> > >> Thanks for considering! > >> - Jouke > > > >I would still be interested in seeing this patch series I sent two months > ago considered. I am not in a rush: this is just a friendly reminder. > > I am interested in this series as well, although something more general > might also be interesting, like a general version compare function like > $(compare 1.6.1 1.6.100), and that also take into account character-based > versioning, like $(compare A10.88 B20.94). > > -Randall > > >
RE: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On September 13, 2021 2:40 PM, Jouke Witteveen wrote: >On Fri, Jul 16, 2021 at 2:04 PM Jouke Witteveen wrote: >> >> Numbers can come from $(words ...), automatic variables such as >> $(MAKELEVEL), from environment variables, or from shell output such as >> through $(shell expr ...). The $(compare ...) function allows >> conditional evaluation controlled by numerical variables. >> >> * NEWS: Announce this feature. >> * doc/make.texi (Functions for Conditionals): Document 'compare'. >> * src/function.c (func_compare): Create the 'compare' built-in function. >> * tests/scripts/functions/compare: Test the 'compare' built-in function. >> --- >> >> This is a cleaned-up and documented version of a proposal submitted a >> year ago. The interface was conceived by Edward Welbourne and myself. >> Personally, I would not introduce mathematical operators to make, but >> given that numbers are a thing and they do pop up in variables, a >> comparison function makes sense to me. >> >> Thanks for considering! >> - Jouke > >I would still be interested in seeing this patch series I sent two months ago >considered. I am not in a rush: this is just a friendly reminder. I am interested in this series as well, although something more general might also be interesting, like a general version compare function like $(compare 1.6.1 1.6.100), and that also take into account character-based versioning, like $(compare A10.88 B20.94). -Randall
Re: [PATCH 3/3] Introduce $(compare ...) for numerical comparison
On Fri, Jul 16, 2021 at 2:04 PM Jouke Witteveen wrote: > > Numbers can come from $(words ...), automatic variables such as > $(MAKELEVEL), from environment variables, or from shell output such as > through $(shell expr ...). The $(compare ...) function allows > conditional evaluation controlled by numerical variables. > > * NEWS: Announce this feature. > * doc/make.texi (Functions for Conditionals): Document 'compare'. > * src/function.c (func_compare): Create the 'compare' built-in function. > * tests/scripts/functions/compare: Test the 'compare' built-in function. > --- > > This is a cleaned-up and documented version of a proposal submitted a > year ago. The interface was conceived by Edward Welbourne and myself. > Personally, I would not introduce mathematical operators to make, but > given that numbers are a thing and they do pop up in variables, a > comparison function makes sense to me. > > Thanks for considering! > - Jouke I would still be interested in seeing this patch series I sent two months ago considered. I am not in a rush: this is just a friendly reminder. Regards, - Jouke