or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

arithmetic.mdbitwise.mdcomparison.mdconversion.mdindex.mdproperties.md
tile.json

bitwise.mddocs/

Bitwise Operations

Bitwise operations on BigInteger values using two's complement representation, including AND, OR, XOR, NOT, bit shifts, and bit length calculation.

Capabilities

Bitwise Logical Operations

All bitwise operations treat operands as if they were represented using two's complement representation.

Bitwise AND

Perform bitwise AND operation.

/**
 * Performs bitwise AND operation
 * Operands are treated using two's complement representation
 * @param number - Value to AND with
 * @returns New BigInteger with result
 */
and(number: BigNumber): BigInteger;

Usage Examples:

const bigInt = require('big-integer');

// Bitwise AND with positive numbers
bigInt(6).and(3);   // 2 (0b110 & 0b011 = 0b010)

// Bitwise AND with negative numbers (two's complement)
bigInt(6).and(-3);  // 4 (0b110 & ...11111101 = 0b100)

// Masking operation
bigInt(255).and(15);  // 15 (extract lower 4 bits)

Bitwise OR

Perform bitwise OR operation.

/**
 * Performs bitwise OR operation
 * Operands are treated using two's complement representation
 * @param number - Value to OR with
 * @returns New BigInteger with result
 */
or(number: BigNumber): BigInteger;

Usage Examples:

// Bitwise OR with positive numbers
bigInt(13).or(10);  // 15 (0b1101 | 0b1010 = 0b1111)

// Bitwise OR with negative numbers (two's complement)
bigInt(13).or(-8);  // -3

// Setting bits
bigInt(0).or(5);  // 5 (set bits at positions 0 and 2)

Bitwise XOR

Perform bitwise XOR (exclusive OR) operation.

/**
 * Performs bitwise XOR operation
 * Operands are treated using two's complement representation
 * @param number - Value to XOR with
 * @returns New BigInteger with result
 */
xor(number: BigNumber): BigInteger;

Usage Examples:

// Bitwise XOR with positive numbers
bigInt(12).xor(5);   // 9 (0b1100 ^ 0b0101 = 0b1001)

// Bitwise XOR with negative numbers (two's complement)
bigInt(12).xor(-5);  // -9

// Toggling bits
const value = bigInt(15);
const mask = bigInt(8);
value.xor(mask);  // 7 (toggle bit at position 3)

Bitwise NOT

Perform bitwise NOT (complement) operation.

/**
 * Performs bitwise NOT operation
 * Operands are treated using two's complement representation
 * @param number - Value to NOT
 * @returns New BigInteger with bitwise complement
 */
not(): BigInteger;

Usage Examples:

// Bitwise NOT
bigInt(10).not();  // -11 (~0b1010 = ...11110101 = -11 in two's complement)

// NOT of zero
bigInt(0).not();   // -1

// NOT of -1
bigInt(-1).not();  // 0

Bit Shift Operations

Left Shift

Shift bits to the left (equivalent to multiplying by powers of 2).

/**
 * Shifts the number left by n places in binary representation
 * Negative n shifts right
 * @param n - Number of positions to shift
 * @returns New BigInteger shifted left
 * @throws Error if n is outside range [-9007199254740992, 9007199254740992]
 */
shiftLeft(n: BigNumber): BigInteger;

Usage Examples:

// Left shift (multiply by power of 2)
bigInt(8).shiftLeft(2);   // 32 (8 * 2^2)

// Left shift by 10 (multiply by 1024)
bigInt(5).shiftLeft(10);  // 5120

// Negative shift amount shifts right
bigInt(8).shiftLeft(-2);  // 2 (equivalent to shiftRight(2))

// Large shifts
bigInt(1).shiftLeft(100);  // 1267650600228229401496703205376

Right Shift

Shift bits to the right (equivalent to dividing by powers of 2).

/**
 * Shifts the number right by n places in binary representation
 * Negative n shifts left
 * @param n - Number of positions to shift
 * @returns New BigInteger shifted right
 * @throws Error if n is outside range [-9007199254740992, 9007199254740992]
 */
shiftRight(n: BigNumber): BigInteger;

Usage Examples:

// Right shift (divide by power of 2)
bigInt(8).shiftRight(2);   // 2 (8 / 2^2)

// Right shift by 10 (divide by 1024)
bigInt(5120).shiftRight(10);  // 5

