summary refs log tree commit diff
path: root/src/usr.bin/jot/jot.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr.bin/jot/jot.c')
-rw-r--r--src/usr.bin/jot/jot.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/src/usr.bin/jot/jot.c b/src/usr.bin/jot/jot.c
index 8952ead..e4fdade 100644
--- a/src/usr.bin/jot/jot.c
+++ b/src/usr.bin/jot/jot.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: jot.c,v 1.26 2015/10/09 01:37:07 deraadt Exp $	*/
+/*	$OpenBSD: jot.c,v 1.27 2016/01/10 01:15:52 tb Exp $	*/
 /*	$NetBSD: jot.c,v 1.3 1994/12/02 20:29:43 pk Exp $	*/
 
 /*-
@@ -40,6 +40,8 @@
 #include <stdbool.h>
 #include <ctype.h>
 #include <limits.h>
+#include <math.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -268,11 +270,45 @@ main(int argc, char *argv[])
 	if (reps == 0)
 		infinity = true;
 	if (randomize) {
-		x = (ender - begin) * (ender > begin ? 1 : -1);
+		bool		use_unif;
+		uint32_t	pow10 = 1;
+		uint32_t	uintx = 0; /* Initialized to make gcc happy. */
+
+		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;
+			ender = x;
+		}
+		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++;
+		}
+
 		for (i = 1; i <= reps || infinity; i++) {
 			double v;
-			y = arc4random() / ((double)0xffffffff + 1);
-			v = y * x + begin;
+
+			if (use_unif) {
+				y = arc4random_uniform(uintx) / (double)pow10;
+				v = y + begin;
+			} else {
+				y = arc4random() / ((double)0xffffffff + 1);
+				v = y * x + begin;
+			}
 			if (putdata(v, reps == i && !infinity))
 				errx(1, "range error in conversion: %f", v);
 		}