tree-multimap-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 (37) hide show
  1. package/dist/types/common/error.d.ts +23 -0
  2. package/dist/types/common/index.d.ts +1 -0
  3. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +10 -0
  4. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +7 -1
  5. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  6. package/dist/types/data-structures/graph/directed-graph.d.ts +1 -0
  7. package/dist/types/data-structures/graph/undirected-graph.d.ts +14 -0
  8. package/dist/types/data-structures/queue/deque.d.ts +41 -1
  9. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  10. package/dist/umd/tree-multimap-typed.js +445 -123
  11. package/dist/umd/tree-multimap-typed.js.map +1 -1
  12. package/dist/umd/tree-multimap-typed.min.js +4 -2
  13. package/dist/umd/tree-multimap-typed.min.js.map +1 -1
  14. package/package.json +2 -2
  15. package/src/common/error.ts +60 -0
  16. package/src/common/index.ts +2 -0
  17. package/src/data-structures/base/iterable-element-base.ts +3 -2
  18. package/src/data-structures/binary-tree/binary-indexed-tree.ts +6 -5
  19. package/src/data-structures/binary-tree/binary-tree.ts +113 -42
  20. package/src/data-structures/binary-tree/bst.ts +11 -3
  21. package/src/data-structures/binary-tree/red-black-tree.ts +20 -0
  22. package/src/data-structures/binary-tree/tree-map.ts +8 -7
  23. package/src/data-structures/binary-tree/tree-multi-map.ts +4 -4
  24. package/src/data-structures/binary-tree/tree-multi-set.ts +5 -4
  25. package/src/data-structures/binary-tree/tree-set.ts +7 -6
  26. package/src/data-structures/graph/abstract-graph.ts +106 -1
  27. package/src/data-structures/graph/directed-graph.ts +4 -0
  28. package/src/data-structures/graph/undirected-graph.ts +95 -0
  29. package/src/data-structures/hash/hash-map.ts +13 -2
  30. package/src/data-structures/heap/heap.ts +4 -3
  31. package/src/data-structures/heap/max-heap.ts +2 -3
  32. package/src/data-structures/matrix/matrix.ts +9 -10
  33. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -3
  34. package/src/data-structures/queue/deque.ts +71 -3
  35. package/src/data-structures/trie/trie.ts +2 -1
  36. package/src/types/data-structures/queue/deque.ts +7 -0
  37. package/src/utils/utils.ts +4 -2
