1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
|
*lua-bit.txt* Nvim
*lua-bit*
LUA BITOP REFERENCE MANUAL
Adapted from <https://bitop.luajit.org>
Lua BitOp is a C extension module for Lua 5.1/5.2 which adds bitwise
operations on numbers.
Type |gO| to see the table of contents.
==============================================================================
API FUNCTIONS *lua-bit-api*
This list of API functions is not intended to replace a tutorial. If you are
not familiar with the terms used, you may want to study the Wikipedia article
on bitwise operations (https://en.wikipedia.org/wiki/Bitwise_operation) first.
------------------------------------------------------------------------------
Loading the BitOp module
*lua-bit-module*
The suggested way to use the BitOp module is to add the following to the start
of every Lua file that needs one of its functions: >lua
local bit = require("bit")
<
This makes the dependency explicit, limits the scope to the current file and
provides faster access to the bit.* functions, too. It's good programming
practice not to rely on the global variable bit being set (assuming some other
part of your application has already loaded the module). The require function
ensures the module is only loaded once, in any case.
------------------------------------------------------------------------------
Defining Shortcuts
*lua-bit-shortcuts*
It's a common (but not a required) practice to cache often used module
functions in locals. This serves as a shortcut to save some typing and also
speeds up resolving them (only relevant if called hundreds of thousands of
times).
>lua
local bnot = bit.bnot
local band, bor, bxor = bit.band, bit.bor, bit.bxor
local lshift, rshift, rol = bit.lshift, bit.rshift, bit.rol
-- etc...
-- Example use of the shortcuts:
local function tr_i(a, b, c, d, x, s)
return rol(bxor(c, bor(b, bnot(d))) + a + x, s) + b
end
<
Remember that `and`, `or` and `not` are reserved keywords in Lua. They cannot
be used for variable names or literal field names. That's why the
corresponding bitwise functions have been named `band`, `bor`, and `bnot` (and
`bxor` for consistency).
While we are at it: a common pitfall is to use bit as the name of a local
temporary variable — well, don't! :-)
------------------------------------------------------------------------------
About the Examples
The examples below show small Lua one-liners. Their expected output is shown
after `-->`. This is interpreted as a comment marker by Lua so you can cut &
paste the whole line to a Lua prompt and experiment with it.
Note that all bit operations return signed 32 bit numbers (rationale). And
these print as signed decimal numbers by default.
For clarity the examples assume the definition of a helper function
`printx()`. This prints its argument as an unsigned 32 bit hexadecimal number
on all platforms:
>lua
function printx(x)
print("0x"..bit.tohex(x))
end
<
------------------------------------------------------------------------------
Bit operations
*lua-bitop*
y = bit.tobit(x) *bit.tobit()*
Normalizes a number to the numeric range for bit operations and returns
it. This function is usually not needed since all bit operations already
normalize all of their input arguments. See |lua-bit-semantics|.
Example: >lua
print(0xffffffff) --> 4294967295 (see Note)
print(bit.tobit(0xffffffff)) --> -1
printx(bit.tobit(0xffffffff)) --> 0xffffffff
print(bit.tobit(0xffffffff + 1)) --> 0
print(bit.tobit(2^40 + 1234)) --> 1234
<
Note: |lua-bit-hex-literals| explains why the numbers printed in the first
two lines differ (if your Lua installation uses a double number type).
y = bit.tohex(x [,n]) *bit.tohex()*
Converts its first argument to a hex string. The number of hex digits is
given by the absolute value of the optional second argument. Positive
numbers between 1 and 8 generate lowercase hex digits. Negative numbers
generate uppercase hex digits. Only the least-significant `4*|n|` bits are
used. The default is to generate 8 lowercase hex digits.
Example: >lua
print(bit.tohex(1)) --> 00000001
print(bit.tohex(-1)) --> ffffffff
print(bit.tohex(0xffffffff)) --> ffffffff
print(bit.tohex(-1, -8)) --> FFFFFFFF
print(bit.tohex(0x21, 4)) --> 0021
print(bit.tohex(0x87654321, 4)) --> 4321
<
y = bit.bnot(x) *bit.bnot()*
Returns the bitwise `not` of its argument.
Example: >lua
print(bit.bnot(0)) --> -1
printx(bit.bnot(0)) --> 0xffffffff
print(bit.bnot(-1)) --> 0
print(bit.bnot(0xffffffff)) --> 0
printx(bit.bnot(0x12345678)) --> 0xedcba987
<
y = bit.bor(x1 [,x2...]) *bit.bor()*
y = bit.band(x1 [,x2...]) *bit.band()*
y = bit.bxor(x1 [,x2...]) *bit.bxor()*
Returns either the bitwise `or`, bitwise `and`, or bitwise `xor` of all of its
arguments. Note that more than two arguments are allowed.
Example: >lua
print(bit.bor(1, 2, 4, 8)) --> 15
printx(bit.band(0x12345678, 0xff)) --> 0x00000078
printx(bit.bxor(0xa5a5f0f0, 0xaa55ff00)) --> 0x0ff00ff0
<
y = bit.lshift(x, n) *bit.lshift()*
y = bit.rshift(x, n) *bit.rshift()*
y = bit.arshift(x, n) *bit.arshift()*
Returns either the bitwise `logical left-shift`, bitwise `logical`
`right-shift`, or bitwise `arithmetic right-shift` of its first argument
by the number of bits given by the second argument.
Logical shifts treat the first argument as an unsigned number and shift in
0-bits. Arithmetic right-shift treats the most-significant bit as a sign
bit and replicates it. Only the lower 5 bits of the shift count are used
(reduces to the range [0..31]).
Example: >lua
print(bit.lshift(1, 0)) --> 1
print(bit.lshift(1, 8)) --> 256
print(bit.lshift(1, 40)) --> 256
print(bit.rshift(256, 8)) --> 1
print(bit.rshift(-256, 8)) --> 16777215
print(bit.arshift(256, 8)) --> 1
print(bit.arshift(-256, 8)) --> -1
printx(bit.lshift(0x87654321, 12)) --> 0x54321000
printx(bit.rshift(0x87654321, 12)) --> 0x00087654
printx(bit.arshift(0x87654321, 12)) --> 0xfff87654
<
y = bit.rol(x, n) *bit.rol()*
y = bit.ror(x, n) *bit.ror()*
Returns either the bitwise `left rotation`, or bitwise `right rotation` of its
first argument by the number of bits given by the second argument. Bits
shifted out on one side are shifted back in on the other side.
Only the lower 5 bits of the rotate count are used (reduces to the range
[0..31]).
Example: >lua
printx(bit.rol(0x12345678, 12)) --> 0x45678123
printx(bit.ror(0x12345678, 12)) --> 0x67812345
<
y = bit.bswap(x)
Swaps the bytes of its argument and returns it. This can be used to
convert little-endian 32 bit numbers to big-endian 32 bit numbers or vice
versa.
Example: >lua
printx(bit.bswap(0x12345678)) --> 0x78563412
printx(bit.bswap(0x78563412)) --> 0x12345678
<
------------------------------------------------------------------------------
Example Program
This is an implementation of the (naïve) Sieve of Eratosthenes algorithm. It
counts the number of primes up to some maximum number.
A Lua table is used to hold a bit-vector. Every array index has 32 bits of the
vector. Bitwise operations are used to access and modify them. Note that the
shift counts don't need to be masked since this is already done by the BitOp
shift and rotate functions.
>lua
local bit = require("bit")
local band, bxor = bit.band, bit.bxor
local rshift, rol = bit.rshift, bit.rol
local m = tonumber(arg and arg[1]) or 100000
if m < 2 then m = 2 end
local count = 0
local p = {}
for i=0,(m+31)/32 do p[i] = -1 end
for i=2,m do
if band(rshift(p[rshift(i, 5)], i), 1) ~= 0 then
count = count + 1
for j=i+i,m,i do
local jx = rshift(j, 5)
p[jx] = band(p[jx], rol(-2, j))
end
end
end
io.write(string.format("Found %d primes up to %d\n", count, m))
<
Lua BitOp is quite fast. This program runs in less than 90 milliseconds on a 3
GHz CPU with a standard Lua installation, but performs more than a million
calls to bitwise functions. If you're looking for even more speed, check out
|lua-luajit|.
------------------------------------------------------------------------------
Caveats *lua-bit-caveats*
Signed Results ~
Returning signed numbers from bitwise operations may be surprising to
programmers coming from other programming languages which have both signed and
unsigned types. But as long as you treat the results of bitwise operations
uniformly everywhere, this shouldn't cause any problems.
Preferably format results with `bit.tohex` if you want a reliable unsigned
string representation. Avoid the `"%x"` or `"%u"` formats for `string.format`. They
fail on some architectures for negative numbers and can return more than 8 hex
digits on others.
You may also want to avoid the default number to string coercion, since this
is a signed conversion. The coercion is used for string concatenation and all
standard library functions which accept string arguments (such as `print()` or
`io.write()`).
Conditionals ~
If you're transcribing some code from C/C++, watch out for bit operations in
conditionals. In C/C++ any non-zero value is implicitly considered as `true`.
E.g. this C code: >c
if (x & 3) ...
<
must not be turned into this Lua code: >lua
if band(x, 3) then ... -- wrong!
<
In Lua all objects except `nil` and `false` are considered `true`. This
includes all numbers. An explicit comparison against zero is required in this
case: >lua
if band(x, 3) ~= 0 then ... -- correct!
Comparing Against Hex Literals ~
Comparing the results of bitwise operations (signed numbers) against hex
literals (unsigned numbers) needs some additional care. The following
conditional expression may or may not work right, depending on the platform
you run it on: >lua
bit.bor(x, 1) == 0xffffffff
<
E.g. it's never true on a Lua installation with the default number type. Some
simple solutions:
Never use hex literals larger than 0x7fffffff in comparisons: >lua
bit.bor(x, 1) == -1
<
Or convert them with bit.tobit() before comparing: >lua
bit.bor(x, 1) == bit.tobit(0xffffffff)
<
Or use a generic workaround with bit.bxor(): >lua
bit.bxor(bit.bor(x, 1), 0xffffffff) == 0
<
Or use a case-specific workaround: >lua
bit.rshift(x, 1) == 0x7fffffff
<
==============================================================================
OPERATIONAL SEMANTICS AND RATIONALE *lua-bit-semantics*
Input and Output Ranges ~
*lua-bit-io-ranges*
Bitwise operations cannot sensibly be applied to FP numbers (or their
underlying bit patterns). They must be converted to integers before operating
on them and then back to FP numbers.
It's desirable to define semantics that work the same across all platforms.
This dictates that all operations are based on the common denominator of 32
bit integers. The `float` type provides only 24 bits of precision. This makes it
unsuitable for use in bitwise operations. Lua BitOp refuses to compile against
a Lua installation with this number type.
Bit operations only deal with the underlying bit patterns and generally ignore
signedness (except for arithmetic right-shift). They are commonly displayed
and treated like unsigned numbers, though.
But the Lua number type must be signed and may be limited to 32 bits. Defining
the result type as an unsigned number would not be cross-platform safe. All
bit operations are thus defined to return results in the range of signed 32
bit numbers (converted to the Lua number type).
*lua-bit-hex-literals*
Hexadecimal literals are treated as unsigned numbers by the Lua parser before
converting them to the Lua number type. This means they can be out of the
range of signed 32 bit integers if the Lua number type has a greater range.
E.g. 0xffffffff has a value of 4294967295 in the default installation, but may
be -1 on embedded systems. It's highly desirable that hex literals are treated
uniformly across systems when used in bitwise operations. All bit operations
accept arguments in the signed or the unsigned 32 bit range (and more, see
below). Numbers with the same underlying bit pattern are treated the same by
all operations.
Modular Arithmetic ~
*lua-bit-modular-arith*
Arithmetic operations on n-bit integers are usually based on the rules of
modular arithmetic modulo 2^n. Numbers wrap around when the mathematical result
of operations is outside their defined range. This simplifies hardware
implementations and some algorithms actually require this behavior (like many
cryptographic functions).
E.g. for 32 bit integers the following holds: `0xffffffff + 1 = 0`
Arithmetic modulo 2^32 is trivially available if the Lua number type is a 32
bit integer. Otherwise normalization steps must be inserted. Modular
arithmetic should work the same across all platforms as far as possible:
- For the default number type of double, arguments can be in the range of
±2^51 and still be safely normalized across all platforms by taking their
least-significant 32 bits. The limit is derived from the way doubles are
converted to integers.
- The function bit.tobit can be used to explicitly normalize numbers to
implement modular addition or subtraction. E.g. >lua
bit.tobit(0xffffffff + 1)
returns 0 on all platforms.
- The limit on the argument range implies that modular multiplication is
usually restricted to multiplying already normalized numbers with small
constants. FP numbers are limited to 53 bits of precision, anyway. E.g.
(2^30+1)^2 does not return an odd number when computed with doubles.
BTW: The `tr_i` function shown here |lua-bit-shortcuts| is one of the
non-linear functions of the (flawed) MD5 cryptographic hash and relies on
modular arithmetic for correct operation. The result is fed back to other
bitwise operations (not shown) and does not need to be normalized until the
last step.
Restricted and undefined behaviors ~
*lua-bit-restrictions*
The following rules are intended to give a precise and useful definition (for
the programmer), yet give the implementation (interpreter and compiler) the
maximum flexibility and the freedom to apply advanced optimizations. It's
strongly advised not to rely on undefined or implementation-defined behavior.
- All kinds of floating-point numbers are acceptable to the bitwise
operations. None of them cause an error, but some may invoke undefined
behavior:
- -0 is treated the same as +0 on input and is never returned as a result.
- Passing ±Inf, NaN or numbers outside the range of ±2^51 as input yields
an undefined result.
- Non-integral numbers may be rounded or truncated in an
implementation-defined way. This means the result could differ between
different BitOp versions, different Lua VMs, on different platforms or
even between interpreted vs. compiled code (as in LuaJIT). Avoid
passing fractional numbers to bitwise functions. Use `math.floor()` or
`math.ceil()` to get defined behavior.
- Lua provides auto-coercion of string arguments to numbers by default. This
behavior is deprecated for bitwise operations.
==============================================================================
COPYRIGHT
Lua BitOp is Copyright (C) 2008-2012 Mike Pall.
Lua BitOp is free software, released under the MIT license.
==============================================================================
vim:tw=78:ts=4:sw=4:sts=4:et:ft=help:norl:
|