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
@@ -183,6 +183,55 @@ var IterableEntryBase = class {
183
183
  }
184
184
  };
185
185
 
186
+ // src/common/error.ts
187
+ var ERR = {
188
+ // Range / index
189
+ indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
190
+ invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
191
+ // Type / argument
192
+ invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
193
+ comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
194
+ invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
195
+ notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
196
+ invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
197
+ invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
198
+ invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
199
+ reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
200
+ callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
201
+ // State / operation
202
+ invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
203
+ // Matrix
204
+ matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
205
+ matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
206
+ matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
207
+ matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
208
+ matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
209
+ };
210
+
211
+ // src/common/index.ts
212
+ var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
213
+ DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
214
+ DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
215
+ return DFSOperation2;
216
+ })(DFSOperation || {});
217
+ var Range = class {
218
+ constructor(low, high, includeLow = true, includeHigh = true) {
219
+ this.low = low;
220
+ this.high = high;
221
+ this.includeLow = includeLow;
222
+ this.includeHigh = includeHigh;
223
+ }
224
+ static {
225
+ __name(this, "Range");
226
+ }
227
+ // Determine whether a key is within the range
228
+ isInRange(key, comparator) {
229
+ const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
230
+ const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
231
+ return lowCheck && highCheck;
232
+ }
233
+ };
234
+
186
235
  // src/data-structures/base/iterable-element-base.ts
