Skip to main content
Home
This release is 3 versions behind 0.1.9 — the latest version of @kitsu/bfs. Jump to latest

@kitsu/bfs@0.1.6

bitset library based on fixedbitset

This package works with Cloudflare Workers, Node.js, Deno, Bun, Browsers
This package works with Cloudflare Workers
This package works with Node.js
This package works with Deno
This package works with Bun
This package works with Browsers
JSR Score
64%
Published
a month ago (0.1.6)
Package root>bitflags.ts
function* chain<T>(...iterators: IteratorObject<T>[]): Generator<T> { for (const iter of iterators) { for (const value of Iterator.from(iter)) { yield value } } } export type Bit = 1 | 0 export type Bits = number export type Index = number export interface IBitSet { get flags(): Bits get length(): number add(index: Index): Bits clear(): void difference(other: IBitSet): IteratorObject<Index> extend(indices: Iterable<Index>): void grow(bits: number): void has(index: Index): boolean intersection(other: IBitSet): IteratorObject<Index> isDisjoint(other: IBitSet): boolean isSubset(other: IBitSet): boolean isSuperset(other: IBitSet): boolean isEmpty(): boolean ones(): IteratorObject<Index> remove(index: Index): Bits set(index: Index, enabled: boolean): Bits symmetricDifference(other: IBitSet): IteratorObject<Index> union(other: IBitSet): IteratorObject<Index> zeroes(): IteratorObject<Index> } export class FixedBitSet implements IBitSet { _value: Bits _length: number get flags(): Bits { return this._value } get length(): number { return this._length } constructor(value: Bits = 0, length: number = 32) { this._value = value this._length = length } static from(value: Iterable<Index> | FixedBitSet): FixedBitSet { if (value instanceof FixedBitSet) { return value } const iter = Iterator.from(value) const next = iter.next() if (next.value == null || next.done) { return new FixedBitSet() } let bits = next.value let len = 0 for (const index of iter) { bits |= 1 << index len = index } return new FixedBitSet(bits, Math.max(32, len)) } static has(value: Bits, index: Index): boolean { return (value & (1 << index)) !== 0 } static *ones(value: Bits, length: number = 32): Generator<Index> { for (let i = 0; i < length; i++) { if ((value & 1) > 0) { yield i } value = value >> 1 } } static *zeros(value: Bits, length: number = 32): Generator<Index> { for (let i = 0; i < length; i++) { if ((value & 1) === 0) { yield i } value = value >> 1 } } static length(value: Bits): number { value = value - (value >> 1) & 0x55555555 value = (value & 0x33333333) + (value >> 2) & 0x33333333 return ((value + (value >> 4) & 0xF0F0F0F) * 0x1010101) >> 24 } static *intersection(a: IBitSet, b: IBitSet): Generator<Index> { for (const index of FixedBitSet.ones(a.flags)) { if (b.has(index)) { yield index } } } static *difference(a: IBitSet, b: IBitSet): Generator<Index> { for (const index of FixedBitSet.ones(a.flags)) { if (!b.has(index)) { yield index } } } static *union(a: IBitSet, b: IBitSet): Generator<Index> { for ( const index of chain( FixedBitSet.ones(a.flags, a.length), FixedBitSet.difference(b, a), ) ) { yield index } } static *symmetricDifference(a: IBitSet, b: IBitSet): Generator<Index> { for ( const index of chain( FixedBitSet.difference(a, b), FixedBitSet.difference(b, a), ) ) { yield index } } static isDisjoint(a: IBitSet, b: IBitSet): boolean { return FixedBitSet.intersection(a, b).next().done || false } static isSubset(a: IBitSet, b: IBitSet): boolean { for (const index of FixedBitSet.ones(a.flags, a.length)) { if (!b.has(index)) { return false } } return true } static isSuperset(a: IBitSet, b: IBitSet): boolean { return b.isSubset(a) } static isEmpty(value: Bits): boolean { return value === 0 } static add(value: Bits, index: Index): Bits { return value |= 1 << index } static remove(value: Bits, index: Index): Bits { return value & ~(1 << index) } static set(value: Bits, index: Index, enabled: boolean): Bits { return enabled ? FixedBitSet.add(value, index) : FixedBitSet.remove(value, index) } clear() { this._value = 0 } has(b: Index): boolean { return FixedBitSet.has(this._value, b) } set(index: Index, enabled: boolean): Bits { this._value = FixedBitSet.set(this._value, index, enabled) return this._value } extend(indices: Iterable<Index>): void { for (const index of indices) { if (index >= this._length) { this.grow(index + 1) } this.add(index) } } grow(bits: number): void { if (bits > this._length) { this._length = bits } } growAndAdd(index: Index): Bits { this.grow(index) return this.add(index) } union(other: IBitSet): IteratorObject<Index> { return FixedBitSet.union(this, other) } add(index: Index): Bits { this._value = FixedBitSet.add(this._value, index) return this._value } remove(index: Index): Bits { this._value = FixedBitSet.remove(this._value, index) return this._value } isDisjoint(other: IBitSet): boolean { return FixedBitSet.isDisjoint(this, other) } isSubset(other: IBitSet): boolean { return FixedBitSet.isSubset(this, other) } isSuperset(other: IBitSet): boolean { return FixedBitSet.isSuperset(this, other) } isEmpty(): boolean { return FixedBitSet.isEmpty(this._value) } ones(): IteratorObject<Index> { return FixedBitSet.ones(this._value, this._length) } zeroes(): IteratorObject<Index> { return FixedBitSet.zeros(this._value, this._length) } intersection(other: IBitSet): IteratorObject<Index> { return FixedBitSet.intersection(this, other) } difference(other: IBitSet): IteratorObject<Index> { return FixedBitSet.difference(this, other) } symmetricDifference(other: IBitSet): IteratorObject<Index> { return FixedBitSet.symmetricDifference(this, other) } toString(): string { return this._value.toString(2) } *[Symbol.iterator](): Generator<Bit> { const len = this._length let value = this._value for (let i = 0; i < len; i++) { yield (value & 1) as Bit value = value >> 1 } } }