Re: seq: fix check for rounding error/truncation

2023-06-12 Thread Todd C . Miller
On Mon, 12 Jun 2023 18:48:56 +0100, Stuart Henderson wrote:

> Neither of these are really ideal, and mean that we still need gseq
> for integers >= 1,000,000
>
> $ seq 99 99
> 99
> $ seq 100 100
> 1e+06
>
> $ gseq 105 105
> 105

That probably requires a separate code path specifically for integers.
One thing at a time.

 - todd



Re: seq: fix check for rounding error/truncation

2023-06-12 Thread Stuart Henderson
On 2023/06/12 11:20, Todd C. Miller wrote:
> We need to compare the printable version of the last value displayed,
> not the floating point representation.  Otherwise, we may print the
> last value twice.
> 
> Old:
> 
> $ seq 105 105
> 1.05e+06
> 1.05e+06
> 
> New:
> 
> $ seq 105 105
> 1.05e+06

Neither of these are really ideal, and mean that we still need gseq
for integers >= 1,000,000

$ seq 99 99
99
$ seq 100 100
1e+06

$ gseq 105 105
105

> We really need seq regression tests.  I have a few that I will
> commit after this is in.
> 
>  - todd
> 
> Index: usr.bin/seq/seq.c
> ===
> RCS file: /cvs/src/usr.bin/seq/seq.c,v
> retrieving revision 1.6
> diff -u -p -u -r1.6 seq.c
> --- usr.bin/seq/seq.c 25 Feb 2022 16:00:39 -  1.6
> +++ usr.bin/seq/seq.c 12 Jun 2023 17:13:44 -
> @@ -89,13 +89,13 @@ main(int argc, char *argv[])
>   double first = 1.0;
>   double last = 0.0;
>   double incr = 0.0;
> - double last_shown_value = 0.0;
> + double prev = 0.0;
>   double cur, step;
>   struct lconv *locale;
>   char *fmt = NULL;
>   const char *sep = "\n";
>   const char *term = "\n";
> - char *cur_print, *last_print;
> + char *cur_print, *last_print, *prev_print;
>   char pad = ZERO;
>  
>   if (pledge("stdio", NULL) == -1)
> @@ -181,29 +181,31 @@ main(int argc, char *argv[])
>   if (cur != first)
>   fputs(sep, stdout);
>   printf(fmt, cur);
> - last_shown_value = cur;
> + prev = cur;
>   }
>  
>   /*
>* Did we miss the last value of the range in the loop above?
>*
>* We might have, so check if the printable version of the last
> -  * computed value ('cur') and desired 'last' value are equal.  If they
> -  * are equal after formatting truncation, but 'cur' and
> -  * 'last_shown_value' are not equal, it means the exit condition of the
> -  * loop held true due to a rounding error and we still need to print
> -  * 'last'.
> +  * computed value ('cur') and desired 'last' value are equal.  If
> +  * they are equal after formatting truncation, but 'cur' and 'prev'
> +  * are different, it means the exit condition of the loop held true
> +  * due to a rounding error and we still need to print 'last'.
>*/
>   if (asprintf(&cur_print, fmt, cur) == -1 ||
> - asprintf(&last_print, fmt, last) == -1)
> + asprintf(&last_print, fmt, last) == -1 ||
> + asprintf(&prev_print, fmt, prev) == -1)
>   err(1, "asprintf");
> - if (strcmp(cur_print, last_print) == 0 && cur != last_shown_value) {
> + if (strcmp(cur_print, last_print) == 0 &&
> + strcmp(cur_print, prev_print) != 0) {
>   if (cur != first)
>   fputs(sep, stdout);
>   fputs(last_print, stdout);
>   }
>   free(cur_print);
>   free(last_print);
> + free(prev_print);
>  
>   fputs(term, stdout);
>  
> 



Re: seq: fix check for rounding error/truncation

2023-06-12 Thread Todd C . Miller
For context, see:

https://chaos.social/@Gottox/110527807405964874

https://github.com/chimera-linux/chimerautils/commit/1ecc1e99d4a309631e846a868b5a422f996704ac



seq: fix check for rounding error/truncation

2023-06-12 Thread Todd C . Miller
We need to compare the printable version of the last value displayed,
not the floating point representation.  Otherwise, we may print the
last value twice.

Old:

$ seq 105 105
1.05e+06
1.05e+06

New:

$ seq 105 105
1.05e+06

We really need seq regression tests.  I have a few that I will
commit after this is in.

 - todd

Index: usr.bin/seq/seq.c
===
RCS file: /cvs/src/usr.bin/seq/seq.c,v
retrieving revision 1.6
diff -u -p -u -r1.6 seq.c
--- usr.bin/seq/seq.c   25 Feb 2022 16:00:39 -  1.6
+++ usr.bin/seq/seq.c   12 Jun 2023 17:13:44 -
@@ -89,13 +89,13 @@ main(int argc, char *argv[])
double first = 1.0;
double last = 0.0;
double incr = 0.0;
-   double last_shown_value = 0.0;
+   double prev = 0.0;
double cur, step;
struct lconv *locale;
char *fmt = NULL;
const char *sep = "\n";
const char *term = "\n";
-   char *cur_print, *last_print;
+   char *cur_print, *last_print, *prev_print;
char pad = ZERO;
 
if (pledge("stdio", NULL) == -1)
@@ -181,29 +181,31 @@ main(int argc, char *argv[])
if (cur != first)
fputs(sep, stdout);
printf(fmt, cur);
-   last_shown_value = cur;
+   prev = cur;
}
 
/*
 * Did we miss the last value of the range in the loop above?
 *
 * We might have, so check if the printable version of the last
-* computed value ('cur') and desired 'last' value are equal.  If they
-* are equal after formatting truncation, but 'cur' and
-* 'last_shown_value' are not equal, it means the exit condition of the
-* loop held true due to a rounding error and we still need to print
-* 'last'.
+* computed value ('cur') and desired 'last' value are equal.  If
+* they are equal after formatting truncation, but 'cur' and 'prev'
+* are different, it means the exit condition of the loop held true
+* due to a rounding error and we still need to print 'last'.
 */
if (asprintf(&cur_print, fmt, cur) == -1 ||
-   asprintf(&last_print, fmt, last) == -1)
+   asprintf(&last_print, fmt, last) == -1 ||
+   asprintf(&prev_print, fmt, prev) == -1)
err(1, "asprintf");
-   if (strcmp(cur_print, last_print) == 0 && cur != last_shown_value) {
+   if (strcmp(cur_print, last_print) == 0 &&
+   strcmp(cur_print, prev_print) != 0) {
if (cur != first)
fputs(sep, stdout);
fputs(last_print, stdout);
}
free(cur_print);
free(last_print);
+   free(prev_print);
 
fputs(term, stdout);