Movatterモバイル変換


[0]ホーム

URL:


Lua-bit

Nvim:help pages,generated fromsource using thetree-sitter-vimdoc parser.


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 bitwiseoperations on numbers.

API FUNCTIONSlua-bit-api

This list of API functions is not intended to replace a tutorial. If you arenot familiar with the terms used, you may want to study the Wikipedia articleon 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 startof every Lua file that needs one of its functions:
local bit = require("bit")
This makes the dependency explicit, limits the scope to the current file andprovides faster access to the bit.* functions, too. It's good programmingpractice not to rely on the global variable bit being set (assuming some otherpart of your application has already loaded the module). The require functionensures 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 modulefunctions in locals. This serves as a shortcut to save some typing and alsospeeds up resolving them (only relevant if called hundreds of thousands oftimes).
local bnot = bit.bnotlocal band, bor, bxor = bit.band, bit.bor, bit.bxorlocal 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) + bend
Remember thatand,or andnot are reserved keywords in Lua. They cannotbe used for variable names or literal field names. That's why thecorresponding bitwise functions have been namedband,bor, andbnot (andbxor for consistency).
While we are at it: a common pitfall is to use bit as the name of a localtemporary variable — well, don't! :-)

About the Examples

The examples below show small Lua one-liners. Their expected output is shownafter-->. 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). Andthese print as signed decimal numbers by default.
For clarity the examples assume the definition of a helper functionprintx(). This prints its argument as an unsigned 32 bit hexadecimal numberon all platforms:
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. Seelua-bit-semantics.
Example:
print(0xffffffff)                --> 4294967295 (see Note)print(bit.tobit(0xffffffff))     --> -1printx(bit.tobit(0xffffffff))    --> 0xffffffffprint(bit.tobit(0xffffffff + 1)) --> 0print(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-significant4*|n| bits are used. The default is to generate 8 lowercase hex digits.
Example:
print(bit.tohex(1))              --> 00000001print(bit.tohex(-1))             --> ffffffffprint(bit.tohex(0xffffffff))     --> ffffffffprint(bit.tohex(-1, -8))         --> FFFFFFFFprint(bit.tohex(0x21, 4))        --> 0021print(bit.tohex(0x87654321, 4))  --> 4321
y = bit.bnot(x)bit.bnot()
Returns the bitwisenot of its argument.
Example:
print(bit.bnot(0))            --> -1printx(bit.bnot(0))           --> 0xffffffffprint(bit.bnot(-1))           --> 0print(bit.bnot(0xffffffff))   --> 0printx(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 bitwiseor, bitwiseand, or bitwisexor of all of its arguments. Note that more than two arguments are allowed.
Example:
print(bit.bor(1, 2, 4, 8))                --> 15printx(bit.band(0x12345678, 0xff))        --> 0x00000078printx(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 bitwiselogical left-shift, bitwiselogicalright-shift, or bitwisearithmetic 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:
print(bit.lshift(1, 0))              --> 1print(bit.lshift(1, 8))              --> 256print(bit.lshift(1, 40))             --> 256print(bit.rshift(256, 8))            --> 1print(bit.rshift(-256, 8))           --> 16777215print(bit.arshift(256, 8))           --> 1print(bit.arshift(-256, 8))          --> -1printx(bit.lshift(0x87654321, 12))   --> 0x54321000printx(bit.rshift(0x87654321, 12))   --> 0x00087654printx(bit.arshift(0x87654321, 12))  --> 0xfff87654
y = bit.rol(x, n)bit.rol()
y = bit.ror(x, n)bit.ror()
Returns either the bitwiseleft rotation, or bitwiseright 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:
printx(bit.rol(0x12345678, 12))   --> 0x45678123printx(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:
printx(bit.bswap(0x12345678)) --> 0x78563412printx(bit.bswap(0x78563412)) --> 0x12345678

Example Program

This is an implementation of the (naïve) Sieve of Eratosthenes algorithm. Itcounts 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 thevector. Bitwise operations are used to access and modify them. Note that theshift counts don't need to be masked since this is already done by the BitOpshift and rotate functions.
local bit = require("bit")local band, bxor = bit.band, bit.bxorlocal rshift, rol = bit.rshift, bit.rollocal m = tonumber(arg and arg[1]) or 100000if m < 2 then m = 2 endlocal count = 0local p = {}for i=0,(m+31)/32 do p[i] = -1 endfor 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  endendio.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 3GHz CPU with a standard Lua installation, but performs more than a millioncalls to bitwise functions. If you're looking for even more speed, check outlua-luajit.

Caveatslua-bit-caveats

Signed Results
Returning signed numbers from bitwise operations may be surprising toprogrammers coming from other programming languages which have both signed andunsigned types. But as long as you treat the results of bitwise operationsuniformly everywhere, this shouldn't cause any problems.
Preferably format results withbit.tohex if you want a reliable unsignedstring representation. Avoid the"%x" or"%u" formats forstring.format. Theyfail on some architectures for negative numbers and can return more than 8 hexdigits on others.
You may also want to avoid the default number to string coercion, since thisis a signed conversion. The coercion is used for string concatenation and allstandard library functions which accept string arguments (such asprint() orio.write()).
Conditionals
If you're transcribing some code from C/C++, watch out for bit operations inconditionals. In C/C++ any non-zero value is implicitly considered astrue.E.g. this C code:
if (x & 3) ...
must not be turned into this Lua code:
if band(x, 3) then ... -- wrong!
In Lua all objects exceptnil andfalse are consideredtrue. Thisincludes all numbers. An explicit comparison against zero is required in thiscase:
if band(x, 3) ~= 0 then ... -- correct!
Comparing Against Hex Literals
Comparing the results of bitwise operations (signed numbers) against hexliterals (unsigned numbers) needs some additional care. The followingconditional expression may or may not work right, depending on the platformyou run it on:
bit.bor(x, 1) == 0xffffffff
E.g. it's never true on a Lua installation with the default number type. Somesimple solutions:
Never use hex literals larger than 0x7fffffff in comparisons:
bit.bor(x, 1) == -1
Or convert them with bit.tobit() before comparing:
bit.bor(x, 1) == bit.tobit(0xffffffff)
Or use a generic workaround with bit.bxor():
bit.bxor(bit.bor(x, 1), 0xffffffff) == 0
Or use a case-specific workaround:
bit.rshift(x, 1) == 0x7fffffff

OPERATIONAL SEMANTICS AND RATIONALElua-bit-semantics

Input and Output Ranges
lua-bit-io-ranges
Bitwise operations cannot sensibly be applied to FP numbers (or theirunderlying bit patterns). They must be converted to integers before operatingon 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 32bit integers. Thefloat type provides only 24 bits of precision. This makes itunsuitable for use in bitwise operations. Lua BitOp refuses to compile againsta Lua installation with this number type.
Bit operations only deal with the underlying bit patterns and generally ignoresignedness (except for arithmetic right-shift). They are commonly displayedand treated like unsigned numbers, though.
But the Lua number type must be signed and may be limited to 32 bits. Definingthe result type as an unsigned number would not be cross-platform safe. Allbit operations are thus defined to return results in the range of signed 32bit numbers (converted to the Lua number type).
lua-bit-hex-literals
Hexadecimal literals are treated as unsigned numbers by the Lua parser beforeconverting them to the Lua number type. This means they can be out of therange 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 maybe -1 on embedded systems. It's highly desirable that hex literals are treateduniformly across systems when used in bitwise operations. All bit operationsaccept arguments in the signed or the unsigned 32 bit range (and more, seebelow). Numbers with the same underlying bit pattern are treated the same byall operations.
Modular Arithmetic
lua-bit-modular-arith
Arithmetic operations on n-bit integers are usually based on the rules ofmodular arithmetic modulo 2^n. Numbers wrap around when the mathematical resultof operations is outside their defined range. This simplifies hardwareimplementations and some algorithms actually require this behavior (like manycryptographic 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 32bit integer. Otherwise normalization steps must be inserted. Modulararithmetic 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.
              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: Thetr_i function shown herelua-bit-shortcuts is one of thenon-linear functions of the (flawed) MD5 cryptographic hash and relies onmodular arithmetic for correct operation. The result is fed back to otherbitwise operations (not shown) and does not need to be normalized until thelast step.
Restricted and undefined behaviors
lua-bit-restrictions
The following rules are intended to give a precise and useful definition (forthe programmer), yet give the implementation (interpreter and compiler) themaximum flexibility and the freedom to apply advanced optimizations. It'sstrongly 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. Usemath.floor() ormath.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-2025 Mike Pall.Lua BitOp is free software, released under the MIT license.
Main
Commands index
Quick reference

API FUNCTIONS
Loading the BitOp module
Defining Shortcuts
About the Examples
Bit operations
Example Program
Caveats
OPERATIONAL SEMANTICS AND RATIONALE
COPYRIGHT

[8]ページ先頭

©2009-2025 Movatter.jp