aboutsummaryrefslogtreecommitdiff
path: root/lmathlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-03-27 15:22:40 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-03-27 15:22:40 -0300
commit37a1b72706b6e55e60b8d73bcbe269921976825e (patch)
tree4584d132e9b9f963faba8ed8199ef470cb5cab47 /lmathlib.c
parentef5d171cc89b19ac1fea905b99d819b5f97cba00 (diff)
downloadlua-37a1b72706b6e55e60b8d73bcbe269921976825e.tar.gz
lua-37a1b72706b6e55e60b8d73bcbe269921976825e.tar.bz2
lua-37a1b72706b6e55e60b8d73bcbe269921976825e.zip
Small optimization in 'project' from math.random
When computing the Mersenne number, instead of spreading 1's a fixed number of times (with shifts of 1, 2, 4, 8, 16, and 32), spread only until the number becomes a Mersenne number.
Diffstat (limited to 'lmathlib.c')
-rw-r--r--lmathlib.c30
1 files changed, 9 insertions, 21 deletions
diff --git a/lmathlib.c b/lmathlib.c
index a0981772..bd34c888 100644
--- a/lmathlib.c
+++ b/lmathlib.c
@@ -533,7 +533,7 @@ typedef struct {
533** Project the random integer 'ran' into the interval [0, n]. 533** Project the random integer 'ran' into the interval [0, n].
534** Because 'ran' has 2^B possible values, the projection can only be 534** Because 'ran' has 2^B possible values, the projection can only be
535** uniform when the size of the interval is a power of 2 (exact 535** uniform when the size of the interval is a power of 2 (exact
536** division). Otherwise, to get a uniform projection into [0, n], we 536** division). So, to get a uniform projection into [0, n], we
537** first compute 'lim', the smallest Mersenne number not smaller than 537** first compute 'lim', the smallest Mersenne number not smaller than
538** 'n'. We then project 'ran' into the interval [0, lim]. If the result 538** 'n'. We then project 'ran' into the interval [0, lim]. If the result
539** is inside [0, n], we are done. Otherwise, we try with another 'ran', 539** is inside [0, n], we are done. Otherwise, we try with another 'ran',
@@ -541,26 +541,14 @@ typedef struct {
541*/ 541*/
542static lua_Unsigned project (lua_Unsigned ran, lua_Unsigned n, 542static lua_Unsigned project (lua_Unsigned ran, lua_Unsigned n,
543 RanState *state) { 543 RanState *state) {
544 if ((n & (n + 1)) == 0) /* is 'n + 1' a power of 2? */ 544 lua_Unsigned lim = n; /* to compute the Mersenne number */
545 return ran & n; /* no bias */ 545 int sh; /* how much to spread bits to the right in 'lim' */
546 else { 546 /* spread '1' bits in 'lim' until it becomes a Mersenne number */
547 lua_Unsigned lim = n; 547 for (sh = 1; (lim & (lim + 1)) != 0; sh *= 2)
548 /* compute the smallest (2^b - 1) not smaller than 'n' */ 548 lim |= (lim >> sh); /* spread '1's to the right */
549 lim |= (lim >> 1); 549 while ((ran &= lim) > n) /* project 'ran' into [0..lim] and test */
550 lim |= (lim >> 2); 550 ran = I2UInt(nextrand(state->s)); /* not inside [0..n]? try again */
551 lim |= (lim >> 4); 551 return ran;
552 lim |= (lim >> 8);
553 lim |= (lim >> 16);
554#if (LUA_MAXUNSIGNED >> 31) >= 3
555 lim |= (lim >> 32); /* integer type has more than 32 bits */
556#endif
557 lua_assert((lim & (lim + 1)) == 0 /* 'lim + 1' is a power of 2, */
558 && lim >= n /* not smaller than 'n', */
559 && (lim >> 1) < n); /* and it is the smallest one */
560 while ((ran &= lim) > n) /* project 'ran' into [0..lim] */
561 ran = I2UInt(nextrand(state->s)); /* not inside [0..n]? try again */
562 return ran;
563 }
564} 552}
565 553
566 554