diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-09 12:33:01 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-09 12:33:01 -0300 |
| commit | 7c519dfbd0c68b952f0849e01deaa3750e1f8153 (patch) | |
| tree | dde3ddbba310877db725df37a0d9f2cbe4e2a8f9 /testes/math.lua | |
| parent | f59e6a93c0ad38a27a420e51abf8f13d962446b5 (diff) | |
| download | lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.tar.gz lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.tar.bz2 lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.zip | |
Added manual and tests for version 5.4-w2
Diffstat (limited to 'testes/math.lua')
| -rw-r--r-- | testes/math.lua | 931 |
1 files changed, 931 insertions, 0 deletions
diff --git a/testes/math.lua b/testes/math.lua new file mode 100644 index 00000000..66998460 --- /dev/null +++ b/testes/math.lua | |||
| @@ -0,0 +1,931 @@ | |||
| 1 | -- $Id: math.lua,v 1.86 2018/05/09 14:55:52 roberto Exp $ | ||
| 2 | -- See Copyright Notice in file all.lua | ||
| 3 | |||
| 4 | print("testing numbers and math lib") | ||
| 5 | |||
| 6 | local minint = math.mininteger | ||
| 7 | local maxint = math.maxinteger | ||
| 8 | |||
| 9 | local intbits = math.floor(math.log(maxint, 2) + 0.5) + 1 | ||
| 10 | assert((1 << intbits) == 0) | ||
| 11 | |||
| 12 | assert(minint == 1 << (intbits - 1)) | ||
| 13 | assert(maxint == minint - 1) | ||
| 14 | |||
| 15 | -- number of bits in the mantissa of a floating-point number | ||
| 16 | local floatbits = 24 | ||
| 17 | do | ||
| 18 | local p = 2.0^floatbits | ||
| 19 | while p < p + 1.0 do | ||
| 20 | p = p * 2.0 | ||
| 21 | floatbits = floatbits + 1 | ||
| 22 | end | ||
| 23 | end | ||
| 24 | |||
| 25 | local function isNaN (x) | ||
| 26 | return (x ~= x) | ||
| 27 | end | ||
| 28 | |||
| 29 | assert(isNaN(0/0)) | ||
| 30 | assert(not isNaN(1/0)) | ||
| 31 | |||
| 32 | |||
| 33 | do | ||
| 34 | local x = 2.0^floatbits | ||
| 35 | assert(x > x - 1.0 and x == x + 1.0) | ||
| 36 | |||
| 37 | print(string.format("%d-bit integers, %d-bit (mantissa) floats", | ||
| 38 | intbits, floatbits)) | ||
| 39 | end | ||
| 40 | |||
| 41 | assert(math.type(0) == "integer" and math.type(0.0) == "float" | ||
| 42 | and math.type("10") == nil) | ||
| 43 | |||
| 44 | |||
| 45 | local function checkerror (msg, f, ...) | ||
| 46 | local s, err = pcall(f, ...) | ||
| 47 | assert(not s and string.find(err, msg)) | ||
| 48 | end | ||
| 49 | |||
| 50 | local msgf2i = "number.* has no integer representation" | ||
| 51 | |||
| 52 | -- float equality | ||
| 53 | function eq (a,b,limit) | ||
| 54 | if not limit then | ||
| 55 | if floatbits >= 50 then limit = 1E-11 | ||
| 56 | else limit = 1E-5 | ||
| 57 | end | ||
| 58 | end | ||
| 59 | -- a == b needed for +inf/-inf | ||
| 60 | return a == b or math.abs(a-b) <= limit | ||
| 61 | end | ||
| 62 | |||
| 63 | |||
| 64 | -- equality with types | ||
| 65 | function eqT (a,b) | ||
| 66 | return a == b and math.type(a) == math.type(b) | ||
| 67 | end | ||
| 68 | |||
| 69 | |||
| 70 | -- basic float notation | ||
| 71 | assert(0e12 == 0 and .0 == 0 and 0. == 0 and .2e2 == 20 and 2.E-1 == 0.2) | ||
| 72 | |||
| 73 | do | ||
| 74 | local a,b,c = "2", " 3e0 ", " 10 " | ||
| 75 | assert(a+b == 5 and -b == -3 and b+"2" == 5 and "10"-c == 0) | ||
| 76 | assert(type(a) == 'string' and type(b) == 'string' and type(c) == 'string') | ||
| 77 | assert(a == "2" and b == " 3e0 " and c == " 10 " and -c == -" 10 ") | ||
| 78 | assert(c%a == 0 and a^b == 08) | ||
| 79 | a = 0 | ||
| 80 | assert(a == -a and 0 == -0) | ||
| 81 | end | ||
| 82 | |||
| 83 | do | ||
| 84 | local x = -1 | ||
| 85 | local mz = 0/x -- minus zero | ||
| 86 | t = {[0] = 10, 20, 30, 40, 50} | ||
| 87 | assert(t[mz] == t[0] and t[-0] == t[0]) | ||
| 88 | end | ||
| 89 | |||
| 90 | do -- tests for 'modf' | ||
| 91 | local a,b = math.modf(3.5) | ||
| 92 | assert(a == 3.0 and b == 0.5) | ||
| 93 | a,b = math.modf(-2.5) | ||
| 94 | assert(a == -2.0 and b == -0.5) | ||
| 95 | a,b = math.modf(-3e23) | ||
| 96 | assert(a == -3e23 and b == 0.0) | ||
| 97 | a,b = math.modf(3e35) | ||
| 98 | assert(a == 3e35 and b == 0.0) | ||
| 99 | a,b = math.modf(-1/0) -- -inf | ||
| 100 | assert(a == -1/0 and b == 0.0) | ||
| 101 | a,b = math.modf(1/0) -- inf | ||
| 102 | assert(a == 1/0 and b == 0.0) | ||
| 103 | a,b = math.modf(0/0) -- NaN | ||
| 104 | assert(isNaN(a) and isNaN(b)) | ||
| 105 | a,b = math.modf(3) -- integer argument | ||
| 106 | assert(eqT(a, 3) and eqT(b, 0.0)) | ||
| 107 | a,b = math.modf(minint) | ||
| 108 | assert(eqT(a, minint) and eqT(b, 0.0)) | ||
| 109 | end | ||
| 110 | |||
| 111 | assert(math.huge > 10e30) | ||
| 112 | assert(-math.huge < -10e30) | ||
| 113 | |||
| 114 | |||
| 115 | -- integer arithmetic | ||
| 116 | assert(minint < minint + 1) | ||
| 117 | assert(maxint - 1 < maxint) | ||
| 118 | assert(0 - minint == minint) | ||
| 119 | assert(minint * minint == 0) | ||
| 120 | assert(maxint * maxint * maxint == maxint) | ||
| 121 | |||
| 122 | |||
| 123 | -- testing floor division and conversions | ||
| 124 | |||
| 125 | for _, i in pairs{-16, -15, -3, -2, -1, 0, 1, 2, 3, 15} do | ||
| 126 | for _, j in pairs{-16, -15, -3, -2, -1, 1, 2, 3, 15} do | ||
| 127 | for _, ti in pairs{0, 0.0} do -- try 'i' as integer and as float | ||
| 128 | for _, tj in pairs{0, 0.0} do -- try 'j' as integer and as float | ||
| 129 | local x = i + ti | ||
| 130 | local y = j + tj | ||
| 131 | assert(i//j == math.floor(i/j)) | ||
| 132 | end | ||
| 133 | end | ||
| 134 | end | ||
| 135 | end | ||
| 136 | |||
| 137 | assert(1//0.0 == 1/0) | ||
| 138 | assert(-1 // 0.0 == -1/0) | ||
| 139 | assert(eqT(3.5 // 1.5, 2.0)) | ||
| 140 | assert(eqT(3.5 // -1.5, -3.0)) | ||
| 141 | |||
| 142 | assert(maxint // maxint == 1) | ||
| 143 | assert(maxint // 1 == maxint) | ||
| 144 | assert((maxint - 1) // maxint == 0) | ||
| 145 | assert(maxint // (maxint - 1) == 1) | ||
| 146 | assert(minint // minint == 1) | ||
| 147 | assert(minint // minint == 1) | ||
| 148 | assert((minint + 1) // minint == 0) | ||
| 149 | assert(minint // (minint + 1) == 1) | ||
| 150 | assert(minint // 1 == minint) | ||
| 151 | |||
| 152 | assert(minint // -1 == -minint) | ||
| 153 | assert(minint // -2 == 2^(intbits - 2)) | ||
| 154 | assert(maxint // -1 == -maxint) | ||
| 155 | |||
| 156 | |||
| 157 | -- negative exponents | ||
| 158 | do | ||
| 159 | assert(2^-3 == 1 / 2^3) | ||
| 160 | assert(eq((-3)^-3, 1 / (-3)^3)) | ||
| 161 | for i = -3, 3 do -- variables avoid constant folding | ||
| 162 | for j = -3, 3 do | ||
| 163 | -- domain errors (0^(-n)) are not portable | ||
| 164 | if not _port or i ~= 0 or j > 0 then | ||
| 165 | assert(eq(i^j, 1 / i^(-j))) | ||
| 166 | end | ||
| 167 | end | ||
| 168 | end | ||
| 169 | end | ||
| 170 | |||
| 171 | -- comparison between floats and integers (border cases) | ||
| 172 | if floatbits < intbits then | ||
| 173 | assert(2.0^floatbits == (1 << floatbits)) | ||
| 174 | assert(2.0^floatbits - 1.0 == (1 << floatbits) - 1.0) | ||
| 175 | assert(2.0^floatbits - 1.0 ~= (1 << floatbits)) | ||
| 176 | -- float is rounded, int is not | ||
| 177 | assert(2.0^floatbits + 1.0 ~= (1 << floatbits) + 1) | ||
| 178 | else -- floats can express all integers with full accuracy | ||
| 179 | assert(maxint == maxint + 0.0) | ||
| 180 | assert(maxint - 1 == maxint - 1.0) | ||
| 181 | assert(minint + 1 == minint + 1.0) | ||
| 182 | assert(maxint ~= maxint - 1.0) | ||
| 183 | end | ||
| 184 | assert(maxint + 0.0 == 2.0^(intbits - 1) - 1.0) | ||
| 185 | assert(minint + 0.0 == minint) | ||
| 186 | assert(minint + 0.0 == -2.0^(intbits - 1)) | ||
| 187 | |||
| 188 | |||
| 189 | -- order between floats and integers | ||
| 190 | assert(1 < 1.1); assert(not (1 < 0.9)) | ||
| 191 | assert(1 <= 1.1); assert(not (1 <= 0.9)) | ||
| 192 | assert(-1 < -0.9); assert(not (-1 < -1.1)) | ||
| 193 | assert(1 <= 1.1); assert(not (-1 <= -1.1)) | ||
| 194 | assert(-1 < -0.9); assert(not (-1 < -1.1)) | ||
| 195 | assert(-1 <= -0.9); assert(not (-1 <= -1.1)) | ||
| 196 | assert(minint <= minint + 0.0) | ||
| 197 | assert(minint + 0.0 <= minint) | ||
| 198 | assert(not (minint < minint + 0.0)) | ||
| 199 | assert(not (minint + 0.0 < minint)) | ||
| 200 | assert(maxint < minint * -1.0) | ||
| 201 | assert(maxint <= minint * -1.0) | ||
| 202 | |||
| 203 | do | ||
| 204 | local fmaxi1 = 2^(intbits - 1) | ||
| 205 | assert(maxint < fmaxi1) | ||
| 206 | assert(maxint <= fmaxi1) | ||
| 207 | assert(not (fmaxi1 <= maxint)) | ||
| 208 | assert(minint <= -2^(intbits - 1)) | ||
| 209 | assert(-2^(intbits - 1) <= minint) | ||
| 210 | end | ||
| 211 | |||
| 212 | if floatbits < intbits then | ||
| 213 | print("testing order (floats cannot represent all integers)") | ||
| 214 | local fmax = 2^floatbits | ||
| 215 | local ifmax = fmax | 0 | ||
| 216 | assert(fmax < ifmax + 1) | ||
| 217 | assert(fmax - 1 < ifmax) | ||
| 218 | assert(-(fmax - 1) > -ifmax) | ||
| 219 | assert(not (fmax <= ifmax - 1)) | ||
| 220 | assert(-fmax > -(ifmax + 1)) | ||
| 221 | assert(not (-fmax >= -(ifmax - 1))) | ||
| 222 | |||
| 223 | assert(fmax/2 - 0.5 < ifmax//2) | ||
| 224 | assert(-(fmax/2 - 0.5) > -ifmax//2) | ||
| 225 | |||
| 226 | assert(maxint < 2^intbits) | ||
| 227 | assert(minint > -2^intbits) | ||
| 228 | assert(maxint <= 2^intbits) | ||
| 229 | assert(minint >= -2^intbits) | ||
| 230 | else | ||
| 231 | print("testing order (floats can represent all integers)") | ||
| 232 | assert(maxint < maxint + 1.0) | ||
| 233 | assert(maxint < maxint + 0.5) | ||
| 234 | assert(maxint - 1.0 < maxint) | ||
| 235 | assert(maxint - 0.5 < maxint) | ||
| 236 | assert(not (maxint + 0.0 < maxint)) | ||
| 237 | assert(maxint + 0.0 <= maxint) | ||
| 238 | assert(not (maxint < maxint + 0.0)) | ||
| 239 | assert(maxint + 0.0 <= maxint) | ||
| 240 | assert(maxint <= maxint + 0.0) | ||
| 241 | assert(not (maxint + 1.0 <= maxint)) | ||
| 242 | assert(not (maxint + 0.5 <= maxint)) | ||
| 243 | assert(not (maxint <= maxint - 1.0)) | ||
| 244 | assert(not (maxint <= maxint - 0.5)) | ||
| 245 | |||
| 246 | assert(minint < minint + 1.0) | ||
| 247 | assert(minint < minint + 0.5) | ||
| 248 | assert(minint <= minint + 0.5) | ||
| 249 | assert(minint - 1.0 < minint) | ||
| 250 | assert(minint - 1.0 <= minint) | ||
| 251 | assert(not (minint + 0.0 < minint)) | ||
| 252 | assert(not (minint + 0.5 < minint)) | ||
| 253 | assert(not (minint < minint + 0.0)) | ||
| 254 | assert(minint + 0.0 <= minint) | ||
| 255 | assert(minint <= minint + 0.0) | ||
| 256 | assert(not (minint + 1.0 <= minint)) | ||
| 257 | assert(not (minint + 0.5 <= minint)) | ||
| 258 | assert(not (minint <= minint - 1.0)) | ||
| 259 | end | ||
| 260 | |||
| 261 | do | ||
| 262 | local NaN = 0/0 | ||
| 263 | assert(not (NaN < 0)) | ||
| 264 | assert(not (NaN > minint)) | ||
| 265 | assert(not (NaN <= -9)) | ||
| 266 | assert(not (NaN <= maxint)) | ||
| 267 | assert(not (NaN < maxint)) | ||
| 268 | assert(not (minint <= NaN)) | ||
| 269 | assert(not (minint < NaN)) | ||
| 270 | assert(not (4 <= NaN)) | ||
| 271 | assert(not (4 < NaN)) | ||
| 272 | end | ||
| 273 | |||
| 274 | |||
| 275 | -- avoiding errors at compile time | ||
| 276 | local function checkcompt (msg, code) | ||
| 277 | checkerror(msg, assert(load(code))) | ||
| 278 | end | ||
| 279 | checkcompt("divide by zero", "return 2 // 0") | ||
| 280 | checkcompt(msgf2i, "return 2.3 >> 0") | ||
| 281 | checkcompt(msgf2i, ("return 2.0^%d & 1"):format(intbits - 1)) | ||
| 282 | checkcompt("field 'huge'", "return math.huge << 1") | ||
| 283 | checkcompt(msgf2i, ("return 1 | 2.0^%d"):format(intbits - 1)) | ||
| 284 | checkcompt(msgf2i, "return 2.3 ~ 0.0") | ||
| 285 | |||
| 286 | |||
| 287 | -- testing overflow errors when converting from float to integer (runtime) | ||
| 288 | local function f2i (x) return x | x end | ||
| 289 | checkerror(msgf2i, f2i, math.huge) -- +inf | ||
| 290 | checkerror(msgf2i, f2i, -math.huge) -- -inf | ||
| 291 | checkerror(msgf2i, f2i, 0/0) -- NaN | ||
| 292 | |||
| 293 | if floatbits < intbits then | ||
| 294 | -- conversion tests when float cannot represent all integers | ||
| 295 | assert(maxint + 1.0 == maxint + 0.0) | ||
| 296 | assert(minint - 1.0 == minint + 0.0) | ||
| 297 | checkerror(msgf2i, f2i, maxint + 0.0) | ||
| 298 | assert(f2i(2.0^(intbits - 2)) == 1 << (intbits - 2)) | ||
| 299 | assert(f2i(-2.0^(intbits - 2)) == -(1 << (intbits - 2))) | ||
| 300 | assert((2.0^(floatbits - 1) + 1.0) // 1 == (1 << (floatbits - 1)) + 1) | ||
| 301 | -- maximum integer representable as a float | ||
| 302 | local mf = maxint - (1 << (floatbits - intbits)) + 1 | ||
| 303 | assert(f2i(mf + 0.0) == mf) -- OK up to here | ||
| 304 | mf = mf + 1 | ||
| 305 | assert(f2i(mf + 0.0) ~= mf) -- no more representable | ||
| 306 | else | ||
| 307 | -- conversion tests when float can represent all integers | ||
| 308 | assert(maxint + 1.0 > maxint) | ||
| 309 | assert(minint - 1.0 < minint) | ||
| 310 | assert(f2i(maxint + 0.0) == maxint) | ||
| 311 | checkerror("no integer rep", f2i, maxint + 1.0) | ||
| 312 | checkerror("no integer rep", f2i, minint - 1.0) | ||
| 313 | end | ||
| 314 | |||
| 315 | -- 'minint' should be representable as a float no matter the precision | ||
| 316 | assert(f2i(minint + 0.0) == minint) | ||
| 317 | |||
| 318 | |||
| 319 | -- testing numeric strings | ||
| 320 | |||
| 321 | assert("2" + 1 == 3) | ||
| 322 | assert("2 " + 1 == 3) | ||
| 323 | assert(" -2 " + 1 == -1) | ||
| 324 | assert(" -0xa " + 1 == -9) | ||
| 325 | |||
| 326 | |||
| 327 | -- Literal integer Overflows (new behavior in 5.3.3) | ||
| 328 | do | ||
| 329 | -- no overflows | ||
| 330 | assert(eqT(tonumber(tostring(maxint)), maxint)) | ||
| 331 | assert(eqT(tonumber(tostring(minint)), minint)) | ||
| 332 | |||
| 333 | -- add 1 to last digit as a string (it cannot be 9...) | ||
| 334 | local function incd (n) | ||
| 335 | local s = string.format("%d", n) | ||
| 336 | s = string.gsub(s, "%d$", function (d) | ||
| 337 | assert(d ~= '9') | ||
| 338 | return string.char(string.byte(d) + 1) | ||
| 339 | end) | ||
| 340 | return s | ||
| 341 | end | ||
| 342 | |||
| 343 | -- 'tonumber' with overflow by 1 | ||
| 344 | assert(eqT(tonumber(incd(maxint)), maxint + 1.0)) | ||
| 345 | assert(eqT(tonumber(incd(minint)), minint - 1.0)) | ||
| 346 | |||
| 347 | -- large numbers | ||
| 348 | assert(eqT(tonumber("1"..string.rep("0", 30)), 1e30)) | ||
| 349 | assert(eqT(tonumber("-1"..string.rep("0", 30)), -1e30)) | ||
| 350 | |||
| 351 | -- hexa format still wraps around | ||
| 352 | assert(eqT(tonumber("0x1"..string.rep("0", 30)), 0)) | ||
| 353 | |||
| 354 | -- lexer in the limits | ||
| 355 | assert(minint == load("return " .. minint)()) | ||
| 356 | assert(eqT(maxint, load("return " .. maxint)())) | ||
| 357 | |||
| 358 | assert(eqT(10000000000000000000000.0, 10000000000000000000000)) | ||
| 359 | assert(eqT(-10000000000000000000000.0, -10000000000000000000000)) | ||
| 360 | end | ||
| 361 | |||
| 362 | |||
| 363 | -- testing 'tonumber' | ||
| 364 | |||
| 365 | -- 'tonumber' with numbers | ||
| 366 | assert(tonumber(3.4) == 3.4) | ||
| 367 | assert(eqT(tonumber(3), 3)) | ||
| 368 | assert(eqT(tonumber(maxint), maxint) and eqT(tonumber(minint), minint)) | ||
| 369 | assert(tonumber(1/0) == 1/0) | ||
| 370 | |||
| 371 | -- 'tonumber' with strings | ||
| 372 | assert(tonumber("0") == 0) | ||
| 373 | assert(tonumber("") == nil) | ||
| 374 | assert(tonumber(" ") == nil) | ||
| 375 | assert(tonumber("-") == nil) | ||
| 376 | assert(tonumber(" -0x ") == nil) | ||
| 377 | assert(tonumber{} == nil) | ||
| 378 | assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and | ||
| 379 | tonumber'.01' == 0.01 and tonumber'-1.' == -1 and | ||
| 380 | tonumber'+1.' == 1) | ||
| 381 | assert(tonumber'+ 0.01' == nil and tonumber'+.e1' == nil and | ||
| 382 | tonumber'1e' == nil and tonumber'1.0e+' == nil and | ||
| 383 | tonumber'.' == nil) | ||
| 384 | assert(tonumber('-012') == -010-2) | ||
| 385 | assert(tonumber('-1.2e2') == - - -120) | ||
| 386 | |||
| 387 | assert(tonumber("0xffffffffffff") == (1 << (4*12)) - 1) | ||
| 388 | assert(tonumber("0x"..string.rep("f", (intbits//4))) == -1) | ||
| 389 | assert(tonumber("-0x"..string.rep("f", (intbits//4))) == 1) | ||
| 390 | |||
| 391 | -- testing 'tonumber' with base | ||
| 392 | assert(tonumber(' 001010 ', 2) == 10) | ||
| 393 | assert(tonumber(' 001010 ', 10) == 001010) | ||
| 394 | assert(tonumber(' -1010 ', 2) == -10) | ||
| 395 | assert(tonumber('10', 36) == 36) | ||
| 396 | assert(tonumber(' -10 ', 36) == -36) | ||
| 397 | assert(tonumber(' +1Z ', 36) == 36 + 35) | ||
| 398 | assert(tonumber(' -1z ', 36) == -36 + -35) | ||
| 399 | assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15))))))) | ||
| 400 | assert(tonumber(string.rep('1', (intbits - 2)), 2) + 1 == 2^(intbits - 2)) | ||
| 401 | assert(tonumber('ffffFFFF', 16)+1 == (1 << 32)) | ||
| 402 | assert(tonumber('0ffffFFFF', 16)+1 == (1 << 32)) | ||
| 403 | assert(tonumber('-0ffffffFFFF', 16) - 1 == -(1 << 40)) | ||
| 404 | for i = 2,36 do | ||
| 405 | local i2 = i * i | ||
| 406 | local i10 = i2 * i2 * i2 * i2 * i2 -- i^10 | ||
| 407 | assert(tonumber('\t10000000000\t', i) == i10) | ||
| 408 | end | ||
| 409 | |||
| 410 | if not _soft then | ||
| 411 | -- tests with very long numerals | ||
| 412 | assert(tonumber("0x"..string.rep("f", 13)..".0") == 2.0^(4*13) - 1) | ||
| 413 | assert(tonumber("0x"..string.rep("f", 150)..".0") == 2.0^(4*150) - 1) | ||
| 414 | assert(tonumber("0x"..string.rep("f", 300)..".0") == 2.0^(4*300) - 1) | ||
| 415 | assert(tonumber("0x"..string.rep("f", 500)..".0") == 2.0^(4*500) - 1) | ||
| 416 | assert(tonumber('0x3.' .. string.rep('0', 1000)) == 3) | ||
| 417 | assert(tonumber('0x' .. string.rep('0', 1000) .. 'a') == 10) | ||
| 418 | assert(tonumber('0x0.' .. string.rep('0', 13).."1") == 2.0^(-4*14)) | ||
| 419 | assert(tonumber('0x0.' .. string.rep('0', 150).."1") == 2.0^(-4*151)) | ||
| 420 | assert(tonumber('0x0.' .. string.rep('0', 300).."1") == 2.0^(-4*301)) | ||
| 421 | assert(tonumber('0x0.' .. string.rep('0', 500).."1") == 2.0^(-4*501)) | ||
| 422 | |||
| 423 | assert(tonumber('0xe03' .. string.rep('0', 1000) .. 'p-4000') == 3587.0) | ||
| 424 | assert(tonumber('0x.' .. string.rep('0', 1000) .. '74p4004') == 0x7.4) | ||
| 425 | end | ||
| 426 | |||
| 427 | -- testing 'tonumber' for invalid formats | ||
| 428 | |||
| 429 | local function f (...) | ||
| 430 | if select('#', ...) == 1 then | ||
| 431 | return (...) | ||
| 432 | else | ||
| 433 | return "***" | ||
| 434 | end | ||
| 435 | end | ||
| 436 | |||
| 437 | assert(f(tonumber('fFfa', 15)) == nil) | ||
| 438 | assert(f(tonumber('099', 8)) == nil) | ||
| 439 | assert(f(tonumber('1\0', 2)) == nil) | ||
| 440 | assert(f(tonumber('', 8)) == nil) | ||
| 441 | assert(f(tonumber(' ', 9)) == nil) | ||
| 442 | assert(f(tonumber(' ', 9)) == nil) | ||
| 443 | assert(f(tonumber('0xf', 10)) == nil) | ||
| 444 | |||
| 445 | assert(f(tonumber('inf')) == nil) | ||
| 446 | assert(f(tonumber(' INF ')) == nil) | ||
| 447 | assert(f(tonumber('Nan')) == nil) | ||
| 448 | assert(f(tonumber('nan')) == nil) | ||
| 449 | |||
| 450 | assert(f(tonumber(' ')) == nil) | ||
| 451 | assert(f(tonumber('')) == nil) | ||
| 452 | assert(f(tonumber('1 a')) == nil) | ||
| 453 | assert(f(tonumber('1 a', 2)) == nil) | ||
| 454 | assert(f(tonumber('1\0')) == nil) | ||
| 455 | assert(f(tonumber('1 \0')) == nil) | ||
| 456 | assert(f(tonumber('1\0 ')) == nil) | ||
| 457 | assert(f(tonumber('e1')) == nil) | ||
| 458 | assert(f(tonumber('e 1')) == nil) | ||
| 459 | assert(f(tonumber(' 3.4.5 ')) == nil) | ||
| 460 | |||
| 461 | |||
| 462 | -- testing 'tonumber' for invalid hexadecimal formats | ||
| 463 | |||
| 464 | assert(tonumber('0x') == nil) | ||
| 465 | assert(tonumber('x') == nil) | ||
| 466 | assert(tonumber('x3') == nil) | ||
| 467 | assert(tonumber('0x3.3.3') == nil) -- two decimal points | ||
| 468 | assert(tonumber('00x2') == nil) | ||
| 469 | assert(tonumber('0x 2') == nil) | ||
| 470 | assert(tonumber('0 x2') == nil) | ||
| 471 | assert(tonumber('23x') == nil) | ||
| 472 | assert(tonumber('- 0xaa') == nil) | ||
| 473 | assert(tonumber('-0xaaP ') == nil) -- no exponent | ||
| 474 | assert(tonumber('0x0.51p') == nil) | ||
| 475 | assert(tonumber('0x5p+-2') == nil) | ||
| 476 | |||
| 477 | |||
| 478 | -- testing hexadecimal numerals | ||
| 479 | |||
| 480 | assert(0x10 == 16 and 0xfff == 2^12 - 1 and 0XFB == 251) | ||
| 481 | assert(0x0p12 == 0 and 0x.0p-3 == 0) | ||
| 482 | assert(0xFFFFFFFF == (1 << 32) - 1) | ||
| 483 | assert(tonumber('+0x2') == 2) | ||
| 484 | assert(tonumber('-0xaA') == -170) | ||
| 485 | assert(tonumber('-0xffFFFfff') == -(1 << 32) + 1) | ||
| 486 | |||
| 487 | -- possible confusion with decimal exponent | ||
| 488 | assert(0E+1 == 0 and 0xE+1 == 15 and 0xe-1 == 13) | ||
| 489 | |||
| 490 | |||
| 491 | -- floating hexas | ||
| 492 | |||
| 493 | assert(tonumber(' 0x2.5 ') == 0x25/16) | ||
| 494 | assert(tonumber(' -0x2.5 ') == -0x25/16) | ||
| 495 | assert(tonumber(' +0x0.51p+8 ') == 0x51) | ||
| 496 | assert(0x.FfffFFFF == 1 - '0x.00000001') | ||
| 497 | assert('0xA.a' + 0 == 10 + 10/16) | ||
| 498 | assert(0xa.aP4 == 0XAA) | ||
| 499 | assert(0x4P-2 == 1) | ||
| 500 | assert(0x1.1 == '0x1.' + '+0x.1') | ||
| 501 | assert(0Xabcdef.0 == 0x.ABCDEFp+24) | ||
| 502 | |||
| 503 | |||
| 504 | assert(1.1 == 1.+.1) | ||
| 505 | assert(100.0 == 1E2 and .01 == 1e-2) | ||
| 506 | assert(1111111111 - 1111111110 == 1000.00e-03) | ||
| 507 | assert(1.1 == '1.'+'.1') | ||
| 508 | assert(tonumber'1111111111' - tonumber'1111111110' == | ||
| 509 | tonumber" +0.001e+3 \n\t") | ||
| 510 | |||
| 511 | assert(0.1e-30 > 0.9E-31 and 0.9E30 < 0.1e31) | ||
| 512 | |||
| 513 | assert(0.123456 > 0.123455) | ||
| 514 | |||
| 515 | assert(tonumber('+1.23E18') == 1.23*10.0^18) | ||
| 516 | |||
| 517 | -- testing order operators | ||
| 518 | assert(not(1<1) and (1<2) and not(2<1)) | ||
| 519 | assert(not('a'<'a') and ('a'<'b') and not('b'<'a')) | ||
| 520 | assert((1<=1) and (1<=2) and not(2<=1)) | ||
| 521 | assert(('a'<='a') and ('a'<='b') and not('b'<='a')) | ||
| 522 | assert(not(1>1) and not(1>2) and (2>1)) | ||
| 523 | assert(not('a'>'a') and not('a'>'b') and ('b'>'a')) | ||
| 524 | assert((1>=1) and not(1>=2) and (2>=1)) | ||
| 525 | assert(('a'>='a') and not('a'>='b') and ('b'>='a')) | ||
| 526 | assert(1.3 < 1.4 and 1.3 <= 1.4 and not (1.3 < 1.3) and 1.3 <= 1.3) | ||
| 527 | |||
| 528 | -- testing mod operator | ||
| 529 | assert(eqT(-4 % 3, 2)) | ||
| 530 | assert(eqT(4 % -3, -2)) | ||
| 531 | assert(eqT(-4.0 % 3, 2.0)) | ||
| 532 | assert(eqT(4 % -3.0, -2.0)) | ||
| 533 | assert(math.pi - math.pi % 1 == 3) | ||
| 534 | assert(math.pi - math.pi % 0.001 == 3.141) | ||
| 535 | |||
| 536 | assert(eqT(minint % minint, 0)) | ||
| 537 | assert(eqT(maxint % maxint, 0)) | ||
| 538 | assert((minint + 1) % minint == minint + 1) | ||
| 539 | assert((maxint - 1) % maxint == maxint - 1) | ||
| 540 | assert(minint % maxint == maxint - 1) | ||
| 541 | |||
| 542 | assert(minint % -1 == 0) | ||
| 543 | assert(minint % -2 == 0) | ||
| 544 | assert(maxint % -2 == -1) | ||
| 545 | |||
| 546 | -- non-portable tests because Windows C library cannot compute | ||
| 547 | -- fmod(1, huge) correctly | ||
| 548 | if not _port then | ||
| 549 | local function anan (x) assert(isNaN(x)) end -- assert Not a Number | ||
| 550 | anan(0.0 % 0) | ||
| 551 | anan(1.3 % 0) | ||
| 552 | anan(math.huge % 1) | ||
| 553 | anan(math.huge % 1e30) | ||
| 554 | anan(-math.huge % 1e30) | ||
| 555 | anan(-math.huge % -1e30) | ||
| 556 | assert(1 % math.huge == 1) | ||
| 557 | assert(1e30 % math.huge == 1e30) | ||
| 558 | assert(1e30 % -math.huge == -math.huge) | ||
| 559 | assert(-1 % math.huge == math.huge) | ||
| 560 | assert(-1 % -math.huge == -1) | ||
| 561 | end | ||
| 562 | |||
| 563 | |||
| 564 | -- testing unsigned comparisons | ||
| 565 | assert(math.ult(3, 4)) | ||
| 566 | assert(not math.ult(4, 4)) | ||
| 567 | assert(math.ult(-2, -1)) | ||
| 568 | assert(math.ult(2, -1)) | ||
| 569 | assert(not math.ult(-2, -2)) | ||
| 570 | assert(math.ult(maxint, minint)) | ||
| 571 | assert(not math.ult(minint, maxint)) | ||
| 572 | |||
| 573 | |||
| 574 | assert(eq(math.sin(-9.8)^2 + math.cos(-9.8)^2, 1)) | ||
| 575 | assert(eq(math.tan(math.pi/4), 1)) | ||
| 576 | assert(eq(math.sin(math.pi/2), 1) and eq(math.cos(math.pi/2), 0)) | ||
| 577 | assert(eq(math.atan(1), math.pi/4) and eq(math.acos(0), math.pi/2) and | ||
| 578 | eq(math.asin(1), math.pi/2)) | ||
| 579 | assert(eq(math.deg(math.pi/2), 90) and eq(math.rad(90), math.pi/2)) | ||
| 580 | assert(math.abs(-10.43) == 10.43) | ||
| 581 | assert(eqT(math.abs(minint), minint)) | ||
| 582 | assert(eqT(math.abs(maxint), maxint)) | ||
| 583 | assert(eqT(math.abs(-maxint), maxint)) | ||
| 584 | assert(eq(math.atan(1,0), math.pi/2)) | ||
| 585 | assert(math.fmod(10,3) == 1) | ||
| 586 | assert(eq(math.sqrt(10)^2, 10)) | ||
| 587 | assert(eq(math.log(2, 10), math.log(2)/math.log(10))) | ||
| 588 | assert(eq(math.log(2, 2), 1)) | ||
| 589 | assert(eq(math.log(9, 3), 2)) | ||
| 590 | assert(eq(math.exp(0), 1)) | ||
| 591 | assert(eq(math.sin(10), math.sin(10%(2*math.pi)))) | ||
| 592 | |||
| 593 | |||
| 594 | assert(tonumber(' 1.3e-2 ') == 1.3e-2) | ||
| 595 | assert(tonumber(' -1.00000000000001 ') == -1.00000000000001) | ||
| 596 | |||
| 597 | -- testing constant limits | ||
| 598 | -- 2^23 = 8388608 | ||
| 599 | assert(8388609 + -8388609 == 0) | ||
| 600 | assert(8388608 + -8388608 == 0) | ||
| 601 | assert(8388607 + -8388607 == 0) | ||
| 602 | |||
| 603 | |||
| 604 | |||
| 605 | do -- testing floor & ceil | ||
| 606 | assert(eqT(math.floor(3.4), 3)) | ||
| 607 | assert(eqT(math.ceil(3.4), 4)) | ||
| 608 | assert(eqT(math.floor(-3.4), -4)) | ||
| 609 | assert(eqT(math.ceil(-3.4), -3)) | ||
| 610 | assert(eqT(math.floor(maxint), maxint)) | ||
| 611 | assert(eqT(math.ceil(maxint), maxint)) | ||
| 612 | assert(eqT(math.floor(minint), minint)) | ||
| 613 | assert(eqT(math.floor(minint + 0.0), minint)) | ||
| 614 | assert(eqT(math.ceil(minint), minint)) | ||
| 615 | assert(eqT(math.ceil(minint + 0.0), minint)) | ||
| 616 | assert(math.floor(1e50) == 1e50) | ||
| 617 | assert(math.ceil(1e50) == 1e50) | ||
| 618 | assert(math.floor(-1e50) == -1e50) | ||
| 619 | assert(math.ceil(-1e50) == -1e50) | ||
| 620 | for _, p in pairs{31,32,63,64} do | ||
| 621 | assert(math.floor(2^p) == 2^p) | ||
| 622 | assert(math.floor(2^p + 0.5) == 2^p) | ||
| 623 | assert(math.ceil(2^p) == 2^p) | ||
| 624 | assert(math.ceil(2^p - 0.5) == 2^p) | ||
| 625 | end | ||
| 626 | checkerror("number expected", math.floor, {}) | ||
| 627 | checkerror("number expected", math.ceil, print) | ||
| 628 | assert(eqT(math.tointeger(minint), minint)) | ||
| 629 | assert(eqT(math.tointeger(minint .. ""), minint)) | ||
| 630 | assert(eqT(math.tointeger(maxint), maxint)) | ||
| 631 | assert(eqT(math.tointeger(maxint .. ""), maxint)) | ||
| 632 | assert(eqT(math.tointeger(minint + 0.0), minint)) | ||
| 633 | assert(math.tointeger(0.0 - minint) == nil) | ||
| 634 | assert(math.tointeger(math.pi) == nil) | ||
| 635 | assert(math.tointeger(-math.pi) == nil) | ||
| 636 | assert(math.floor(math.huge) == math.huge) | ||
| 637 | assert(math.ceil(math.huge) == math.huge) | ||
| 638 | assert(math.tointeger(math.huge) == nil) | ||
| 639 | assert(math.floor(-math.huge) == -math.huge) | ||
| 640 | assert(math.ceil(-math.huge) == -math.huge) | ||
| 641 | assert(math.tointeger(-math.huge) == nil) | ||
| 642 | assert(math.tointeger("34.0") == 34) | ||
| 643 | assert(math.tointeger("34.3") == nil) | ||
| 644 | assert(math.tointeger({}) == nil) | ||
| 645 | assert(math.tointeger(0/0) == nil) -- NaN | ||
| 646 | end | ||
| 647 | |||
| 648 | |||
| 649 | -- testing fmod for integers | ||
| 650 | for i = -6, 6 do | ||
| 651 | for j = -6, 6 do | ||
| 652 | if j ~= 0 then | ||
| 653 | local mi = math.fmod(i, j) | ||
| 654 | local mf = math.fmod(i + 0.0, j) | ||
| 655 | assert(mi == mf) | ||
| 656 | assert(math.type(mi) == 'integer' and math.type(mf) == 'float') | ||
| 657 | if (i >= 0 and j >= 0) or (i <= 0 and j <= 0) or mi == 0 then | ||
| 658 | assert(eqT(mi, i % j)) | ||
| 659 | end | ||
| 660 | end | ||
| 661 | end | ||
| 662 | end | ||
| 663 | assert(eqT(math.fmod(minint, minint), 0)) | ||
| 664 | assert(eqT(math.fmod(maxint, maxint), 0)) | ||
| 665 | assert(eqT(math.fmod(minint + 1, minint), minint + 1)) | ||
| 666 | assert(eqT(math.fmod(maxint - 1, maxint), maxint - 1)) | ||
| 667 | |||
| 668 | checkerror("zero", math.fmod, 3, 0) | ||
| 669 | |||
| 670 | |||
| 671 | do -- testing max/min | ||
| 672 | checkerror("value expected", math.max) | ||
| 673 | checkerror("value expected", math.min) | ||
| 674 | assert(eqT(math.max(3), 3)) | ||
| 675 | assert(eqT(math.max(3, 5, 9, 1), 9)) | ||
| 676 | assert(math.max(maxint, 10e60) == 10e60) | ||
| 677 | assert(eqT(math.max(minint, minint + 1), minint + 1)) | ||
| 678 | assert(eqT(math.min(3), 3)) | ||
| 679 | assert(eqT(math.min(3, 5, 9, 1), 1)) | ||
| 680 | assert(math.min(3.2, 5.9, -9.2, 1.1) == -9.2) | ||
| 681 | assert(math.min(1.9, 1.7, 1.72) == 1.7) | ||
| 682 | assert(math.min(-10e60, minint) == -10e60) | ||
| 683 | assert(eqT(math.min(maxint, maxint - 1), maxint - 1)) | ||
| 684 | assert(eqT(math.min(maxint - 2, maxint, maxint - 1), maxint - 2)) | ||
| 685 | end | ||
| 686 | -- testing implicit convertions | ||
| 687 | |||
| 688 | local a,b = '10', '20' | ||
| 689 | assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20) | ||
| 690 | assert(a == '10' and b == '20') | ||
| 691 | |||
| 692 | |||
| 693 | do | ||
| 694 | print("testing -0 and NaN") | ||
| 695 | local mz, z = -0.0, 0.0 | ||
| 696 | assert(mz == z) | ||
| 697 | assert(1/mz < 0 and 0 < 1/z) | ||
| 698 | local a = {[mz] = 1} | ||
| 699 | assert(a[z] == 1 and a[mz] == 1) | ||
| 700 | a[z] = 2 | ||
| 701 | assert(a[z] == 2 and a[mz] == 2) | ||
| 702 | local inf = math.huge * 2 + 1 | ||
| 703 | mz, z = -1/inf, 1/inf | ||
| 704 | assert(mz == z) | ||
| 705 | assert(1/mz < 0 and 0 < 1/z) | ||
| 706 | local NaN = inf - inf | ||
| 707 | assert(NaN ~= NaN) | ||
| 708 | assert(not (NaN < NaN)) | ||
| 709 | assert(not (NaN <= NaN)) | ||
| 710 | assert(not (NaN > NaN)) | ||
| 711 | assert(not (NaN >= NaN)) | ||
| 712 | assert(not (0 < NaN) and not (NaN < 0)) | ||
| 713 | local NaN1 = 0/0 | ||
| 714 | assert(NaN ~= NaN1 and not (NaN <= NaN1) and not (NaN1 <= NaN)) | ||
| 715 | local a = {} | ||
| 716 | assert(not pcall(rawset, a, NaN, 1)) | ||
| 717 | assert(a[NaN] == undef) | ||
| 718 | a[1] = 1 | ||
| 719 | assert(not pcall(rawset, a, NaN, 1)) | ||
| 720 | assert(a[NaN] == undef) | ||
| 721 | -- strings with same binary representation as 0.0 (might create problems | ||
| 722 | -- for constant manipulation in the pre-compiler) | ||
| 723 | local a1, a2, a3, a4, a5 = 0, 0, "\0\0\0\0\0\0\0\0", 0, "\0\0\0\0\0\0\0\0" | ||
| 724 | assert(a1 == a2 and a2 == a4 and a1 ~= a3) | ||
| 725 | assert(a3 == a5) | ||
| 726 | end | ||
| 727 | |||
| 728 | |||
| 729 | print("testing 'math.random'") | ||
| 730 | |||
| 731 | local random, max, min = math.random, math.max, math.min | ||
| 732 | |||
| 733 | local function testnear (val, ref, tol) | ||
| 734 | return (math.abs(val - ref) < ref * tol) | ||
| 735 | end | ||
| 736 | |||
| 737 | |||
| 738 | -- low-level!! For the current implementation of random in Lua, | ||
| 739 | -- the first call after seed 1007 should return 0x7a7040a5a323c9d6 | ||
| 740 | do | ||
| 741 | -- all computations assume at most 32-bit integers | ||
| 742 | local h = 0x7a7040a5 -- higher half | ||
| 743 | local l = 0xa323c9d6 -- lower half | ||
| 744 | |||
| 745 | math.randomseed(1007) | ||
| 746 | -- get the low 'intbits' of the 64-bit expected result | ||
| 747 | local res = (h << 32 | l) & ~(~0 << intbits) | ||
| 748 | assert(random(0) == res) | ||
| 749 | |||
| 750 | math.randomseed(1007, 0) | ||
| 751 | -- using lower bits to generate random floats; (the '% 2^32' converts | ||
| 752 | -- 32-bit integers to floats as unsigned) | ||
| 753 | local res | ||
| 754 | if floatbits <= 32 then | ||
| 755 | -- get all bits from the lower half | ||
| 756 | res = (l & ~(~0 << floatbits)) % 2^32 | ||
| 757 | else | ||
| 758 | -- get 32 bits from the lower half and the rest from the higher half | ||
| 759 | res = ((h & ~(~0 << (floatbits - 32))) % 2^32) * 2^32 + (l % 2^32) | ||
| 760 | end | ||
| 761 | assert(random() * 2^floatbits == res) | ||
| 762 | end | ||
| 763 | |||
| 764 | math.randomseed(0, os.time()) | ||
| 765 | |||
| 766 | do -- test random for floats | ||
| 767 | local randbits = math.min(floatbits, 64) -- at most 64 random bits | ||
| 768 | local mult = 2^randbits -- to make random float into an integral | ||
| 769 | local counts = {} -- counts for bits | ||
| 770 | for i = 1, randbits do counts[i] = 0 end | ||
| 771 | local up = -math.huge | ||
| 772 | local low = math.huge | ||
| 773 | local rounds = 100 * randbits -- 100 times for each bit | ||
| 774 | local totalrounds = 0 | ||
| 775 | ::doagain:: -- will repeat test until we get good statistics | ||
| 776 | for i = 0, rounds do | ||
| 777 | local t = random() | ||
| 778 | assert(0 <= t and t < 1) | ||
| 779 | up = max(up, t) | ||
| 780 | low = min(low, t) | ||
| 781 | assert(t * mult % 1 == 0) -- no extra bits | ||
| 782 | local bit = i % randbits -- bit to be tested | ||
| 783 | if (t * 2^bit) % 1 >= 0.5 then -- is bit set? | ||
| 784 | counts[bit + 1] = counts[bit + 1] + 1 -- increment its count | ||
| 785 | end | ||
| 786 | end | ||
| 787 | totalrounds = totalrounds + rounds | ||
| 788 | if not (eq(up, 1, 0.001) and eq(low, 0, 0.001)) then | ||
| 789 | goto doagain | ||
| 790 | end | ||
| 791 | -- all bit counts should be near 50% | ||
| 792 | local expected = (totalrounds / randbits / 2) | ||
| 793 | for i = 1, randbits do | ||
| 794 | if not testnear(counts[i], expected, 0.10) then | ||
| 795 | goto doagain | ||
| 796 | end | ||
| 797 | end | ||
| 798 | print(string.format("float random range in %d calls: [%f, %f]", | ||
| 799 | totalrounds, low, up)) | ||
| 800 | end | ||
| 801 | |||
| 802 | |||
| 803 | do -- test random for full integers | ||
| 804 | local up = 0 | ||
| 805 | local low = 0 | ||
| 806 | local counts = {} -- counts for bits | ||
| 807 | for i = 1, intbits do counts[i] = 0 end | ||
| 808 | local rounds = 100 * intbits -- 100 times for each bit | ||
| 809 | local totalrounds = 0 | ||
| 810 | ::doagain:: -- will repeat test until we get good statistics | ||
| 811 | for i = 0, rounds do | ||
| 812 | local t = random(0) | ||
| 813 | up = max(up, t) | ||
| 814 | low = min(low, t) | ||
| 815 | local bit = i % intbits -- bit to be tested | ||
| 816 | -- increment its count if it is set | ||
| 817 | counts[bit + 1] = counts[bit + 1] + ((t >> bit) & 1) | ||
| 818 | end | ||
| 819 | totalrounds = totalrounds + rounds | ||
| 820 | local lim = maxint >> 10 | ||
| 821 | if not (maxint - up < lim and low - minint < lim) then | ||
| 822 | goto doagain | ||
| 823 | end | ||
| 824 | -- all bit counts should be near 50% | ||
| 825 | local expected = (totalrounds / intbits / 2) | ||
| 826 | for i = 1, intbits do | ||
| 827 | if not testnear(counts[i], expected, 0.10) then | ||
| 828 | goto doagain | ||
| 829 | end | ||
| 830 | end | ||
| 831 | print(string.format( | ||
| 832 | "integer random range in %d calls: [minint + %.0fppm, maxint - %.0fppm]", | ||
| 833 | totalrounds, (minint - low) / minint * 1e6, | ||
| 834 | (maxint - up) / maxint * 1e6)) | ||
| 835 | end | ||
| 836 | |||
| 837 | do | ||
| 838 | -- test distribution for a dice | ||
| 839 | local count = {0, 0, 0, 0, 0, 0} | ||
| 840 | local rep = 200 | ||
| 841 | local totalrep = 0 | ||
| 842 | ::doagain:: | ||
| 843 | for i = 1, rep * 6 do | ||
| 844 | local r = random(6) | ||
| 845 | count[r] = count[r] + 1 | ||
| 846 | end | ||
| 847 | totalrep = totalrep + rep | ||
| 848 | for i = 1, 6 do | ||
| 849 | if not testnear(count[i], totalrep, 0.05) then | ||
| 850 | goto doagain | ||
| 851 | end | ||
| 852 | end | ||
| 853 | end | ||
| 854 | |||
| 855 | do | ||
| 856 | local function aux (x1, x2) -- test random for small intervals | ||
| 857 | local mark = {}; local count = 0 -- to check that all values appeared | ||
| 858 | while true do | ||
| 859 | local t = random(x1, x2) | ||
| 860 | assert(x1 <= t and t <= x2) | ||
| 861 | if not mark[t] then -- new value | ||
| 862 | mark[t] = true | ||
| 863 | count = count + 1 | ||
| 864 | if count == x2 - x1 + 1 then -- all values appeared; OK | ||
| 865 | goto ok | ||
| 866 | end | ||
| 867 | end | ||
| 868 | end | ||
| 869 | ::ok:: | ||
| 870 | end | ||
| 871 | |||
| 872 | aux(-10,0) | ||
| 873 | aux(1, 6) | ||
| 874 | aux(1, 2) | ||
| 875 | aux(1, 32) | ||
| 876 | aux(-10, 10) | ||
| 877 | aux(-10,-10) -- unit set | ||
| 878 | aux(minint, minint) -- unit set | ||
| 879 | aux(maxint, maxint) -- unit set | ||
| 880 | aux(minint, minint + 9) | ||
| 881 | aux(maxint - 3, maxint) | ||
| 882 | end | ||
| 883 | |||
| 884 | do | ||
| 885 | local function aux(p1, p2) -- test random for large intervals | ||
| 886 | local max = minint | ||
| 887 | local min = maxint | ||
| 888 | local n = 100 | ||
| 889 | local mark = {}; local count = 0 -- to count how many different values | ||
| 890 | ::doagain:: | ||
| 891 | for _ = 1, n do | ||
| 892 | local t = random(p1, p2) | ||
| 893 | if not mark[t] then -- new value | ||
| 894 | assert(p1 <= t and t <= p2) | ||
| 895 | max = math.max(max, t) | ||
| 896 | min = math.min(min, t) | ||
| 897 | mark[t] = true | ||
| 898 | count = count + 1 | ||
| 899 | end | ||
| 900 | end | ||
| 901 | -- at least 80% of values are different | ||
| 902 | if not (count >= n * 0.8) then | ||
| 903 | goto doagain | ||
| 904 | end | ||
| 905 | -- min and max not too far from formal min and max | ||
| 906 | local diff = (p2 - p1) >> 4 | ||
| 907 | if not (min < p1 + diff and max > p2 - diff) then | ||
| 908 | goto doagain | ||
| 909 | end | ||
| 910 | end | ||
| 911 | aux(0, maxint) | ||
| 912 | aux(1, maxint) | ||
| 913 | aux(minint, -1) | ||
| 914 | aux(minint // 2, maxint // 2) | ||
| 915 | aux(minint, maxint) | ||
| 916 | aux(minint + 1, maxint) | ||
| 917 | aux(minint, maxint - 1) | ||
| 918 | aux(0, 1 << (intbits - 5)) | ||
| 919 | end | ||
| 920 | |||
| 921 | |||
| 922 | assert(not pcall(random, 1, 2, 3)) -- too many arguments | ||
| 923 | |||
| 924 | -- empty interval | ||
| 925 | assert(not pcall(random, minint + 1, minint)) | ||
| 926 | assert(not pcall(random, maxint, maxint - 1)) | ||
| 927 | assert(not pcall(random, maxint, minint)) | ||
| 928 | |||
| 929 | |||
| 930 | |||
| 931 | print('OK') | ||
