2025-07-30 11:11:46 +08:00
|
|
|
|
import { IBigIntLike, BigIntFactory } from './BigIntCompatibility';
|
|
|
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 高性能位操作类
|
2025-07-30 11:11:46 +08:00
|
|
|
|
*
|
|
|
|
|
|
* 基于BigInt实现,支持任意数量的位操作。
|
|
|
|
|
|
* 自动适配运行环境,在不支持BigInt的环境中使用兼容实现。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @example
|
|
|
|
|
|
* ```typescript
|
|
|
|
|
|
* const bits = new Bits();
|
|
|
|
|
|
* bits.set(0);
|
|
|
|
|
|
* bits.set(5);
|
|
|
|
|
|
* console.log(bits.get(0)); // true
|
|
|
|
|
|
* console.log(bits.get(1)); // false
|
|
|
|
|
|
* ```
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
export class Bits {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
private _value: IBigIntLike;
|
2025-06-07 20:32:43 +08:00
|
|
|
|
|
2025-07-30 11:11:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 构造函数
|
|
|
|
|
|
* @param initialValue 初始值,可以是IBigIntLike或数值
|
|
|
|
|
|
*/
|
|
|
|
|
|
constructor(initialValue?: IBigIntLike | number | string) {
|
|
|
|
|
|
if (initialValue && typeof initialValue === 'object') {
|
|
|
|
|
|
this._value = initialValue;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this._value = BigIntFactory.create(initialValue || 0);
|
|
|
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-13 23:32:24 +08:00
|
|
|
|
/**
|
2025-06-07 20:32:43 +08:00
|
|
|
|
* 设置指定位置的位为1
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param index 位索引(从0开始)
|
|
|
|
|
|
* @throws {Error} 当索引为负数时抛出错误
|
2023-03-13 23:32:24 +08:00
|
|
|
|
*/
|
2025-06-07 20:32:43 +08:00
|
|
|
|
public set(index: number): void {
|
2025-06-16 09:36:36 +08:00
|
|
|
|
if (index < 0) {
|
|
|
|
|
|
throw new Error('Bit index cannot be negative');
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
2025-07-30 11:11:46 +08:00
|
|
|
|
const mask = BigIntFactory.one().shiftLeft(index);
|
|
|
|
|
|
this._value = this._value.or(mask);
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
2021-05-07 16:23:15 +08:00
|
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 清除指定位置的位(设为0)
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param index 位索引(从0开始)
|
|
|
|
|
|
* @throws {Error} 当索引为负数时抛出错误
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public clear(index: number): void {
|
2025-06-16 09:36:36 +08:00
|
|
|
|
if (index < 0) {
|
|
|
|
|
|
throw new Error('Bit index cannot be negative');
|
2021-05-07 16:23:15 +08:00
|
|
|
|
}
|
2025-07-30 11:11:46 +08:00
|
|
|
|
const mask = BigIntFactory.one().shiftLeft(index).not();
|
|
|
|
|
|
this._value = this._value.and(mask);
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
2021-05-07 16:23:15 +08:00
|
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取指定位置的位值
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param index 位索引(从0开始)
|
|
|
|
|
|
* @returns 位值(true表示1,false表示0)
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public get(index: number): boolean {
|
2025-06-16 09:36:36 +08:00
|
|
|
|
if (index < 0) {
|
2025-06-07 20:32:43 +08:00
|
|
|
|
return false;
|
2021-05-07 16:23:15 +08:00
|
|
|
|
}
|
2025-07-30 11:11:46 +08:00
|
|
|
|
const mask = BigIntFactory.one().shiftLeft(index);
|
|
|
|
|
|
return !this._value.and(mask).isZero();
|
2021-05-07 16:23:15 +08:00
|
|
|
|
}
|
2023-03-13 23:32:24 +08:00
|
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 检查是否包含所有指定的位
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param other 另一个Bits对象
|
|
|
|
|
|
* @returns 是否包含所有指定的位
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public containsAll(other: Bits): boolean {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
const intersection = this._value.and(other._value);
|
|
|
|
|
|
return intersection.equals(other._value);
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查是否包含任意一个指定的位
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param other 另一个Bits对象
|
|
|
|
|
|
* @returns 是否包含任意一个指定的位
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public intersects(other: Bits): boolean {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
return !this._value.and(other._value).isZero();
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查是否不包含任何指定的位
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param other 另一个Bits对象
|
|
|
|
|
|
* @returns 是否不包含任何指定的位
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public excludes(other: Bits): boolean {
|
|
|
|
|
|
return !this.intersects(other);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 清空所有位
|
|
|
|
|
|
*/
|
|
|
|
|
|
public clearAll(): void {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
this._value = BigIntFactory.zero();
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查是否为空(没有设置任何位)
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @returns 是否为空
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public isEmpty(): boolean {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
return this._value.isZero();
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取设置的位数量
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @returns 设置为1的位数量
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public cardinality(): number {
|
|
|
|
|
|
let count = 0;
|
2025-07-30 11:11:46 +08:00
|
|
|
|
let value = this._value.clone();
|
2025-06-16 09:36:36 +08:00
|
|
|
|
|
2025-07-30 11:11:46 +08:00
|
|
|
|
while (!value.isZero()) {
|
|
|
|
|
|
const one = BigIntFactory.one();
|
|
|
|
|
|
if (!value.and(one).isZero()) {
|
2025-06-16 09:36:36 +08:00
|
|
|
|
count++;
|
|
|
|
|
|
}
|
2025-07-30 11:11:46 +08:00
|
|
|
|
value = value.shiftRight(1);
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
2025-06-16 09:36:36 +08:00
|
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
|
return count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-06-16 09:36:36 +08:00
|
|
|
|
* 位运算:与
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param other 另一个Bits对象
|
|
|
|
|
|
* @returns 新的Bits对象,包含与运算结果
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public and(other: Bits): Bits {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
return new Bits(this._value.and(other._value));
|
2025-06-16 09:36:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 位运算:或
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param other 另一个Bits对象
|
|
|
|
|
|
* @returns 新的Bits对象,包含或运算结果
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
2025-06-16 09:36:36 +08:00
|
|
|
|
public or(other: Bits): Bits {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
return new Bits(this._value.or(other._value));
|
2025-06-16 09:36:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 位运算:异或
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param other 另一个Bits对象
|
|
|
|
|
|
* @returns 新的Bits对象,包含异或运算结果
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public xor(other: Bits): Bits {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
return new Bits(this._value.xor(other._value));
|
2025-06-16 09:36:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 位运算:非
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param maxBits 最大位数限制,默认64位
|
|
|
|
|
|
* @returns 新的Bits对象,包含非运算结果
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public not(maxBits: number = 64): Bits {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
return new Bits(this._value.not(maxBits));
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 复制另一个Bits对象
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param other 要复制的Bits对象
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public copyFrom(other: Bits): void {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
this._value = other._value.clone();
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建当前Bits的副本
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @returns 新的Bits对象副本
|
2025-06-07 20:32:43 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public clone(): Bits {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
return new Bits(this._value.clone());
|
2025-06-16 09:36:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* 获取原始值
|
|
|
|
|
|
* @returns 原始的IBigIntLike值
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
2025-07-30 11:11:46 +08:00
|
|
|
|
public getValue(): IBigIntLike {
|
2025-06-16 09:36:36 +08:00
|
|
|
|
return this._value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* 设置原始值
|
|
|
|
|
|
* @param value 新的值,可以是IBigIntLike或数值
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
2025-07-30 11:11:46 +08:00
|
|
|
|
public setValue(value: IBigIntLike | number | string): void {
|
|
|
|
|
|
if (typeof value === 'object') {
|
|
|
|
|
|
this._value = value;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this._value = BigIntFactory.create(value);
|
|
|
|
|
|
}
|
2025-06-16 09:36:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取调试信息
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @returns 返回显示设置位索引的字符串
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public toString(): string {
|
|
|
|
|
|
const bits: string[] = [];
|
|
|
|
|
|
let index = 0;
|
2025-07-30 11:11:46 +08:00
|
|
|
|
let value = this._value.clone();
|
2025-06-16 09:36:36 +08:00
|
|
|
|
|
2025-07-30 11:11:46 +08:00
|
|
|
|
while (!value.isZero()) {
|
|
|
|
|
|
const one = BigIntFactory.one();
|
|
|
|
|
|
if (!value.and(one).isZero()) {
|
2025-06-16 09:36:36 +08:00
|
|
|
|
bits.push(index.toString());
|
|
|
|
|
|
}
|
2025-07-30 11:11:46 +08:00
|
|
|
|
value = value.shiftRight(1);
|
2025-06-16 09:36:36 +08:00
|
|
|
|
index++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return `Bits[${bits.join(', ')}]`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取二进制表示
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param maxBits 最大位数,默认64位
|
|
|
|
|
|
* @returns 二进制字符串表示
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public toBinaryString(maxBits: number = 64): string {
|
|
|
|
|
|
let result = '';
|
|
|
|
|
|
for (let i = maxBits - 1; i >= 0; i--) {
|
|
|
|
|
|
result += this.get(i) ? '1' : '0';
|
|
|
|
|
|
if (i % 8 === 0 && i > 0) {
|
|
|
|
|
|
result += ' ';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取十六进制表示
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @returns 十六进制字符串表示
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public toHexString(): string {
|
|
|
|
|
|
return '0x' + this._value.toString(16).toUpperCase();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 从二进制字符串创建Bits
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param binaryString 二进制字符串
|
|
|
|
|
|
* @returns 新的Bits对象
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public static fromBinaryString(binaryString: string): Bits {
|
|
|
|
|
|
const cleanString = binaryString.replace(/\s/g, '');
|
2025-07-30 11:11:46 +08:00
|
|
|
|
const value = BigIntFactory.fromBinaryString(cleanString);
|
2025-06-16 09:36:36 +08:00
|
|
|
|
return new Bits(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 从十六进制字符串创建Bits
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param hexString 十六进制字符串
|
|
|
|
|
|
* @returns 新的Bits对象
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public static fromHexString(hexString: string): Bits {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
const value = BigIntFactory.fromHexString(hexString);
|
2025-06-16 09:36:36 +08:00
|
|
|
|
return new Bits(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 比较两个Bits对象是否相等
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @param other 另一个Bits对象
|
|
|
|
|
|
* @returns 是否相等
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public equals(other: Bits): boolean {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
return this._value.equals(other._value);
|
2025-06-16 09:36:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取最高位的索引
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @returns 最高位的索引,如果为空则返回-1
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public getHighestBitIndex(): number {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
if (this._value.isZero()) {
|
2025-06-16 09:36:36 +08:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let index = 0;
|
2025-07-30 11:11:46 +08:00
|
|
|
|
let value = this._value.clone();
|
2025-06-16 09:36:36 +08:00
|
|
|
|
|
2025-07-30 11:11:46 +08:00
|
|
|
|
while (!value.shiftRight(1).isZero()) {
|
|
|
|
|
|
value = value.shiftRight(1);
|
2025-06-16 09:36:36 +08:00
|
|
|
|
index++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return index;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取最低位的索引
|
2025-07-30 11:11:46 +08:00
|
|
|
|
* @returns 最低位的索引,如果为空则返回-1
|
2025-06-16 09:36:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public getLowestBitIndex(): number {
|
2025-07-30 11:11:46 +08:00
|
|
|
|
if (this._value.isZero()) {
|
2025-06-16 09:36:36 +08:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let index = 0;
|
2025-07-30 11:11:46 +08:00
|
|
|
|
let value = this._value.clone();
|
|
|
|
|
|
const one = BigIntFactory.one();
|
2025-06-16 09:36:36 +08:00
|
|
|
|
|
2025-07-30 11:11:46 +08:00
|
|
|
|
while (value.and(one).isZero()) {
|
|
|
|
|
|
value = value.shiftRight(1);
|
2025-06-16 09:36:36 +08:00
|
|
|
|
index++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return index;
|
2025-06-07 20:32:43 +08:00
|
|
|
|
}
|
2021-05-07 16:23:15 +08:00
|
|
|
|
}
|