Files
esengine/source/src/ECS/Utils/BitSet.ts

137 lines
4.2 KiB
TypeScript
Raw Normal View History

2020-07-23 09:10:27 +08:00
module es {
/**
*
*
* ;
*/
2020-07-28 16:25:20 +08:00
export class BitSet {
2020-07-23 09:10:27 +08:00
private static LONG_MASK: number = 0x3f;
private _bits: number[];
2020-07-28 16:25:20 +08:00
constructor(nbits: number = 64) {
let length = nbits >> 6;
2020-07-23 09:10:27 +08:00
if ((nbits & BitSet.LONG_MASK) != 0)
2020-07-28 16:25:20 +08:00
length++;
2020-07-23 09:10:27 +08:00
this._bits = new Array(length);
this._bits.fill(0);
2020-07-23 09:10:27 +08:00
}
2020-06-08 20:11:58 +08:00
2020-07-28 16:25:20 +08:00
public and(bs: BitSet) {
2020-07-23 09:10:27 +08:00
let max = Math.min(this._bits.length, bs._bits.length);
let i;
for (let i = 0; i < max; ++i)
this._bits[i] &= bs._bits[i];
2020-06-08 20:11:58 +08:00
2020-07-23 09:10:27 +08:00
while (i < this._bits.length)
2020-07-28 16:25:20 +08:00
this._bits[i++] = 0;
2020-07-23 09:10:27 +08:00
}
2020-06-08 20:11:58 +08:00
2020-07-28 16:25:20 +08:00
public andNot(bs: BitSet) {
2020-07-23 09:10:27 +08:00
let i = Math.min(this._bits.length, bs._bits.length);
2020-07-28 16:25:20 +08:00
while (--i >= 0)
2020-07-23 09:10:27 +08:00
this._bits[i] &= ~bs._bits[i];
}
2020-06-08 20:11:58 +08:00
2020-07-28 16:25:20 +08:00
public cardinality(): number {
let card = 0;
2020-07-28 16:25:20 +08:00
for (let i = this._bits.length - 1; i >= 0; i--) {
2020-07-23 09:10:27 +08:00
let a = this._bits[i];
if (a == 0)
continue;
2020-07-28 16:25:20 +08:00
if (a == -1) {
2020-07-23 09:10:27 +08:00
card += 64;
continue;
}
a = ((a >> 1) & 0x5555555555555555) + (a & 0x5555555555555555);
a = ((a >> 2) & 0x3333333333333333) + (a & 0x3333333333333333);
let b = ((a >> 32) + a) >>> 0;
2020-07-23 09:10:27 +08:00
b = ((b >> 4) & 0x0f0f0f0f) + (b & 0x0f0f0f0f);
b = ((b >> 8) & 0x00ff00ff) + (b & 0x00ff00ff);
card += ((b >> 16) & 0x0000ffff) + (b & 0x0000ffff);
}
2020-06-08 20:11:58 +08:00
2020-07-23 09:10:27 +08:00
return card;
}
2020-06-08 20:11:58 +08:00
2020-07-28 16:25:20 +08:00
public clear(pos?: number) {
if (pos != undefined) {
2020-07-23 09:10:27 +08:00
let offset = pos >> 6;
this.ensure(offset);
this._bits[offset] &= ~(1 << pos);
2020-07-28 16:25:20 +08:00
} else {
for (let i = 0; i < this._bits.length; i++)
2020-07-23 09:10:27 +08:00
this._bits[i] = 0;
2020-06-08 20:11:58 +08:00
}
}
2020-07-28 16:25:20 +08:00
public get(pos: number): boolean {
2020-06-08 20:11:58 +08:00
let offset = pos >> 6;
2020-07-23 09:10:27 +08:00
if (offset >= this._bits.length)
return false;
2020-06-08 20:11:58 +08:00
2020-07-23 09:10:27 +08:00
return (this._bits[offset] & (1 << pos)) != 0;
2020-06-08 20:11:58 +08:00
}
2020-07-28 16:25:20 +08:00
public intersects(set: BitSet) {
2020-07-23 09:10:27 +08:00
let i = Math.min(this._bits.length, set._bits.length);
2020-07-28 16:25:20 +08:00
while (--i >= 0) {
2020-07-23 09:10:27 +08:00
if ((this._bits[i] & set._bits[i]) != 0)
return true;
}
2020-06-08 20:11:58 +08:00
2020-07-23 09:10:27 +08:00
return false;
2020-06-08 20:11:58 +08:00
}
2020-07-28 16:25:20 +08:00
public isEmpty(): boolean {
for (let i = this._bits.length - 1; i >= 0; i--) {
2020-07-23 09:10:27 +08:00
if (this._bits[i])
return false;
}
2020-06-08 20:11:58 +08:00
2020-07-23 09:10:27 +08:00
return true;
2020-06-08 20:11:58 +08:00
}
2020-07-28 16:25:20 +08:00
public nextSetBit(from: number) {
2020-07-23 09:10:27 +08:00
let offset = from >> 6;
let mask = 1 << from;
2020-07-28 16:25:20 +08:00
while (offset < this._bits.length) {
2020-07-23 09:10:27 +08:00
let h = this._bits[offset];
do {
if ((h & mask) != 0)
return from;
mask <<= 1;
2020-07-28 16:25:20 +08:00
from++;
2020-07-23 09:10:27 +08:00
} while (mask != 0);
mask = 1;
2020-07-28 16:25:20 +08:00
offset++;
2020-07-23 09:10:27 +08:00
}
2020-06-08 20:11:58 +08:00
2020-07-23 09:10:27 +08:00
return -1;
2020-06-08 20:11:58 +08:00
}
2020-07-28 16:25:20 +08:00
public set(pos: number, value: boolean = true) {
if (value) {
2020-07-23 09:10:27 +08:00
let offset = pos >> 6;
this.ensure(offset);
this._bits[offset] |= 1 << pos;
2020-07-28 16:25:20 +08:00
} else {
2020-07-23 09:10:27 +08:00
this.clear(pos);
}
}
2020-07-28 16:25:20 +08:00
private ensure(lastElt: number) {
if (lastElt >= this._bits.length) {
let startIndex = this._bits.length;
this._bits.length = lastElt + 1;
this._bits.fill(0, startIndex, lastElt + 1);
2020-07-28 16:25:20 +08:00
}
}
2020-06-08 20:11:58 +08:00
}
2020-07-23 09:10:27 +08:00
}