data-structure-typed 2.4.4 → 2.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +24 -1
  3. package/dist/cjs/index.cjs +459 -132
  4. package/dist/cjs-legacy/index.cjs +459 -130
  5. package/dist/esm/index.mjs +459 -133
  6. package/dist/esm-legacy/index.mjs +459 -131
  7. package/dist/types/common/error.d.ts +23 -0
  8. package/dist/types/common/index.d.ts +1 -0
  9. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +10 -0
  10. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +7 -1
  11. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  12. package/dist/types/data-structures/graph/directed-graph.d.ts +1 -0
  13. package/dist/types/data-structures/graph/undirected-graph.d.ts +14 -0
  14. package/dist/types/data-structures/queue/deque.d.ts +41 -1
  15. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  16. package/dist/umd/data-structure-typed.js +458 -129
  17. package/dist/umd/data-structure-typed.min.js +4 -2
  18. package/package.json +2 -2
  19. package/src/common/error.ts +60 -0
  20. package/src/common/index.ts +2 -0
  21. package/src/data-structures/base/iterable-element-base.ts +3 -2
  22. package/src/data-structures/binary-tree/binary-indexed-tree.ts +6 -5
  23. package/src/data-structures/binary-tree/binary-tree.ts +113 -42
  24. package/src/data-structures/binary-tree/bst.ts +11 -3
  25. package/src/data-structures/binary-tree/red-black-tree.ts +20 -0
  26. package/src/data-structures/binary-tree/tree-map.ts +8 -7
  27. package/src/data-structures/binary-tree/tree-multi-map.ts +4 -4
  28. package/src/data-structures/binary-tree/tree-multi-set.ts +5 -4
  29. package/src/data-structures/binary-tree/tree-set.ts +7 -6
  30. package/src/data-structures/graph/abstract-graph.ts +106 -1
  31. package/src/data-structures/graph/directed-graph.ts +4 -0
  32. package/src/data-structures/graph/undirected-graph.ts +95 -0
  33. package/src/data-structures/hash/hash-map.ts +13 -2
  34. package/src/data-structures/heap/heap.ts +4 -3
  35. package/src/data-structures/heap/max-heap.ts +2 -3
  36. package/src/data-structures/matrix/matrix.ts +9 -10
  37. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -3
  38. package/src/data-structures/queue/deque.ts +71 -3
  39. package/src/data-structures/trie/trie.ts +2 -1
  40. package/src/types/data-structures/queue/deque.ts +7 -0
  41. package/src/utils/utils.ts +4 -2
