High-performance collection library for TypeScript supporting value semantics (deep equality) and recursive structures. Version 8 introduces a new hash-based architecture optimized for high-throughput workloads like SAT solvers and graph algorithms.
RecursiveSet provides mathematical sets and maps where equality is determined by structure/content rather than object reference (e.g., {1, 2} is equal to {2, 1}).
Key Architectural Features:
- Open Addressing: Uses linear probing with a load factor of 0.75 for cache-efficient lookups.
- Backshift Deletion: Maintains probe chain integrity without "tombstones," preventing performance degradation over time.
- Zero-Allocation Hashing: Uses static buffers and raw bitwise operations to hash numbers without triggering the Garbage Collector.
- Structure of Arrays (SoA): Data is stored in flat arrays to maximize CPU cache locality.
npm install recursive-setSets automatically deduplicate elements based on their value or structure.
import { RecursiveSet } from "recursive-set";
// Primitive values
const numbers = new RecursiveSet(1, 2, 3);
numbers.add(1); // No effect, 1 is already present
// Recursive structures (Sets of Sets)
const setA = new RecursiveSet(1, 2);
const setB = new RecursiveSet(2, 1);
const metaSet = new RecursiveSet<RecursiveSet<number>>();
metaSet.add(setA);
metaSet.add(setB);
console.log(metaSet.size); // 1, because setA equals setBRecursiveMap allows using complex objects (like Tuples or Sets) as keys.
import { RecursiveMap, Tuple } from "recursive-set";
const transitions = new RecursiveMap<Tuple<[string, string]>, number>();
const edge = new Tuple("q0", "q1");
transitions.set(edge, 1);
// Retrieval using a new, structurally identical key
console.log(transitions.get(new Tuple("q0", "q1"))); // 1To guarantee hash stability, collections become immutable (frozen) once their hash code is computed or they are inserted into another collection.
const A = new RecursiveSet(1);
const B = new RecursiveSet(A); // Accessing A's hash to store it in B freezes A.
try {
A.add(2); // Throws Error: Frozen Set modified.
} catch (e) {
// Expected behavior
}
// Use mutableCopy to continue editing
const C = A.mutableCopy();
C.add(2);This library optimizes for raw speed and assumes strict adherence to the following contracts. Violating them leads to undefined behavior.
-
Finite Numbers Only:
NaNandInfinityare strictly forbidden. They break strict equality checks and integer optimization paths. -
Strict Value Semantics: Plain JavaScript objects (
{}) are not supported. Keys must implement theStructuralinterface (provideequals,hashCode, andtoString). -
Hash Quality: The
$O(1)$ performance guarantee relies on a good distribution. Returning a constanthashCode(e.g.,42) forces all elements into a single bucket, degrading performance to$O(N)$ . -
Deterministic Visualization: Custom
toString()implementations must utilizecompareVisualLogicfor nested structures. Failing to do so results in unstable string output. -
Immutability: Once an object is added to a collection, its
hashCodemust not change. -
No Circular Dependencies: A
RecursiveSetcannot contain itself, directly or indirectly. Runtime checks are omitted for performance; creating a cycle will cause a Stack Overflow during hashing.
type Primitive = number | string;
type Value = Primitive | Structural;
interface Structural {
readonly hashCode: number;
equals(other: unknown): boolean;
toString(): string;
}new RecursiveSet<T>(...elements: T[]): Creates a set from the given arguments.
-
add(element: T): void: Adds an element ($O(1)$ amortized). -
remove(element: T): void: Removes an element ($O(1)$ amortized).
All operations return a new RecursiveSet instance.
union(other): RecursiveSet<T>intersection(other): RecursiveSet<T>-
difference(other): RecursiveSet<T>($A \setminus B$ ) symmetricDifference(other): RecursiveSet<T>cartesianProduct<U>(other): RecursiveSet<Tuple<[T, U]>>-
powerset(): RecursiveSet<RecursiveSet<T>>(Throws if size > 20)
has(element: T): booleanequals(other: unknown): booleanisSubset(other): booleanisSuperset(other): booleanmutableCopy(): RecursiveSet<T>: Returns a shallow mutable clone.size: numberhashCode: number: Computes hash and freezes the set.
A hash map supporting Value keys.
set(key: K, value: V): voidget(key: K): V | undefineddelete(key: K): booleanhas(key: K): booleanmutableCopy(): RecursiveMap<K, V>
An immutable, hashable sequence of values. Useful for composite keys.
new Tuple(...elements: T[])get(index: number): T[index]length: number
This library was developed as a student research project under the supervision of Karl Stroetmann.
Special thanks for his architectural guidance on homogeneous sets and the theoretical foundations required for high-performance set engines.
git clone [https://github.com/cstrerath/recursive-set.git](https://github.com/cstrerath/recursive-set.git)
npm install
npm run build
npx tsx test/test.ts
npx tsx test/nqueens.tsMIT License © 2025 Christian Strerath. See LICENSE.