From 8bb03da906e1f8f750123214b15a19d7d4e166c1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 Jul 2021 19:38:03 +0200 Subject: [PATCH] awk: rand() could return 1.0, fix this - should be in [0,1) 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 --- 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);