@@ -48,6 +48,7 @@ var dataStructureTyped = (() => {
48
48
  DirectedVertex: () => DirectedVertex,
49
49
  DoublyLinkedList: () => DoublyLinkedList,
50
50
  DoublyLinkedListNode: () => DoublyLinkedListNode,
51
+ ERR: () => ERR,
51
52
  FibonacciHeap: () => FibonacciHeap,
52
53
  FibonacciHeapNode: () => FibonacciHeapNode,
53
54
  HashMap: () => HashMap,
@@ -285,6 +286,52 @@ var dataStructureTyped = (() => {
285
286
  }
286
287
  };
287
288
 
289
+ // src/common/error.ts
290
+ var ERR = {
291
+ // Range / index
292
+ indexOutOfRange: (index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`,
293
+ invalidIndex: (ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`,
294
+ // Type / argument
295
+ invalidArgument: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
296
+ comparatorRequired: (ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`,
297
+ invalidKey: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
298
+ notAFunction: (name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`,
299
+ invalidEntry: (ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`,
300
+ invalidNaN: (ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`,
301
+ invalidDate: (ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`,
302
+ reduceEmpty: (ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`,
303
+ callbackReturnType: (expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`,
304
+ // State / operation
305
+ invalidOperation: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
306
+ // Matrix
307
+ matrixDimensionMismatch: (op) => `Matrix: Dimensions must be compatible for ${op}.`,
308
+ matrixSingular: () => "Matrix: Singular matrix, inverse does not exist.",
309
+ matrixNotSquare: () => "Matrix: Must be square for inversion.",
310
+ matrixNotRectangular: () => "Matrix: Must be rectangular for transposition.",
311
+ matrixRowMismatch: (expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`
312
+ };
313
+
314
+ // src/common/index.ts
315
+ var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
316
+ DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
317
+ DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
318
+ return DFSOperation2;
319
+ })(DFSOperation || {});
320
+ var Range = class {
321
+ constructor(low, high, includeLow = true, includeHigh = true) {
322
+ this.low = low;
323
+ this.high = high;
324
+ this.includeLow = includeLow;
325
+ this.includeHigh = includeHigh;
326
+ }
327
+ // Determine whether a key is within the range
328
+ isInRange(key, comparator) {
329
+ const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
330
+ const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
331
+ return lowCheck && highCheck;
332
+ }
333
+ };
334
+
288
335
  // src/data-structures/base/iterable-element-base.ts
289
336
  var IterableElementBase = class {
290
337
  /**
@@ -307,7 +354,7 @@ var dataStructureTyped = (() => {
307
354
  if (options) {
308
355
  const { toElementFn } = options;
309
356
  if (typeof toElementFn === "function") this._toElementFn = toElementFn;
310
- else if (toElementFn) throw new TypeError("toElementFn must be a function type");
357
+ else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
311
358
  }
312
359
  }
313
360
  /**
@@ -463,7 +510,7 @@ var dataStructureTyped = (() => {
463
510
  acc = initialValue;
464
511
  } else {
465
512
  const first = iter.next();
466
- if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
513
+ if (first.done) throw new TypeError(ERR.reduceEmpty());
467
514
  acc = first.value;
468
515
  index = 1;
469
516
  }
@@ -531,8 +578,10 @@ var dataStructureTyped = (() => {
531
578
  }
532
579
  return 1 << 31 - Math.clz32(value);
533
580
  };
534
- var rangeCheck = (index, min, max, message = "Index out of bounds.") => {
535
- if (index < min || index > max) throw new RangeError(message);
581
+ var rangeCheck = (index, min, max, message) => {
582
+ if (index < min || index > max) {
583
+ throw new RangeError(message != null ? message : `Index ${index} is out of range [${min}, ${max}].`);
584
+ }
536
585
  };
537
586
  var throwRangeError = (message = "The value is off-limits.") => {
538
587
  throw new RangeError(message);
@@ -894,8 +943,8 @@ var dataStructureTyped = (() => {
894
943
  if (this.isEntry(rawElement)) {
895
944
  return rawElement;
896
945
  }
897
- throw new Error(
898
- "If `entryOrRawElements` does not adhere to [key,value], provide `options.toEntryFn` to transform raw records."
946
+ throw new TypeError(
947
+ ERR.invalidArgument("If elements do not adhere to [key, value], provide options.toEntryFn to transform raw records.", "HashMap")
899
948
  );
900
949
  });
901
950
  __publicField(this, "_size", 0);
@@ -1180,6 +1229,13 @@ var dataStructureTyped = (() => {
1180
1229
  }
1181
1230
  }
1182
1231
  _deleteNode(node) {
1232
+ const key = node.key;
1233
+ if (isWeakKey(key)) {
1234
+ this._objMap.delete(key);
1235
+ } else {
1236
+ const hash = this._hashFn(key);
1237
+ delete this._noObjMap[hash];
1238
+ }
1183
1239
  const { prev, next } = node;
1184
1240
  prev.next = next;
1185
1241
  next.prev = prev;
@@ -3660,17 +3716,16 @@ var dataStructureTyped = (() => {
3660
3716
 
3661
3717
  // src/data-structures/queue/deque.ts
3662
3718
  var Deque = class extends LinearBase {
3663
- /**
3664
- * Create a Deque and optionally bulk-insert elements.
3665
- * @remarks Time O(N), Space O(N)
3666
- * @param [elements] - Iterable (or iterable-like) of elements/records to insert.
3667
- * @param [options] - Options such as bucketSize, toElementFn, and maxLen.
3668
- * @returns New Deque instance.
3669
- */
3670
3719
  constructor(elements = [], options) {
3671
3720
  super(options);
3672
3721
  __publicField(this, "_equals", (a, b) => Object.is(a, b));
3673
3722
  __publicField(this, "_bucketSize", 1 << 12);
3723
+ __publicField(this, "_autoCompactRatio", 0.5);
3724
+ /**
3725
+ * Counter for shift/pop operations since last compaction check.
3726
+ * Only checks ratio every `_bucketSize` operations to minimize overhead.
3727
+ */
3728
+ __publicField(this, "_compactCounter", 0);
3674
3729
  __publicField(this, "_bucketFirst", 0);
3675
3730
  __publicField(this, "_firstInBucket", 0);
3676
3731
  __publicField(this, "_bucketLast", 0);
@@ -3679,8 +3734,9 @@ var dataStructureTyped = (() => {
3679
3734
  __publicField(this, "_buckets", []);
3680
3735
  __publicField(this, "_length", 0);
3681
3736
  if (options) {
3682
- const { bucketSize } = options;
3737
+ const { bucketSize, autoCompactRatio } = options;
3683
3738
  if (typeof bucketSize === "number") this._bucketSize = bucketSize;
3739
+ if (typeof autoCompactRatio === "number") this._autoCompactRatio = autoCompactRatio;
3684
3740
  }
3685
3741
  let _size;
3686
3742
  if ("length" in elements) {
@@ -3705,6 +3761,24 @@ var dataStructureTyped = (() => {
3705
3761
  get bucketSize() {
3706
3762
  return this._bucketSize;
3707
3763
  }
3764
+ /**
3765
+ * Get the auto-compaction ratio.
3766
+ * When `elements / (bucketCount * bucketSize)` drops below this ratio after
3767
+ * enough shift/pop operations, the deque auto-compacts.
3768
+ * @remarks Time O(1), Space O(1)
3769
+ * @returns Current ratio threshold. 0 means auto-compact is disabled.
3770
+ */
3771
+ get autoCompactRatio() {
3772
+ return this._autoCompactRatio;
3773
+ }
3774
+ /**
3775
+ * Set the auto-compaction ratio.
3776
+ * @remarks Time O(1), Space O(1)
3777
+ * @param value - Ratio in [0,1]. 0 disables auto-compact.
3778
+ */
3779
+ set autoCompactRatio(value) {
3780
+ this._autoCompactRatio = value;
3781
+ }
3708
3782
  /**
3709
3783
  * Get the index of the first bucket in use.
3710
3784
  * @remarks Time O(1), Space O(1)
@@ -3836,6 +3910,7 @@ var dataStructureTyped = (() => {
3836
3910
  }
3837
3911
  }
3838
3912
  this._length -= 1;
3913
+ this._autoCompact();
3839
3914
  return element;
3840
3915
  }
3841
3916
  /**
@@ -3858,6 +3933,7 @@ var dataStructureTyped = (() => {
3858
3933
  }
3859
3934
  }
3860
3935
  this._length -= 1;
3936
+ this._autoCompact();
3861
3937
  return element;
3862
3938
  }
3863
3939
  /**
@@ -4190,11 +4266,40 @@ var dataStructureTyped = (() => {
4190
4266
  * @remarks Time O(N), Space O(1)
4191
4267
  * @returns void
4192
4268
  */
4269
+ /**
4270
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
4271
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
4272
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
4273
+ */
4274
+ _autoCompact() {
4275
+ if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
4276
+ this._compactCounter++;
4277
+ if (this._compactCounter < this._bucketSize) return;
4278
+ this._compactCounter = 0;
4279
+ const utilization = this._length / (this._bucketCount * this._bucketSize);
4280
+ if (utilization < this._autoCompactRatio) {
4281
+ this.shrinkToFit();
4282
+ }
4283
+ }
4284
+ /**
4285
+ * Compact the deque by removing unused buckets.
4286
+ * @remarks Time O(N), Space O(1)
4287
+ * @returns True if compaction was performed (bucket count reduced).
4288
+ */
4289
+ /**
4290
+ * Compact the deque by removing unused buckets.
4291
+ * @remarks Time O(N), Space O(1)
4292
+ * @returns True if compaction was performed (bucket count reduced).
4293
+ */
4294
+ compact() {
4295
+ const before = this._bucketCount;
4296
+ this.shrinkToFit();
4297
+ return this._bucketCount < before;
4298
+ }
4193
4299
  shrinkToFit() {
4194
4300
  if (this._length === 0) return;
4195
4301
  const newBuckets = [];
4196
- if (this._bucketFirst === this._bucketLast) return;
4197
- else if (this._bucketFirst < this._bucketLast) {
4302
+ if (this._bucketFirst <= this._bucketLast) {
4198
4303
  for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
4199
4304
  newBuckets.push(this._buckets[i]);
4200
4305
  }
@@ -4209,6 +4314,8 @@ var dataStructureTyped = (() => {
4209
4314
  this._bucketFirst = 0;
4210
4315
  this._bucketLast = newBuckets.length - 1;
4211
4316
  this._buckets = newBuckets;
4317
+ this._bucketCount = newBuckets.length;
4318
+ this._compactCounter = 0;
4212
4319
  }
4213
4320
  /**
4214
4321
  * Deep clone this deque, preserving options.
@@ -4404,7 +4511,7 @@ var dataStructureTyped = (() => {
4404
4511
  __publicField(this, "_elements", []);
4405
4512
  __publicField(this, "_DEFAULT_COMPARATOR", (a, b) => {
4406
4513
  if (typeof a === "object" || typeof b === "object") {
4407
- throw TypeError("When comparing object types, define a custom comparator in options.");
4514
+ throw new TypeError(ERR.comparatorRequired("Heap"));
4408
4515
  }
4409
4516
  if (a > b) return 1;
4410
4517
  if (a < b) return -1;
@@ -4714,7 +4821,7 @@ var dataStructureTyped = (() => {
4714
4821
  */
4715
4822
  map(callback, options, thisArg) {
4716
4823
  const { comparator, toElementFn, ...rest } = options != null ? options : {};
4717
- if (!comparator) throw new TypeError("Heap.map requires options.comparator for EM");
4824
+ if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
4718
4825
  const out = this._createLike([], { ...rest, comparator, toElementFn });
4719
4826
  let i = 0;
4720
4827
  for (const x of this) {
@@ -4842,7 +4949,7 @@ var dataStructureTyped = (() => {
4842
4949
  __publicField(this, "_comparator");
4843
4950
  this.clear();
4844
4951
  this._comparator = comparator || this._defaultComparator;
4845
- if (typeof this.comparator !== "function") throw new Error("FibonacciHeap: comparator must be a function.");
4952
+ if (typeof this.comparator !== "function") throw new TypeError(ERR.notAFunction("comparator", "FibonacciHeap"));
4846
4953
  }
4847
4954
  /**
4848
4955
  * Get the circular root list head.
@@ -5051,9 +5158,7 @@ var dataStructureTyped = (() => {
5051
5158
  super(elements, {
5052
5159
  comparator: (a, b) => {
5053
5160
  if (typeof a === "object" || typeof b === "object") {
5054
- throw TypeError(
5055
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
5056
- );
5161
+ throw new TypeError(ERR.comparatorRequired("MaxHeap"));
5057
5162
  }
5058
5163
  if (a < b) return 1;
5059
5164
  if (a > b) return -1;
@@ -5210,7 +5315,7 @@ var dataStructureTyped = (() => {
5210
5315
  const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
5211
5316
  return this._addEdge(newEdge);
5212
5317
  } else {
5213
- throw new Error("dest must be a Vertex or vertex key while srcOrEdge is an Edge");
5318
+ throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
5214
5319
  }
5215
5320
  }
5216
5321
  }
@@ -5894,6 +5999,94 @@ var dataStructureTyped = (() => {
5894
5999
  _getVertexKey(vertexOrKey) {
5895
6000
  return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
5896
6001
  }
6002
+ /**
6003
+ * The edge connector string used in visual output.
6004
+ * Override in subclasses (e.g., '--' for undirected, '->' for directed).
6005
+ */
6006
+ get _edgeConnector() {
6007
+ return "--";
6008
+ }
6009
+ /**
6010
+ * Generate a text-based visual representation of the graph.
6011
+ *
6012
+ * **Adjacency list format:**
6013
+ * ```
6014
+ * Graph (5 vertices, 6 edges):
6015
+ * A -> B (1), C (2)
6016
+ * B -> D (3)
6017
+ * C -> (no outgoing edges)
6018
+ * D -> A (1)
6019
+ * E (isolated)
6020
+ * ```
6021
+ *
6022
+ * @param options - Optional display settings.
6023
+ * @param options.showWeight - Whether to show edge weights (default: true).
6024
+ * @returns The visual string.
6025
+ */
6026
+ toVisual(options) {
6027
+ var _a;
6028
+ const showWeight = (_a = options == null ? void 0 : options.showWeight) != null ? _a : true;
6029
+ const vertices = [...this._vertexMap.values()];
6030
+ const vertexCount = vertices.length;
6031
+ const edgeCount = this.edgeSet().length;
6032
+ const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
6033
+ for (const vertex of vertices) {
6034
+ const neighbors = this.getNeighbors(vertex);
6035
+ if (neighbors.length === 0) {
6036
+ lines.push(` ${vertex.key} (isolated)`);
6037
+ } else {
6038
+ const edgeStrs = neighbors.map((neighbor) => {
6039
+ const edge = this.getEdge(vertex, neighbor);
6040
+ if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
6041
+ return `${neighbor.key} (${edge.weight})`;
6042
+ }
6043
+ return `${neighbor.key}`;
6044
+ });
6045
+ lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
6046
+ }
6047
+ }
6048
+ return lines.join("\n");
6049
+ }
6050
+ /**
6051
+ * Generate DOT language representation for Graphviz.
6052
+ *
6053
+ * @param options - Optional display settings.
6054
+ * @param options.name - Graph name (default: 'G').
6055
+ * @param options.showWeight - Whether to label edges with weight (default: true).
6056
+ * @returns DOT format string.
6057
+ */
6058
+ toDot(options) {
6059
+ var _a, _b;
6060
+ const name = (_a = options == null ? void 0 : options.name) != null ? _a : "G";
6061
+ const showWeight = (_b = options == null ? void 0 : options.showWeight) != null ? _b : true;
6062
+ const isDirected = this._edgeConnector === "->";
6063
+ const graphType = isDirected ? "digraph" : "graph";
6064
+ const edgeOp = isDirected ? "->" : "--";
6065
+ const lines = [`${graphType} ${name} {`];
6066
+ for (const vertex of this._vertexMap.values()) {
6067
+ lines.push(` "${vertex.key}";`);
6068
+ }
6069
+ const visited = /* @__PURE__ */ new Set();
6070
+ for (const vertex of this._vertexMap.values()) {
6071
+ for (const neighbor of this.getNeighbors(vertex)) {
6072
+ const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
6073
+ if (visited.has(edgeId)) continue;
6074
+ visited.add(edgeId);
6075
+ const edge = this.getEdge(vertex, neighbor);
6076
+ const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
6077
+ lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
6078
+ }
6079
+ }
6080
+ lines.push("}");
6081
+ return lines.join("\n");
6082
+ }
6083
+ /**
6084
+ * Print the graph to console.
6085
+ * @param options - Display settings passed to `toVisual`.
6086
+ */
6087
+ print(options) {
6088
+ console.log(this.toVisual(options));
6089
+ }
5897
6090
  };
5898
6091
 
5899
6092
  // src/data-structures/graph/directed-graph.ts
@@ -5922,6 +6115,9 @@ var dataStructureTyped = (() => {
5922
6115
  __publicField(this, "_outEdgeMap", /* @__PURE__ */ new Map());
5923
6116
  __publicField(this, "_inEdgeMap", /* @__PURE__ */ new Map());
5924
6117
  }
6118
+ get _edgeConnector() {
6119
+ return "->";
6120
+ }
5925
6121
  get outEdgeMap() {
5926
6122
  return this._outEdgeMap;
5927
6123
  }
@@ -6696,6 +6892,84 @@ var dataStructureTyped = (() => {
6696
6892
  cutVertices
6697
6893
  };
6698
6894
  }
6895
+ /**
6896
+ * Find biconnected components using edge-stack Tarjan variant.
6897
+ * A biconnected component is a maximal biconnected subgraph.
6898
+ * @returns Array of edge arrays, each representing a biconnected component.
6899
+ * @remarks Time O(V + E), Space O(V + E)
6900
+ */
6901
+ getBiconnectedComponents() {
6902
+ const dfn = /* @__PURE__ */ new Map();
6903
+ const low = /* @__PURE__ */ new Map();
6904
+ const edgeStack = [];
6905
+ const components = [];
6906
+ let time = 0;
6907
+ const dfs = (vertex, parent) => {
6908
+ dfn.set(vertex, time);
6909
+ low.set(vertex, time);
6910
+ time++;
6911
+ const neighbors = this.getNeighbors(vertex);
6912
+ let childCount = 0;
6913
+ for (const neighbor of neighbors) {
6914
+ const edge = this.getEdge(vertex, neighbor);
6915
+ if (!edge) continue;
6916
+ if (!dfn.has(neighbor)) {
6917
+ childCount++;
6918
+ edgeStack.push(edge);
6919
+ dfs(neighbor, vertex);
6920
+ low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
6921
+ if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
6922
+ const component = [];
6923
+ let e;
6924
+ do {
6925
+ e = edgeStack.pop();
6926
+ if (e) component.push(e);
6927
+ } while (e && e !== edge);
6928
+ if (component.length > 0) components.push(component);
6929
+ }
6930
+ } else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
6931
+ edgeStack.push(edge);
6932
+ low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
6933
+ }
6934
+ }
6935
+ };
6936
+ for (const vertex of this.vertexMap.values()) {
6937
+ if (!dfn.has(vertex)) {
6938
+ dfs(vertex, void 0);
6939
+ if (edgeStack.length > 0) {
6940
+ components.push([...edgeStack]);
6941
+ edgeStack.length = 0;
6942
+ }
6943
+ }
6944
+ }
6945
+ return components;
6946
+ }
6947
+ /**
6948
+ * Detect whether the graph contains a cycle.
6949
+ * Uses DFS with parent tracking.
6950
+ * @returns `true` if a cycle exists, `false` otherwise.
6951
+ * @remarks Time O(V + E), Space O(V)
6952
+ */
6953
+ hasCycle() {
6954
+ const visited = /* @__PURE__ */ new Set();
6955
+ const dfs = (vertex, parent) => {
6956
+ visited.add(vertex);
6957
+ for (const neighbor of this.getNeighbors(vertex)) {
6958
+ if (!visited.has(neighbor)) {
6959
+ if (dfs(neighbor, vertex)) return true;
6960
+ } else if (neighbor !== parent) {
6961
+ return true;
6962
+ }
6963
+ }
6964
+ return false;
6965
+ };
6966
+ for (const vertex of this.vertexMap.values()) {
6967
+ if (!visited.has(vertex)) {
6968
+ if (dfs(vertex, void 0)) return true;
6969
+ }
6970
+ }
6971
+ return false;
6972
+ }
6699
6973
  /**
6700
6974
  * Get bridges discovered by `tarjan()`.
6701
6975
  * @returns Array of edges that are bridges.
@@ -6840,27 +7114,6 @@ var dataStructureTyped = (() => {
6840
7114
  }
6841
7115
  };
6842
7116
 
6843
- // src/common/index.ts
6844
- var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
6845
- DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
6846
- DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
6847
- return DFSOperation2;
6848
- })(DFSOperation || {});
6849
- var Range = class {
6850
- constructor(low, high, includeLow = true, includeHigh = true) {
6851
- this.low = low;
6852
- this.high = high;
6853
- this.includeLow = includeLow;
6854
- this.includeHigh = includeHigh;
6855
- }
6856
- // Determine whether a key is within the range
6857
- isInRange(key, comparator) {
6858
- const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
6859
- const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
6860
- return lowCheck && highCheck;
6861
- }
6862
- };
6863
-
6864
7117
  // src/data-structures/binary-tree/binary-tree.ts
6865
7118
  var BinaryTreeNode = class {
6866
7119
  /**
@@ -6996,7 +7249,7 @@ var dataStructureTyped = (() => {
6996
7249
  return "MAL_NODE";
6997
7250
  }
6998
7251
  };
6999
- var BinaryTree = class extends IterableEntryBase {
7252
+ var BinaryTree = class _BinaryTree extends IterableEntryBase {
7000
7253
  /**
7001
7254
  * Creates an instance of BinaryTree.
7002
7255
  * @remarks Time O(N * M), where N is the number of items in `keysNodesEntriesOrRaws` and M is the tree size at insertion time (due to O(M) `set` operation). Space O(N) for storing the nodes.
@@ -7031,7 +7284,7 @@ var dataStructureTyped = (() => {
7031
7284
  if (isMapMode !== void 0) this._isMapMode = isMapMode;
7032
7285
  if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
7033
7286
  if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
7034
- else if (toEntryFn) throw TypeError("toEntryFn must be a function type");
7287
+ else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
7035
7288
  }
7036
7289
  if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
7037
7290
  }
@@ -7259,7 +7512,7 @@ var dataStructureTyped = (() => {
7259
7512
  if (!this._root) {
7260
7513
  this._setRoot(newNode);
7261
7514
  if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
7262
- this._size = 1;
7515
+ if (newNode !== null) this._size = 1;
7263
7516
  return true;
7264
7517
  }
7265
7518
  const queue = new Queue([this._root]);
@@ -7291,7 +7544,7 @@ var dataStructureTyped = (() => {
7291
7544
  potentialParent.right = newNode;
7292
7545
  }
7293
7546
  if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
7294
- this._size++;
7547
+ if (newNode !== null) this._size++;
7295
7548
  return true;
7296
7549
  }
7297
7550
  return false;
@@ -7860,7 +8113,7 @@ var dataStructureTyped = (() => {
7860
8113
  }
7861
8114
  /**
7862
8115
  * Finds all leaf nodes in the tree.
7863
- * @remarks Time O(N), visits every node. Space O(H) for recursive stack or O(N) for iterative queue.
8116
+ * @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
7864
8117
  *
7865
8118
  * @template C - The type of the callback function.
7866
8119
  * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
@@ -7883,15 +8136,15 @@ var dataStructureTyped = (() => {
7883
8136
  };
7884
8137
  dfs(startNode);
7885
8138
  } else {
7886
- const queue = new Queue([startNode]);
7887
- while (queue.length > 0) {
7888
- const cur = queue.shift();
8139
+ const stack = [startNode];
8140
+ while (stack.length > 0) {
8141
+ const cur = stack.pop();
7889
8142
  if (this.isRealNode(cur)) {
7890
8143
  if (this.isLeaf(cur)) {
7891
8144
  leaves.push(callback(cur));
7892
8145
  }
7893
- if (this.isRealNode(cur.left)) queue.push(cur.left);
7894
- if (this.isRealNode(cur.right)) queue.push(cur.right);
8146
+ if (this.isRealNode(cur.right)) stack.push(cur.right);
8147
+ if (this.isRealNode(cur.left)) stack.push(cur.left);
7895
8148
  }
7896
8149
  }
7897
8150
  }
@@ -8347,42 +8600,98 @@ var dataStructureTyped = (() => {
8347
8600
  _displayAux(node, options) {
8348
8601
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8349
8602
  const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
8350
- if (node === null && !isShowNull) {
8351
- return emptyDisplayLayout;
8352
- } else if (node === void 0 && !isShowUndefined) {
8353
- return emptyDisplayLayout;
8354
- } else if (this.isNIL(node) && !isShowRedBlackNIL) {
8355
- return emptyDisplayLayout;
8356
- } else if (node !== null && node !== void 0) {
8357
- const key = node.key, line = this.isNIL(node) ? "S" : String(key), width = line.length;
8358
- return _buildNodeDisplay(
8359
- line,
8360
- width,
8361
- this._displayAux(node.left, options),
8362
- this._displayAux(node.right, options)
8363
- );
8364
- } else {
8365
- const line = node === void 0 ? "U" : "N", width = line.length;
8366
- return _buildNodeDisplay(line, width, [[""], 1, 0, 0], [[""], 1, 0, 0]);
8367
- }
8368
- function _buildNodeDisplay(line, width, left, right) {
8369
- const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
8370
- const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
8371
- const firstLine = " ".repeat(Math.max(0, leftMiddle + 1)) + "_".repeat(Math.max(0, leftWidth - leftMiddle - 1)) + line + "_".repeat(Math.max(0, rightMiddle)) + " ".repeat(Math.max(0, rightWidth - rightMiddle));
8372
- const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
8373
- const mergedLines = [firstLine, secondLine];
8374
- for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
8375
- const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
8376
- const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
8377
- mergedLines.push(leftLine + " ".repeat(width) + rightLine);
8603
+ const newFrame = (n) => ({
8604
+ node: n,
8605
+ stage: 0,
8606
+ leftLayout: emptyDisplayLayout,
8607
+ rightLayout: emptyDisplayLayout
8608
+ });
8609
+ const stack = [newFrame(node)];
8610
+ let result = emptyDisplayLayout;
8611
+ const setChildResult = (layout) => {
8612
+ if (stack.length === 0) {
8613
+ result = layout;
8614
+ return;
8615
+ }
8616
+ const parent = stack[stack.length - 1];
8617
+ if (parent.stage === 1) parent.leftLayout = layout;
8618
+ else parent.rightLayout = layout;
8619
+ };
8620
+ while (stack.length > 0) {
8621
+ const frame = stack[stack.length - 1];
8622
+ const cur = frame.node;
8623
+ if (frame.stage === 0) {
8624
+ if (this._isDisplayLeaf(cur, options)) {
8625
+ stack.pop();
8626
+ const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
8627
+ setChildResult(layout);
8628
+ continue;
8629
+ }
8630
+ frame.stage = 1;
8631
+ stack.push(newFrame(cur.left));
8632
+ } else if (frame.stage === 1) {
8633
+ frame.stage = 2;
8634
+ stack.push(newFrame(cur.right));
8635
+ } else {
8636
+ stack.pop();
8637
+ const line = this.isNIL(cur) ? "S" : String(cur.key);
8638
+ const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
8639
+ setChildResult(layout);
8378
8640
  }
8379
- return [
8380
- mergedLines,
8381
- leftWidth + width + rightWidth,
8382
- Math.max(leftHeight, rightHeight) + 2,
8383
- leftWidth + Math.floor(width / 2)
8384
- ];
8385
8641
  }
8642
+ return result;
8643
+ }
8644
+ static _buildNodeDisplay(line, width, left, right) {
8645
+ const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
8646
+ const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
8647
+ const firstLine = " ".repeat(Math.max(0, leftMiddle + 1)) + "_".repeat(Math.max(0, leftWidth - leftMiddle - 1)) + line + "_".repeat(Math.max(0, rightMiddle)) + " ".repeat(Math.max(0, rightWidth - rightMiddle));
8648
+ const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
8649
+ const mergedLines = [firstLine, secondLine];
8650
+ for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
8651
+ const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
8652
+ const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
8653
+ mergedLines.push(leftLine + " ".repeat(width) + rightLine);
8654
+ }
8655
+ return [
8656
+ mergedLines,
8657
+ leftWidth + width + rightWidth,
8658
+ Math.max(leftHeight, rightHeight) + 2,
8659
+ leftWidth + Math.floor(width / 2)
8660
+ ];
8661
+ }
8662
+ /**
8663
+ * Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
8664
+ */
8665
+ _isDisplayLeaf(node, options) {
8666
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8667
+ if (node === null && !isShowNull) return true;
8668
+ if (node === void 0 && !isShowUndefined) return true;
8669
+ if (this.isNIL(node) && !isShowRedBlackNIL) return true;
8670
+ if (node === null || node === void 0) return true;
8671
+ const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
8672
+ const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
8673
+ return !hasDisplayableLeft && !hasDisplayableRight;
8674
+ }
8675
+ _hasDisplayableChild(child, options) {
8676
+ if (child === null) return !!options.isShowNull;
8677
+ if (child === void 0) return !!options.isShowUndefined;
8678
+ if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
8679
+ return true;
8680
+ }
8681
+ /**
8682
+ * Resolve a display leaf node to its layout.
8683
+ */
8684
+ _resolveDisplayLeaf(node, options, emptyDisplayLayout) {
8685
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8686
+ if (node === null && !isShowNull) return emptyDisplayLayout;
8687
+ if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
8688
+ if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
8689
+ if (node !== null && node !== void 0) {
8690
+ const line2 = this.isNIL(node) ? "S" : String(node.key);
8691
+ return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
8692
+ }
8693
+ const line = node === void 0 ? "U" : "N";
8694
+ return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
8386
8695
  }
8387
8696
  /**
8388
8697
  * (Protected) Swaps the key/value properties of two nodes.
@@ -9384,9 +9693,15 @@ var dataStructureTyped = (() => {
9384
9693
  if (a < b) return -1;
9385
9694
  return 0;
9386
9695
  }
9696
+ if (a instanceof Date && b instanceof Date) {
9697
+ const ta = a.getTime();
9698
+ const tb = b.getTime();
9699
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
9700
+ return ta > tb ? 1 : ta < tb ? -1 : 0;
9701
+ }
9387
9702
  if (typeof a === "object" || typeof b === "object") {
9388
- throw TypeError(
9389
- `When comparing object type keys, a custom comparator must be provided in the constructor's options!`
9703
+ throw new TypeError(
9704
+ ERR.comparatorRequired("BST")
9390
9705
  );
9391
9706
  }
9392
9707
  return 0;
@@ -9898,7 +10213,7 @@ var dataStructureTyped = (() => {
9898
10213
  */
9899
10214
  read(count) {
9900
10215
  if (!Number.isInteger(count)) {
9901
- throw new Error("Invalid count");
10216
+ throw new Error(ERR.invalidArgument("count must be an integer", "BinaryIndexedTree"));
9902
10217
  }
9903
10218
  return this._read(Math.max(Math.min(count, this.max), 0));
9904
10219
  }
@@ -9910,7 +10225,7 @@ var dataStructureTyped = (() => {
9910
10225
  */
9911
10226
  lowerBound(sum) {
9912
10227
  if (this.negativeCount > 0) {
9913
- throw new Error("Sequence is not non-descending");
10228
+ throw new Error(ERR.invalidOperation("Sequence is not non-descending.", "BinaryIndexedTree"));
9914
10229
  }
9915
10230
  return this._binarySearch(sum, (x, y) => x < y);
9916
10231
  }
@@ -9923,7 +10238,7 @@ var dataStructureTyped = (() => {
9923
10238
  */
9924
10239
  upperBound(sum) {
9925
10240
  if (this.negativeCount > 0) {
9926
- throw new Error("Must not be descending");
10241
+ throw new Error(ERR.invalidOperation("Sequence must not be descending.", "BinaryIndexedTree"));
9927
10242
  }
9928
10243
  return this._binarySearch(sum, (x, y) => x <= y);
9929
10244
  }
@@ -9974,10 +10289,10 @@ var dataStructureTyped = (() => {
9974
10289
  */
9975
10290
  _checkIndex(index) {
9976
10291
  if (!Number.isInteger(index)) {
9977
- throw new Error("Invalid index: Index must be an integer.");
10292
+ throw new TypeError(ERR.invalidIndex("BinaryIndexedTree"));
9978
10293
  }
9979
10294
  if (index < 0 || index >= this.max) {
9980
- throw new Error("Index out of range: Index must be within the range [0, this.max).");
10295
+ throw new RangeError(ERR.indexOutOfRange(index, 0, this.max - 1, "BinaryIndexedTree"));
9981
10296
  }
9982
10297
  }
9983
10298
  /**
@@ -11554,6 +11869,24 @@ var dataStructureTyped = (() => {
11554
11869
  * @param [thisArg] - See parameter type for details.
11555
11870
  * @returns A new RedBlackTree with mapped entries.
11556
11871
  */
11872
+ /**
11873
+ * Red-Black trees are self-balancing — `perfectlyBalance` rebuilds via
11874
+ * sorted bulk insert, which naturally produces a balanced RBT.
11875
+ * @remarks Time O(N), Space O(N)
11876
+ */
11877
+ perfectlyBalance(iterationType) {
11878
+ const entries = [];
11879
+ for (const [key, value] of this) entries.push([key, value]);
11880
+ if (entries.length <= 1) return true;
11881
+ this.clear();
11882
+ this.setMany(
11883
+ entries.map(([k]) => k),
11884
+ entries.map(([, v]) => v),
11885
+ true
11886
+ // isBalanceAdd
11887
+ );
11888
+ return true;
11889
+ }
11557
11890
  map(callback, options, thisArg) {
11558
11891
  const out = this._createLike([], options);
11559
11892
  let index = 0;
@@ -11876,7 +12209,7 @@ var dataStructureTyped = (() => {
11876
12209
  static createDefaultComparator() {
11877
12210
  return (a, b) => {
11878
12211
  if (typeof a === "number" && typeof b === "number") {
11879
- if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeSet: NaN is not a valid key");
12212
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeSet"));
11880
12213
  const aa = Object.is(a, -0) ? 0 : a;
11881
12214
  const bb = Object.is(b, -0) ? 0 : b;
11882
12215
  return aa > bb ? 1 : aa < bb ? -1 : 0;
@@ -11887,10 +12220,10 @@ var dataStructureTyped = (() => {
11887
12220
  if (a instanceof Date && b instanceof Date) {
11888
12221
  const ta = a.getTime();
11889
12222
  const tb = b.getTime();
11890
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeSet: invalid Date key");
12223
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeSet"));
11891
12224
  return ta > tb ? 1 : ta < tb ? -1 : 0;
11892
12225
  }
11893
- throw new TypeError("TreeSet: comparator is required for non-number/non-string/non-Date keys");
12226
+ throw new TypeError(ERR.comparatorRequired("TreeSet"));
11894
12227
  };
11895
12228
  }
11896
12229
  /**
@@ -11908,15 +12241,15 @@ var dataStructureTyped = (() => {
11908
12241
  _validateKey(key) {
11909
12242
  if (!__privateGet(this, _isDefaultComparator)) return;
11910
12243
  if (typeof key === "number") {
11911
- if (Number.isNaN(key)) throw new TypeError("TreeSet: NaN is not a valid key");
12244
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeSet"));
11912
12245
  return;
11913
12246
  }
11914
12247
  if (typeof key === "string") return;
11915
12248
  if (key instanceof Date) {
11916
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeSet: invalid Date key");
12249
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeSet"));
11917
12250
  return;
11918
12251
  }
11919
- throw new TypeError("TreeSet: comparator is required for non-number/non-string/non-Date keys");
12252
+ throw new TypeError(ERR.comparatorRequired("TreeSet"));
11920
12253
  }
11921
12254
  /**
11922
12255
  * Add a key to the set (no-op if already present).
@@ -12236,15 +12569,15 @@ var dataStructureTyped = (() => {
12236
12569
  _validateKey(key) {
12237
12570
  if (!__privateGet(this, _isDefaultComparator2)) return;
12238
12571
  if (typeof key === "number") {
12239
- if (Number.isNaN(key)) throw new TypeError("TreeMultiMap: NaN is not a valid key");
12572
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiMap"));
12240
12573
  return;
12241
12574
  }
12242
12575
  if (typeof key === "string") return;
12243
12576
  if (key instanceof Date) {
12244
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiMap: invalid Date key");
12577
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiMap"));
12245
12578
  return;
12246
12579
  }
12247
- throw new TypeError("TreeMultiMap: comparator is required for non-number/non-string/non-Date keys");
12580
+ throw new TypeError(ERR.comparatorRequired("TreeMultiMap"));
12248
12581
  }
12249
12582
  /**
12250
12583
  * Number of distinct keys.
@@ -12668,7 +13001,7 @@ var dataStructureTyped = (() => {
12668
13001
  [k, v] = toEntryFn(item);
12669
13002
  } else {
12670
13003
  if (!Array.isArray(item) || item.length < 2) {
12671
- throw new TypeError("TreeMap: each entry must be a [key, value] tuple");
13004
+ throw new TypeError(ERR.invalidEntry("TreeMap"));
12672
13005
  }
12673
13006
  k = item[0];
12674
13007
  v = item[1];
@@ -12689,7 +13022,7 @@ var dataStructureTyped = (() => {
12689
13022
  static createDefaultComparator() {
12690
13023
  return (a, b) => {
12691
13024
  if (typeof a === "number" && typeof b === "number") {
12692
- if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeMap: NaN is not a valid key");
13025
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeMap"));
12693
13026
  const aa = Object.is(a, -0) ? 0 : a;
12694
13027
  const bb = Object.is(b, -0) ? 0 : b;
12695
13028
  return aa > bb ? 1 : aa < bb ? -1 : 0;
@@ -12700,24 +13033,24 @@ var dataStructureTyped = (() => {
12700
13033
  if (a instanceof Date && b instanceof Date) {
12701
13034
  const ta = a.getTime();
12702
13035
  const tb = b.getTime();
12703
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeMap: invalid Date key");
13036
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeMap"));
12704
13037
  return ta > tb ? 1 : ta < tb ? -1 : 0;
12705
13038
  }
12706
- throw new TypeError("TreeMap: comparator is required for non-number/non-string/non-Date keys");
13039
+ throw new TypeError(ERR.comparatorRequired("TreeMap"));
12707
13040
  };
12708
13041
  }
12709
13042
  _validateKey(key) {
12710
13043
  if (!__privateGet(this, _isDefaultComparator3)) return;
12711
13044
  if (typeof key === "number") {
12712
- if (Number.isNaN(key)) throw new TypeError("TreeMap: NaN is not a valid key");
13045
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMap"));
12713
13046
  return;
12714
13047
  }
12715
13048
  if (typeof key === "string") return;
12716
13049
  if (key instanceof Date) {
12717
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMap: invalid Date key");
13050
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMap"));
12718
13051
  return;
12719
13052
  }
12720
- throw new TypeError("TreeMap: comparator is required for non-number/non-string/non-Date keys");
13053
+ throw new TypeError(ERR.comparatorRequired("TreeMap"));
12721
13054
  }
12722
13055
  /**
12723
13056
  * Number of entries in the map.
@@ -13045,22 +13378,22 @@ var dataStructureTyped = (() => {
13045
13378
  _validateKey(key) {
13046
13379
  if (!__privateGet(this, _isDefaultComparator4)) return;
13047
13380
  if (typeof key === "number") {
13048
- if (Number.isNaN(key)) throw new TypeError("TreeMultiSet: NaN is not a valid key");
13381
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiSet"));
13049
13382
  return;
13050
13383
  }
13051
13384
  if (typeof key === "string") return;
13052
13385
  if (key instanceof Date) {
13053
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiSet: invalid Date key");
13386
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiSet"));
13054
13387
  return;
13055
13388
  }
13056
- throw new TypeError("TreeMultiSet: comparator is required for non-number/non-string/non-Date keys");
13389
+ throw new TypeError(ERR.comparatorRequired("TreeMultiSet"));
13057
13390
  }
13058
13391
  /**
13059
13392
  * Validates that count is a non-negative safe integer.
13060
13393
  * @remarks Time O(1), Space O(1)
13061
13394
  */
13062
13395
  _validateCount(n) {
13063
- if (!Number.isSafeInteger(n) || n < 0) throw new RangeError("TreeMultiSet: count must be a safe integer >= 0");
13396
+ if (!Number.isSafeInteger(n) || n < 0) throw new RangeError(ERR.invalidArgument("count must be a safe integer >= 0.", "TreeMultiSet"));
13064
13397
  }
13065
13398
  /**
13066
13399
  * Total occurrences (sumCounts).
@@ -13483,9 +13816,7 @@ var dataStructureTyped = (() => {
13483
13816
  super(elements, {
13484
13817
  comparator: (a, b) => {
13485
13818
  if (typeof a === "object" || typeof b === "object") {
13486
- throw TypeError(
13487
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
13488
- );
13819
+ throw new TypeError(ERR.comparatorRequired("MaxPriorityQueue"));
13489
13820
  }
13490
13821
  if (a < b) return 1;
13491
13822
  if (a > b) return -1;
@@ -13624,7 +13955,7 @@ var dataStructureTyped = (() => {
13624
13955
  */
13625
13956
  add(matrix) {
13626
13957
  if (!this.isMatchForCalculate(matrix)) {
13627
- throw new Error("Matrix dimensions must match for addition.");
13958
+ throw new Error(ERR.matrixDimensionMismatch("addition"));
13628
13959
  }
13629
13960
  const resultData = [];
13630
13961
  for (let i = 0; i < this.rows; i++) {
@@ -13656,7 +13987,7 @@ var dataStructureTyped = (() => {
13656
13987
  */
13657
13988
  subtract(matrix) {
13658
13989
  if (!this.isMatchForCalculate(matrix)) {
13659
- throw new Error("Matrix dimensions must match for subtraction.");
13990
+ throw new Error(ERR.matrixDimensionMismatch("subtraction"));
13660
13991
  }
13661
13992
  const resultData = [];
13662
13993
  for (let i = 0; i < this.rows; i++) {
@@ -13687,7 +14018,7 @@ var dataStructureTyped = (() => {
13687
14018
  */
13688
14019
  multiply(matrix) {
13689
14020
  if (this.cols !== matrix.rows) {
13690
- throw new Error("Matrix dimensions must be compatible for multiplication (A.cols = B.rows).");
14021
+ throw new Error(ERR.matrixDimensionMismatch("multiplication (A.cols must equal B.rows)"));
13691
14022
  }
13692
14023
  const resultData = [];
13693
14024
  for (let i = 0; i < this.rows; i++) {
@@ -13721,7 +14052,7 @@ var dataStructureTyped = (() => {
13721
14052
  */
13722
14053
  transpose() {
13723
14054
  if (this.data.some((row) => row.length !== this.rows)) {
13724
- throw new Error("Matrix must be rectangular for transposition.");
14055
+ throw new Error(ERR.matrixNotRectangular());
13725
14056
  }
13726
14057
  const resultData = [];
13727
14058
  for (let j = 0; j < this.cols; j++) {
@@ -13746,7 +14077,7 @@ var dataStructureTyped = (() => {
13746
14077
  inverse() {
13747
14078
  var _a;
13748
14079
  if (this.rows !== this.cols) {
13749
- throw new Error("Matrix must be square for inversion.");
14080
+ throw new Error(ERR.matrixNotSquare());
13750
14081
  }
13751
14082
  const augmentedMatrixData = [];
13752
14083
  for (let i = 0; i < this.rows; i++) {
@@ -13768,12 +14099,12 @@ var dataStructureTyped = (() => {
13768
14099
  pivotRow++;
13769
14100
  }
13770
14101
  if (pivotRow === this.rows) {
13771
- throw new Error("Matrix is singular, and its inverse does not exist.");
14102
+ throw new Error(ERR.matrixSingular());
13772
14103
  }
13773
14104
  augmentedMatrix._swapRows(i, pivotRow);
13774
14105
  const pivotElement = (_a = augmentedMatrix.get(i, i)) != null ? _a : 1;
13775
14106
  if (pivotElement === 0) {
13776
- throw new Error("Matrix is singular, and its inverse does not exist (division by zero).");
14107
+ throw new Error(ERR.matrixSingular());
13777
14108
  }
13778
14109
  augmentedMatrix._scaleRow(i, 1 / pivotElement);
13779
14110
  for (let j = 0; j < this.rows; j++) {
@@ -13803,9 +14134,7 @@ var dataStructureTyped = (() => {
13803
14134
  */
13804
14135
  dot(matrix) {
13805
14136
  if (this.cols !== matrix.rows) {
13806
- throw new Error(
13807
- "Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product."
13808
- );
14137
+ throw new Error(ERR.matrixDimensionMismatch("dot product (A.cols must equal B.rows)"));
13809
14138
  }
13810
14139
  const resultData = [];
13811
14140
  for (let i = 0; i < this.rows; i++) {
@@ -14419,7 +14748,7 @@ var dataStructureTyped = (() => {
14419
14748
  for (const x of this) {
14420
14749
  const v = thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
14421
14750
  if (typeof v !== "string") {
14422
- throw new TypeError(`Trie.map callback must return string; got ${typeof v}`);
14751
+ throw new TypeError(ERR.callbackReturnType("string", typeof v, "Trie.map"));
14423
14752
  }
14424
14753
  newTrie.add(v);
14425
14754
  }