Skip to content

Commit

Permalink
refactor(binary): update deps, use new Fn types
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Sep 5, 2020
1 parent 17a0be0 commit 424f516
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 90 deletions.
1 change: 1 addition & 0 deletions packages/binary/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.1",
"@microsoft/api-extractor": "^7.9.11",
"@thi.ng/api": "^6.12.3",
"@types/mocha": "^8.0.3",
"@types/node": "^14.6.1",
"mocha": "^8.1.2",
Expand Down
12 changes: 7 additions & 5 deletions packages/binary/src/count.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { FnN, FnN2 } from "@thi.ng/api";

/**
* Returns number of 1 bits in `x`.
*
* @param x -
*/
export const popCount = (x: number) => (
export const popCount: FnN = (x) => (
(x = x - ((x >>> 1) & 0x55555555)),
(x = (x & 0x33333333) + ((x >>> 2) & 0x33333333)),
(((x + (x >>> 4)) & 0xf0f0f0f) * 0x1010101) >>> 24
Expand All @@ -17,7 +19,7 @@ export const popCount = (x: number) => (
* @param x -
* @param y -
*/
export const hammingDist = (x: number, y: number) => popCount(x ^ y);
export const hammingDist: FnN2 = (x, y) => popCount(x ^ y);

/**
* Math.clz32() polyfill (corrected).
Expand All @@ -26,10 +28,10 @@ export const hammingDist = (x: number, y: number) => popCount(x ^ y);
*
* @param x -
*/
export const clz32 = (x: number) =>
export const clz32: FnN = (x) =>
x !== 0 ? 31 - ((Math.log(x >>> 0) / Math.LN2) | 0) : 32;

export const ctz32 = (x: number) => {
export const ctz32: FnN = (x) => {
let c = 32;
x &= -x;
x && c--;
Expand All @@ -47,4 +49,4 @@ export const ctz32 = (x: number) => {
*
* @param x -
*/
export const bitSize = (x: number) => (x > 1 ? Math.ceil(Math.log2(x)) : 0);
export const bitSize: FnN = (x) => (x > 1 ? Math.ceil(Math.log2(x)) : 0);
5 changes: 3 additions & 2 deletions packages/binary/src/edit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defMask } from "./mask";
import type { FnU3 } from "@thi.ng/api";
import type { Bit } from "./api";
import { defMask } from "./mask";

/**
* Clears bit in given uint `x`.
Expand Down Expand Up @@ -35,5 +36,5 @@ export const bitSetWindow = (
return (x & ~m) | ((y << (1 << from)) & m);
};

export const bitClearWindow = (x: number, from: number, to: number) =>
export const bitClearWindow: FnU3<number> = (x, from, to) =>
x & ~defMask(from, to);
34 changes: 18 additions & 16 deletions packages/binary/src/float.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { FnN, FnN2 } from "@thi.ng/api";

const F64 = new Float64Array(1);
const F32 = new Float32Array(F64.buffer);
const I32 = new Int32Array(F64.buffer);
Expand All @@ -8,13 +10,13 @@ const U32 = new Uint32Array(F64.buffer);
*/
export const IS_LE = ((F64[0] = 2), U32[1] === 0x40000000);

export const floatToIntBits = (x: number) => ((F32[0] = x), I32[0]);
export const floatToIntBits: FnN = (x) => ((F32[0] = x), I32[0]);

export const floatToUintBits = (x: number) => ((F32[0] = x), U32[0]);
export const floatToUintBits: FnN = (x) => ((F32[0] = x), U32[0]);

export const intBitsToFloat = (x: number) => ((I32[0] = x), F32[0]);
export const intBitsToFloat: FnN = (x) => ((I32[0] = x), F32[0]);

export const uintBitsToFloat = (x: number) => ((U32[0] = x), F32[0]);
export const uintBitsToFloat: FnN = (x) => ((U32[0] = x), F32[0]);

/**
* Returns i32 representation of f64 as [hi, lo] tuple (takes
Expand Down Expand Up @@ -42,7 +44,7 @@ export const floatToUintBits64 = (x: number): [number, number] => (
* @param hi
* @param lo
*/
export const intBitsToFloat64 = (hi: number, lo: number) => {
export const intBitsToFloat64: FnN2 = (hi, lo) => {
IS_LE ? ((I32[1] = hi), (I32[0] = lo)) : ((I32[0] = hi), (I32[1] = lo));
return F64[0];
};
Expand All @@ -53,7 +55,7 @@ export const intBitsToFloat64 = (hi: number, lo: number) => {
* @param hi
* @param lo
*/
export const uintBitsToFloat64 = (hi: number, lo: number) => {
export const uintBitsToFloat64: FnN2 = (hi, lo) => {
IS_LE ? ((U32[1] = hi), (U32[0] = lo)) : ((U32[0] = hi), (U32[1] = lo));
return F64[0];
};
Expand All @@ -67,48 +69,48 @@ export const uintBitsToFloat64 = (hi: number, lo: number) => {
*
* @param x - value to convert
*/
export const floatToSortableInt = (x: number) => {
export const floatToSortableInt: FnN = (x) => {
if (x === -0) x = 0;
const i = floatToIntBits(x);
return x < 0 ? ~i | (1 << 31) : i;
};

const clamp11 = (x: number) => (x < -1 ? -1 : x > 1 ? 1 : x);
const clamp11: FnN = (x) => (x < -1 ? -1 : x > 1 ? 1 : x);

/**
* Converts normalized float ([-1..1] range) to u8.
*
* @param x
*/
export const f32u8 = (x: number) => (clamp11(x) * 0x7f) & 0xff;
export const f32u8: FnN = (x) => (clamp11(x) * 0x7f) & 0xff;

/**
* Converts normalized float ([-1..1] range) to u16.
*
* @param x
*/
export const f32u16 = (x: number) => (clamp11(x) * 0x7fff) & 0xffff;
export const f32u16: FnN = (x) => (clamp11(x) * 0x7fff) & 0xffff;

/**
* Converts normalized float ([-1..1] range) to u24.
*
* @param x
*/
export const f32u24 = (x: number) => (clamp11(x) * 0x7fffff) & 0xffffff;
export const f32u24: FnN = (x) => (clamp11(x) * 0x7fffff) & 0xffffff;

/**
* Converts normalized float ([-1..1] range) to u32.
*
* @param x
*/
export const f32u32 = (x: number) => (clamp11(x) * 0x7fffffff) >>> 0;
export const f32u32: FnN = (x) => (clamp11(x) * 0x7fffffff) >>> 0;

/**
* Reverse op of {@link f32u8}.
*
* @param x
*/
export const u8f32 = (x: number) => (
export const u8f32: FnN = (x) => (
(x &= 0xff), (x | ((x >> 7) * 0xffffff00)) / 0x7f
);

Expand All @@ -117,7 +119,7 @@ export const u8f32 = (x: number) => (
*
* @param x
*/
export const u16f32 = (x: number) => (
export const u16f32: FnN = (x) => (
(x &= 0xffff), (x | ((x >> 15) * 0xffff0000)) / 0x7fff
);

Expand All @@ -126,7 +128,7 @@ export const u16f32 = (x: number) => (
*
* @param x
*/
export const u24f32 = (x: number) => (
export const u24f32: FnN = (x) => (
(x &= 0xffffff), (x | ((x >> 23) * 0xff000000)) / 0x7fffff
);

Expand All @@ -135,4 +137,4 @@ export const u24f32 = (x: number) => (
*
* @param x
*/
export const u32f32 = (x: number) => (x | 0) / 0x7fffffff;
export const u32f32: FnN = (x) => (x | 0) / 0x7fffffff;
6 changes: 4 additions & 2 deletions packages/binary/src/gray.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { FnN } from "@thi.ng/api";

/**
* Converts 32bit unsigned int to Gray code (reflected binary). Gray
* codes of successive values always have a Hamming distance of 1 (i.e.
Expand All @@ -7,14 +9,14 @@
*
* @param x - u32
*/
export const encodeGray32 = (x: number) => (x ^ (x >>> 1)) >>> 0;
export const encodeGray32: FnN = (x) => (x ^ (x >>> 1)) >>> 0;

/**
* Converts 32bit Gray code to binary / unsigned int.
*
* {@link https://en.wikipedia.org/wiki/Gray_code}
*/
export const decodeGray32 = (x: number) => {
export const decodeGray32: FnN = (x) => {
x = x ^ (x >>> 16);
x = x ^ (x >>> 8);
x = x ^ (x >>> 4);
Expand Down
85 changes: 34 additions & 51 deletions packages/binary/src/logic.ts
Original file line number Diff line number Diff line change
@@ -1,83 +1,66 @@
import type { FnN, FnN2, FnN3, FnN4, FnN5, FnU3, FnU4 } from "@thi.ng/api";
import { maskL } from "./mask";

export const bitNot = (x: number) => ~x;
export const bitNot: FnN = (x) => ~x;

export const bitAnd = (a: number, b: number) => a & b;
export const bitAnd: FnN2 = (a, b) => a & b;

export const bitNand = (a: number, b: number) => ~(a & b);
export const bitNand: FnN2 = (a, b) => ~(a & b);

export const bitOr = (a: number, b: number) => a | b;
export const bitOr: FnN2 = (a, b) => a | b;

export const bitNor = (a: number, b: number) => ~(a | b);
export const bitNor: FnN2 = (a, b) => ~(a | b);

export const bitXor = (a: number, b: number) => a ^ b;
export const bitXor: FnN2 = (a, b) => a ^ b;

export const bitXnor = (a: number, b: number) => ~(a ^ b);
export const bitXnor: FnN2 = (a, b) => ~(a ^ b);

export const bitImply = (a: number, b: number) => ~a | b;
export const bitImply: FnN2 = (a, b) => ~a | b;

export const bitAoi21 = (a: number, b: number, c: number) => ~(a | (b & c));
export const bitAoi21: FnN3 = (a, b, c) => ~(a | (b & c));

export const bitOai21 = (a: number, b: number, c: number) => ~(a & (b | c));
export const bitOai21: FnN3 = (a, b, c) => ~(a & (b | c));

export const bitAoi22 = (a: number, b: number, c: number, d: number) =>
~((a & b) | (c & d));
export const bitAoi22: FnN4 = (a, b, c, d) => ~((a & b) | (c & d));

export const bitOai22 = (a: number, b: number, c: number, d: number) =>
~((a | b) & (c | d));
export const bitOai22: FnN4 = (a, b, c, d) => ~((a | b) & (c | d));

export const bitMux = (a: number, b: number, s: number) =>
((a & ~s) | (b & s)) >>> 0;
export const bitMux: FnN3 = (a, b, s) => ((a & ~s) | (b & s)) >>> 0;

export const bitDemux = (a: number, b: number, s: number): [number, number] => [
export const bitDemux: FnU3<number, [number, number]> = (a, b, s) => [
(a & ~s) >>> 0,
(b & s) >>> 0,
];

export const bitNotM = (n: number, x: number) => maskL(n, ~x);
export const bitNotM: FnN2 = (n, x) => maskL(n, ~x);

export const bitAndM = (n: number, a: number, b: number) => maskL(n, a & b);
export const bitAndM: FnN3 = (n, a, b) => maskL(n, a & b);

export const bitNandM = (n: number, a: number, b: number) => maskL(n, ~(a & b));
export const bitNandM: FnN3 = (n, a, b) => maskL(n, ~(a & b));

export const bitOrM = (n: number, a: number, b: number) => maskL(n, a | b);
export const bitOrM: FnN3 = (n, a, b) => maskL(n, a | b);

export const bitNorM = (n: number, a: number, b: number) => maskL(n, ~(a | b));
export const bitNorM: FnN3 = (n, a, b) => maskL(n, ~(a | b));

export const bitXorM = (n: number, a: number, b: number) => maskL(n, a ^ b);
export const bitXorM: FnN3 = (n, a, b) => maskL(n, a ^ b);

export const bitXnorM = (n: number, a: number, b: number) => maskL(n, ~(a ^ b));
export const bitXnorM: FnN3 = (n, a, b) => maskL(n, ~(a ^ b));

export const bitImplyM = (n: number, a: number, b: number) => maskL(n, ~a | b);
export const bitImplyM: FnN3 = (n, a, b) => maskL(n, ~a | b);

export const bitAoi21M = (n: number, a: number, b: number, c: number) =>
maskL(n, ~(a | (b & c)));
export const bitAoi21M: FnN4 = (n, a, b, c) => maskL(n, ~(a | (b & c)));

export const bitOai21M = (n: number, a: number, b: number, c: number) =>
maskL(n, ~(a & (b | c)));
export const bitOai21M: FnN4 = (n, a, b, c) => maskL(n, ~(a & (b | c)));

export const bitAoi22M = (
n: number,
a: number,
b: number,
c: number,
d: number
) => maskL(n, ~((a & b) | (c & d)));
export const bitAoi22M: FnN5 = (n, a, b, c, d) =>
maskL(n, ~((a & b) | (c & d)));

export const bitOai22M = (
n: number,
a: number,
b: number,
c: number,
d: number
) => maskL(n, ~((a | b) & (c | d)));
export const bitOai22M: FnN5 = (n, a, b, c, d) =>
maskL(n, ~((a | b) & (c | d)));

export const bitMuxM = (n: number, a: number, b: number, s: number) =>
maskL(n, (a & ~s) | (b & s));
export const bitMuxM: FnN4 = (n, a, b, s) => maskL(n, (a & ~s) | (b & s));

export const bitDemuxM = (
n: number,
a: number,
b: number,
s: number
): [number, number] => [maskL(n, a & ~s), maskL(n, b & s)];
export const bitDemuxM: FnU4<number, [number, number]> = (n, a, b, s) => [
maskL(n, a & ~s),
maskL(n, b & s),
];
7 changes: 4 additions & 3 deletions packages/binary/src/mask.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { FnU2 } from "@thi.ng/api";
import { MASKS } from "./constants";

/**
Expand All @@ -13,20 +14,20 @@ import { MASKS } from "./constants";
* @param a - first bit
* @param b - last bit
*/
export const defMask = (a: number, b: number) => (~MASKS[a] & MASKS[b]) >>> 0;
export const defMask: FnU2<number> = (a, b) => (~MASKS[a] & MASKS[b]) >>> 0;

/**
* Returns unsigned version of `x` with only lowest `n` bits.
*
* @param n - number of LSB bits
* @param x - value
*/
export const maskL = (n: number, x: number) => (x & MASKS[n]) >>> 0;
export const maskL: FnU2<number> = (n, x) => (x & MASKS[n]) >>> 0;

/**
* Returns unsigned version of `x` with only highest `n` bits.
*
* @param n - number of MSB bits
* @param x - value
*/
export const maskH = (n: number, x: number) => (x & ~MASKS[n]) >>> 0;
export const maskH: FnU2<number> = (n, x) => (x & ~MASKS[n]) >>> 0;
5 changes: 3 additions & 2 deletions packages/binary/src/pow.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { FnN } from "@thi.ng/api";
import type { Pow2 } from "./api";

// http://graphics.stanford.edu/~seander/bithacks.html

export const isPow2 = (x: number): x is Pow2 => !!x && !(x & (x - 1));

export const ceilPow2 = (x: number) => {
export const ceilPow2: FnN = (x) => {
x += <any>(x === 0);
--x;
x |= x >>> 1;
Expand All @@ -15,7 +16,7 @@ export const ceilPow2 = (x: number) => {
return x + 1;
};

export const floorPow2 = (x: number) => {
export const floorPow2: FnN = (x) => {
x |= x >>> 1;
x |= x >>> 2;
x |= x >>> 4;
Expand Down
Loading

0 comments on commit 424f516

Please sign in to comment.