diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-08-28 12:36:58 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-08-28 12:36:58 -0300 |
commit | 5382a22e0eea878339c504b2a9a3b36bcd839fcc (patch) | |
tree | f4208ffe221d2f42920c751c3624f17d89b07079 /llimits.h | |
parent | 8c8a91f2ef7acccb99e3737913faad8d48b39571 (diff) | |
download | lua-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.h | 14 |
1 files changed, 8 insertions, 6 deletions
@@ -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 */ |