On Sat, Jul 16, 2016 at 09:46:29PM +0200, Theo Buehler wrote:
> I see two options apart from reverting my commit.
>
> 1. Just fix the bug Otto noticed. Remove the section on randomness
> completely and fix one example in the manual. That's what the patch
> in this mail does. The patch for jot.c is the same as in my previous
> mail.
>
> 2. Restore the previous behavior when -w or -c is specified together
> with -r and fix the bug Otto noticed. I will send this patch in a
> second mail.
>
> sobrado@ and I checked that this patch would match the behavior of Linux
> and NetBSD. In particular, the format string does not change the output
> drastically:
>
> $ jot -r 100000 1 3 | sort -n | uniq -c
> 33148 1
> 33452 2
> 33400 3
> $ jot -w %d -r 100000 1 3 | sort -n | uniq -c
> 33373 1
> 33239 2
> 33388 3
>
> I think this behavior makes sense: if the output consists of integers
> anyway, then a %d format should not alter it, independently of what
> happens under the hood.
>
> The downside is that it breaks scripts that relied on the previous
> behavior that was explicitly mentioned in the manual (as Philippe found
> the hard way; sorry about that!).
>
i know we need to tread carefully with breaking scripts, but i think the
balance is that we need a sane world too. i think we should take the stand
for simplicity and sanity (option 1).
ok for the man page.
jmc
> Index: jot.1
> ===================================================================
> RCS file: /var/cvs/src/usr.bin/jot/jot.1,v
> retrieving revision 1.19
> diff -u -p -r1.19 jot.1
> --- jot.1 4 Jan 2016 23:21:28 -0000 1.19
> +++ jot.1 16 Jul 2016 19:09:59 -0000
> @@ -225,41 +225,6 @@ specifying an integer format:
> .Bd -literal -offset indent
> $ jot -w %d 6 1 10 0.5
> .Ed
> -.Pp
> -For random sequences, the output format also influences the range
> -and distribution of the generated numbers:
> -.Bd -literal -offset indent
> -$ jot -r 100000 1 3 | sort -n | uniq -c
> -24950 1
> -50038 2
> -25012 3
> -.Ed
> -.Pp
> -The values at the beginning and end of the interval
> -are generated less frequently than the other values.
> -There are several ways to solve this problem and generate evenly distributed
> -integers:
> -.Bd -literal -offset indent
> -$ jot -r -p 0 100000 0.5 3.5 | sort -n | uniq -c
> -33374 1
> -33363 2
> -33263 3
> -
> -$ jot -w %d -r 100000 1 4 | sort -n | uniq -c
> -33306 1
> -33473 2
> -33221 3
> -.Ed
> -.Pp
> -Note that with random sequences, all numbers generated will
> -be smaller than the upper bound.
> -The largest value generated will be a tiny bit smaller than
> -the upper bound.
> -For floating point formats, the value is rounded as described
> -before being printed.
> -For integer formats, the highest value printed will be one less
> -than the requested upper bound, because the generated value will
> -be truncated.
> .Sh EXAMPLES
> Print 21 evenly spaced numbers increasing from \-1 to 1:
> .Pp
> @@ -280,7 +245,7 @@ comes after the character
> .Sq z
> in the ASCII character set):
> .Pp
> -.Dl "$ jot \-r \-c 160 a { | rs \-g0 0 8"
> +.Dl "$ jot \-r \-c 160 a z | rs \-g0 0 8"
> .Pp
> Infinitely many
> .Xr yes 1 Ns 's
> Index: jot.c
> ===================================================================
> RCS file: /var/cvs/src/usr.bin/jot/jot.c,v
> retrieving revision 1.27
> diff -u -p -r1.27 jot.c
> --- jot.c 10 Jan 2016 01:15:52 -0000 1.27
> +++ jot.c 16 Jul 2016 19:10:18 -0000
> @@ -277,9 +277,6 @@ main(int argc, char *argv[])
> if (prec > 9) /* pow(10, prec) > UINT32_MAX */
> errx(1, "requested precision too large");
>
> - while (prec-- > 0)
> - pow10 *= 10;
> -
> if (ender < begin) {
> x = begin;
> begin = ender;
> @@ -287,16 +284,22 @@ main(int argc, char *argv[])
> }
> x = ender - begin;
>
> - /*
> - * If pow10 * (ender - begin) is an integer, use
> - * arc4random_uniform().
> - */
> - use_unif = fmod(pow10 * (ender - begin), 1) == 0;
> - if (use_unif) {
> - uintx = pow10 * (ender - begin);
> - if (uintx >= UINT32_MAX)
> - errx(1, "requested range too large");
> - uintx++;
> + if (prec == 0 && (fmod(ender, 1) != 0 || fmod(begin, 1) != 0))
> + use_unif = 0;
> + else {
> + while (prec-- > 0)
> + pow10 *= 10;
> + /*
> + * If pow10 * (ender - begin) is an integer, use
> + * arc4random_uniform().
> + */
> + use_unif = fmod(pow10 * (ender - begin), 1) == 0;
> + if (use_unif) {
> + uintx = pow10 * (ender - begin);
> + if (uintx >= UINT32_MAX)
> + errx(1, "requested range too large");
> + uintx++;
> + }
> }
>
> for (i = 1; i <= reps || infinity; i++) {