187
236
  var IterableElementBase = class {
188
237
  static {
@@ -201,7 +250,7 @@ var IterableElementBase = class {
201
250
  if (options) {
202
251
  const { toElementFn } = options;
203
252
  if (typeof toElementFn === "function") this._toElementFn = toElementFn;
204
- else if (toElementFn) throw new TypeError("toElementFn must be a function type");
253
+ else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
205
254
  }
206
255
  }
207
256
  /**
@@ -364,7 +413,7 @@ var IterableElementBase = class {
364
413
  acc = initialValue;
365
414
  } else {
366
415
  const first = iter.next();
367
- if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
416
+ if (first.done) throw new TypeError(ERR.reduceEmpty());
368
417
  acc = first.value;
369
418
  index = 1;
370
419
  }
@@ -432,8 +481,10 @@ var getMSB = /* @__PURE__ */ __name((value) => {
432
481
  }
433
482
  return 1 << 31 - Math.clz32(value);
434
483
  }, "getMSB");
435
- var rangeCheck = /* @__PURE__ */ __name((index, min, max, message = "Index out of bounds.") => {
436
- if (index < min || index > max) throw new RangeError(message);
484
+ var rangeCheck = /* @__PURE__ */ __name((index, min, max, message) => {
485
+ if (index < min || index > max) {
486
+ throw new RangeError(message ?? `Index ${index} is out of range [${min}, ${max}].`);
487
+ }
437
488
  }, "rangeCheck");
438
489
  var throwRangeError = /* @__PURE__ */ __name((message = "The value is off-limits.") => {
439
490
  throw new RangeError(message);
@@ -856,8 +907,8 @@ var LinkedHashMap = class extends IterableEntryBase {
856
907
  if (this.isEntry(rawElement)) {
857
908
  return rawElement;
858
909
  }
859
- throw new Error(
860
- "If `entryOrRawElements` does not adhere to [key,value], provide `options.toEntryFn` to transform raw records."
910
+ throw new TypeError(
911
+ ERR.invalidArgument("If elements do not adhere to [key, value], provide options.toEntryFn to transform raw records.", "HashMap")
861
912
  );
862
913
  }, "_toEntryFn");
863
914
  get toEntryFn() {
@@ -1094,6 +1145,13 @@ var LinkedHashMap = class extends IterableEntryBase {
1094
1145
  }
1095
1146
  }
1096
1147
  _deleteNode(node) {
1148
+ const key = node.key;
1149
+ if (isWeakKey(key)) {
1150
+ this._objMap.delete(key);
1151
+ } else {
1152
+ const hash = this._hashFn(key);
1153
+ delete this._noObjMap[hash];
1154
+ }
1097
1155
  const { prev, next } = node;
1098
1156
  prev.next = next;
1099
1157
  next.prev = prev;
@@ -3608,18 +3666,12 @@ var Deque = class extends LinearBase {
3608
3666
  __name(this, "Deque");
3609
3667
  }
3610
3668
  _equals = /* @__PURE__ */ __name((a, b) => Object.is(a, b), "_equals");
3611
- /**
3612
- * Create a Deque and optionally bulk-insert elements.
3613
- * @remarks Time O(N), Space O(N)
3614
- * @param [elements] - Iterable (or iterable-like) of elements/records to insert.
3615
- * @param [options] - Options such as bucketSize, toElementFn, and maxLen.
3616
- * @returns New Deque instance.
3617
- */
3618
3669
  constructor(elements = [], options) {
3619
3670
  super(options);
3620
3671
  if (options) {
3621
- const { bucketSize } = options;
3672
+ const { bucketSize, autoCompactRatio } = options;
3622
3673
  if (typeof bucketSize === "number") this._bucketSize = bucketSize;
3674
+ if (typeof autoCompactRatio === "number") this._autoCompactRatio = autoCompactRatio;
3623
3675
  }
3624
3676
  let _size;
3625
3677
  if ("length" in elements) {
@@ -3645,6 +3697,30 @@ var Deque = class extends LinearBase {
3645
3697
  get bucketSize() {
3646
3698
  return this._bucketSize;
3647
3699
  }
3700
+ _autoCompactRatio = 0.5;
3701
+ /**
3702
+ * Get the auto-compaction ratio.
3703
+ * When `elements / (bucketCount * bucketSize)` drops below this ratio after
3704
+ * enough shift/pop operations, the deque auto-compacts.
3705
+ * @remarks Time O(1), Space O(1)
3706
+ * @returns Current ratio threshold. 0 means auto-compact is disabled.
3707
+ */
3708
+ get autoCompactRatio() {
3709
+ return this._autoCompactRatio;
3710
+ }
3711
+ /**
3712
+ * Set the auto-compaction ratio.
3713
+ * @remarks Time O(1), Space O(1)
3714
+ * @param value - Ratio in [0,1]. 0 disables auto-compact.
3715
+ */
3716
+ set autoCompactRatio(value) {
3717
+ this._autoCompactRatio = value;
3718
+ }
3719
+ /**
3720
+ * Counter for shift/pop operations since last compaction check.
3721
+ * Only checks ratio every `_bucketSize` operations to minimize overhead.
3722
+ */
3723
+ _compactCounter = 0;
3648
3724
  _bucketFirst = 0;
3649
3725
  /**
3650
3726
  * Get the index of the first bucket in use.
@@ -3783,6 +3859,7 @@ var Deque = class extends LinearBase {
3783
3859
  }
3784
3860
  }
3785
3861
  this._length -= 1;
3862
+ this._autoCompact();
3786
3863
  return element;
3787
3864
  }
3788
3865
  /**
@@ -3805,6 +3882,7 @@ var Deque = class extends LinearBase {
3805
3882
  }
3806
3883
  }
3807
3884
  this._length -= 1;
3885
+ this._autoCompact();
3808
3886
  return element;
3809
3887
  }
3810
3888
  /**
@@ -4137,11 +4215,40 @@ var Deque = class extends LinearBase {
4137
4215
  * @remarks Time O(N), Space O(1)
4138
4216
  * @returns void
4139
4217
  */
4218
+ /**
4219
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
4220
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
4221
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
4222
+ */
4223
+ _autoCompact() {
4224
+ if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
4225
+ this._compactCounter++;
4226
+ if (this._compactCounter < this._bucketSize) return;
4227
+ this._compactCounter = 0;
4228
+ const utilization = this._length / (this._bucketCount * this._bucketSize);
4229
+ if (utilization < this._autoCompactRatio) {
4230
+ this.shrinkToFit();
4231
+ }
4232
+ }
4233
+ /**
4234
+ * Compact the deque by removing unused buckets.
4235
+ * @remarks Time O(N), Space O(1)
4236
+ * @returns True if compaction was performed (bucket count reduced).
4237
+ */
4238
+ /**
4239
+ * Compact the deque by removing unused buckets.
4240
+ * @remarks Time O(N), Space O(1)
4241
+ * @returns True if compaction was performed (bucket count reduced).
4242
+ */
4243
+ compact() {
4244
+ const before = this._bucketCount;
4245
+ this.shrinkToFit();
4246
+ return this._bucketCount < before;
4247
+ }
4140
4248
  shrinkToFit() {
4141
4249
  if (this._length === 0) return;
4142
4250
  const newBuckets = [];
4143
- if (this._bucketFirst === this._bucketLast) return;
4144
- else if (this._bucketFirst < this._bucketLast) {
4251
+ if (this._bucketFirst <= this._bucketLast) {
4145
4252
  for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
4146
4253
  newBuckets.push(this._buckets[i]);
4147
4254
  }
@@ -4156,6 +4263,8 @@ var Deque = class extends LinearBase {
4156
4263
  this._bucketFirst = 0;
4157
4264
  this._bucketLast = newBuckets.length - 1;
4158
4265
  this._buckets = newBuckets;
4266
+ this._bucketCount = newBuckets.length;
4267
+ this._compactCounter = 0;
4159
4268
  }
4160
4269
  /**
4161
4270
  * Deep clone this deque, preserving options.
@@ -4654,7 +4763,7 @@ var Heap = class _Heap extends IterableElementBase {
4654
4763
  */
4655
4764
  map(callback, options, thisArg) {
4656
4765
  const { comparator, toElementFn, ...rest } = options ?? {};
4657
- if (!comparator) throw new TypeError("Heap.map requires options.comparator for EM");
4766
+ if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
4658
4767
  const out = this._createLike([], { ...rest, comparator, toElementFn });
4659
4768
  let i = 0;
4660
4769
  for (const x of this) {
@@ -4681,7 +4790,7 @@ var Heap = class _Heap extends IterableElementBase {
4681
4790
  }
4682
4791
  _DEFAULT_COMPARATOR = /* @__PURE__ */ __name((a, b) => {
4683
4792
  if (typeof a === "object" || typeof b === "object") {
4684
- throw TypeError("When comparing object types, define a custom comparator in options.");
4793
+ throw new TypeError(ERR.comparatorRequired("Heap"));
4685
4794
  }
4686
4795
  if (a > b) return 1;
4687
4796
  if (a < b) return -1;
@@ -4793,7 +4902,7 @@ var FibonacciHeap = class {
4793
4902
  constructor(comparator) {
4794
4903
  this.clear();
4795
4904
  this._comparator = comparator || this._defaultComparator;
4796
- if (typeof this.comparator !== "function") throw new Error("FibonacciHeap: comparator must be a function.");
4905
+ if (typeof this.comparator !== "function") throw new TypeError(ERR.notAFunction("comparator", "FibonacciHeap"));
4797
4906
  }
4798
4907
  _root;
4799
4908
  /**
@@ -5009,9 +5118,7 @@ var MaxHeap = class extends Heap {
5009
5118
  super(elements, {
5010
5119
  comparator: /* @__PURE__ */ __name((a, b) => {
5011
5120
  if (typeof a === "object" || typeof b === "object") {
5012
- throw TypeError(
5013
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
5014
- );
5121
+ throw new TypeError(ERR.comparatorRequired("MaxHeap"));
5015
5122
  }
5016
5123
  if (a < b) return 1;
5017
5124
  if (a > b) return -1;
@@ -5180,7 +5287,7 @@ var AbstractGraph = class extends IterableEntryBase {
5180
5287
  const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
5181
5288
  return this._addEdge(newEdge);
5182
5289
  } else {
5183
- throw new Error("dest must be a Vertex or vertex key while srcOrEdge is an Edge");
5290
+ throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
5184
5291
  }
5185
5292
  }
5186
5293
  }
@@ -5860,6 +5967,92 @@ var AbstractGraph = class extends IterableEntryBase {
5860
5967
  _getVertexKey(vertexOrKey) {
5861
5968
  return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
5862
5969
  }
5970
+ /**
5971
+ * The edge connector string used in visual output.
5972
+ * Override in subclasses (e.g., '--' for undirected, '->' for directed).
5973
+ */
5974
+ get _edgeConnector() {
5975
+ return "--";
5976
+ }
5977
+ /**
5978
+ * Generate a text-based visual representation of the graph.
5979
+ *
5980
+ * **Adjacency list format:**
5981
+ * ```
5982
+ * Graph (5 vertices, 6 edges):
5983
+ * A -> B (1), C (2)
5984
+ * B -> D (3)
5985
+ * C -> (no outgoing edges)
5986
+ * D -> A (1)
5987
+ * E (isolated)
5988
+ * ```
5989
+ *
5990
+ * @param options - Optional display settings.
5991
+ * @param options.showWeight - Whether to show edge weights (default: true).
5992
+ * @returns The visual string.
5993
+ */
5994
+ toVisual(options) {
5995
+ const showWeight = options?.showWeight ?? true;
5996
+ const vertices = [...this._vertexMap.values()];
5997
+ const vertexCount = vertices.length;
5998
+ const edgeCount = this.edgeSet().length;
5999
+ const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
6000
+ for (const vertex of vertices) {
6001
+ const neighbors = this.getNeighbors(vertex);
6002
+ if (neighbors.length === 0) {
6003
+ lines.push(` ${vertex.key} (isolated)`);
6004
+ } else {
6005
+ const edgeStrs = neighbors.map((neighbor) => {
6006
+ const edge = this.getEdge(vertex, neighbor);
6007
+ if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
6008
+ return `${neighbor.key} (${edge.weight})`;
6009
+ }
6010
+ return `${neighbor.key}`;
6011
+ });
6012
+ lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
6013
+ }
6014
+ }
6015
+ return lines.join("\n");
6016
+ }
6017
+ /**
6018
+ * Generate DOT language representation for Graphviz.
6019
+ *
6020
+ * @param options - Optional display settings.
6021
+ * @param options.name - Graph name (default: 'G').
6022
+ * @param options.showWeight - Whether to label edges with weight (default: true).
6023
+ * @returns DOT format string.
6024
+ */
6025
+ toDot(options) {
6026
+ const name = options?.name ?? "G";
6027
+ const showWeight = options?.showWeight ?? true;
6028
+ const isDirected = this._edgeConnector === "->";
6029
+ const graphType = isDirected ? "digraph" : "graph";
6030
+ const edgeOp = isDirected ? "->" : "--";
6031
+ const lines = [`${graphType} ${name} {`];
6032
+ for (const vertex of this._vertexMap.values()) {
6033
+ lines.push(` "${vertex.key}";`);
6034
+ }
6035
+ const visited = /* @__PURE__ */ new Set();
6036
+ for (const vertex of this._vertexMap.values()) {
6037
+ for (const neighbor of this.getNeighbors(vertex)) {
6038
+ const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
6039
+ if (visited.has(edgeId)) continue;
6040
+ visited.add(edgeId);
6041
+ const edge = this.getEdge(vertex, neighbor);
6042
+ const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
6043
+ lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
6044
+ }
6045
+ }
6046
+ lines.push("}");
6047
+ return lines.join("\n");
6048
+ }
6049
+ /**
6050
+ * Print the graph to console.
6051
+ * @param options - Display settings passed to `toVisual`.
6052
+ */
6053
+ print(options) {
6054
+ console.log(this.toVisual(options));
6055
+ }
5863
6056
  };
5864
6057
 
5865
6058
  // src/data-structures/graph/directed-graph.ts
@@ -5895,6 +6088,9 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
5895
6088
  constructor(options) {
5896
6089
  super(options);
5897
6090
  }
6091
+ get _edgeConnector() {
6092
+ return "->";
6093
+ }
5898
6094
  _outEdgeMap = /* @__PURE__ */ new Map();
5899
6095
  get outEdgeMap() {
5900
6096
  return this._outEdgeMap;
@@ -6676,6 +6872,84 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
6676
6872
  cutVertices
6677
6873
  };
6678
6874
  }
6875
+ /**
6876
+ * Find biconnected components using edge-stack Tarjan variant.
6877
+ * A biconnected component is a maximal biconnected subgraph.
6878
+ * @returns Array of edge arrays, each representing a biconnected component.
6879
+ * @remarks Time O(V + E), Space O(V + E)
6880
+ */
6881
+ getBiconnectedComponents() {
6882
+ const dfn = /* @__PURE__ */ new Map();
6883
+ const low = /* @__PURE__ */ new Map();
6884
+ const edgeStack = [];
6885
+ const components = [];
6886
+ let time = 0;
6887
+ const dfs = /* @__PURE__ */ __name((vertex, parent) => {
6888
+ dfn.set(vertex, time);
6889
+ low.set(vertex, time);
6890
+ time++;
6891
+ const neighbors = this.getNeighbors(vertex);
6892
+ let childCount = 0;
6893
+ for (const neighbor of neighbors) {
6894
+ const edge = this.getEdge(vertex, neighbor);
6895
+ if (!edge) continue;
6896
+ if (!dfn.has(neighbor)) {
6897
+ childCount++;
6898
+ edgeStack.push(edge);
6899
+ dfs(neighbor, vertex);
6900
+ low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
6901
+ if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
6902
+ const component = [];
6903
+ let e;
6904
+ do {
6905
+ e = edgeStack.pop();
6906
+ if (e) component.push(e);
6907
+ } while (e && e !== edge);
6908
+ if (component.length > 0) components.push(component);
6909
+ }
6910
+ } else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
6911
+ edgeStack.push(edge);
6912
+ low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
6913
+ }
6914
+ }
6915
+ }, "dfs");
6916
+ for (const vertex of this.vertexMap.values()) {
6917
+ if (!dfn.has(vertex)) {
6918
+ dfs(vertex, void 0);
6919
+ if (edgeStack.length > 0) {
6920
+ components.push([...edgeStack]);
6921
+ edgeStack.length = 0;
6922
+ }
6923
+ }
6924
+ }
6925
+ return components;
6926
+ }
6927
+ /**
6928
+ * Detect whether the graph contains a cycle.
6929
+ * Uses DFS with parent tracking.
6930
+ * @returns `true` if a cycle exists, `false` otherwise.
6931
+ * @remarks Time O(V + E), Space O(V)
6932
+ */
6933
+ hasCycle() {
6934
+ const visited = /* @__PURE__ */ new Set();
6935
+ const dfs = /* @__PURE__ */ __name((vertex, parent) => {
6936
+ visited.add(vertex);
6937
+ for (const neighbor of this.getNeighbors(vertex)) {
6938
+ if (!visited.has(neighbor)) {
6939
+ if (dfs(neighbor, vertex)) return true;
6940
+ } else if (neighbor !== parent) {
6941
+ return true;
6942
+ }
6943
+ }
6944
+ return false;
6945
+ }, "dfs");
6946
+ for (const vertex of this.vertexMap.values()) {
6947
+ if (!visited.has(vertex)) {
6948
+ if (dfs(vertex, void 0)) return true;
6949
+ }
6950
+ }
6951
+ return false;
6952
+ }
6679
6953
  /**
6680
6954
  * Get bridges discovered by `tarjan()`.
6681
6955
  * @returns Array of edges that are bridges.
@@ -6829,30 +7103,6 @@ var MapGraph = class _MapGraph extends DirectedGraph {
6829
7103
  }
6830
7104
  };
6831
7105
 
6832
- // src/common/index.ts
6833
- var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
6834
- DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
6835
- DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
6836
- return DFSOperation2;
6837
- })(DFSOperation || {});
6838
- var Range = class {
6839
- constructor(low, high, includeLow = true, includeHigh = true) {
6840
- this.low = low;
6841
- this.high = high;
6842
- this.includeLow = includeLow;
6843
- this.includeHigh = includeHigh;
6844
- }
6845
- static {
6846
- __name(this, "Range");
6847
- }
6848
- // Determine whether a key is within the range
6849
- isInRange(key, comparator) {
6850
- const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
6851
- const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
6852
- return lowCheck && highCheck;
6853
- }
6854
- };
6855
-
6856
7106
  // src/data-structures/binary-tree/binary-tree.ts
6857
7107
  var BinaryTreeNode = class {
6858
7108
  static {
@@ -6991,7 +7241,7 @@ var BinaryTreeNode = class {
6991
7241
  return "MAL_NODE";
6992
7242
  }
6993
7243
  };
6994
- var BinaryTree = class extends IterableEntryBase {
7244
+ var BinaryTree = class _BinaryTree extends IterableEntryBase {
6995
7245
  static {
6996
7246
  __name(this, "BinaryTree");
6997
7247
  }
@@ -7011,7 +7261,7 @@ var BinaryTree = class extends IterableEntryBase {
7011
7261
  if (isMapMode !== void 0) this._isMapMode = isMapMode;
7012
7262
  if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
7013
7263
  if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
7014
- else if (toEntryFn) throw TypeError("toEntryFn must be a function type");
7264
+ else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
7015
7265
  }
7016
7266
  if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
7017
7267
  }
@@ -7249,7 +7499,7 @@ var BinaryTree = class extends IterableEntryBase {
7249
7499
  if (!this._root) {
7250
7500
  this._setRoot(newNode);
7251
7501
  if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
7252
- this._size = 1;
7502
+ if (newNode !== null) this._size = 1;
7253
7503
  return true;
7254
7504
  }
7255
7505
  const queue = new Queue([this._root]);
@@ -7281,7 +7531,7 @@ var BinaryTree = class extends IterableEntryBase {
7281
7531
  potentialParent.right = newNode;
7282
7532
  }
7283
7533
  if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
7284
- this._size++;
7534
+ if (newNode !== null) this._size++;
7285
7535
  return true;
7286
7536
  }
7287
7537
  return false;
@@ -7849,7 +8099,7 @@ var BinaryTree = class extends IterableEntryBase {
7849
8099
  }
7850
8100
  /**
7851
8101
  * Finds all leaf nodes in the tree.
7852
- * @remarks Time O(N), visits every node. Space O(H) for recursive stack or O(N) for iterative queue.
8102
+ * @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
7853
8103
  *
7854
8104
  * @template C - The type of the callback function.
7855
8105
  * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
@@ -7872,15 +8122,15 @@ var BinaryTree = class extends IterableEntryBase {
7872
8122
  }, "dfs");
7873
8123
  dfs(startNode);
7874
8124
  } else {
7875
- const queue = new Queue([startNode]);
7876
- while (queue.length > 0) {
7877
- const cur = queue.shift();
8125
+ const stack = [startNode];
8126
+ while (stack.length > 0) {
8127
+ const cur = stack.pop();
7878
8128
  if (this.isRealNode(cur)) {
7879
8129
  if (this.isLeaf(cur)) {
7880
8130
  leaves.push(callback(cur));
7881
8131
  }
7882
- if (this.isRealNode(cur.left)) queue.push(cur.left);
7883
- if (this.isRealNode(cur.right)) queue.push(cur.right);
8132
+ if (this.isRealNode(cur.right)) stack.push(cur.right);
8133
+ if (this.isRealNode(cur.left)) stack.push(cur.left);
7884
8134
  }
7885
8135
  }
7886
8136
  }
@@ -8342,42 +8592,98 @@ var BinaryTree = class extends IterableEntryBase {
8342
8592
  _displayAux(node, options) {
8343
8593
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8344
8594
  const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
8345
- if (node === null && !isShowNull) {
8346
- return emptyDisplayLayout;
8347
- } else if (node === void 0 && !isShowUndefined) {
8348
- return emptyDisplayLayout;
8349
- } else if (this.isNIL(node) && !isShowRedBlackNIL) {
8350
- return emptyDisplayLayout;
8351
- } else if (node !== null && node !== void 0) {
8352
- const key = node.key, line = this.isNIL(node) ? "S" : String(key), width = line.length;
8353
- return _buildNodeDisplay(
8354
- line,
8355
- width,
8356
- this._displayAux(node.left, options),
8357
- this._displayAux(node.right, options)
8358
- );
8359
- } else {
8360
- const line = node === void 0 ? "U" : "N", width = line.length;
8361
- return _buildNodeDisplay(line, width, [[""], 1, 0, 0], [[""], 1, 0, 0]);
8362
- }
8363
- function _buildNodeDisplay(line, width, left, right) {
8364
- const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
8365
- const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
8366
- 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));
8367
- const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
8368
- const mergedLines = [firstLine, secondLine];
8369
- for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
8370
- const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
8371
- const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
8372
- mergedLines.push(leftLine + " ".repeat(width) + rightLine);
8595
+ const newFrame = /* @__PURE__ */ __name((n) => ({
8596
+ node: n,
8597
+ stage: 0,
8598
+ leftLayout: emptyDisplayLayout,
8599
+ rightLayout: emptyDisplayLayout
8600
+ }), "newFrame");
8601
+ const stack = [newFrame(node)];
8602
+ let result = emptyDisplayLayout;
8603
+ const setChildResult = /* @__PURE__ */ __name((layout) => {
8604
+ if (stack.length === 0) {
8605
+ result = layout;
8606
+ return;
8607
+ }
8608
+ const parent = stack[stack.length - 1];
8609
+ if (parent.stage === 1) parent.leftLayout = layout;
8610
+ else parent.rightLayout = layout;
8611
+ }, "setChildResult");
8612
+ while (stack.length > 0) {
8613
+ const frame = stack[stack.length - 1];
8614
+ const cur = frame.node;
8615
+ if (frame.stage === 0) {
8616
+ if (this._isDisplayLeaf(cur, options)) {
8617
+ stack.pop();
8618
+ const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
8619
+ setChildResult(layout);
8620
+ continue;
8621
+ }
8622
+ frame.stage = 1;
8623
+ stack.push(newFrame(cur.left));
8624
+ } else if (frame.stage === 1) {
8625
+ frame.stage = 2;
8626
+ stack.push(newFrame(cur.right));
8627
+ } else {
8628
+ stack.pop();
8629
+ const line = this.isNIL(cur) ? "S" : String(cur.key);
8630
+ const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
8631
+ setChildResult(layout);
8373
8632
  }
8374
- return [
8375
- mergedLines,
8376
- leftWidth + width + rightWidth,
8377
- Math.max(leftHeight, rightHeight) + 2,
8378
- leftWidth + Math.floor(width / 2)
8379
- ];
8380
8633
  }
8634
+ return result;
8635
+ }
8636
+ static _buildNodeDisplay(line, width, left, right) {
8637
+ const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
8638
+ const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
8639
+ 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));
8640
+ const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
8641
+ const mergedLines = [firstLine, secondLine];
8642
+ for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
8643
+ const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
8644
+ const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
8645
+ mergedLines.push(leftLine + " ".repeat(width) + rightLine);
8646
+ }
8647
+ return [
8648
+ mergedLines,
8649
+ leftWidth + width + rightWidth,
8650
+ Math.max(leftHeight, rightHeight) + 2,
8651
+ leftWidth + Math.floor(width / 2)
8652
+ ];
8653
+ }
8654
+ /**
8655
+ * Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
8656
+ */
8657
+ _isDisplayLeaf(node, options) {
8658
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8659
+ if (node === null && !isShowNull) return true;
8660
+ if (node === void 0 && !isShowUndefined) return true;
8661
+ if (this.isNIL(node) && !isShowRedBlackNIL) return true;
8662
+ if (node === null || node === void 0) return true;
8663
+ const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
8664
+ const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
8665
+ return !hasDisplayableLeft && !hasDisplayableRight;
8666
+ }
8667
+ _hasDisplayableChild(child, options) {
8668
+ if (child === null) return !!options.isShowNull;
8669
+ if (child === void 0) return !!options.isShowUndefined;
8670
+ if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
8671
+ return true;
8672
+ }
8673
+ /**
8674
+ * Resolve a display leaf node to its layout.
8675
+ */
8676
+ _resolveDisplayLeaf(node, options, emptyDisplayLayout) {
8677
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8678
+ if (node === null && !isShowNull) return emptyDisplayLayout;
8679
+ if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
8680
+ if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
8681
+ if (node !== null && node !== void 0) {
8682
+ const line2 = this.isNIL(node) ? "S" : String(node.key);
8683
+ return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
8684
+ }
8685
+ const line = node === void 0 ? "U" : "N";
8686
+ return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
8381
8687
  }
8382
8688
  /**
8383
8689
  * (Protected) Swaps the key/value properties of two nodes.
@@ -9383,9 +9689,15 @@ var BST = class extends BinaryTree {
9383
9689
  if (a < b) return -1;
9384
9690
  return 0;
9385
9691
  }
9692
+ if (a instanceof Date && b instanceof Date) {
9693
+ const ta = a.getTime();
9694
+ const tb = b.getTime();
9695
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
9696
+ return ta > tb ? 1 : ta < tb ? -1 : 0;
9697
+ }
9386
9698
  if (typeof a === "object" || typeof b === "object") {
9387
- throw TypeError(
9388
- `When comparing object type keys, a custom comparator must be provided in the constructor's options!`
9699
+ throw new TypeError(
9700
+ ERR.comparatorRequired("BST")
9389
9701
  );
9390
9702
  }
9391
9703
  return 0;
@@ -9897,7 +10209,7 @@ var BinaryIndexedTree = class {
9897
10209
  */
9898
10210
  read(count) {
9899
10211
  if (!Number.isInteger(count)) {
9900
- throw new Error("Invalid count");
10212
+ throw new Error(ERR.invalidArgument("count must be an integer", "BinaryIndexedTree"));
9901
10213
  }
9902
10214
  return this._read(Math.max(Math.min(count, this.max), 0));
9903
10215
  }
@@ -9909,7 +10221,7 @@ var BinaryIndexedTree = class {
9909
10221
  */
9910
10222
  lowerBound(sum) {
9911
10223
  if (this.negativeCount > 0) {
9912
- throw new Error("Sequence is not non-descending");
10224
+ throw new Error(ERR.invalidOperation("Sequence is not non-descending.", "BinaryIndexedTree"));
9913
10225
  }
9914
10226
  return this._binarySearch(sum, (x, y) => x < y);
9915
10227
  }
@@ -9922,7 +10234,7 @@ var BinaryIndexedTree = class {
9922
10234
  */
9923
10235
  upperBound(sum) {
9924
10236
  if (this.negativeCount > 0) {
9925
- throw new Error("Must not be descending");
10237
+ throw new Error(ERR.invalidOperation("Sequence must not be descending.", "BinaryIndexedTree"));
9926
10238
  }
9927
10239
  return this._binarySearch(sum, (x, y) => x <= y);
9928
10240
  }
@@ -9973,10 +10285,10 @@ var BinaryIndexedTree = class {
9973
10285
  */
9974
10286
  _checkIndex(index) {
9975
10287
  if (!Number.isInteger(index)) {
9976
- throw new Error("Invalid index: Index must be an integer.");
10288
+ throw new TypeError(ERR.invalidIndex("BinaryIndexedTree"));
9977
10289
  }
9978
10290
  if (index < 0 || index >= this.max) {
9979
- throw new Error("Index out of range: Index must be within the range [0, this.max).");
10291
+ throw new RangeError(ERR.indexOutOfRange(index, 0, this.max - 1, "BinaryIndexedTree"));
9980
10292
  }
9981
10293
  }
9982
10294
  /**
@@ -11568,6 +11880,24 @@ var RedBlackTree = class extends BST {
11568
11880
  * @param [thisArg] - See parameter type for details.
11569
11881
  * @returns A new RedBlackTree with mapped entries.
11570
11882
  */
11883
+ /**
11884
+ * Red-Black trees are self-balancing — `perfectlyBalance` rebuilds via
11885
+ * sorted bulk insert, which naturally produces a balanced RBT.
11886
+ * @remarks Time O(N), Space O(N)
11887
+ */
11888
+ perfectlyBalance(iterationType) {
11889
+ const entries = [];
11890
+ for (const [key, value] of this) entries.push([key, value]);
11891
+ if (entries.length <= 1) return true;
11892
+ this.clear();
11893
+ this.setMany(
11894
+ entries.map(([k]) => k),
11895
+ entries.map(([, v]) => v),
11896
+ true
11897
+ // isBalanceAdd
11898
+ );
11899
+ return true;
11900
+ }
11571
11901
  map(callback, options, thisArg) {
11572
11902
  const out = this._createLike([], options);
11573
11903
  let index = 0;
@@ -11889,7 +12219,7 @@ var TreeSet = class _TreeSet {
11889
12219
  static createDefaultComparator() {
11890
12220
  return (a, b) => {
11891
12221
  if (typeof a === "number" && typeof b === "number") {
11892
- if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeSet: NaN is not a valid key");
12222
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeSet"));
11893
12223
  const aa = Object.is(a, -0) ? 0 : a;
11894
12224
  const bb = Object.is(b, -0) ? 0 : b;
11895
12225
  return aa > bb ? 1 : aa < bb ? -1 : 0;
@@ -11900,10 +12230,10 @@ var TreeSet = class _TreeSet {
11900
12230
  if (a instanceof Date && b instanceof Date) {
11901
12231
  const ta = a.getTime();
11902
12232
  const tb = b.getTime();
11903
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeSet: invalid Date key");
12233
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeSet"));
11904
12234
  return ta > tb ? 1 : ta < tb ? -1 : 0;
11905
12235
  }
11906
- throw new TypeError("TreeSet: comparator is required for non-number/non-string/non-Date keys");
12236
+ throw new TypeError(ERR.comparatorRequired("TreeSet"));
11907
12237
  };
11908
12238
  }
11909
12239
  /**
@@ -11921,15 +12251,15 @@ var TreeSet = class _TreeSet {
11921
12251
  _validateKey(key) {
11922
12252
  if (!this.#isDefaultComparator) return;
11923
12253
  if (typeof key === "number") {
11924
- if (Number.isNaN(key)) throw new TypeError("TreeSet: NaN is not a valid key");
12254
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeSet"));
11925
12255
  return;
11926
12256
  }
11927
12257
  if (typeof key === "string") return;
11928
12258
  if (key instanceof Date) {
11929
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeSet: invalid Date key");
12259
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeSet"));
11930
12260
  return;
11931
12261
  }
11932
- throw new TypeError("TreeSet: comparator is required for non-number/non-string/non-Date keys");
12262
+ throw new TypeError(ERR.comparatorRequired("TreeSet"));
11933
12263
  }
11934
12264
  /**
11935
12265
  * Add a key to the set (no-op if already present).
@@ -12248,15 +12578,15 @@ var TreeMultiMap = class _TreeMultiMap {
12248
12578
  _validateKey(key) {
12249
12579
  if (!this.#isDefaultComparator) return;
12250
12580
  if (typeof key === "number") {
12251
- if (Number.isNaN(key)) throw new TypeError("TreeMultiMap: NaN is not a valid key");
12581
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiMap"));
12252
12582
  return;
12253
12583
  }
12254
12584
  if (typeof key === "string") return;
12255
12585
  if (key instanceof Date) {
12256
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiMap: invalid Date key");
12586
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiMap"));
12257
12587
  return;
12258
12588
  }
12259
- throw new TypeError("TreeMultiMap: comparator is required for non-number/non-string/non-Date keys");
12589
+ throw new TypeError(ERR.comparatorRequired("TreeMultiMap"));
12260
12590
  }
12261
12591
  /**
12262
12592
  * Number of distinct keys.
@@ -12678,7 +13008,7 @@ var TreeMap = class _TreeMap {
12678
13008
  [k, v] = toEntryFn(item);
12679
13009
  } else {
12680
13010
  if (!Array.isArray(item) || item.length < 2) {
12681
- throw new TypeError("TreeMap: each entry must be a [key, value] tuple");
13011
+ throw new TypeError(ERR.invalidEntry("TreeMap"));
12682
13012
  }
12683
13013
  k = item[0];
12684
13014
  v = item[1];
@@ -12699,7 +13029,7 @@ var TreeMap = class _TreeMap {
12699
13029
  static createDefaultComparator() {
12700
13030
  return (a, b) => {
12701
13031
  if (typeof a === "number" && typeof b === "number") {
12702
- if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeMap: NaN is not a valid key");
13032
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeMap"));
12703
13033
  const aa = Object.is(a, -0) ? 0 : a;
12704
13034
  const bb = Object.is(b, -0) ? 0 : b;
12705
13035
  return aa > bb ? 1 : aa < bb ? -1 : 0;
@@ -12710,24 +13040,24 @@ var TreeMap = class _TreeMap {
12710
13040
  if (a instanceof Date && b instanceof Date) {
12711
13041
  const ta = a.getTime();
12712
13042
  const tb = b.getTime();
12713
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeMap: invalid Date key");
13043
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeMap"));
12714
13044
  return ta > tb ? 1 : ta < tb ? -1 : 0;
12715
13045
  }
12716
- throw new TypeError("TreeMap: comparator is required for non-number/non-string/non-Date keys");
13046
+ throw new TypeError(ERR.comparatorRequired("TreeMap"));
12717
13047
  };
12718
13048
  }
12719
13049
  _validateKey(key) {
12720
13050
  if (!this.#isDefaultComparator) return;
12721
13051
  if (typeof key === "number") {
12722
- if (Number.isNaN(key)) throw new TypeError("TreeMap: NaN is not a valid key");
13052
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMap"));
12723
13053
  return;
12724
13054
  }
12725
13055
  if (typeof key === "string") return;
12726
13056
  if (key instanceof Date) {
12727
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMap: invalid Date key");
13057
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMap"));
12728
13058
  return;
12729
13059
  }
12730
- throw new TypeError("TreeMap: comparator is required for non-number/non-string/non-Date keys");
13060
+ throw new TypeError(ERR.comparatorRequired("TreeMap"));
12731
13061
  }
12732
13062
  /**
12733
13063
  * Number of entries in the map.
@@ -13051,22 +13381,22 @@ var TreeMultiSet = class _TreeMultiSet {
13051
13381
  _validateKey(key) {
13052
13382
  if (!this.#isDefaultComparator) return;
13053
13383
  if (typeof key === "number") {
13054
- if (Number.isNaN(key)) throw new TypeError("TreeMultiSet: NaN is not a valid key");
13384
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiSet"));
13055
13385
  return;
13056
13386
  }
13057
13387
  if (typeof key === "string") return;
13058
13388
  if (key instanceof Date) {
13059
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiSet: invalid Date key");
13389
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiSet"));
13060
13390
  return;
13061
13391
  }
13062
- throw new TypeError("TreeMultiSet: comparator is required for non-number/non-string/non-Date keys");
13392
+ throw new TypeError(ERR.comparatorRequired("TreeMultiSet"));
13063
13393
  }
13064
13394
  /**
13065
13395
  * Validates that count is a non-negative safe integer.
13066
13396
  * @remarks Time O(1), Space O(1)
13067
13397
  */
13068
13398
  _validateCount(n) {
13069
- if (!Number.isSafeInteger(n) || n < 0) throw new RangeError("TreeMultiSet: count must be a safe integer >= 0");
13399
+ if (!Number.isSafeInteger(n) || n < 0) throw new RangeError(ERR.invalidArgument("count must be a safe integer >= 0.", "TreeMultiSet"));
13070
13400
  }
13071
13401
  /**
13072
13402
  * Total occurrences (sumCounts).
@@ -13490,9 +13820,7 @@ var MaxPriorityQueue = class extends PriorityQueue {
13490
13820
  super(elements, {
13491
13821
  comparator: /* @__PURE__ */ __name((a, b) => {
13492
13822
  if (typeof a === "object" || typeof b === "object") {
13493
- throw TypeError(
13494
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
13495
- );
13823
+ throw new TypeError(ERR.comparatorRequired("MaxPriorityQueue"));
13496
13824
  }
13497
13825
  if (a < b) return 1;
13498
13826
  if (a > b) return -1;
@@ -13633,7 +13961,7 @@ var Matrix = class _Matrix {
13633
13961
  */
13634
13962
  add(matrix) {
13635
13963
  if (!this.isMatchForCalculate(matrix)) {
13636
- throw new Error("Matrix dimensions must match for addition.");
13964
+ throw new Error(ERR.matrixDimensionMismatch("addition"));
13637
13965
  }
13638
13966
  const resultData = [];
13639
13967
  for (let i = 0; i < this.rows; i++) {
@@ -13665,7 +13993,7 @@ var Matrix = class _Matrix {
13665
13993
  */
13666
13994
  subtract(matrix) {
13667
13995
  if (!this.isMatchForCalculate(matrix)) {
13668
- throw new Error("Matrix dimensions must match for subtraction.");
13996
+ throw new Error(ERR.matrixDimensionMismatch("subtraction"));
13669
13997
  }
13670
13998
  const resultData = [];
13671
13999
  for (let i = 0; i < this.rows; i++) {
@@ -13696,7 +14024,7 @@ var Matrix = class _Matrix {
13696
14024
  */
13697
14025
  multiply(matrix) {
13698
14026
  if (this.cols !== matrix.rows) {
13699
- throw new Error("Matrix dimensions must be compatible for multiplication (A.cols = B.rows).");
14027
+ throw new Error(ERR.matrixDimensionMismatch("multiplication (A.cols must equal B.rows)"));
13700
14028
  }
13701
14029
  const resultData = [];
13702
14030
  for (let i = 0; i < this.rows; i++) {
@@ -13730,7 +14058,7 @@ var Matrix = class _Matrix {
13730
14058
  */
13731
14059
  transpose() {
13732
14060
  if (this.data.some((row) => row.length !== this.rows)) {
13733
- throw new Error("Matrix must be rectangular for transposition.");
14061
+ throw new Error(ERR.matrixNotRectangular());
13734
14062
  }
13735
14063
  const resultData = [];
13736
14064
  for (let j = 0; j < this.cols; j++) {
@@ -13754,7 +14082,7 @@ var Matrix = class _Matrix {
13754
14082
  */
13755
14083
  inverse() {
13756
14084
  if (this.rows !== this.cols) {
13757
- throw new Error("Matrix must be square for inversion.");
14085
+ throw new Error(ERR.matrixNotSquare());
13758
14086
  }
13759
14087
  const augmentedMatrixData = [];
13760
14088
  for (let i = 0; i < this.rows; i++) {
@@ -13776,12 +14104,12 @@ var Matrix = class _Matrix {
13776
14104
  pivotRow++;
13777
14105
  }
13778
14106
  if (pivotRow === this.rows) {
13779
- throw new Error("Matrix is singular, and its inverse does not exist.");
14107
+ throw new Error(ERR.matrixSingular());
13780
14108
  }
13781
14109
  augmentedMatrix._swapRows(i, pivotRow);
13782
14110
  const pivotElement = augmentedMatrix.get(i, i) ?? 1;
13783
14111
  if (pivotElement === 0) {
13784
- throw new Error("Matrix is singular, and its inverse does not exist (division by zero).");
14112
+ throw new Error(ERR.matrixSingular());
13785
14113
  }
13786
14114
  augmentedMatrix._scaleRow(i, 1 / pivotElement);
13787
14115
  for (let j = 0; j < this.rows; j++) {
@@ -13811,9 +14139,7 @@ var Matrix = class _Matrix {
13811
14139
  */
13812
14140
  dot(matrix) {
13813
14141
  if (this.cols !== matrix.rows) {
13814
- throw new Error(
13815
- "Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product."
13816
- );
14142
+ throw new Error(ERR.matrixDimensionMismatch("dot product (A.cols must equal B.rows)"));
13817
14143
  }
13818
14144
  const resultData = [];
13819
14145
  for (let i = 0; i < this.rows; i++) {
@@ -14439,7 +14765,7 @@ var Trie = class extends IterableElementBase {
14439
14765
  for (const x of this) {
14440
14766
  const v = thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
14441
14767
  if (typeof v !== "string") {
14442
- throw new TypeError(`Trie.map callback must return string; got ${typeof v}`);
14768
+ throw new TypeError(ERR.callbackReturnType("string", typeof v, "Trie.map"));
14443
14769
  }
14444
14770
  newTrie.add(v);
14445
14771
  }
@@ -14671,6 +14997,6 @@ var TreeNode = class _TreeNode {
14671
14997
  * @license MIT License
14672
14998
  */
14673
14999
 
14674
- export { AVLTree, AVLTreeNode, AbstractEdge, AbstractGraph, AbstractVertex, BST, BSTNode, BinaryIndexedTree, BinaryTree, BinaryTreeNode, Character, DFSOperation, Deque, DirectedEdge, DirectedGraph, DirectedVertex, DoublyLinkedList, DoublyLinkedListNode, FibonacciHeap, FibonacciHeapNode, HashMap, Heap, IterableElementBase, IterableEntryBase, LinkedHashMap, LinkedListQueue, MapEdge, MapGraph, MapVertex, Matrix, MaxHeap, MaxPriorityQueue, MinHeap, MinPriorityQueue, Navigator, PriorityQueue, Queue, Range, RedBlackTree, RedBlackTreeNode, SegmentTree, SegmentTreeNode, SinglyLinkedList, SinglyLinkedListNode, SkipList, SkipListNode, Stack, TreeMap, TreeMultiMap, TreeMultiMapNode, TreeMultiSet, TreeNode, TreeSet, Trie, TrieNode, UndirectedEdge, UndirectedGraph, UndirectedVertex, arrayRemove, asyncTrampoline, calcMinUnitsRequired, getMSB, isComparable, isTrampolineThunk, isWeakKey, makeAsyncTrampoline, makeTrampoline, makeTrampolineThunk, rangeCheck, roundFixed, throwRangeError, toBinaryString, trampoline, uuidV4 };
15000
+ export { AVLTree, AVLTreeNode, AbstractEdge, AbstractGraph, AbstractVertex, BST, BSTNode, BinaryIndexedTree, BinaryTree, BinaryTreeNode, Character, DFSOperation, Deque, DirectedEdge, DirectedGraph, DirectedVertex, DoublyLinkedList, DoublyLinkedListNode, ERR, FibonacciHeap, FibonacciHeapNode, HashMap, Heap, IterableElementBase, IterableEntryBase, LinkedHashMap, LinkedListQueue, MapEdge, MapGraph, MapVertex, Matrix, MaxHeap, MaxPriorityQueue, MinHeap, MinPriorityQueue, Navigator, PriorityQueue, Queue, Range, RedBlackTree, RedBlackTreeNode, SegmentTree, SegmentTreeNode, SinglyLinkedList, SinglyLinkedListNode, SkipList, SkipListNode, Stack, TreeMap, TreeMultiMap, TreeMultiMapNode, TreeMultiSet, TreeNode, TreeSet, Trie, TrieNode, UndirectedEdge, UndirectedGraph, UndirectedVertex, arrayRemove, asyncTrampoline, calcMinUnitsRequired, getMSB, isComparable, isTrampolineThunk, isWeakKey, makeAsyncTrampoline, makeTrampoline, makeTrampolineThunk, rangeCheck, roundFixed, throwRangeError, toBinaryString, trampoline, uuidV4 };
14675
15001
  //# sourceMappingURL=index.mjs.map
14676
15002
  //# sourceMappingURL=index.mjs.map