aboutsummaryrefslogtreecommitdiff
path: root/lmathlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-04-17 13:09:40 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-04-17 13:09:40 -0300
commitcbe4998bc29d5b98636f39cad5812c77a4fc2d77 (patch)
tree205eebeb126fb2de27b1f03927abd53f9f5cd26d /lmathlib.c
parent0172c9552cb3e93d75ddf07ede874293b7313104 (diff)
downloadlua-cbe4998bc29d5b98636f39cad5812c77a4fc2d77.tar.gz
lua-cbe4998bc29d5b98636f39cad5812c77a4fc2d77.tar.bz2
lua-cbe4998bc29d5b98636f39cad5812c77a4fc2d77.zip
'math.random(n,m)' interval restricted in size, to avoid using conversion
between 'double' and 'unsigned' (which can be slow and unreliable)
Diffstat (limited to 'lmathlib.c')
-rw-r--r--lmathlib.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/lmathlib.c b/lmathlib.c
index 6814b1e3..5d56a32f 100644
--- a/lmathlib.c
+++ b/lmathlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lmathlib.c,v 1.95 2014/04/03 14:18:19 roberto Exp roberto $ 2** $Id: lmathlib.c,v 1.97 2014/04/10 17:53:33 roberto Exp roberto $
3** Standard mathematical library 3** Standard mathematical library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -228,12 +228,14 @@ static int math_max (lua_State *L) {
228 return 1; 228 return 1;
229} 229}
230 230
231 231/*
232** This function uses 'double' (instead of 'lua_Number') to ensure that
233** all bits from 'l_rand' can be represented, and that 'RAND_MAX + 1.0'
234** will keep full precision (ensuring that 'r' is always less than 1.0.)
235*/
232static int math_random (lua_State *L) { 236static int math_random (lua_State *L) {
233 lua_Integer low, up; 237 lua_Integer low, up;
234 lua_Number r = (lua_Number)l_rand() * (1.0 / ((lua_Number)RAND_MAX + 1.0)); 238 double r = (double)l_rand() * (1.0 / ((double)RAND_MAX + 1.0));
235 if (r >= 1.0) /* can occur if lua_Number has no precision for RAND_MAX */
236 r = 0.0; /* statistically irrelevant; avoids out-of-range results */
237 switch (lua_gettop(L)) { /* check number of arguments */ 239 switch (lua_gettop(L)) { /* check number of arguments */
238 case 0: { /* no arguments */ 240 case 0: { /* no arguments */
239 lua_pushnumber(L, r); /* Number between 0 and 1 */ 241 lua_pushnumber(L, r); /* Number between 0 and 1 */
@@ -252,9 +254,11 @@ static int math_random (lua_State *L) {
252 default: return luaL_error(L, "wrong number of arguments"); 254 default: return luaL_error(L, "wrong number of arguments");
253 } 255 }
254 /* random integer in the interval [low, up] */ 256 /* random integer in the interval [low, up] */
255 luaL_argcheck(L, low <= up, 1, "interval is empty"); 257 luaL_argcheck(L, low <= up, 1, "interval is empty");
256 r *= ((lua_Number)((lua_Unsigned)up - (lua_Unsigned)low) + 1.0); 258 luaL_argcheck(L, (lua_Unsigned)up - low <= (lua_Unsigned)LUA_MAXINTEGER,
257 lua_pushinteger(L, (lua_Integer)((lua_Unsigned)r + (lua_Unsigned)low)); 259 1, "interval too large");
260 r *= (double)(up - low) + 1.0;
261 lua_pushinteger(L, (lua_Integer)r + low);
258 return 1; 262 return 1;
259} 263}
260 264