// Negative shift amount shifts left
bigInt(8).shiftRight(-2);  // 32 (equivalent to shiftLeft(2))

// Right shift with negative numbers (arithmetic shift)
bigInt(-16).shiftRight(2);  // -4

Shift Range Restrictions:

Both shiftLeft and shiftRight throw an error if the shift amount is outside the range [-9007199254740992, 9007199254740992]. This is the safe integer range for JavaScript numbers.

// Valid shift
bigInt(1).shiftLeft(1000);  // OK

// Invalid shift - outside safe range
try {
  bigInt(1).shiftLeft(9007199254740993);  // Throws Error
} catch (e) {
  console.error("Shift amount outside valid range");
}

Bit Length

Bit Length Calculation

Calculate the number of bits required to represent a BigInteger in binary.

/**
 * Returns the number of bits required to represent the number in binary
 * For positive numbers, this is ceil(log2(n + 1))
 * For negative numbers, uses two's complement representation
 * @returns BigInteger representing the bit length
 */
bitLength(): BigInteger;

Usage Examples:

// Bit length of small numbers
bigInt(5).bitLength();   // 3 (binary: 101)
bigInt(7).bitLength();   // 3 (binary: 111)
bigInt(8).bitLength();   // 4 (binary: 1000)

// Bit length of power of 2
bigInt(256).bitLength(); // 9 (binary: 100000000)

// Bit length of zero
bigInt(0).bitLength();   // 0

// Large number
bigInt("123456789").bitLength();  // 27

Two's Complement Representation

All bitwise operations in BigInteger.js use two's complement representation, which is the standard way to represent signed integers in binary. Key points:

  1. Positive Numbers: Represented directly in binary

    • Example: 6 = 0b110
  2. Negative Numbers: Represented as the bitwise complement plus one

    • Example: -6 = NOT(0b110) + 1 = ...11111010 (infinite leading 1s)
  3. Sign Extension: Negative numbers conceptually have infinite leading 1-bits

    • This affects operations like AND, OR, XOR with negative operands

Examples of Two's Complement:

// Understanding two's complement with AND
bigInt(6).and(3);    // 2  (0b110 & 0b011)
bigInt(6).and(-3);   // 4  (0b110 & ...11111101)

// Understanding two's complement with OR
bigInt(12).or(-10);  // -10 (all bits from -10 remain)

// NOT operation flips all bits (including conceptual leading zeros)
bigInt(5).not();     // -6 (NOT(0b101) = ...11111010 = -6)

Practical Use Cases

Bit Manipulation

// Set a specific bit
function setBit(num, position) {
  return num.or(bigInt.one.shiftLeft(position));
}

// Clear a specific bit
function clearBit(num, position) {
  return num.and(bigInt.one.shiftLeft(position).not());
}

// Toggle a specific bit
function toggleBit(num, position) {
  return num.xor(bigInt.one.shiftLeft(position));
}

// Test if bit is set
function isBitSet(num, position) {
  return num.shiftRight(position).and(1).equals(1);
}

// Examples
let value = bigInt(0);
value = setBit(value, 3);     // Set bit 3: value = 8
value = setBit(value, 1);     // Set bit 1: value = 10
value = toggleBit(value, 3);  // Toggle bit 3: value = 2

Masking

// Extract lower n bits
function getLowerBits(num, n) {
  const mask = bigInt.one.shiftLeft(n).subtract(1);
  return num.and(mask);
}

// Extract specific byte
function getByte(num, byteIndex) {
  return num.shiftRight(byteIndex * 8).and(255);
}

// Examples
const value = bigInt("0xABCDEF", 16);
getLowerBits(value, 8);  // 0xEF (239)
getByte(value, 1);       // 0xCD (205)

Fast Multiplication/Division by Powers of 2

// Multiply by 2^n (faster than multiply)
const num = bigInt(5);
num.shiftLeft(10);  // 5 * 1024 = 5120

// Divide by 2^n (faster than divide)
const big = bigInt(5120);
big.shiftRight(10);  // 5120 / 1024 = 5

Performance Notes

  • AND, OR, XOR, NOT: O(n) where n is the number of digits/bits
  • Shift Operations: O(n) but very fast for small shift amounts
  • Bit Length: O(n) where n is the number of digits

Shift operations are significantly faster than equivalent multiplication or division operations when working with powers of 2.