extra-bit
Version:
The [bit] is a basic unit of information in information theory, computing.<br>
233 lines • 14.6 kB
JavaScript
// METHODS
// =======
// Get integer with 1s of specified width in bits.
function ones(w) {
return (1 << w) - 1;
}
/**
* Get bits at specified index.
* @param x an int32
* @param i bit index
* @param w bit width [1]
*/ export function get(x, i, w = 1) {
return x >>> i & ones(w);
}
/**
* Get bits as per mask.
* @param x an int32
* @param m bit mask
*/ export function getAs(x, m) {
return x & m;
}
/**
* Set bits at specified index.
* @param x an int32
* @param i bit index
* @param v bit value [1]
* @param w bit width [1]
*/ export function set(x, i, v = 1, w = 1) {
return x & ~(ones(w) << i) | v << i;
}
/**
* Set bits as per mask.
* @param x an int32
* @param m bit mask
* @param f bit value [1]
*/ export function setAs(x, m, f = 1) {
return x & ~m | -f & m;
}
/**
* Toggle bits at specified index.
* @param x an int32
* @param i bit index
* @param w bit width [1]
*/ export function toggle(x, i, w = 1) {
return x ^ ones(w) << i;
}
/**
* Toggle bits as per mask.
* @param x an int32
* @param m bit mask
*/ export function toggleAs(x, m) {
return x ^ m;
}
/**
* Swap bit sequences at specified indices.
* @param x an int32
* @param i first bit index
* @param j second bit index
* @param w bit width [1]
*/ export function swap(x, i, j, w = 1) {
const t = (x >>> i ^ x >>> j) & ones(w);
return x ^ (t << i | t << j);
}
const MOD37_POS32 = [
32,
0,
1,
26,
2,
23,
27,
0,
3,
16,
24,
30,
28,
11,
0,
13,
4,
7,
17,
0,
25,
22,
31,
15,
29,
10,
12,
6,
0,
21,
14,
9,
5,
20,
8,
19,
18
];
/**
* Find index of first set bit from LSB.
* @param x an int32
*/ export function scan(x) {
return MOD37_POS32[(-x & x) % 37];
}
const DEBRUIJN_POS32 = [
0,
9,
1,
10,
13,
21,
2,
29,
11,
14,
16,
18,
22,
25,
3,
30,
8,
12,
20,
28,
15,
17,
24,
7,
19,
27,
23,
6,
26,
5,
4,
31
];
/**
* Find index of first set bit from MSB.
* @param x an int32
*/ export function scanReverse(x) {
x |= x >>> 1;
x |= x >>> 2;
x |= x >>> 4;
x |= x >>> 8;
x |= x >>> 16;
return DEBRUIJN_POS32[x * 0x07C4ACDD >>> 27];
}
/**
* Count bits set.
* @param x an int32
*/ export function count(x) {
x = x - (x >>> 1 & 0x55555555);
x = (x & 0x33333333) + (x >>> 2 & 0x33333333);
return (x + (x >>> 4) & 0x0F0F0F0F) * 0x01010101 >>> 24;
}
// Calculate 1-bit parity.
function parity1(x) {
x ^= x >>> 16;
x ^= x >>> 8;
x ^= x >>> 4;
x &= 0xF;
return 0x6996 >>> x & 1;
}
/**
* Calculate n-bit parity.
* @param x an int32
* @param n number of bits [1]
*/ export function parity(x, n = 1) {
if (n === 1) return parity1(x);
const m = (1 << n) - 1;
let a = 0 | 0;
while(x){
a ^= x & m;
x >>>= n;
}
return a;
}
/**
* Rotate bits by a certain amount.
* @param x an int32
* @param n rotate amount (+ve: left, -ve: right)
*/ export function rotate(x, n = 0) {
return n < 0 ? x << 32 + n | x >>> -n : x << n | x >> 32 - n;
}
/**
* Reverse all bits.
* @param x an int32
*/ export function reverse(x) {
x = x >>> 1 & 0x55555555 | (x & 0x55555555) << 1;
x = x >>> 2 & 0x33333333 | (x & 0x33333333) << 2;
x = x >>> 4 & 0x0F0F0F0F | (x & 0x0F0F0F0F) << 4;
x = x >>> 8 & 0x00FF00FF | (x & 0x00FF00FF) << 8;
return x >>> 16 | x << 16;
}
/**
* Merge bits as per mask.
* @param x first int32
* @param y second int32
* @param m bit mask (0 ⇒ from x)
*/ export function merge(x, y, m) {
return x ^ (x ^ y) & m;
}
/**
* Interleave bits of two int16s.
* @param x first int16
* @param y second int16
* @returns int32
*/ export function interleave(x, y) {
x = (x | x << 8) & 0x00FF00FF;
x = (x | x << 4) & 0x0F0F0F0F;
x = (x | x << 2) & 0x33333333;
x = (x | x << 1) & 0x55555555;
y = (y | y << 8) & 0x00FF00FF;
y = (y | y << 4) & 0x0F0F0F0F;
y = (y | y << 2) & 0x33333333;
y = (y | y << 1) & 0x55555555;
return y | x << 1;
}
/**
* Sign extend variable bit-width integer.
* @param x variable bit-width integer
* @param w bit width (32)
*/ export function signExtend(x, w = 32) {
w = 32 - w;
return x << w >> w;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9leHRyYS1iaXQvZXh0cmEtYml0L2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIE1FVEhPRFNcbi8vID09PT09PT1cblxuLy8gR2V0IGludGVnZXIgd2l0aCAxcyBvZiBzcGVjaWZpZWQgd2lkdGggaW4gYml0cy5cbmZ1bmN0aW9uIG9uZXModzogbnVtYmVyKSB7XG4gIHJldHVybiAoMTw8dykgLSAxO1xufVxuXG5cbi8qKlxuICogR2V0IGJpdHMgYXQgc3BlY2lmaWVkIGluZGV4LlxuICogQHBhcmFtIHggYW4gaW50MzJcbiAqIEBwYXJhbSBpIGJpdCBpbmRleFxuICogQHBhcmFtIHcgYml0IHdpZHRoIFsxXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0KHg6IG51bWJlciwgaTogbnVtYmVyLCB3OiBudW1iZXI9MSk6IG51bWJlciB7XG4gIHJldHVybiAoeD4+PmkpICYgb25lcyh3KTtcbn1cblxuXG4vKipcbiAqIEdldCBiaXRzIGFzIHBlciBtYXNrLlxuICogQHBhcmFtIHggYW4gaW50MzJcbiAqIEBwYXJhbSBtIGJpdCBtYXNrXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBcyh4OiBudW1iZXIsIG06IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB4ICYgbTtcbn1cblxuXG4vKipcbiAqIFNldCBiaXRzIGF0IHNwZWNpZmllZCBpbmRleC5cbiAqIEBwYXJhbSB4IGFuIGludDMyXG4gKiBAcGFyYW0gaSBiaXQgaW5kZXhcbiAqIEBwYXJhbSB2IGJpdCB2YWx1ZSBbMV1cbiAqIEBwYXJhbSB3IGJpdCB3aWR0aCBbMV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldCh4OiBudW1iZXIsIGk6IG51bWJlciwgdjogbnVtYmVyPTEsIHc6IG51bWJlcj0xKTogbnVtYmVyIHtcbiAgcmV0dXJuICh4ICYgfihvbmVzKHcpPDxpKSkgfCAodjw8aSk7XG59XG5cblxuLyoqXG4gKiBTZXQgYml0cyBhcyBwZXIgbWFzay5cbiAqIEBwYXJhbSB4IGFuIGludDMyXG4gKiBAcGFyYW0gbSBiaXQgbWFza1xuICogQHBhcmFtIGYgYml0IHZhbHVlIFsxXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0QXMoeDogbnVtYmVyLCBtOiBudW1iZXIsIGY6IG51bWJlcj0xKTogbnVtYmVyIHtcbiAgcmV0dXJuICh4ICYgfm0pIHwgKC1mICYgbSk7XG59XG5cblxuLyoqXG4gKiBUb2dnbGUgYml0cyBhdCBzcGVjaWZpZWQgaW5kZXguXG4gKiBAcGFyYW0geCBhbiBpbnQzMlxuICogQHBhcmFtIGkgYml0IGluZGV4XG4gKiBAcGFyYW0gdyBiaXQgd2lkdGggWzFdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b2dnbGUoeDogbnVtYmVyLCBpOiBudW1iZXIsIHc6IG51bWJlcj0xKTogbnVtYmVyIHtcbiAgcmV0dXJuIHggXiAob25lcyh3KTw8aSk7XG59XG5cblxuLyoqXG4gKiBUb2dnbGUgYml0cyBhcyBwZXIgbWFzay5cbiAqIEBwYXJhbSB4IGFuIGludDMyXG4gKiBAcGFyYW0gbSBiaXQgbWFza1xuICovXG5leHBvcnQgZnVuY3Rpb24gdG9nZ2xlQXMoeDogbnVtYmVyLCBtOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4geCBeIG07XG59XG5cblxuLyoqXG4gKiBTd2FwIGJpdCBzZXF1ZW5jZXMgYXQgc3BlY2lmaWVkIGluZGljZXMuXG4gKiBAcGFyYW0geCBhbiBpbnQzMlxuICogQHBhcmFtIGkgZmlyc3QgYml0IGluZGV4XG4gKiBAcGFyYW0gaiBzZWNvbmQgYml0IGluZGV4XG4gKiBAcGFyYW0gdyBiaXQgd2lkdGggWzFdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzd2FwKHg6IG51bWJlciwgaTogbnVtYmVyLCBqOiBudW1iZXIsIHc6IG51bWJlcj0xKTogbnVtYmVyIHtcbiAgY29uc3QgdCA9ICgoeD4+PmkpXih4Pj4+aikpICYgb25lcyh3KTtcbiAgcmV0dXJuIHggXiAoKHQ8PGkpfCh0PDxqKSk7XG59XG5cblxuY29uc3QgTU9EMzdfUE9TMzI6IG51bWJlcltdID0gW1xuICAzMiwgMCwgMSwgMjYsIDIsIDIzLCAyNywgMCwgMywgMTYsIDI0LCAzMCwgMjgsIDExLCAwLCAxMywgNCwgNywgMTcsIDAsXG4gIDI1LCAyMiwgMzEsIDE1LCAyOSwgMTAsIDEyLCA2LCAwLCAyMSwgMTQsIDksIDUsIDIwLCA4LCAxOSwgMThcbl07XG5cblxuLyoqXG4gKiBGaW5kIGluZGV4IG9mIGZpcnN0IHNldCBiaXQgZnJvbSBMU0IuXG4gKiBAcGFyYW0geCBhbiBpbnQzMlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2Nhbih4OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gTU9EMzdfUE9TMzJbKC14ICYgeCkgJSAzN107XG59XG5cblxuY29uc3QgREVCUlVJSk5fUE9TMzI6IG51bWJlcltdID0gW1xuICAwLCAgOSwgIDEsIDEwLCAxMywgMjEsICAyLCAyOSwgMTEsIDE0LCAxNiwgMTgsIDIyLCAyNSwgIDMsIDMwLFxuICA4LCAxMiwgMjAsIDI4LCAxNSwgMTcsIDI0LCAgNywgMTksIDI3LCAyMywgIDYsIDI2LCAgNSwgIDQsIDMxXG5dO1xuXG5cbi8qKlxuICogRmluZCBpbmRleCBvZiBmaXJzdCBzZXQgYml0IGZyb20gTVNCLlxuICogQHBhcmFtIHggYW4gaW50MzJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYW5SZXZlcnNlKHg6IG51bWJlcik6IG51bWJlciB7XG4gIHggfD0geD4+PjE7XG4gIHggfD0geD4+PjI7XG4gIHggfD0geD4+PjQ7XG4gIHggfD0geD4+Pjg7XG4gIHggfD0geD4+PjE2O1xuICByZXR1cm4gREVCUlVJSk5fUE9TMzJbKHgqMHgwN0M0QUNERCk+Pj4yN107XG59XG5cblxuLyoqXG4gKiBDb3VudCBiaXRzIHNldC5cbiAqIEBwYXJhbSB4IGFuIGludDMyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3VudCh4OiBudW1iZXIpOiBudW1iZXIge1xuICB4ID0geCAtICgoeD4+PjEpICYgMHg1NTU1NTU1NSk7XG4gIHggPSAoeCAmIDB4MzMzMzMzMzMpICsgKCh4Pj4+MikgJiAweDMzMzMzMzMzKTtcbiAgcmV0dXJuICgoeCArICh4Pj4+NCkgJiAweDBGMEYwRjBGKSAqIDB4MDEwMTAxMDEpPj4+MjQ7XG59XG5cblxuLy8gQ2FsY3VsYXRlIDEtYml0IHBhcml0eS5cbmZ1bmN0aW9uIHBhcml0eTEoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgeCBePSB4Pj4+MTY7XG4gIHggXj0geD4+Pjg7XG4gIHggXj0geD4+PjQ7XG4gIHggJj0gMHhGO1xuICByZXR1cm4gKDB4Njk5Nj4+PngpICYgMTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgbi1iaXQgcGFyaXR5LlxuICogQHBhcmFtIHggYW4gaW50MzJcbiAqIEBwYXJhbSBuIG51bWJlciBvZiBiaXRzIFsxXVxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyaXR5KHg6IG51bWJlciwgbjogbnVtYmVyPTEpOiBudW1iZXIge1xuICBpZiAobj09PTEpIHJldHVybiBwYXJpdHkxKHgpO1xuICBjb25zdCBtID0gKDE8PG4pLTE7IGxldCBhID0gMHwwO1xuICB3aGlsZSAoeCkge1xuICAgIGEgXj0geCZtO1xuICAgIHggPj4+PSBuO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogUm90YXRlIGJpdHMgYnkgYSBjZXJ0YWluIGFtb3VudC5cbiAqIEBwYXJhbSB4IGFuIGludDMyXG4gKiBAcGFyYW0gbiByb3RhdGUgYW1vdW50ICgrdmU6IGxlZnQsIC12ZTogcmlnaHQpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByb3RhdGUoeDogbnVtYmVyLCBuOiBudW1iZXI9MCk6IG51bWJlciB7XG4gIHJldHVybiBuPDA/IHg8PDMyK24gfCB4Pj4+LW4gOiB4PDxuIHwgeD4+MzItbjtcbn1cblxuXG4vKipcbiAqIFJldmVyc2UgYWxsIGJpdHMuXG4gKiBAcGFyYW0geCBhbiBpbnQzMlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmV2ZXJzZSh4OiBudW1iZXIpOiBudW1iZXIge1xuICB4ID0gKCh4Pj4+MSkgJiAweDU1NTU1NTU1KSB8ICgoeCAmIDB4NTU1NTU1NTUpPDwxKTtcbiAgeCA9ICgoeD4+PjIpICYgMHgzMzMzMzMzMykgfCAoKHggJiAweDMzMzMzMzMzKTw8Mik7XG4gIHggPSAoKHg+Pj40KSAmIDB4MEYwRjBGMEYpIHwgKCh4ICYgMHgwRjBGMEYwRik8PDQpO1xuICB4ID0gKCh4Pj4+OCkgJiAweDAwRkYwMEZGKSB8ICgoeCAmIDB4MDBGRjAwRkYpPDw4KTtcbiAgcmV0dXJuICh4Pj4+MTYpIHwgKHg8PDE2KTtcbn1cblxuXG4vKipcbiAqIE1lcmdlIGJpdHMgYXMgcGVyIG1hc2suXG4gKiBAcGFyYW0geCBmaXJzdCBpbnQzMlxuICogQHBhcmFtIHkgc2Vjb25kIGludDMyXG4gKiBAcGFyYW0gbSBiaXQgbWFzayAoMCDih5IgZnJvbSB4KVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWVyZ2UoeDogbnVtYmVyLCB5OiBudW1iZXIsIG06IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB4IF4gKCh4XnkpICYgbSk7XG59XG5cblxuLyoqXG4gKiBJbnRlcmxlYXZlIGJpdHMgb2YgdHdvIGludDE2cy5cbiAqIEBwYXJhbSB4IGZpcnN0IGludDE2XG4gKiBAcGFyYW0geSBzZWNvbmQgaW50MTZcbiAqIEByZXR1cm5zIGludDMyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcmxlYXZlKHg6IG51bWJlciwgeTogbnVtYmVyKTogbnVtYmVyIHtcbiAgeCA9ICh4IHwgKHg8PDgpKSAmIDB4MDBGRjAwRkY7XG4gIHggPSAoeCB8ICh4PDw0KSkgJiAweDBGMEYwRjBGO1xuICB4ID0gKHggfCAoeDw8MikpICYgMHgzMzMzMzMzMztcbiAgeCA9ICh4IHwgKHg8PDEpKSAmIDB4NTU1NTU1NTU7XG4gIHkgPSAoeSB8ICh5PDw4KSkgJiAweDAwRkYwMEZGO1xuICB5ID0gKHkgfCAoeTw8NCkpICYgMHgwRjBGMEYwRjtcbiAgeSA9ICh5IHwgKHk8PDIpKSAmIDB4MzMzMzMzMzM7XG4gIHkgPSAoeSB8ICh5PDwxKSkgJiAweDU1NTU1NTU1O1xuICByZXR1cm4geSB8ICh4PDwxKTtcbn1cblxuXG4vKipcbiAqIFNpZ24gZXh0ZW5kIHZhcmlhYmxlIGJpdC13aWR0aCBpbnRlZ2VyLlxuICogQHBhcmFtIHggdmFyaWFibGUgYml0LXdpZHRoIGludGVnZXJcbiAqIEBwYXJhbSB3IGJpdCB3aWR0aCAoMzIpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduRXh0ZW5kKHg6IG51bWJlciwgdzogbnVtYmVyPTMyKTogbnVtYmVyIHtcbiAgdyA9IDMyLXc7XG4gIHJldHVybiAoeDw8dyk+Pnc7XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsVUFBVTtBQUNWLFVBQVU7QUFFVixrREFBa0Q7QUFDbEQsU0FBUyxLQUFLLENBQVM7RUFDckIsT0FBTyxDQUFDLEtBQUcsQ0FBQyxJQUFJO0FBQ2xCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsSUFBSSxDQUFTLEVBQUUsQ0FBUyxFQUFFLElBQVUsQ0FBQztFQUNuRCxPQUFPLEFBQUMsTUFBSSxJQUFLLEtBQUs7QUFDeEI7QUFHQTs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLE1BQU0sQ0FBUyxFQUFFLENBQVM7RUFDeEMsT0FBTyxJQUFJO0FBQ2I7QUFHQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsSUFBSSxDQUFTLEVBQUUsQ0FBUyxFQUFFLElBQVUsQ0FBQyxFQUFFLElBQVUsQ0FBQztFQUNoRSxPQUFPLEFBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxNQUFJLENBQUMsSUFBTSxLQUFHO0FBQ25DO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsTUFBTSxDQUFTLEVBQUUsQ0FBUyxFQUFFLElBQVUsQ0FBQztFQUNyRCxPQUFPLEFBQUMsSUFBSSxDQUFDLElBQU0sQ0FBQyxJQUFJO0FBQzFCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsT0FBTyxDQUFTLEVBQUUsQ0FBUyxFQUFFLElBQVUsQ0FBQztFQUN0RCxPQUFPLElBQUss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