How to copy bits from M into N (numbers) between bit positions i and j (edge‑case‑safe) in TypeScript

1 Answer

0 votes
/**
 * Converts a BigInt to a binary string representation.
 */
function toBinary(x: bigint): string {
    return x.toString(2);
}

/**
 * Replaces bits in N from index i to j (inclusive) with the bits from M.
 * * Logic:
 * 1. Create a mask of 1s for the length (j - i + 1).
 * 2. Clear the target bits in N using the inverse of that mask shifted to i.
 * 3. Mask M to ensure it doesn't overflow the range, then shift it to i.
 * 4. Combine them using OR.
 */
function copyBits(N: bigint, M: bigint, i: number, j: number): bigint {
    // Basic validation
    if (i < 0 || j < 0 || i > j) {
        throw new Error("Invalid bit range: i must be <= j and both non-negative.");
    }

    // Calculate length as a bigint to avoid repeated casting
    const length: any = BigInt(j - i + 1);
    
    // 1. Create a mask of 1s for the width of the range: (1 << length) - 1
    const rangeMask: bigint = (1n << length) - 1n;

    // 2. Shift that mask to the starting position i
    const positionedMask: bigint = rangeMask << BigInt(i);

    // 3. Clear bits i..j in N
    const Ncleared: bigint = N & ~positionedMask;

    // 4. Take the bits from M (ensuring M isn't wider than the range) 
    //    and shift them to position i
    const MmaskedAndShifted: bigint = (M & rangeMask) << BigInt(i);

    // 5. Merge
    return Ncleared | MmaskedAndShifted;
}

function main(): void {
    // N: 100 011111 00 (binary)
    const N = 0b10001111100n; // 1148n
    // M: 110011
    const M = 0b110011n; // 51n

    // We want to replace the middle 6 bits (index 2 to 7)
    const result = copyBits(N, M, 2, 7);

    console.log("=== Bit Manipulation Result ===");
    console.log(`N:      ${toBinary(N).padStart(11, '0')}`);
    console.log(`M:      ${toBinary(M).padStart(11, '0')}`);
    console.log(`Result: ${toBinary(result).padStart(11, '0')}`);
}

main();



/*
OUTPUT:

=== Bit Manipulation Result ===

N:      10001111100
M:      00000110011
Result: 10011001100

*/

 



answered Mar 30 by avibootz

Related questions

...