Skip to content

Commit

Permalink
Fix code formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
magnified103 committed Nov 13, 2024
1 parent 3c99770 commit 7383a94
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 109 deletions.
20 changes: 16 additions & 4 deletions packages/node/src/riblt/decoder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { SourceSymbol, CodedSymbol, SymbolFactory, HashedSymbol } from "./symbol.js";
import { CodingPrefix } from "./encoder.js";
import type {
CodedSymbol,
HashedSymbol,
SourceSymbol,
SymbolFactory,
} from "./symbol.js";


export class Decoder<T extends SourceSymbol> extends CodingPrefix<T> {
Expand Down Expand Up @@ -32,7 +37,11 @@ export class Decoder<T extends SourceSymbol> extends CodingPrefix<T> {
}

// called at most once for each index
addCodedSymbol(index: number, localSymbol: CodedSymbol<T>, remoteSymbol: CodedSymbol<T>): void {
addCodedSymbol(
index: number,
localSymbol: CodedSymbol<T>,
remoteSymbol: CodedSymbol<T>
): void {
this.extendPrefix(index + 1);
this.codedSymbols[index].apply(localSymbol, localSymbol.count);
this.codedSymbols[index].apply(remoteSymbol, -remoteSymbol.count);
Expand All @@ -44,15 +53,18 @@ export class Decoder<T extends SourceSymbol> extends CodingPrefix<T> {
if (!this.isDecoded[index]) {
// console.log(`+ map ${hashedSymbol}, dir=${direction} to index ${index}`)
this.codedSymbols[index].apply(hashedSymbol, direction);
this.modifiedCodedSymbols.push(index);
if (!this.visited[index]) {
this.visited[index] = true;
this.modifiedCodedSymbols.push(index);
}
}
}

tryDecode(): boolean {
while (this.modifiedCodedSymbols.length > 0) {
const candidates: number[] = [];
for (const index of this.modifiedCodedSymbols) {
if (this.isDecoded[index] || this.visited[index]) {
if (this.isDecoded[index]) {
continue;
}
this.visited[index] = true;
Expand Down
21 changes: 17 additions & 4 deletions packages/node/src/riblt/encoder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { type SourceSymbol, type SymbolFactory, type CodedSymbol, HashedSymbol } from "./symbol.js"
import { RandomMapping } from "./mapping.js";
import {
type SourceSymbol,
HashedSymbol,
type SymbolFactory,
type CodedSymbol
} from "./symbol.js"


class SymbolMapping {
Expand Down Expand Up @@ -92,13 +97,17 @@ export class CodingPrefix<T extends SourceSymbol> {
}

addSymbol(symbol: T, direction = 1): void {
const hashedSymbol = new HashedSymbol<T>(this.symbolFactory.cloneSource(symbol));
const hashedSymbol = new HashedSymbol<T>(
this.symbolFactory.cloneSource(symbol)
);
const mapping = new RandomMapping(hashedSymbol.checksum, 0);

this.sourceSymbols.push(hashedSymbol);
this.sourceSymbolDirections.push(direction);
this.mapGenerators.push(mapping);
this.queue.push(new SymbolMapping(this.sourceSymbols.length - 1, mapping.lastIdx));
this.queue.push(
new SymbolMapping(this.sourceSymbols.length - 1, mapping.lastIdx)
);
}

maps(index: number, hashedSymbol: HashedSymbol<T>, direction: number): void {
Expand All @@ -117,7 +126,11 @@ export class CodingPrefix<T extends SourceSymbol> {
while (mapping.codedIdx < size) {
const sourceIdx = mapping.sourceIdx;
const codedIdx = mapping.codedIdx;
this.maps(codedIdx, this.sourceSymbols[sourceIdx], this.sourceSymbolDirections[sourceIdx]);
this.maps(
codedIdx,
this.sourceSymbols[sourceIdx],
this.sourceSymbolDirections[sourceIdx]
);
mapping.codedIdx = this.mapGenerators[sourceIdx].nextIndex();
}
this.queue.push(mapping);
Expand Down
33 changes: 20 additions & 13 deletions packages/node/src/riblt/mapping.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
import * as crypto from "node:crypto";

function rotl(x: bigint, k: bigint) {
return BigInt.asUintN(64, ((x << k) | (x >> (64n - k))));
}

export class RandomMapping {
private state: Uint8Array;
private s: BigUint64Array;
lastIdx: number;

constructor(seed: Uint8Array, lastIdx = 0) {
this.state = crypto.createHash("sha1").update(seed).digest();
this.s = new BigUint64Array(crypto.createHash("sha256").update(seed).digest().buffer);
this.lastIdx = lastIdx;
}

nextIndex(): number {
let prng = 0n;
prng |= BigInt(this.state[0]) << 0n;
prng |= BigInt(this.state[1]) << 8n;
prng |= BigInt(this.state[2]) << 16n;
prng |= BigInt(this.state[3]) << 24n;
prng |= BigInt(this.state[4]) << 32n;
prng |= BigInt(this.state[5]) << 40n;
prng |= BigInt(this.state[6]) << 48n;
prng |= BigInt(this.state[7]) << 56n;
// https://prng.di.unimi.it/xoshiro256starstar.c
const result = BigInt.asUintN(64, rotl(BigInt.asUintN(64, this.s[1] * 5n), 7n) * 9n);

const t = BigInt.asUintN(64, this.s[1] << 17n);

this.s[2] ^= this.s[0];
this.s[3] ^= this.s[1];
this.s[1] ^= this.s[2];
this.s[0] ^= this.s[3];

this.s[2] ^= t;

this.s[3] = rotl(this.s[3], 45n);

this.lastIdx += Math.ceil(
(this.lastIdx + 1.5) * (2 ** 32 / Math.sqrt(Number(prng) + 1) - 1),
(this.lastIdx + 1.5) * (2 ** 32 / Math.sqrt(Number(result) + 1) - 1),
);
this.state = crypto.createHash("sha1").update(this.state).digest();
return this.lastIdx;
}
}
2 changes: 1 addition & 1 deletion packages/node/src/riblt/symbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class HashedSymbol<T extends SourceSymbol> {
}

toString(): string {
return `HashedSymbol(sum=${this.sum}, hash=[${this.checksum}])`
return `HashedSymbol(sum=${this.sum}, hash=[${this.checksum}])`;
}
}

Expand Down
181 changes: 94 additions & 87 deletions packages/node/tests/riblt.test.ts
Original file line number Diff line number Diff line change
@@ -1,104 +1,111 @@
import * as crypto from 'node:crypto';
import { beforeEach, describe, expect, test } from "vitest";
import { Encoder } from "../src/riblt/encoder.js";
import { Decoder } from "../src/riblt/decoder.js";
import { SymbolFactory, type SourceSymbol } from "../src/riblt/symbol.js";
import * as crypto from 'node:crypto';
import { Encoder } from "../src/riblt/encoder.js";
import { type SourceSymbol, SymbolFactory } from "../src/riblt/symbol.js";


class VertexSymbol implements SourceSymbol {
data: number;

constructor(data: number) {
this.data = data;
}

xor(s: VertexSymbol): void {
this.data ^= s.data;
}

hash(): Uint8Array {
return new Uint8Array(crypto.createHash('sha1').update(new Uint32Array([this.data])).digest());
}

equals(s: VertexSymbol): boolean {
return this.data === s.data;
}

toString(): string {
return `${this.data}`;
}
data: number;

constructor(data: number) {
this.data = data;
}

xor(s: VertexSymbol): void {
this.data ^= s.data;
}

hash(): Uint8Array {
return new Uint8Array(
crypto
.createHash('sha1')
.update(new Uint32Array([this.data]))
.digest(),
);
}

equals(s: VertexSymbol): boolean {
return this.data === s.data;
}

toString(): string {
return `${this.data}`;
}
}


class VertexSymbolFactory extends SymbolFactory<VertexSymbol> {
emptySource(): VertexSymbol {
return new VertexSymbol(0);
}
emptySource(): VertexSymbol {
return new VertexSymbol(0);
}

emptyHash(): Uint8Array {
return new Uint8Array(20);
}
emptyHash(): Uint8Array {
return new Uint8Array(20);
}

cloneSource(s: VertexSymbol): VertexSymbol {
return new VertexSymbol(s.data);
}
cloneSource(s: VertexSymbol): VertexSymbol {
return new VertexSymbol(s.data);
}

newTestSymbol(i): VertexSymbol {
return new VertexSymbol(i);
}
newTestSymbol(i): VertexSymbol {
return new VertexSymbol(i);
}
}


describe("RIBLT test", async () => {
const factory = new VertexSymbolFactory();


test.each([10, 20, 40, 100, 1000, 10000, 50000, 100000])("d=%i", async (d) => {
const nlocal = d >> 1;
const nremote = d >> 1;
const ncommon = d;

let symbolIndex = 0;

const localEncoder = new Encoder(factory);
const remoteEncoder = new Encoder(factory);
const localDecoder = new Decoder(factory);

const localSymbols: VertexSymbol[] = [];
const remoteSymbols: VertexSymbol[] = [];

for (let i = 0; i < nlocal; i++) {
const localSymbol = factory.newTestSymbol(symbolIndex++);
localSymbols.push(localSymbol);
localEncoder.addSymbol(localSymbol);
}
for (let i = 0; i < nremote; i++) {
const remoteSymbol = factory.newTestSymbol(symbolIndex++);
remoteSymbols.push(remoteSymbol);
remoteEncoder.addSymbol(remoteSymbol);
}
for (let i = 0; i < ncommon; i++) {
const localSymbol = factory.newTestSymbol(symbolIndex++);
const remoteSymbol = factory.cloneSource(localSymbol);
localEncoder.addSymbol(localSymbol);
remoteEncoder.addSymbol(remoteSymbol);
}

let sequenceSize = 0;
do {
sequenceSize++;
localEncoder.producePrefix(sequenceSize);
remoteEncoder.producePrefix(sequenceSize);
// console.log(`localEncoder[${sequenceSize - 1}]: ${localEncoder.codedSymbols[sequenceSize - 1]}`);
// console.log(`remoteEncoder[${sequenceSize - 1}]: ${remoteEncoder.codedSymbols[sequenceSize - 1]}`);
localDecoder.addCodedSymbol(sequenceSize - 1, localEncoder.codedSymbols[sequenceSize - 1], remoteEncoder.codedSymbols[sequenceSize - 1]);
// console.log(`localDecoder[${sequenceSize - 1}]: ${localDecoder.codedSymbols[sequenceSize - 1]}`);
} while (!localDecoder.tryDecode());

// console.log(localDecoder.decodedLocalSymbols);
// console.log(localDecoder.decodedRemoteSymbols);
// console.log(localDecoder.remaining);

console.log(sequenceSize);
});
const factory = new VertexSymbolFactory();


test.each([10, 20, 40, 100, 1000, 10000, 50000, 100000, 300000])(
"d=%i",
async (d) => {
const nlocal = d >> 1;
const nremote = d >> 1;
const ncommon = d;

let symbolIndex = 0;

const localEncoder = new Encoder(factory);
const remoteEncoder = new Encoder(factory);
const localDecoder = new Decoder(factory);

const localSymbols: VertexSymbol[] = [];
const remoteSymbols: VertexSymbol[] = [];

for (let i = 0; i < nlocal; i++) {
const localSymbol = factory.newTestSymbol(symbolIndex++);
localSymbols.push(localSymbol);
localEncoder.addSymbol(localSymbol);
}
for (let i = 0; i < nremote; i++) {
const remoteSymbol = factory.newTestSymbol(symbolIndex++);
remoteSymbols.push(remoteSymbol);
remoteEncoder.addSymbol(remoteSymbol);
}
for (let i = 0; i < ncommon; i++) {
const localSymbol = factory.newTestSymbol(symbolIndex++);
const remoteSymbol = factory.cloneSource(localSymbol);
localEncoder.addSymbol(localSymbol);
remoteEncoder.addSymbol(remoteSymbol);
}

let sequenceSize = 0;
do {
sequenceSize++;
localEncoder.producePrefix(sequenceSize);
remoteEncoder.producePrefix(sequenceSize);
// console.log(`localEncoder[${sequenceSize - 1}]: ${localEncoder.codedSymbols[sequenceSize - 1]}`);
// console.log(`remoteEncoder[${sequenceSize - 1}]: ${remoteEncoder.codedSymbols[sequenceSize - 1]}`);
localDecoder.addCodedSymbol(sequenceSize - 1, localEncoder.codedSymbols[sequenceSize - 1], remoteEncoder.codedSymbols[sequenceSize - 1]);
// console.log(`localDecoder[${sequenceSize - 1}]: ${localDecoder.codedSymbols[sequenceSize - 1]}`);
} while (!localDecoder.tryDecode());

// console.log(localDecoder.decodedLocalSymbols);
// console.log(localDecoder.decodedRemoteSymbols);
// console.log(localDecoder.remaining);

console.log(`${sequenceSize/d} symbols/diff`);
});
});

0 comments on commit 7383a94

Please sign in to comment.