mirror of
https://github.com/robonen/tools.git
synced 2026-03-20 02:44:45 +00:00
feat(packages/stdlib): add bit vector tool
This commit is contained in:
57
packages/stdlib/src/bits/vector/index.test.ts
Normal file
57
packages/stdlib/src/bits/vector/index.test.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { BitVector } from '.';
|
||||||
|
|
||||||
|
describe('BitVector', () => {
|
||||||
|
it('should initialize with the correct size', () => {
|
||||||
|
const size = 16;
|
||||||
|
const expectedSize = Math.ceil(size / 8);
|
||||||
|
const bitVector = new BitVector(size);
|
||||||
|
|
||||||
|
expect(bitVector.length).toBe(expectedSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set and get bits correctly', () => {
|
||||||
|
const bitVector = new BitVector(16);
|
||||||
|
bitVector.setBit(5);
|
||||||
|
|
||||||
|
expect(bitVector.getBit(5)).toBe(true);
|
||||||
|
expect(bitVector.getBit(4)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clear bits correctly', () => {
|
||||||
|
const bitVector = new BitVector(16);
|
||||||
|
bitVector.setBit(5);
|
||||||
|
|
||||||
|
expect(bitVector.getBit(5)).toBe(true);
|
||||||
|
|
||||||
|
bitVector.clearBit(5);
|
||||||
|
|
||||||
|
expect(bitVector.getBit(5)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find the previous bit correctly', () => {
|
||||||
|
const bitVector = new BitVector(100);
|
||||||
|
const indices = [99, 88, 66, 65, 64, 63, 15, 14, 1, 0];
|
||||||
|
const result = [];
|
||||||
|
indices.forEach(index => bitVector.setBit(index));
|
||||||
|
|
||||||
|
for (let i = bitVector.previousBit(100); i !== -1; i = bitVector.previousBit(i)) {
|
||||||
|
result.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(result).toEqual(indices);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return -1 when no previous bit is found', () => {
|
||||||
|
const bitVector = new BitVector(16);
|
||||||
|
|
||||||
|
expect(bitVector.previousBit(0)).toBe(-1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw RangeError when previousBit is called with an unreachable value', () => {
|
||||||
|
const bitVector = new BitVector(16);
|
||||||
|
bitVector.setBit(5);
|
||||||
|
|
||||||
|
expect(() => bitVector.previousBit(24)).toThrow(new RangeError('Unreachable value'));
|
||||||
|
});
|
||||||
|
});
|
||||||
61
packages/stdlib/src/bits/vector/index.ts
Normal file
61
packages/stdlib/src/bits/vector/index.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
export interface BitVector {
|
||||||
|
getBit(index: number): boolean;
|
||||||
|
setBit(index: number): void;
|
||||||
|
clearBit(index: number): void;
|
||||||
|
previousBit(index: number): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name BitVector
|
||||||
|
* @category Bits
|
||||||
|
* @description A bit vector is a vector of bits that can be used to store a collection of bits
|
||||||
|
*
|
||||||
|
* @since 0.0.3
|
||||||
|
*/
|
||||||
|
export class BitVector extends Uint8Array implements BitVector {
|
||||||
|
constructor(size: number) {
|
||||||
|
super(Math.ceil(size / 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
getBit(index: number) {
|
||||||
|
const value = this[index >> 3]! & (1 << (index & 7));
|
||||||
|
return value !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBit(index: number) {
|
||||||
|
this[index >> 3]! |= 1 << (index & 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearBit(index: number): void {
|
||||||
|
this[index >> 3]! &= ~(1 << (index & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
previousBit(index: number): number {
|
||||||
|
while (index !== ((index >> 3) << 3)) {
|
||||||
|
--index;
|
||||||
|
|
||||||
|
if (this.getBit(index)) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let byteIndex = (index >> 3) - 1;
|
||||||
|
|
||||||
|
while (byteIndex >= 0 && this[byteIndex] === 0)
|
||||||
|
--byteIndex;
|
||||||
|
|
||||||
|
if (byteIndex < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
index = (byteIndex << 3) + 7;
|
||||||
|
|
||||||
|
while (index >= (byteIndex << 3)) {
|
||||||
|
if (this.getBit(index))
|
||||||
|
return index;
|
||||||
|
|
||||||
|
--index;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RangeError('Unreachable value');
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user