diff --git a/packages/bitfield/src/bitfield.ts b/packages/bitfield/src/bitfield.ts index 54636156d8..b7c174ff41 100644 --- a/packages/bitfield/src/bitfield.ts +++ b/packages/bitfield/src/bitfield.ts @@ -1,11 +1,19 @@ -import { align } from "@thi.ng/binary"; -import { toString } from "./util"; +import { assert } from "@thi.ng/api"; +import { + align, + bitAnd, + bitNot, + bitOr, + bitXor +} from "@thi.ng/binary"; +import { binOp, toString } from "./util"; +import type { Fn2, IClear, ICopy } from "@thi.ng/api"; /** * 1D bit field, backed by a Uint32Array. Hence size is always rounded * up to a multiple of 32. */ -export class BitField { +export class BitField implements IClear, ICopy { data: Uint32Array; n: number; @@ -16,6 +24,16 @@ export class BitField { !isNumber && this.setRange(0, bits); } + clear() { + this.data.fill(0); + } + + copy() { + const dest = new BitField(this.n); + dest.data.set(this.data); + return dest; + } + /** * Resizes bitfield to new size given (rounded up to multiples of * 32). @@ -98,9 +116,35 @@ export class BitField { return r; } + and(field: BitField) { + return this.binOp(field, bitAnd); + } + + or(field: BitField) { + return this.binOp(field, bitOr); + } + + xor(field: BitField) { + return this.binOp(field, bitXor); + } + + not() { + return this.binOp(this, bitNot); + } + toString() { return toString(this.data); } + + protected binOp(field: BitField, op: Fn2) { + this.ensureSize(field); + binOp(this.data, field.data, op); + return this; + } + + protected ensureSize(field: BitField) { + assert(field.n === this.n, `fields must be same size`); + } } export const bitField = (bits: number | string | ArrayLike) => diff --git a/packages/bitfield/src/bitmatrix.ts b/packages/bitfield/src/bitmatrix.ts index d2ededd053..e3e4289709 100644 --- a/packages/bitfield/src/bitmatrix.ts +++ b/packages/bitfield/src/bitmatrix.ts @@ -1,11 +1,19 @@ -import { align } from "@thi.ng/binary"; -import { toString } from "./util"; +import { assert } from "@thi.ng/api"; +import { + align, + bitAnd, + bitNot, + bitOr, + bitXor +} from "@thi.ng/binary"; +import { binOp, toString } from "./util"; +import type { Fn2, IClear, ICopy } from "@thi.ng/api"; /** * MxN row-major 2D bit matrix, backed by a Uint32Array. Hence the width * (number of columns) is always rounded up to a multiple of 32. */ -export class BitMatrix { +export class BitMatrix implements IClear, ICopy { data: Uint32Array; stride: number; m: number; @@ -18,6 +26,16 @@ export class BitMatrix { this.data = new Uint32Array(rows * this.stride); } + clear() { + this.data.fill(0); + } + + copy() { + const dest = new BitMatrix(this.m, this.n); + dest.data.set(this.data); + return dest; + } + /** * Resizes matrix to new size given (width always rounded up to * multiples of 32). @@ -99,6 +117,22 @@ export class BitMatrix { return r; } + and(mat: BitMatrix) { + return this.binOp(mat, bitAnd); + } + + or(mat: BitMatrix) { + return this.binOp(mat, bitOr); + } + + xor(mat: BitMatrix) { + return this.binOp(mat, bitXor); + } + + not() { + return this.binOp(this, bitNot); + } + toString() { const res: string[] = []; for (let i = 0, j = 0, s = this.stride; i < this.m; i++, j += s) { @@ -106,6 +140,19 @@ export class BitMatrix { } return res.join("\n"); } + + protected binOp(field: BitMatrix, op: Fn2) { + this.ensureSize(field); + binOp(this.data, field.data, op); + return this; + } + + protected ensureSize(field: BitMatrix) { + assert( + field.m === this.m && field.n === this.n, + `matrices must be same size` + ); + } } export const bitMatrix = (rows: number, cols = rows) => diff --git a/packages/bitfield/src/util.ts b/packages/bitfield/src/util.ts index 3f0a77fa97..2f51117bdd 100644 --- a/packages/bitfield/src/util.ts +++ b/packages/bitfield/src/util.ts @@ -1,4 +1,5 @@ import { B32 } from "@thi.ng/strings"; +import type { Fn2 } from "@thi.ng/api"; /** * Converts 1D bitfield to binary string. @@ -8,3 +9,18 @@ import { B32 } from "@thi.ng/strings"; * @internal */ export const toString = (data: Uint32Array) => [...data].map(B32).join(""); + +/** + * @param dest - + * @param src - + * @param op - + * + * @internal + */ +export const binOp = ( + dest: Uint32Array, + src: Uint32Array, + op: Fn2 +) => { + for (let i = src.length; --i >= 0; ) dest[i] = op(src[i], dest[i]); +};