Skip to content

Commit

Permalink
feat(bitfield): add ILength impl, add .density()
Browse files Browse the repository at this point in the history
- refactor popCount() impls to use fn from @thi.ng/binary pkg
  • Loading branch information
postspectacular committed Jul 18, 2022
1 parent d59e0c4 commit 2f6e654
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 25 deletions.
20 changes: 16 additions & 4 deletions packages/bitfield/src/bitfield.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type { Fn2, IClear, ICopy } from "@thi.ng/api";
import type { Fn2, IClear, ICopy, ILength } from "@thi.ng/api";
import { align } from "@thi.ng/binary/align";
import { popCountArray } from "@thi.ng/binary/count";
import { bitAnd, bitNot, bitOr, bitXor } from "@thi.ng/binary/logic";
import { assert } from "@thi.ng/errors/assert";
import { binOp, popCount, toString } from "./util.js";
import { binOp, toString } from "./util.js";

/**
* 1D bit field, backed by a Uint32Array. Hence size is always rounded
* up to a multiple of 32.
*/
export class BitField implements IClear, ICopy<BitField> {
export class BitField implements IClear, ICopy<BitField>, ILength {
data: Uint32Array;
n: number;

Expand All @@ -19,6 +20,10 @@ export class BitField implements IClear, ICopy<BitField> {
!isNumber && this.setRange(0, <any>bits);
}

get length() {
return this.n;
}

/**
* Yields iterator of the field's individual bits.
*/
Expand Down Expand Up @@ -135,7 +140,14 @@ export class BitField implements IClear, ICopy<BitField> {
* Returns number of set bits (1's) in the bitfield.
*/
popCount() {
return popCount(this.data);
return popCountArray(this.data);
}

/**
* Same as {@link BitField.popCount}, but as normalized ratio/percentage.
*/
density() {
return this.popCount() / this.n;
}

and(field: BitField) {
Expand Down
23 changes: 21 additions & 2 deletions packages/bitfield/src/bitmatrix.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { Fn2, IClear, ICopy } from "@thi.ng/api";
import { align } from "@thi.ng/binary/align";
import { popCountArray } from "@thi.ng/binary/count";
import { bitAnd, bitNot, bitOr, bitXor } from "@thi.ng/binary/logic";
import { assert } from "@thi.ng/errors/assert";
import { ensureIndex } from "@thi.ng/errors/out-of-bounds";
import { BitField } from "./bitfield.js";
import { binOp, popCount, toString } from "./util.js";
import { binOp, toString } from "./util.js";

/**
* MxN row-major 2D bit matrix, backed by a Uint32Array. Hence the width
Expand All @@ -23,6 +24,10 @@ export class BitMatrix implements IClear, ICopy<BitMatrix> {
this.data = new Uint32Array(rows * this.stride);
}

get length() {
return this.m * this.n;
}

clear() {
this.data.fill(0);
}
Expand Down Expand Up @@ -128,10 +133,17 @@ export class BitMatrix implements IClear, ICopy<BitMatrix> {
return this.binOp(this, bitNot);
}

/**
* Returns number of set bits (1's) in the matrix.
*/
popCount() {
return popCountArray(this.data);
}

popCountRow(m: number) {
ensureIndex(m, 0, this.m);
m *= this.stride;
return popCount(this.data.subarray(m, m + this.stride));
return popCountArray(this.data.subarray(m, m + this.stride));
}

popCountColumn(n: number) {
Expand All @@ -145,6 +157,13 @@ export class BitMatrix implements IClear, ICopy<BitMatrix> {
return res;
}

/**
* Same as {@link BitMatrix.popCount}, but as normalized ratio/percentage.
*/
density() {
return this.popCount() / this.length;
}

row(m: number) {
ensureIndex(m, 0, this.m);
const row = new BitField(this.n);
Expand Down
19 changes: 0 additions & 19 deletions packages/bitfield/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// thing:no-export
import type { Fn2 } from "@thi.ng/api";
import { popCount as $popCount } from "@thi.ng/binary/count";
import { B32 } from "@thi.ng/strings/radix";

/**
Expand All @@ -26,21 +25,3 @@ export const binOp = (
) => {
for (let i = src.length; i-- > 0; ) dest[i] = op(src[i], dest[i]);
};

/**
* Returns number of set bits (1's) in the given array (index range).
*
* @param data -
* @param i -
* @param n -
*
* @internal
**/
export const popCount = (data: Uint32Array, i = 0, n = data.length) => {
let num = 0;
for (let m = i + n; i < m; i++) {
const x = data[i];
x > 0 && (num += $popCount(x));
}
return num;
};

0 comments on commit 2f6e654

Please sign in to comment.