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/bitwise.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/bitwise.lua')
| -rwxr-xr-x | testes/bitwise.lua | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/testes/bitwise.lua b/testes/bitwise.lua new file mode 100755 index 00000000..3e7079d3 --- /dev/null +++ b/testes/bitwise.lua | |||
| @@ -0,0 +1,346 @@ | |||
| 1 | -- $Id: bitwise.lua,v 1.27 2018/02/21 17:49:39 roberto Exp $ | ||
| 2 | -- See Copyright Notice in file all.lua | ||
| 3 | |||
| 4 | print("testing bitwise operations") | ||
| 5 | |||
| 6 | require "bwcoercion" | ||
| 7 | |||
| 8 | local numbits = string.packsize('j') * 8 | ||
| 9 | |||
| 10 | assert(~0 == -1) | ||
| 11 | |||
| 12 | assert((1 << (numbits - 1)) == math.mininteger) | ||
| 13 | |||
| 14 | -- basic tests for bitwise operators; | ||
| 15 | -- use variables to avoid constant folding | ||
| 16 | local a, b, c, d | ||
| 17 | a = 0xFFFFFFFFFFFFFFFF | ||
| 18 | assert(a == -1 and a & -1 == a and a & 35 == 35) | ||
| 19 | a = 0xF0F0F0F0F0F0F0F0 | ||
| 20 | assert(a | -1 == -1) | ||
| 21 | assert(a ~ a == 0 and a ~ 0 == a and a ~ ~a == -1) | ||
| 22 | assert(a >> 4 == ~a) | ||
| 23 | a = 0xF0; b = 0xCC; c = 0xAA; d = 0xFD | ||
| 24 | assert(a | b ~ c & d == 0xF4) | ||
| 25 | |||
| 26 | a = 0xF0.0; b = 0xCC.0; c = "0xAA.0"; d = "0xFD.0" | ||
| 27 | assert(a | b ~ c & d == 0xF4) | ||
| 28 | |||
| 29 | a = 0xF0000000; b = 0xCC000000; | ||
| 30 | c = 0xAA000000; d = 0xFD000000 | ||
| 31 | assert(a | b ~ c & d == 0xF4000000) | ||
| 32 | assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1) | ||
| 33 | |||
| 34 | a = a << 32 | ||
| 35 | b = b << 32 | ||
| 36 | c = c << 32 | ||
| 37 | d = d << 32 | ||
| 38 | assert(a | b ~ c & d == 0xF4000000 << 32) | ||
| 39 | assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1) | ||
| 40 | |||
| 41 | assert(-1 >> 1 == (1 << (numbits - 1)) - 1 and 1 << 31 == 0x80000000) | ||
| 42 | assert(-1 >> (numbits - 1) == 1) | ||
| 43 | assert(-1 >> numbits == 0 and | ||
| 44 | -1 >> -numbits == 0 and | ||
| 45 | -1 << numbits == 0 and | ||
| 46 | -1 << -numbits == 0) | ||
| 47 | |||
| 48 | assert((2^30 - 1) << 2^30 == 0) | ||
| 49 | assert((2^30 - 1) >> 2^30 == 0) | ||
| 50 | |||
| 51 | assert(1 >> -3 == 1 << 3 and 1000 >> 5 == 1000 << -5) | ||
| 52 | |||
| 53 | |||
| 54 | -- coercion from strings to integers | ||
| 55 | assert("0xffffffffffffffff" | 0 == -1) | ||
| 56 | assert("0xfffffffffffffffe" & "-1" == -2) | ||
| 57 | assert(" \t-0xfffffffffffffffe\n\t" & "-1" == 2) | ||
| 58 | assert(" \n -45 \t " >> " -2 " == -45 * 4) | ||
| 59 | assert("1234.0" << "5.0" == 1234 * 32) | ||
| 60 | assert("0xffff.0" ~ "0xAAAA" == 0x5555) | ||
| 61 | assert(~"0x0.000p4" == -1) | ||
| 62 | |||
| 63 | assert("7" .. 3 << 1 == 146) | ||
| 64 | assert(10 >> 1 .. "9" == 0) | ||
| 65 | assert(10 | 1 .. "9" == 27) | ||
| 66 | |||
| 67 | do | ||
| 68 | local st, msg = pcall(function () return 4 & "a" end) | ||
| 69 | assert(string.find(msg, "'band'")) | ||
| 70 | |||
| 71 | local st, msg = pcall(function () return ~"a" end) | ||
| 72 | assert(string.find(msg, "'bnot'")) | ||
| 73 | end | ||
| 74 | |||
| 75 | |||
| 76 | -- out of range number | ||
| 77 | assert(not pcall(function () return "0xffffffffffffffff.0" | 0 end)) | ||
| 78 | |||
| 79 | -- embedded zeros | ||
| 80 | assert(not pcall(function () return "0xffffffffffffffff\0" | 0 end)) | ||
| 81 | |||
| 82 | print'+' | ||
| 83 | |||
| 84 | |||
| 85 | package.preload.bit32 = function () --{ | ||
| 86 | |||
| 87 | -- no built-in 'bit32' library: implement it using bitwise operators | ||
| 88 | |||
| 89 | local bit = {} | ||
| 90 | |||
| 91 | function bit.bnot (a) | ||
| 92 | return ~a & 0xFFFFFFFF | ||
| 93 | end | ||
| 94 | |||
| 95 | |||
| 96 | -- | ||
| 97 | -- in all vararg functions, avoid creating 'arg' table when there are | ||
| 98 | -- only 2 (or less) parameters, as 2 parameters is the common case | ||
| 99 | -- | ||
| 100 | |||
| 101 | function bit.band (x, y, z, ...) | ||
| 102 | if not z then | ||
| 103 | return ((x or -1) & (y or -1)) & 0xFFFFFFFF | ||
| 104 | else | ||
| 105 | local arg = {...} | ||
| 106 | local res = x & y & z | ||
| 107 | for i = 1, #arg do res = res & arg[i] end | ||
| 108 | return res & 0xFFFFFFFF | ||
| 109 | end | ||
| 110 | end | ||
| 111 | |||
| 112 | function bit.bor (x, y, z, ...) | ||
| 113 | if not z then | ||
| 114 | return ((x or 0) | (y or 0)) & 0xFFFFFFFF | ||
| 115 | else | ||
| 116 | local arg = {...} | ||
| 117 | local res = x | y | z | ||
| 118 | for i = 1, #arg do res = res | arg[i] end | ||
| 119 | return res & 0xFFFFFFFF | ||
| 120 | end | ||
| 121 | end | ||
| 122 | |||
| 123 | function bit.bxor (x, y, z, ...) | ||
| 124 | if not z then | ||
| 125 | return ((x or 0) ~ (y or 0)) & 0xFFFFFFFF | ||
| 126 | else | ||
| 127 | local arg = {...} | ||
| 128 | local res = x ~ y ~ z | ||
| 129 | for i = 1, #arg do res = res ~ arg[i] end | ||
| 130 | return res & 0xFFFFFFFF | ||
| 131 | end | ||
| 132 | end | ||
| 133 | |||
| 134 | function bit.btest (...) | ||
| 135 | return bit.band(...) ~= 0 | ||
| 136 | end | ||
| 137 | |||
| 138 | function bit.lshift (a, b) | ||
| 139 | return ((a & 0xFFFFFFFF) << b) & 0xFFFFFFFF | ||
| 140 | end | ||
| 141 | |||
| 142 | function bit.rshift (a, b) | ||
| 143 | return ((a & 0xFFFFFFFF) >> b) & 0xFFFFFFFF | ||
| 144 | end | ||
| 145 | |||
| 146 | function bit.arshift (a, b) | ||
| 147 | a = a & 0xFFFFFFFF | ||
| 148 | if b <= 0 or (a & 0x80000000) == 0 then | ||
| 149 | return (a >> b) & 0xFFFFFFFF | ||
| 150 | else | ||
| 151 | return ((a >> b) | ~(0xFFFFFFFF >> b)) & 0xFFFFFFFF | ||
| 152 | end | ||
| 153 | end | ||
| 154 | |||
| 155 | function bit.lrotate (a ,b) | ||
| 156 | b = b & 31 | ||
| 157 | a = a & 0xFFFFFFFF | ||
| 158 | a = (a << b) | (a >> (32 - b)) | ||
| 159 | return a & 0xFFFFFFFF | ||
| 160 | end | ||
| 161 | |||
| 162 | function bit.rrotate (a, b) | ||
| 163 | return bit.lrotate(a, -b) | ||
| 164 | end | ||
| 165 | |||
| 166 | local function checkfield (f, w) | ||
| 167 | w = w or 1 | ||
| 168 | assert(f >= 0, "field cannot be negative") | ||
| 169 | assert(w > 0, "width must be positive") | ||
| 170 | assert(f + w <= 32, "trying to access non-existent bits") | ||
| 171 | return f, ~(-1 << w) | ||
| 172 | end | ||
| 173 | |||
| 174 | function bit.extract (a, f, w) | ||
| 175 | local f, mask = checkfield(f, w) | ||
| 176 | return (a >> f) & mask | ||
| 177 | end | ||
| 178 | |||
| 179 | function bit.replace (a, v, f, w) | ||
| 180 | local f, mask = checkfield(f, w) | ||
| 181 | v = v & mask | ||
| 182 | a = (a & ~(mask << f)) | (v << f) | ||
| 183 | return a & 0xFFFFFFFF | ||
| 184 | end | ||
| 185 | |||
| 186 | return bit | ||
| 187 | |||
| 188 | end --} | ||
| 189 | |||
| 190 | |||
| 191 | print("testing bitwise library") | ||
| 192 | |||
| 193 | local bit32 = require'bit32' | ||
| 194 | |||
| 195 | assert(bit32.band() == bit32.bnot(0)) | ||
| 196 | assert(bit32.btest() == true) | ||
| 197 | assert(bit32.bor() == 0) | ||
| 198 | assert(bit32.bxor() == 0) | ||
| 199 | |||
| 200 | assert(bit32.band() == bit32.band(0xffffffff)) | ||
| 201 | assert(bit32.band(1,2) == 0) | ||
| 202 | |||
| 203 | |||
| 204 | -- out-of-range numbers | ||
| 205 | assert(bit32.band(-1) == 0xffffffff) | ||
| 206 | assert(bit32.band((1 << 33) - 1) == 0xffffffff) | ||
| 207 | assert(bit32.band(-(1 << 33) - 1) == 0xffffffff) | ||
| 208 | assert(bit32.band((1 << 33) + 1) == 1) | ||
| 209 | assert(bit32.band(-(1 << 33) + 1) == 1) | ||
| 210 | assert(bit32.band(-(1 << 40)) == 0) | ||
| 211 | assert(bit32.band(1 << 40) == 0) | ||
| 212 | assert(bit32.band(-(1 << 40) - 2) == 0xfffffffe) | ||
| 213 | assert(bit32.band((1 << 40) - 4) == 0xfffffffc) | ||
| 214 | |||
| 215 | assert(bit32.lrotate(0, -1) == 0) | ||
| 216 | assert(bit32.lrotate(0, 7) == 0) | ||
| 217 | assert(bit32.lrotate(0x12345678, 0) == 0x12345678) | ||
| 218 | assert(bit32.lrotate(0x12345678, 32) == 0x12345678) | ||
| 219 | assert(bit32.lrotate(0x12345678, 4) == 0x23456781) | ||
| 220 | assert(bit32.rrotate(0x12345678, -4) == 0x23456781) | ||
| 221 | assert(bit32.lrotate(0x12345678, -8) == 0x78123456) | ||
| 222 | assert(bit32.rrotate(0x12345678, 8) == 0x78123456) | ||
| 223 | assert(bit32.lrotate(0xaaaaaaaa, 2) == 0xaaaaaaaa) | ||
| 224 | assert(bit32.lrotate(0xaaaaaaaa, -2) == 0xaaaaaaaa) | ||
| 225 | for i = -50, 50 do | ||
| 226 | assert(bit32.lrotate(0x89abcdef, i) == bit32.lrotate(0x89abcdef, i%32)) | ||
| 227 | end | ||
| 228 | |||
| 229 | assert(bit32.lshift(0x12345678, 4) == 0x23456780) | ||
| 230 | assert(bit32.lshift(0x12345678, 8) == 0x34567800) | ||
| 231 | assert(bit32.lshift(0x12345678, -4) == 0x01234567) | ||
| 232 | assert(bit32.lshift(0x12345678, -8) == 0x00123456) | ||
| 233 | assert(bit32.lshift(0x12345678, 32) == 0) | ||
| 234 | assert(bit32.lshift(0x12345678, -32) == 0) | ||
| 235 | assert(bit32.rshift(0x12345678, 4) == 0x01234567) | ||
| 236 | assert(bit32.rshift(0x12345678, 8) == 0x00123456) | ||
| 237 | assert(bit32.rshift(0x12345678, 32) == 0) | ||
| 238 | assert(bit32.rshift(0x12345678, -32) == 0) | ||
| 239 | assert(bit32.arshift(0x12345678, 0) == 0x12345678) | ||
| 240 | assert(bit32.arshift(0x12345678, 1) == 0x12345678 // 2) | ||
| 241 | assert(bit32.arshift(0x12345678, -1) == 0x12345678 * 2) | ||
| 242 | assert(bit32.arshift(-1, 1) == 0xffffffff) | ||
| 243 | assert(bit32.arshift(-1, 24) == 0xffffffff) | ||
| 244 | assert(bit32.arshift(-1, 32) == 0xffffffff) | ||
| 245 | assert(bit32.arshift(-1, -1) == bit32.band(-1 * 2, 0xffffffff)) | ||
| 246 | |||
| 247 | assert(0x12345678 << 4 == 0x123456780) | ||
| 248 | assert(0x12345678 << 8 == 0x1234567800) | ||
| 249 | assert(0x12345678 << -4 == 0x01234567) | ||
| 250 | assert(0x12345678 << -8 == 0x00123456) | ||
| 251 | assert(0x12345678 << 32 == 0x1234567800000000) | ||
| 252 | assert(0x12345678 << -32 == 0) | ||
| 253 | assert(0x12345678 >> 4 == 0x01234567) | ||
| 254 | assert(0x12345678 >> 8 == 0x00123456) | ||
| 255 | assert(0x12345678 >> 32 == 0) | ||
| 256 | assert(0x12345678 >> -32 == 0x1234567800000000) | ||
| 257 | |||
| 258 | print("+") | ||
| 259 | -- some special cases | ||
| 260 | local c = {0, 1, 2, 3, 10, 0x80000000, 0xaaaaaaaa, 0x55555555, | ||
| 261 | 0xffffffff, 0x7fffffff} | ||
| 262 | |||
| 263 | for _, b in pairs(c) do | ||
| 264 | assert(bit32.band(b) == b) | ||
| 265 | assert(bit32.band(b, b) == b) | ||
| 266 | assert(bit32.band(b, b, b, b) == b) | ||
| 267 | assert(bit32.btest(b, b) == (b ~= 0)) | ||
| 268 | assert(bit32.band(b, b, b) == b) | ||
| 269 | assert(bit32.band(b, b, b, ~b) == 0) | ||
| 270 | assert(bit32.btest(b, b, b) == (b ~= 0)) | ||
| 271 | assert(bit32.band(b, bit32.bnot(b)) == 0) | ||
| 272 | assert(bit32.bor(b, bit32.bnot(b)) == bit32.bnot(0)) | ||
| 273 | assert(bit32.bor(b) == b) | ||
| 274 | assert(bit32.bor(b, b) == b) | ||
| 275 | assert(bit32.bor(b, b, b) == b) | ||
| 276 | assert(bit32.bor(b, b, 0, ~b) == 0xffffffff) | ||
| 277 | assert(bit32.bxor(b) == b) | ||
| 278 | assert(bit32.bxor(b, b) == 0) | ||
| 279 | assert(bit32.bxor(b, b, b) == b) | ||
| 280 | assert(bit32.bxor(b, b, b, b) == 0) | ||
| 281 | assert(bit32.bxor(b, 0) == b) | ||
| 282 | assert(bit32.bnot(b) ~= b) | ||
| 283 | assert(bit32.bnot(bit32.bnot(b)) == b) | ||
| 284 | assert(bit32.bnot(b) == (1 << 32) - 1 - b) | ||
| 285 | assert(bit32.lrotate(b, 32) == b) | ||
| 286 | assert(bit32.rrotate(b, 32) == b) | ||
| 287 | assert(bit32.lshift(bit32.lshift(b, -4), 4) == bit32.band(b, bit32.bnot(0xf))) | ||
| 288 | assert(bit32.rshift(bit32.rshift(b, 4), -4) == bit32.band(b, bit32.bnot(0xf))) | ||
| 289 | end | ||
| 290 | |||
| 291 | -- for this test, use at most 24 bits (mantissa of a single float) | ||
| 292 | c = {0, 1, 2, 3, 10, 0x800000, 0xaaaaaa, 0x555555, 0xffffff, 0x7fffff} | ||
| 293 | for _, b in pairs(c) do | ||
| 294 | for i = -40, 40 do | ||
| 295 | local x = bit32.lshift(b, i) | ||
| 296 | local y = math.floor(math.fmod(b * 2.0^i, 2.0^32)) | ||
| 297 | assert(math.fmod(x - y, 2.0^32) == 0) | ||
| 298 | end | ||
| 299 | end | ||
| 300 | |||
| 301 | assert(not pcall(bit32.band, {})) | ||
| 302 | assert(not pcall(bit32.bnot, "a")) | ||
| 303 | assert(not pcall(bit32.lshift, 45)) | ||
| 304 | assert(not pcall(bit32.lshift, 45, print)) | ||
| 305 | assert(not pcall(bit32.rshift, 45, print)) | ||
| 306 | |||
| 307 | print("+") | ||
| 308 | |||
| 309 | |||
| 310 | -- testing extract/replace | ||
| 311 | |||
| 312 | assert(bit32.extract(0x12345678, 0, 4) == 8) | ||
| 313 | assert(bit32.extract(0x12345678, 4, 4) == 7) | ||
| 314 | assert(bit32.extract(0xa0001111, 28, 4) == 0xa) | ||
| 315 | assert(bit32.extract(0xa0001111, 31, 1) == 1) | ||
| 316 | assert(bit32.extract(0x50000111, 31, 1) == 0) | ||
| 317 | assert(bit32.extract(0xf2345679, 0, 32) == 0xf2345679) | ||
| 318 | |||
| 319 | assert(not pcall(bit32.extract, 0, -1)) | ||
| 320 | assert(not pcall(bit32.extract, 0, 32)) | ||
| 321 | assert(not pcall(bit32.extract, 0, 0, 33)) | ||
| 322 | assert(not pcall(bit32.extract, 0, 31, 2)) | ||
| 323 | |||
| 324 | assert(bit32.replace(0x12345678, 5, 28, 4) == 0x52345678) | ||
| 325 | assert(bit32.replace(0x12345678, 0x87654321, 0, 32) == 0x87654321) | ||
| 326 | assert(bit32.replace(0, 1, 2) == 2^2) | ||
| 327 | assert(bit32.replace(0, -1, 4) == 2^4) | ||
| 328 | assert(bit32.replace(-1, 0, 31) == (1 << 31) - 1) | ||
| 329 | assert(bit32.replace(-1, 0, 1, 2) == (1 << 32) - 7) | ||
| 330 | |||
| 331 | |||
| 332 | -- testing conversion of floats | ||
| 333 | |||
| 334 | assert(bit32.bor(3.0) == 3) | ||
| 335 | assert(bit32.bor(-4.0) == 0xfffffffc) | ||
| 336 | |||
| 337 | -- large floats and large-enough integers? | ||
| 338 | if 2.0^50 < 2.0^50 + 1.0 and 2.0^50 < (-1 >> 1) then | ||
| 339 | assert(bit32.bor(2.0^32 - 5.0) == 0xfffffffb) | ||
| 340 | assert(bit32.bor(-2.0^32 - 6.0) == 0xfffffffa) | ||
| 341 | assert(bit32.bor(2.0^48 - 5.0) == 0xfffffffb) | ||
| 342 | assert(bit32.bor(-2.0^48 - 6.0) == 0xfffffffa) | ||
| 343 | end | ||
| 344 | |||
| 345 | print'OK' | ||
| 346 | |||