@@ -215,6 +215,45 @@ var treeMultimapTyped = (() => {
215
215
  };
216
216
  __name(_IterableEntryBase, "IterableEntryBase");
217
217
  var IterableEntryBase = _IterableEntryBase;
218
+ var ERR = {
219
+ // Range / index
220
+ indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
221
+ invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
222
+ // Type / argument
223
+ invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
224
+ comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
225
+ invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
226
+ notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
227
+ invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
228
+ invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
229
+ invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
230
+ reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
231
+ callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
232
+ // State / operation
233
+ invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
234
+ // Matrix
235
+ matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
236
+ matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
237
+ matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
238
+ matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
239
+ matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
240
+ };
241
+ var _Range = class _Range2 {
242
+ constructor(low, high, includeLow = true, includeHigh = true) {
243
+ this.low = low;
244
+ this.high = high;
245
+ this.includeLow = includeLow;
246
+ this.includeHigh = includeHigh;
247
+ }
248
+ // Determine whether a key is within the range
249
+ isInRange(key, comparator) {
250
+ const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
251
+ const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
252
+ return lowCheck && highCheck;
253
+ }
254
+ };
255
+ __name(_Range, "Range");
256
+ var Range = _Range;
218
257
  var _IterableElementBase = class _IterableElementBase2 {
219
258
  /**
220
259
  * Create a new iterable base.
@@ -230,7 +269,7 @@ var treeMultimapTyped = (() => {
230
269
  if (options) {
231
270
  const { toElementFn } = options;
232
271
  if (typeof toElementFn === "function") this._toElementFn = toElementFn;
233
- else if (toElementFn) throw new TypeError("toElementFn must be a function type");
272
+ else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
234
273
  }
235
274
  }
236
275
  /**
@@ -386,7 +425,7 @@ var treeMultimapTyped = (() => {
386
425
  acc = initialValue;
387
426
  } else {
388
427
  const first = iter.next();
389
- if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
428
+ if (first.done) throw new TypeError(ERR.reduceEmpty());
390
429
  acc = first.value;
391
430
  index = 1;
392
431
  }
@@ -454,8 +493,10 @@ var treeMultimapTyped = (() => {
454
493
  }
455
494
  return 1 << 31 - Math.clz32(value);
456
495
  }, "getMSB");
457
- var rangeCheck = /* @__PURE__ */ __name((index, min, max, message = "Index out of bounds.") => {
458
- if (index < min || index > max) throw new RangeError(message);
496
+ var rangeCheck = /* @__PURE__ */ __name((index, min, max, message) => {
497
+ if (index < min || index > max) {
498
+ throw new RangeError(message != null ? message : `Index ${index} is out of range [${min}, ${max}].`);
499
+ }
459
500
  }, "rangeCheck");
460
501
  var isWeakKey = /* @__PURE__ */ __name((input) => {
461
502
  const inputType = typeof input;
@@ -815,8 +856,8 @@ var treeMultimapTyped = (() => {
815
856
  if (this.isEntry(rawElement)) {
816
857
  return rawElement;
817
858
  }
818
- throw new Error(
819
- "If `entryOrRawElements` does not adhere to [key,value], provide `options.toEntryFn` to transform raw records."
859
+ throw new TypeError(
860
+ ERR.invalidArgument("If elements do not adhere to [key, value], provide options.toEntryFn to transform raw records.", "HashMap")
820
861
  );
821
862
  }, "_toEntryFn"));
822
863
  __publicField(this, "_size", 0);
@@ -1101,6 +1142,13 @@ var treeMultimapTyped = (() => {
1101
1142
  }
1102
1143
  }
1103
1144
  _deleteNode(node) {
1145
+ const key = node.key;
1146
+ if (isWeakKey(key)) {
1147
+ this._objMap.delete(key);
1148
+ } else {
1149
+ const hash = this._hashFn(key);
1150
+ delete this._noObjMap[hash];
1151
+ }
1104
1152
  const { prev, next } = node;
1105
1153
  prev.next = next;
1106
1154
  next.prev = prev;
@@ -3589,17 +3637,12 @@ var treeMultimapTyped = (() => {
3589
3637
  };
3590
3638
  __name(_LinkedListQueue, "LinkedListQueue");
3591
3639
  var _Deque = class _Deque2 extends LinearBase {
3592
- /**
3593
- * Create a Deque and optionally bulk-insert elements.
3594
- * @remarks Time O(N), Space O(N)
3595
- * @param [elements] - Iterable (or iterable-like) of elements/records to insert.
3596
- * @param [options] - Options such as bucketSize, toElementFn, and maxLen.
3597
- * @returns New Deque instance.
3598
- */
3599
3640
  constructor(elements = [], options) {
3600
3641
  super(options);
3601
3642
  __publicField(this, "_equals", /* @__PURE__ */ __name((a, b) => Object.is(a, b), "_equals"));
3602
3643
  __publicField(this, "_bucketSize", 1 << 12);
3644
+ __publicField(this, "_autoCompactRatio", 0.5);
3645
+ __publicField(this, "_compactCounter", 0);
3603
3646
  __publicField(this, "_bucketFirst", 0);
3604
3647
  __publicField(this, "_firstInBucket", 0);
3605
3648
  __publicField(this, "_bucketLast", 0);
@@ -3608,8 +3651,9 @@ var treeMultimapTyped = (() => {
3608
3651
  __publicField(this, "_buckets", []);
3609
3652
  __publicField(this, "_length", 0);
3610
3653
  if (options) {
3611
- const { bucketSize } = options;
3654
+ const { bucketSize, autoCompactRatio } = options;
3612
3655
  if (typeof bucketSize === "number") this._bucketSize = bucketSize;
3656
+ if (typeof autoCompactRatio === "number") this._autoCompactRatio = autoCompactRatio;
3613
3657
  }
3614
3658
  let _size;
3615
3659
  if ("length" in elements) {
@@ -3634,6 +3678,24 @@ var treeMultimapTyped = (() => {
3634
3678
  get bucketSize() {
3635
3679
  return this._bucketSize;
3636
3680
  }
3681
+ /**
3682
+ * Get the auto-compaction ratio.
3683
+ * When `elements / (bucketCount * bucketSize)` drops below this ratio after
3684
+ * enough shift/pop operations, the deque auto-compacts.
3685
+ * @remarks Time O(1), Space O(1)
3686
+ * @returns Current ratio threshold. 0 means auto-compact is disabled.
3687
+ */
3688
+ get autoCompactRatio() {
3689
+ return this._autoCompactRatio;
3690
+ }
3691
+ /**
3692
+ * Set the auto-compaction ratio.
3693
+ * @remarks Time O(1), Space O(1)
3694
+ * @param value - Ratio in [0,1]. 0 disables auto-compact.
3695
+ */
3696
+ set autoCompactRatio(value) {
3697
+ this._autoCompactRatio = value;
3698
+ }
3637
3699
  /**
3638
3700
  * Get the index of the first bucket in use.
3639
3701
  * @remarks Time O(1), Space O(1)
@@ -3765,6 +3827,7 @@ var treeMultimapTyped = (() => {
3765
3827
  }
3766
3828
  }
3767
3829
  this._length -= 1;
3830
+ this._autoCompact();
3768
3831
  return element;
3769
3832
  }
3770
3833
  /**
@@ -3787,6 +3850,7 @@ var treeMultimapTyped = (() => {
3787
3850
  }
3788
3851
  }
3789
3852
  this._length -= 1;
3853
+ this._autoCompact();
3790
3854
  return element;
3791
3855
  }
3792
3856
  /**
@@ -4119,11 +4183,40 @@ var treeMultimapTyped = (() => {
4119
4183
  * @remarks Time O(N), Space O(1)
4120
4184
  * @returns void
4121
4185
  */
4186
+ /**
4187
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
4188
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
4189
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
4190
+ */
4191
+ _autoCompact() {
4192
+ if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
4193
+ this._compactCounter++;
4194
+ if (this._compactCounter < this._bucketSize) return;
4195
+ this._compactCounter = 0;
4196
+ const utilization = this._length / (this._bucketCount * this._bucketSize);
4197
+ if (utilization < this._autoCompactRatio) {
4198
+ this.shrinkToFit();
4199
+ }
4200
+ }
4201
+ /**
4202
+ * Compact the deque by removing unused buckets.
4203
+ * @remarks Time O(N), Space O(1)
4204
+ * @returns True if compaction was performed (bucket count reduced).
4205
+ */
4206
+ /**
4207
+ * Compact the deque by removing unused buckets.
4208
+ * @remarks Time O(N), Space O(1)
4209
+ * @returns True if compaction was performed (bucket count reduced).
4210
+ */
4211
+ compact() {
4212
+ const before = this._bucketCount;
4213
+ this.shrinkToFit();
4214
+ return this._bucketCount < before;
4215
+ }
4122
4216
  shrinkToFit() {
4123
4217
  if (this._length === 0) return;
4124
4218
  const newBuckets = [];
4125
- if (this._bucketFirst === this._bucketLast) return;
4126
- else if (this._bucketFirst < this._bucketLast) {
4219
+ if (this._bucketFirst <= this._bucketLast) {
4127
4220
  for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
4128
4221
  newBuckets.push(this._buckets[i]);
4129
4222
  }
@@ -4138,6 +4231,8 @@ var treeMultimapTyped = (() => {
4138
4231
  this._bucketFirst = 0;
4139
4232
  this._bucketLast = newBuckets.length - 1;
4140
4233
  this._buckets = newBuckets;
4234
+ this._bucketCount = newBuckets.length;
4235
+ this._compactCounter = 0;
4141
4236
  }
4142
4237
  /**
4143
4238
  * Deep clone this deque, preserving options.
@@ -4332,7 +4427,7 @@ var treeMultimapTyped = (() => {
4332
4427
  __publicField(this, "_elements", []);
4333
4428
  __publicField(this, "_DEFAULT_COMPARATOR", /* @__PURE__ */ __name((a, b) => {
4334
4429
  if (typeof a === "object" || typeof b === "object") {
4335
- throw TypeError("When comparing object types, define a custom comparator in options.");
4430
+ throw new TypeError(ERR.comparatorRequired("Heap"));
4336
4431
  }
4337
4432
  if (a > b) return 1;
4338
4433
  if (a < b) return -1;
@@ -4642,7 +4737,7 @@ var treeMultimapTyped = (() => {
4642
4737
  */
4643
4738
  map(callback, options, thisArg) {
4644
4739
  const { comparator, toElementFn, ...rest } = options != null ? options : {};
4645
- if (!comparator) throw new TypeError("Heap.map requires options.comparator for EM");
4740
+ if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
4646
4741
  const out = this._createLike([], { ...rest, comparator, toElementFn });
4647
4742
  let i = 0;
4648
4743
  for (const x of this) {
@@ -4774,7 +4869,7 @@ var treeMultimapTyped = (() => {
4774
4869
  __publicField(this, "_comparator");
4775
4870
  this.clear();
4776
4871
  this._comparator = comparator || this._defaultComparator;
4777
- if (typeof this.comparator !== "function") throw new Error("FibonacciHeap: comparator must be a function.");
4872
+ if (typeof this.comparator !== "function") throw new TypeError(ERR.notAFunction("comparator", "FibonacciHeap"));
4778
4873
  }
4779
4874
  /**
4780
4875
  * Get the circular root list head.
@@ -4982,9 +5077,7 @@ var treeMultimapTyped = (() => {
4982
5077
  super(elements, {
4983
5078
  comparator: /* @__PURE__ */ __name((a, b) => {
4984
5079
  if (typeof a === "object" || typeof b === "object") {
4985
- throw TypeError(
4986
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
4987
- );
5080
+ throw new TypeError(ERR.comparatorRequired("MaxHeap"));
4988
5081
  }
4989
5082
  if (a < b) return 1;
4990
5083
  if (a > b) return -1;
@@ -5143,7 +5236,7 @@ var treeMultimapTyped = (() => {
5143
5236
  const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
5144
5237
  return this._addEdge(newEdge);
5145
5238
  } else {
5146
- throw new Error("dest must be a Vertex or vertex key while srcOrEdge is an Edge");
5239
+ throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
5147
5240
  }
5148
5241
  }
5149
5242
  }
@@ -5827,6 +5920,94 @@ var treeMultimapTyped = (() => {
5827
5920
  _getVertexKey(vertexOrKey) {
5828
5921
  return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
5829
5922
  }
5923
+ /**
5924
+ * The edge connector string used in visual output.
5925
+ * Override in subclasses (e.g., '--' for undirected, '->' for directed).
5926
+ */
5927
+ get _edgeConnector() {
5928
+ return "--";
5929
+ }
5930
+ /**
5931
+ * Generate a text-based visual representation of the graph.
5932
+ *
5933
+ * **Adjacency list format:**
5934
+ * ```
5935
+ * Graph (5 vertices, 6 edges):
5936
+ * A -> B (1), C (2)
5937
+ * B -> D (3)
5938
+ * C -> (no outgoing edges)
5939
+ * D -> A (1)
5940
+ * E (isolated)
5941
+ * ```
5942
+ *
5943
+ * @param options - Optional display settings.
5944
+ * @param options.showWeight - Whether to show edge weights (default: true).
5945
+ * @returns The visual string.
5946
+ */
5947
+ toVisual(options) {
5948
+ var _a;
5949
+ const showWeight = (_a = options == null ? void 0 : options.showWeight) != null ? _a : true;
5950
+ const vertices = [...this._vertexMap.values()];
5951
+ const vertexCount = vertices.length;
5952
+ const edgeCount = this.edgeSet().length;
5953
+ const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
5954
+ for (const vertex of vertices) {
5955
+ const neighbors = this.getNeighbors(vertex);
5956
+ if (neighbors.length === 0) {
5957
+ lines.push(` ${vertex.key} (isolated)`);
5958
+ } else {
5959
+ const edgeStrs = neighbors.map((neighbor) => {
5960
+ const edge = this.getEdge(vertex, neighbor);
5961
+ if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
5962
+ return `${neighbor.key} (${edge.weight})`;
5963
+ }
5964
+ return `${neighbor.key}`;
5965
+ });
5966
+ lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
5967
+ }
5968
+ }
5969
+ return lines.join("\n");
5970
+ }
5971
+ /**
5972
+ * Generate DOT language representation for Graphviz.
5973
+ *
5974
+ * @param options - Optional display settings.
5975
+ * @param options.name - Graph name (default: 'G').
5976
+ * @param options.showWeight - Whether to label edges with weight (default: true).
5977
+ * @returns DOT format string.
5978
+ */
5979
+ toDot(options) {
5980
+ var _a, _b;
5981
+ const name = (_a = options == null ? void 0 : options.name) != null ? _a : "G";
5982
+ const showWeight = (_b = options == null ? void 0 : options.showWeight) != null ? _b : true;
5983
+ const isDirected = this._edgeConnector === "->";
5984
+ const graphType = isDirected ? "digraph" : "graph";
5985
+ const edgeOp = isDirected ? "->" : "--";
5986
+ const lines = [`${graphType} ${name} {`];
5987
+ for (const vertex of this._vertexMap.values()) {
5988
+ lines.push(` "${vertex.key}";`);
5989
+ }
5990
+ const visited = /* @__PURE__ */ new Set();
5991
+ for (const vertex of this._vertexMap.values()) {
5992
+ for (const neighbor of this.getNeighbors(vertex)) {
5993
+ const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
5994
+ if (visited.has(edgeId)) continue;
5995
+ visited.add(edgeId);
5996
+ const edge = this.getEdge(vertex, neighbor);
5997
+ const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
5998
+ lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
5999
+ }
6000
+ }
6001
+ lines.push("}");
6002
+ return lines.join("\n");
6003
+ }
6004
+ /**
6005
+ * Print the graph to console.
6006
+ * @param options - Display settings passed to `toVisual`.
6007
+ */
6008
+ print(options) {
6009
+ console.log(this.toVisual(options));
6010
+ }
5830
6011
  };
5831
6012
  __name(_AbstractGraph, "AbstractGraph");
5832
6013
  var AbstractGraph = _AbstractGraph;
@@ -5859,6 +6040,9 @@ var treeMultimapTyped = (() => {
5859
6040
  __publicField(this, "_outEdgeMap", /* @__PURE__ */ new Map());
5860
6041
  __publicField(this, "_inEdgeMap", /* @__PURE__ */ new Map());
5861
6042
  }
6043
+ get _edgeConnector() {
6044
+ return "->";
6045
+ }
5862
6046
  get outEdgeMap() {
5863
6047
  return this._outEdgeMap;
5864
6048
  }
@@ -6637,6 +6821,84 @@ var treeMultimapTyped = (() => {
6637
6821
  cutVertices
6638
6822
  };
6639
6823
  }
6824
+ /**
6825
+ * Find biconnected components using edge-stack Tarjan variant.
6826
+ * A biconnected component is a maximal biconnected subgraph.
6827
+ * @returns Array of edge arrays, each representing a biconnected component.
6828
+ * @remarks Time O(V + E), Space O(V + E)
6829
+ */
6830
+ getBiconnectedComponents() {
6831
+ const dfn = /* @__PURE__ */ new Map();
6832
+ const low = /* @__PURE__ */ new Map();
6833
+ const edgeStack = [];
6834
+ const components = [];
6835
+ let time = 0;
6836
+ const dfs = /* @__PURE__ */ __name((vertex, parent) => {
6837
+ dfn.set(vertex, time);
6838
+ low.set(vertex, time);
6839
+ time++;
6840
+ const neighbors = this.getNeighbors(vertex);
6841
+ let childCount = 0;
6842
+ for (const neighbor of neighbors) {
6843
+ const edge = this.getEdge(vertex, neighbor);
6844
+ if (!edge) continue;
6845
+ if (!dfn.has(neighbor)) {
6846
+ childCount++;
6847
+ edgeStack.push(edge);
6848
+ dfs(neighbor, vertex);
6849
+ low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
6850
+ if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
6851
+ const component = [];
6852
+ let e;
6853
+ do {
6854
+ e = edgeStack.pop();
6855
+ if (e) component.push(e);
6856
+ } while (e && e !== edge);
6857
+ if (component.length > 0) components.push(component);
6858
+ }
6859
+ } else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
6860
+ edgeStack.push(edge);
6861
+ low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
6862
+ }
6863
+ }
6864
+ }, "dfs");
6865
+ for (const vertex of this.vertexMap.values()) {
6866
+ if (!dfn.has(vertex)) {
6867
+ dfs(vertex, void 0);
6868
+ if (edgeStack.length > 0) {
6869
+ components.push([...edgeStack]);
6870
+ edgeStack.length = 0;
6871
+ }
6872
+ }
6873
+ }
6874
+ return components;
6875
+ }
6876
+ /**
6877
+ * Detect whether the graph contains a cycle.
6878
+ * Uses DFS with parent tracking.
6879
+ * @returns `true` if a cycle exists, `false` otherwise.
6880
+ * @remarks Time O(V + E), Space O(V)
6881
+ */
6882
+ hasCycle() {
6883
+ const visited = /* @__PURE__ */ new Set();
6884
+ const dfs = /* @__PURE__ */ __name((vertex, parent) => {
6885
+ visited.add(vertex);
6886
+ for (const neighbor of this.getNeighbors(vertex)) {
6887
+ if (!visited.has(neighbor)) {
6888
+ if (dfs(neighbor, vertex)) return true;
6889
+ } else if (neighbor !== parent) {
6890
+ return true;
6891
+ }
6892
+ }
6893
+ return false;
6894
+ }, "dfs");
6895
+ for (const vertex of this.vertexMap.values()) {
6896
+ if (!visited.has(vertex)) {
6897
+ if (dfs(vertex, void 0)) return true;
6898
+ }
6899
+ }
6900
+ return false;
6901
+ }
6640
6902
  /**
6641
6903
  * Get bridges discovered by `tarjan()`.
6642
6904
  * @returns Array of edges that are bridges.
@@ -6784,22 +7046,6 @@ var treeMultimapTyped = (() => {
6784
7046
  }
6785
7047
  };
6786
7048
  __name(_MapGraph, "MapGraph");
6787
- var _Range = class _Range2 {
6788
- constructor(low, high, includeLow = true, includeHigh = true) {
6789
- this.low = low;
6790
- this.high = high;
6791
- this.includeLow = includeLow;
6792
- this.includeHigh = includeHigh;
6793
- }
6794
- // Determine whether a key is within the range
6795
- isInRange(key, comparator) {
6796
- const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
6797
- const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
6798
- return lowCheck && highCheck;
6799
- }
6800
- };
6801
- __name(_Range, "Range");
6802
- var Range = _Range;
6803
7049
  var _BinaryTreeNode = class _BinaryTreeNode2 {
6804
7050
  /**
6805
7051
  * Creates an instance of BinaryTreeNode.
@@ -6961,7 +7207,7 @@ var treeMultimapTyped = (() => {
6961
7207
  if (isMapMode !== void 0) this._isMapMode = isMapMode;
6962
7208
  if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
6963
7209
  if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
6964
- else if (toEntryFn) throw TypeError("toEntryFn must be a function type");
7210
+ else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
6965
7211
  }
6966
7212
  if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
6967
7213
  }
@@ -7189,7 +7435,7 @@ var treeMultimapTyped = (() => {
7189
7435
  if (!this._root) {
7190
7436
  this._setRoot(newNode);
7191
7437
  if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
7192
- this._size = 1;
7438
+ if (newNode !== null) this._size = 1;
7193
7439
  return true;
7194
7440
  }
7195
7441
  const queue = new Queue([this._root]);
@@ -7221,7 +7467,7 @@ var treeMultimapTyped = (() => {
7221
7467
  potentialParent.right = newNode;
7222
7468
  }
7223
7469
  if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
7224
- this._size++;
7470
+ if (newNode !== null) this._size++;
7225
7471
  return true;
7226
7472
  }
7227
7473
  return false;
@@ -7790,7 +8036,7 @@ var treeMultimapTyped = (() => {
7790
8036
  }
7791
8037
  /**
7792
8038
  * Finds all leaf nodes in the tree.
7793
- * @remarks Time O(N), visits every node. Space O(H) for recursive stack or O(N) for iterative queue.
8039
+ * @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
7794
8040
  *
7795
8041
  * @template C - The type of the callback function.
7796
8042
  * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
@@ -7813,15 +8059,15 @@ var treeMultimapTyped = (() => {
7813
8059
  }, "dfs");
7814
8060
  dfs(startNode);
7815
8061
  } else {
7816
- const queue = new Queue([startNode]);
7817
- while (queue.length > 0) {
7818
- const cur = queue.shift();
8062
+ const stack = [startNode];
8063
+ while (stack.length > 0) {
8064
+ const cur = stack.pop();
7819
8065
  if (this.isRealNode(cur)) {
7820
8066
  if (this.isLeaf(cur)) {
7821
8067
  leaves.push(callback(cur));
7822
8068
  }
7823
- if (this.isRealNode(cur.left)) queue.push(cur.left);
7824
- if (this.isRealNode(cur.right)) queue.push(cur.right);
8069
+ if (this.isRealNode(cur.right)) stack.push(cur.right);
8070
+ if (this.isRealNode(cur.left)) stack.push(cur.left);
7825
8071
  }
7826
8072
  }
7827
8073
  }
@@ -8277,42 +8523,98 @@ var treeMultimapTyped = (() => {
8277
8523
  _displayAux(node, options) {
8278
8524
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8279
8525
  const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
8280
- if (node === null && !isShowNull) {
8281
- return emptyDisplayLayout;
8282
- } else if (node === void 0 && !isShowUndefined) {
8283
- return emptyDisplayLayout;
8284
- } else if (this.isNIL(node) && !isShowRedBlackNIL) {
8285
- return emptyDisplayLayout;
8286
- } else if (node !== null && node !== void 0) {
8287
- const key = node.key, line = this.isNIL(node) ? "S" : String(key), width = line.length;
8288
- return _buildNodeDisplay(
8289
- line,
8290
- width,
8291
- this._displayAux(node.left, options),
8292
- this._displayAux(node.right, options)
8293
- );
8294
- } else {
8295
- const line = node === void 0 ? "U" : "N", width = line.length;
8296
- return _buildNodeDisplay(line, width, [[""], 1, 0, 0], [[""], 1, 0, 0]);
8297
- }
8298
- function _buildNodeDisplay(line, width, left, right) {
8299
- const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
8300
- const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
8301
- 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));
8302
- const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
8303
- const mergedLines = [firstLine, secondLine];
8304
- for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
8305
- const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
8306
- const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
8307
- mergedLines.push(leftLine + " ".repeat(width) + rightLine);
8526
+ const newFrame = /* @__PURE__ */ __name((n) => ({
8527
+ node: n,
8528
+ stage: 0,
8529
+ leftLayout: emptyDisplayLayout,
8530
+ rightLayout: emptyDisplayLayout
8531
+ }), "newFrame");
8532
+ const stack = [newFrame(node)];
8533
+ let result = emptyDisplayLayout;
8534
+ const setChildResult = /* @__PURE__ */ __name((layout) => {
8535
+ if (stack.length === 0) {
8536
+ result = layout;
8537
+ return;
8538
+ }
8539
+ const parent = stack[stack.length - 1];
8540
+ if (parent.stage === 1) parent.leftLayout = layout;
8541
+ else parent.rightLayout = layout;
8542
+ }, "setChildResult");
8543
+ while (stack.length > 0) {
8544
+ const frame = stack[stack.length - 1];
8545
+ const cur = frame.node;
8546
+ if (frame.stage === 0) {
8547
+ if (this._isDisplayLeaf(cur, options)) {
8548
+ stack.pop();
8549
+ const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
8550
+ setChildResult(layout);
8551
+ continue;
8552
+ }
8553
+ frame.stage = 1;
8554
+ stack.push(newFrame(cur.left));
8555
+ } else if (frame.stage === 1) {
8556
+ frame.stage = 2;
8557
+ stack.push(newFrame(cur.right));
8558
+ } else {
8559
+ stack.pop();
8560
+ const line = this.isNIL(cur) ? "S" : String(cur.key);
8561
+ const layout = _BinaryTree2._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
8562
+ setChildResult(layout);
8308
8563
  }
8309
- return [
8310
- mergedLines,
8311
- leftWidth + width + rightWidth,
8312
- Math.max(leftHeight, rightHeight) + 2,
8313
- leftWidth + Math.floor(width / 2)
8314
- ];
8315
8564
  }
8565
+ return result;
8566
+ }
8567
+ static _buildNodeDisplay(line, width, left, right) {
8568
+ const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
8569
+ const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
8570
+ 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));
8571
+ const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
8572
+ const mergedLines = [firstLine, secondLine];
8573
+ for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
8574
+ const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
8575
+ const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
8576
+ mergedLines.push(leftLine + " ".repeat(width) + rightLine);
8577
+ }
8578
+ return [
8579
+ mergedLines,
8580
+ leftWidth + width + rightWidth,
8581
+ Math.max(leftHeight, rightHeight) + 2,
8582
+ leftWidth + Math.floor(width / 2)
8583
+ ];
8584
+ }
8585
+ /**
8586
+ * Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
8587
+ */
8588
+ _isDisplayLeaf(node, options) {
8589
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8590
+ if (node === null && !isShowNull) return true;
8591
+ if (node === void 0 && !isShowUndefined) return true;
8592
+ if (this.isNIL(node) && !isShowRedBlackNIL) return true;
8593
+ if (node === null || node === void 0) return true;
8594
+ const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
8595
+ const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
8596
+ return !hasDisplayableLeft && !hasDisplayableRight;
8597
+ }
8598
+ _hasDisplayableChild(child, options) {
8599
+ if (child === null) return !!options.isShowNull;
8600
+ if (child === void 0) return !!options.isShowUndefined;
8601
+ if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
8602
+ return true;
8603
+ }
8604
+ /**
8605
+ * Resolve a display leaf node to its layout.
8606
+ */
8607
+ _resolveDisplayLeaf(node, options, emptyDisplayLayout) {
8608
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8609
+ if (node === null && !isShowNull) return emptyDisplayLayout;
8610
+ if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
8611
+ if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
8612
+ if (node !== null && node !== void 0) {
8613
+ const line2 = this.isNIL(node) ? "S" : String(node.key);
8614
+ return _BinaryTree2._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
8615
+ }
8616
+ const line = node === void 0 ? "U" : "N";
8617
+ return _BinaryTree2._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
8316
8618
  }
8317
8619
  /**
8318
8620
  * (Protected) Swaps the key/value properties of two nodes.
@@ -9311,9 +9613,15 @@ var treeMultimapTyped = (() => {
9311
9613
  if (a < b) return -1;
9312
9614
  return 0;
9313
9615
  }
9616
+ if (a instanceof Date && b instanceof Date) {
9617
+ const ta = a.getTime();
9618
+ const tb = b.getTime();
9619
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
9620
+ return ta > tb ? 1 : ta < tb ? -1 : 0;
9621
+ }
9314
9622
  if (typeof a === "object" || typeof b === "object") {
9315
- throw TypeError(
9316
- `When comparing object type keys, a custom comparator must be provided in the constructor's options!`
9623
+ throw new TypeError(
9624
+ ERR.comparatorRequired("BST")
9317
9625
  );
9318
9626
  }
9319
9627
  return 0;
@@ -9825,7 +10133,7 @@ var treeMultimapTyped = (() => {
9825
10133
  */
9826
10134
  read(count) {
9827
10135
  if (!Number.isInteger(count)) {
9828
- throw new Error("Invalid count");
10136
+ throw new Error(ERR.invalidArgument("count must be an integer", "BinaryIndexedTree"));
9829
10137
  }
9830
10138
  return this._read(Math.max(Math.min(count, this.max), 0));
9831
10139
  }
@@ -9837,7 +10145,7 @@ var treeMultimapTyped = (() => {
9837
10145
  */
9838
10146
  lowerBound(sum) {
9839
10147
  if (this.negativeCount > 0) {
9840
- throw new Error("Sequence is not non-descending");
10148
+ throw new Error(ERR.invalidOperation("Sequence is not non-descending.", "BinaryIndexedTree"));
9841
10149
  }
9842
10150
  return this._binarySearch(sum, (x, y) => x < y);
9843
10151
  }
@@ -9850,7 +10158,7 @@ var treeMultimapTyped = (() => {
9850
10158
  */
9851
10159
  upperBound(sum) {
9852
10160
  if (this.negativeCount > 0) {
9853
- throw new Error("Must not be descending");
10161
+ throw new Error(ERR.invalidOperation("Sequence must not be descending.", "BinaryIndexedTree"));
9854
10162
  }
9855
10163
  return this._binarySearch(sum, (x, y) => x <= y);
9856
10164
  }
@@ -9901,10 +10209,10 @@ var treeMultimapTyped = (() => {
9901
10209
  */
9902
10210
  _checkIndex(index) {
9903
10211
  if (!Number.isInteger(index)) {
9904
- throw new Error("Invalid index: Index must be an integer.");
10212
+ throw new TypeError(ERR.invalidIndex("BinaryIndexedTree"));
9905
10213
  }
9906
10214
  if (index < 0 || index >= this.max) {
9907
- throw new Error("Index out of range: Index must be within the range [0, this.max).");
10215
+ throw new RangeError(ERR.indexOutOfRange(index, 0, this.max - 1, "BinaryIndexedTree"));
9908
10216
  }
9909
10217
  }
9910
10218
  /**
@@ -11469,6 +11777,24 @@ var treeMultimapTyped = (() => {
11469
11777
  * @param [thisArg] - See parameter type for details.
11470
11778
  * @returns A new RedBlackTree with mapped entries.
11471
11779
  */
11780
+ /**
11781
+ * Red-Black trees are self-balancing — `perfectlyBalance` rebuilds via
11782
+ * sorted bulk insert, which naturally produces a balanced RBT.
11783
+ * @remarks Time O(N), Space O(N)
11784
+ */
11785
+ perfectlyBalance(iterationType) {
11786
+ const entries = [];
11787
+ for (const [key, value] of this) entries.push([key, value]);
11788
+ if (entries.length <= 1) return true;
11789
+ this.clear();
11790
+ this.setMany(
11791
+ entries.map(([k]) => k),
11792
+ entries.map(([, v]) => v),
11793
+ true
11794
+ // isBalanceAdd
11795
+ );
11796
+ return true;
11797
+ }
11472
11798
  map(callback, options, thisArg) {
11473
11799
  const out = this._createLike([], options);
11474
11800
  let index = 0;
@@ -11793,7 +12119,7 @@ var treeMultimapTyped = (() => {
11793
12119
  static createDefaultComparator() {
11794
12120
  return (a, b) => {
11795
12121
  if (typeof a === "number" && typeof b === "number") {
11796
- if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeSet: NaN is not a valid key");
12122
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeSet"));
11797
12123
  const aa = Object.is(a, -0) ? 0 : a;
11798
12124
  const bb = Object.is(b, -0) ? 0 : b;
11799
12125
  return aa > bb ? 1 : aa < bb ? -1 : 0;
@@ -11804,10 +12130,10 @@ var treeMultimapTyped = (() => {
11804
12130
  if (a instanceof Date && b instanceof Date) {
11805
12131
  const ta = a.getTime();
11806
12132
  const tb = b.getTime();
11807
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeSet: invalid Date key");
12133
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeSet"));
11808
12134
  return ta > tb ? 1 : ta < tb ? -1 : 0;
11809
12135
  }
11810
- throw new TypeError("TreeSet: comparator is required for non-number/non-string/non-Date keys");
12136
+ throw new TypeError(ERR.comparatorRequired("TreeSet"));
11811
12137
  };
11812
12138
  }
11813
12139
  /**
@@ -11825,15 +12151,15 @@ var treeMultimapTyped = (() => {
11825
12151
  _validateKey(key) {
11826
12152
  if (!__privateGet(this, _isDefaultComparator)) return;
11827
12153
  if (typeof key === "number") {
11828
- if (Number.isNaN(key)) throw new TypeError("TreeSet: NaN is not a valid key");
12154
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeSet"));
11829
12155
  return;
11830
12156
  }
11831
12157
  if (typeof key === "string") return;
11832
12158
  if (key instanceof Date) {
11833
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeSet: invalid Date key");
12159
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeSet"));
11834
12160
  return;
11835
12161
  }
11836
- throw new TypeError("TreeSet: comparator is required for non-number/non-string/non-Date keys");
12162
+ throw new TypeError(ERR.comparatorRequired("TreeSet"));
11837
12163
  }
11838
12164
  /**
11839
12165
  * Add a key to the set (no-op if already present).
@@ -12154,15 +12480,15 @@ var treeMultimapTyped = (() => {
12154
12480
  _validateKey(key) {
12155
12481
  if (!__privateGet(this, _isDefaultComparator2)) return;
12156
12482
  if (typeof key === "number") {
12157
- if (Number.isNaN(key)) throw new TypeError("TreeMultiMap: NaN is not a valid key");
12483
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiMap"));
12158
12484
  return;
12159
12485
  }
12160
12486
  if (typeof key === "string") return;
12161
12487
  if (key instanceof Date) {
12162
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiMap: invalid Date key");
12488
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiMap"));
12163
12489
  return;
12164
12490
  }
12165
- throw new TypeError("TreeMultiMap: comparator is required for non-number/non-string/non-Date keys");
12491
+ throw new TypeError(ERR.comparatorRequired("TreeMultiMap"));
12166
12492
  }
12167
12493
  /**
12168
12494
  * Number of distinct keys.
@@ -12587,7 +12913,7 @@ var treeMultimapTyped = (() => {
12587
12913
  [k, v] = toEntryFn(item);
12588
12914
  } else {
12589
12915
  if (!Array.isArray(item) || item.length < 2) {
12590
- throw new TypeError("TreeMap: each entry must be a [key, value] tuple");
12916
+ throw new TypeError(ERR.invalidEntry("TreeMap"));
12591
12917
  }
12592
12918
  k = item[0];
12593
12919
  v = item[1];
@@ -12608,7 +12934,7 @@ var treeMultimapTyped = (() => {
12608
12934
  static createDefaultComparator() {
12609
12935
  return (a, b) => {
12610
12936
  if (typeof a === "number" && typeof b === "number") {
12611
- if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeMap: NaN is not a valid key");
12937
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeMap"));
12612
12938
  const aa = Object.is(a, -0) ? 0 : a;
12613
12939
  const bb = Object.is(b, -0) ? 0 : b;
12614
12940
  return aa > bb ? 1 : aa < bb ? -1 : 0;
@@ -12619,24 +12945,24 @@ var treeMultimapTyped = (() => {
12619
12945
  if (a instanceof Date && b instanceof Date) {
12620
12946
  const ta = a.getTime();
12621
12947
  const tb = b.getTime();
12622
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeMap: invalid Date key");
12948
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeMap"));
12623
12949
  return ta > tb ? 1 : ta < tb ? -1 : 0;
12624
12950
  }
12625
- throw new TypeError("TreeMap: comparator is required for non-number/non-string/non-Date keys");
12951
+ throw new TypeError(ERR.comparatorRequired("TreeMap"));
12626
12952
  };
12627
12953
  }
12628
12954
  _validateKey(key) {
12629
12955
  if (!__privateGet(this, _isDefaultComparator3)) return;
12630
12956
  if (typeof key === "number") {
12631
- if (Number.isNaN(key)) throw new TypeError("TreeMap: NaN is not a valid key");
12957
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMap"));
12632
12958
  return;
12633
12959
  }
12634
12960
  if (typeof key === "string") return;
12635
12961
  if (key instanceof Date) {
12636
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMap: invalid Date key");
12962
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMap"));
12637
12963
  return;
12638
12964
  }
12639
- throw new TypeError("TreeMap: comparator is required for non-number/non-string/non-Date keys");
12965
+ throw new TypeError(ERR.comparatorRequired("TreeMap"));
12640
12966
  }
12641
12967
  /**
12642
12968
  * Number of entries in the map.
@@ -12963,22 +13289,22 @@ var treeMultimapTyped = (() => {
12963
13289
  _validateKey(key) {
12964
13290
  if (!__privateGet(this, _isDefaultComparator4)) return;
12965
13291
  if (typeof key === "number") {
12966
- if (Number.isNaN(key)) throw new TypeError("TreeMultiSet: NaN is not a valid key");
13292
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiSet"));
12967
13293
  return;
12968
13294
  }
12969
13295
  if (typeof key === "string") return;
12970
13296
  if (key instanceof Date) {
12971
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiSet: invalid Date key");
13297
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiSet"));
12972
13298
  return;
12973
13299
  }
12974
- throw new TypeError("TreeMultiSet: comparator is required for non-number/non-string/non-Date keys");
13300
+ throw new TypeError(ERR.comparatorRequired("TreeMultiSet"));
12975
13301
  }
12976
13302
  /**
12977
13303
  * Validates that count is a non-negative safe integer.
12978
13304
  * @remarks Time O(1), Space O(1)
12979
13305
  */
12980
13306
  _validateCount(n) {
12981
- if (!Number.isSafeInteger(n) || n < 0) throw new RangeError("TreeMultiSet: count must be a safe integer >= 0");
13307
+ if (!Number.isSafeInteger(n) || n < 0) throw new RangeError(ERR.invalidArgument("count must be a safe integer >= 0.", "TreeMultiSet"));
12982
13308
  }
12983
13309
  /**
12984
13310
  * Total occurrences (sumCounts).
@@ -13398,9 +13724,7 @@ var treeMultimapTyped = (() => {
13398
13724
  super(elements, {
13399
13725
  comparator: /* @__PURE__ */ __name((a, b) => {
13400
13726
  if (typeof a === "object" || typeof b === "object") {
13401
- throw TypeError(
13402
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
13403
- );
13727
+ throw new TypeError(ERR.comparatorRequired("MaxPriorityQueue"));
13404
13728
  }
13405
13729
  if (a < b) return 1;
13406
13730
  if (a > b) return -1;
@@ -13538,7 +13862,7 @@ var treeMultimapTyped = (() => {
13538
13862
  */
13539
13863
  add(matrix) {
13540
13864
  if (!this.isMatchForCalculate(matrix)) {
13541
- throw new Error("Matrix dimensions must match for addition.");
13865
+ throw new Error(ERR.matrixDimensionMismatch("addition"));
13542
13866
  }
13543
13867
  const resultData = [];
13544
13868
  for (let i = 0; i < this.rows; i++) {
@@ -13570,7 +13894,7 @@ var treeMultimapTyped = (() => {
13570
13894
  */
13571
13895
  subtract(matrix) {
13572
13896
  if (!this.isMatchForCalculate(matrix)) {
13573
- throw new Error("Matrix dimensions must match for subtraction.");
13897
+ throw new Error(ERR.matrixDimensionMismatch("subtraction"));
13574
13898
  }
13575
13899
  const resultData = [];
13576
13900
  for (let i = 0; i < this.rows; i++) {
@@ -13601,7 +13925,7 @@ var treeMultimapTyped = (() => {
13601
13925
  */
13602
13926
  multiply(matrix) {
13603
13927
  if (this.cols !== matrix.rows) {
13604
- throw new Error("Matrix dimensions must be compatible for multiplication (A.cols = B.rows).");
13928
+ throw new Error(ERR.matrixDimensionMismatch("multiplication (A.cols must equal B.rows)"));
13605
13929
  }
13606
13930
  const resultData = [];
13607
13931
  for (let i = 0; i < this.rows; i++) {
@@ -13635,7 +13959,7 @@ var treeMultimapTyped = (() => {
13635
13959
  */
13636
13960
  transpose() {
13637
13961
  if (this.data.some((row) => row.length !== this.rows)) {
13638
- throw new Error("Matrix must be rectangular for transposition.");
13962
+ throw new Error(ERR.matrixNotRectangular());
13639
13963
  }
13640
13964
  const resultData = [];
13641
13965
  for (let j = 0; j < this.cols; j++) {
@@ -13660,7 +13984,7 @@ var treeMultimapTyped = (() => {
13660
13984
  inverse() {
13661
13985
  var _a;
13662
13986
  if (this.rows !== this.cols) {
13663
- throw new Error("Matrix must be square for inversion.");
13987
+ throw new Error(ERR.matrixNotSquare());
13664
13988
  }
13665
13989
  const augmentedMatrixData = [];
13666
13990
  for (let i = 0; i < this.rows; i++) {
@@ -13682,12 +14006,12 @@ var treeMultimapTyped = (() => {
13682
14006
  pivotRow++;
13683
14007
  }
13684
14008
  if (pivotRow === this.rows) {
13685
- throw new Error("Matrix is singular, and its inverse does not exist.");
14009
+ throw new Error(ERR.matrixSingular());
13686
14010
  }
13687
14011
  augmentedMatrix._swapRows(i, pivotRow);
13688
14012
  const pivotElement = (_a = augmentedMatrix.get(i, i)) != null ? _a : 1;
13689
14013
  if (pivotElement === 0) {
13690
- throw new Error("Matrix is singular, and its inverse does not exist (division by zero).");
14014
+ throw new Error(ERR.matrixSingular());
13691
14015
  }
13692
14016
  augmentedMatrix._scaleRow(i, 1 / pivotElement);
13693
14017
  for (let j = 0; j < this.rows; j++) {
@@ -13717,9 +14041,7 @@ var treeMultimapTyped = (() => {
13717
14041
  */
13718
14042
  dot(matrix) {
13719
14043
  if (this.cols !== matrix.rows) {
13720
- throw new Error(
13721
- "Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product."
13722
- );
14044
+ throw new Error(ERR.matrixDimensionMismatch("dot product (A.cols must equal B.rows)"));
13723
14045
  }
13724
14046
  const resultData = [];
13725
14047
  for (let i = 0; i < this.rows; i++) {
@@ -14335,7 +14657,7 @@ var treeMultimapTyped = (() => {
14335
14657
  for (const x of this) {
14336
14658
  const v = thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
14337
14659
  if (typeof v !== "string") {
14338
- throw new TypeError(`Trie.map callback must return string; got ${typeof v}`);
14660
+ throw new TypeError(ERR.callbackReturnType("string", typeof v, "Trie.map"));
14339
14661
  }
14340
14662
  newTrie.add(v);
14341
14663
  }