aboutsummaryrefslogtreecommitdiff
path: root/llimits.h
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-08-28 12:36:58 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-08-28 12:36:58 -0300
commit5382a22e0eea878339c504b2a9a3b36bcd839fcc (patch)
treef4208ffe221d2f42920c751c3624f17d89b07079 /llimits.h
parent8c8a91f2ef7acccb99e3737913faad8d48b39571 (diff)
downloadlua-5382a22e0eea878339c504b2a9a3b36bcd839fcc.tar.gz
lua-5382a22e0eea878339c504b2a9a3b36bcd839fcc.tar.bz2
lua-5382a22e0eea878339c504b2a9a3b36bcd839fcc.zip
Corrections in the implementation of '%' for floats.
The multiplication (m*b) used to test whether 'm' is non-zero and 'm' and 'b' have different signs can underflow for very small numbers, giving a wrong result. The use of explicit comparisons solves this problem. This commit also adds several new tests for '%' (both for floats and for integers) to exercise more corner cases, such as very large and very small values.
Diffstat (limited to 'llimits.h')
-rw-r--r--llimits.h14
1 files changed, 8 insertions, 6 deletions
diff --git a/llimits.h b/llimits.h
index 6afa8997..e91310a0 100644
--- a/llimits.h
+++ b/llimits.h
@@ -293,15 +293,17 @@ typedef unsigned long Instruction;
293#endif 293#endif
294 294
295/* 295/*
296** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when 296** modulo: defined as 'a - floor(a/b)*b'; the direct computation
297** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of 297** using this definition has several problems with rounding errors,
298** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b) 298** so it is better to use 'fmod'. 'fmod' gives the result of
299** ~= floor(a/b)'. That happens when the division has a non-integer 299** 'a - trunc(a/b)*b', and therefore must be corrected when
300** negative result, which is equivalent to the test below. 300** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a
301** non-integer negative result, which is equivalent to the tests below.
301*/ 302*/
302#if !defined(luai_nummod) 303#if !defined(luai_nummod)
303#define luai_nummod(L,a,b,m) \ 304#define luai_nummod(L,a,b,m) \
304 { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } 305 { (void)L; (m) = l_mathop(fmod)(a,b); \
306 if (((m) > 0) ? (b) < 0 : ((m) < 0 && (b) > 0)) (m) += (b); }
305#endif 307#endif
306 308
307/* exponentiation */ 309/* exponentiation */