[git commit] awk: rand() could return 1.0, fix this - should be in [0, 1)

Denys Vlasenko vda.linux at googlemail.com
Fri Jul 2 17:38:03 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=8bb03da906e1f8f750123214b15a19d7d4e166c1
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

While at it, make it finer-grained (63 bits of randomness)

function                                             old     new   delta
evaluate                                            3303    3336     +33
.rodata                                           104107  104111      +4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 37/0)               Total: 37 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 editors/awk.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/editors/awk.c b/editors/awk.c
index 8d7777ca6..64fe81be4 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -3118,9 +3118,20 @@ static var *evaluate(node *op, var *res)
 			case F_rn: /*rand*/
 				if (op1)
 					syntax_error("Too many arguments");
-				R_d = (double)rand() / (double)RAND_MAX;
+			{
+#if RAND_MAX >= 0x7fffffff
+				uint32_t u = ((uint32_t)rand() << 16) ^ rand();
+				uint64_t v = ((uint64_t)rand() << 32) | u;
+				/* the above shift+or is optimized out on 32-bit arches */
+# if RAND_MAX > 0x7fffffff
+				v &= 0x7fffffffffffffffUL;
+# endif
+				R_d = (double)v / 0x8000000000000000UL;
+#else
+# error Not implemented for this value of RAND_MAX
+#endif
 				break;
-
+			}
 			case F_co:
 				if (ENABLE_FEATURE_AWK_LIBM) {
 					R_d = cos(L_d);


More information about the busybox-cvs mailing list