@johnhenry/math 0.0.0

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 (242) hide show
  1. package/README.md +165 -0
  2. package/dist/Bivector4.d.ts +52 -0
  3. package/dist/Bivector4.d.ts.map +1 -0
  4. package/dist/Bivector4.js +105 -0
  5. package/dist/Bivector4.js.map +1 -0
  6. package/dist/CellGraph.d.ts +259 -0
  7. package/dist/CellGraph.d.ts.map +1 -0
  8. package/dist/CellGraph.js +637 -0
  9. package/dist/CellGraph.js.map +1 -0
  10. package/dist/Clifford4Internal.d.ts +35 -0
  11. package/dist/Clifford4Internal.d.ts.map +1 -0
  12. package/dist/Clifford4Internal.js +86 -0
  13. package/dist/Clifford4Internal.js.map +1 -0
  14. package/dist/Combinatorics.d.ts +61 -0
  15. package/dist/Combinatorics.d.ts.map +1 -0
  16. package/dist/Combinatorics.js +186 -0
  17. package/dist/Combinatorics.js.map +1 -0
  18. package/dist/CombinatoricsGenerators.d.ts +44 -0
  19. package/dist/CombinatoricsGenerators.d.ts.map +1 -0
  20. package/dist/CombinatoricsGenerators.js +148 -0
  21. package/dist/CombinatoricsGenerators.js.map +1 -0
  22. package/dist/ComplexMath.d.ts +46 -0
  23. package/dist/ComplexMath.d.ts.map +1 -0
  24. package/dist/ComplexMath.js +98 -0
  25. package/dist/ComplexMath.js.map +1 -0
  26. package/dist/ComplexNumber.d.ts +174 -0
  27. package/dist/ComplexNumber.d.ts.map +1 -0
  28. package/dist/ComplexNumber.js +443 -0
  29. package/dist/ComplexNumber.js.map +1 -0
  30. package/dist/Cycle.d.ts +42 -0
  31. package/dist/Cycle.d.ts.map +1 -0
  32. package/dist/Cycle.js +120 -0
  33. package/dist/Cycle.js.map +1 -0
  34. package/dist/Decimal.d.ts +45 -0
  35. package/dist/Decimal.d.ts.map +1 -0
  36. package/dist/Decimal.js +135 -0
  37. package/dist/Decimal.js.map +1 -0
  38. package/dist/Distributions.d.ts +55 -0
  39. package/dist/Distributions.d.ts.map +1 -0
  40. package/dist/Distributions.js +222 -0
  41. package/dist/Distributions.js.map +1 -0
  42. package/dist/DualNumber.d.ts +42 -0
  43. package/dist/DualNumber.d.ts.map +1 -0
  44. package/dist/DualNumber.js +91 -0
  45. package/dist/DualNumber.js.map +1 -0
  46. package/dist/Environment.d.ts +44 -0
  47. package/dist/Environment.d.ts.map +1 -0
  48. package/dist/Environment.js +129 -0
  49. package/dist/Environment.js.map +1 -0
  50. package/dist/Expression.d.ts +19 -0
  51. package/dist/Expression.d.ts.map +1 -0
  52. package/dist/Expression.js +43 -0
  53. package/dist/Expression.js.map +1 -0
  54. package/dist/FFT.d.ts +21 -0
  55. package/dist/FFT.d.ts.map +1 -0
  56. package/dist/FFT.js +136 -0
  57. package/dist/FFT.js.map +1 -0
  58. package/dist/GeometricAlgebra4.d.ts +73 -0
  59. package/dist/GeometricAlgebra4.d.ts.map +1 -0
  60. package/dist/GeometricAlgebra4.js +115 -0
  61. package/dist/GeometricAlgebra4.js.map +1 -0
  62. package/dist/Geometry.d.ts +41 -0
  63. package/dist/Geometry.d.ts.map +1 -0
  64. package/dist/Geometry.js +167 -0
  65. package/dist/Geometry.js.map +1 -0
  66. package/dist/Graph.d.ts +72 -0
  67. package/dist/Graph.d.ts.map +1 -0
  68. package/dist/Graph.js +337 -0
  69. package/dist/Graph.js.map +1 -0
  70. package/dist/Graph3DUtils.d.ts +80 -0
  71. package/dist/Graph3DUtils.d.ts.map +1 -0
  72. package/dist/Graph3DUtils.js +156 -0
  73. package/dist/Graph3DUtils.js.map +1 -0
  74. package/dist/GraphUtils.d.ts +67 -0
  75. package/dist/GraphUtils.d.ts.map +1 -0
  76. package/dist/GraphUtils.js +72 -0
  77. package/dist/GraphUtils.js.map +1 -0
  78. package/dist/GroupTheory.d.ts +73 -0
  79. package/dist/GroupTheory.d.ts.map +1 -0
  80. package/dist/GroupTheory.js +194 -0
  81. package/dist/GroupTheory.js.map +1 -0
  82. package/dist/IntUtils.d.ts +33 -0
  83. package/dist/IntUtils.d.ts.map +1 -0
  84. package/dist/IntUtils.js +185 -0
  85. package/dist/IntUtils.js.map +1 -0
  86. package/dist/Interval.d.ts +44 -0
  87. package/dist/Interval.d.ts.map +1 -0
  88. package/dist/Interval.js +165 -0
  89. package/dist/Interval.js.map +1 -0
  90. package/dist/Lattice.d.ts +48 -0
  91. package/dist/Lattice.d.ts.map +1 -0
  92. package/dist/Lattice.js +65 -0
  93. package/dist/Lattice.js.map +1 -0
  94. package/dist/Logic.d.ts +22 -0
  95. package/dist/Logic.d.ts.map +1 -0
  96. package/dist/Logic.js +34 -0
  97. package/dist/Logic.js.map +1 -0
  98. package/dist/MatrixMath.d.ts +71 -0
  99. package/dist/MatrixMath.d.ts.map +1 -0
  100. package/dist/MatrixMath.js +302 -0
  101. package/dist/MatrixMath.js.map +1 -0
  102. package/dist/NumberTheory.d.ts +49 -0
  103. package/dist/NumberTheory.d.ts.map +1 -0
  104. package/dist/NumberTheory.js +230 -0
  105. package/dist/NumberTheory.js.map +1 -0
  106. package/dist/Numerical.d.ts +85 -0
  107. package/dist/Numerical.d.ts.map +1 -0
  108. package/dist/Numerical.js +343 -0
  109. package/dist/Numerical.js.map +1 -0
  110. package/dist/Permutation.d.ts +43 -0
  111. package/dist/Permutation.d.ts.map +1 -0
  112. package/dist/Permutation.js +142 -0
  113. package/dist/Permutation.js.map +1 -0
  114. package/dist/Polygon.d.ts +64 -0
  115. package/dist/Polygon.d.ts.map +1 -0
  116. package/dist/Polygon.js +221 -0
  117. package/dist/Polygon.js.map +1 -0
  118. package/dist/PolynomialRing.d.ts +74 -0
  119. package/dist/PolynomialRing.d.ts.map +1 -0
  120. package/dist/PolynomialRing.js +231 -0
  121. package/dist/PolynomialRing.js.map +1 -0
  122. package/dist/Quaternion.d.ts +37 -0
  123. package/dist/Quaternion.d.ts.map +1 -0
  124. package/dist/Quaternion.js +106 -0
  125. package/dist/Quaternion.js.map +1 -0
  126. package/dist/Rational.d.ts +34 -0
  127. package/dist/Rational.d.ts.map +1 -0
  128. package/dist/Rational.js +136 -0
  129. package/dist/Rational.js.map +1 -0
  130. package/dist/RealMath.d.ts +112 -0
  131. package/dist/RealMath.d.ts.map +1 -0
  132. package/dist/RealMath.js +262 -0
  133. package/dist/RealMath.js.map +1 -0
  134. package/dist/Rotor4.d.ts +180 -0
  135. package/dist/Rotor4.d.ts.map +1 -0
  136. package/dist/Rotor4.js +388 -0
  137. package/dist/Rotor4.js.map +1 -0
  138. package/dist/SpecialFunctions.d.ts +32 -0
  139. package/dist/SpecialFunctions.d.ts.map +1 -0
  140. package/dist/SpecialFunctions.js +161 -0
  141. package/dist/SpecialFunctions.js.map +1 -0
  142. package/dist/SpecialOperator.d.ts +21 -0
  143. package/dist/SpecialOperator.d.ts.map +1 -0
  144. package/dist/SpecialOperator.js +26 -0
  145. package/dist/SpecialOperator.js.map +1 -0
  146. package/dist/Statistics.d.ts +50 -0
  147. package/dist/Statistics.d.ts.map +1 -0
  148. package/dist/Statistics.js +131 -0
  149. package/dist/Statistics.js.map +1 -0
  150. package/dist/StringEvaluator.d.ts +48 -0
  151. package/dist/StringEvaluator.d.ts.map +1 -0
  152. package/dist/StringEvaluator.js +190 -0
  153. package/dist/StringEvaluator.js.map +1 -0
  154. package/dist/Structure.d.ts +130 -0
  155. package/dist/Structure.d.ts.map +1 -0
  156. package/dist/Structure.js +394 -0
  157. package/dist/Structure.js.map +1 -0
  158. package/dist/Symbolic.d.ts +501 -0
  159. package/dist/Symbolic.d.ts.map +1 -0
  160. package/dist/Symbolic.js +4077 -0
  161. package/dist/Symbolic.js.map +1 -0
  162. package/dist/Type.d.ts +31 -0
  163. package/dist/Type.d.ts.map +1 -0
  164. package/dist/Type.js +47 -0
  165. package/dist/Type.js.map +1 -0
  166. package/dist/Utilities.d.ts +27 -0
  167. package/dist/Utilities.d.ts.map +1 -0
  168. package/dist/Utilities.js +47 -0
  169. package/dist/Utilities.js.map +1 -0
  170. package/dist/Vec4.d.ts +39 -0
  171. package/dist/Vec4.d.ts.map +1 -0
  172. package/dist/Vec4.js +82 -0
  173. package/dist/Vec4.js.map +1 -0
  174. package/dist/Vector.d.ts +83 -0
  175. package/dist/Vector.d.ts.map +1 -0
  176. package/dist/Vector.js +173 -0
  177. package/dist/Vector.js.map +1 -0
  178. package/dist/VectorCalculus.d.ts +42 -0
  179. package/dist/VectorCalculus.d.ts.map +1 -0
  180. package/dist/VectorCalculus.js +82 -0
  181. package/dist/VectorCalculus.js.map +1 -0
  182. package/dist/VectorUtils.d.ts +172 -0
  183. package/dist/VectorUtils.d.ts.map +1 -0
  184. package/dist/VectorUtils.js +706 -0
  185. package/dist/VectorUtils.js.map +1 -0
  186. package/dist/differentiation-rules.d.ts +21 -0
  187. package/dist/differentiation-rules.d.ts.map +1 -0
  188. package/dist/differentiation-rules.js +52 -0
  189. package/dist/differentiation-rules.js.map +1 -0
  190. package/dist/index.d.ts +52 -0
  191. package/dist/index.d.ts.map +1 -0
  192. package/dist/index.js +66 -0
  193. package/dist/index.js.map +1 -0
  194. package/package.json +68 -0
  195. package/src/Bivector4.ts +136 -0
  196. package/src/CellGraph.ts +669 -0
  197. package/src/Clifford4Internal.ts +90 -0
  198. package/src/Combinatorics.ts +183 -0
  199. package/src/CombinatoricsGenerators.ts +144 -0
  200. package/src/ComplexMath.ts +162 -0
  201. package/src/ComplexNumber.ts +491 -0
  202. package/src/Cycle.ts +126 -0
  203. package/src/Decimal.ts +145 -0
  204. package/src/Distributions.ts +269 -0
  205. package/src/DualNumber.ts +105 -0
  206. package/src/Environment.ts +127 -0
  207. package/src/Expression.ts +48 -0
  208. package/src/FFT.ts +146 -0
  209. package/src/GeometricAlgebra4.ts +157 -0
  210. package/src/Geometry.ts +173 -0
  211. package/src/Graph.ts +337 -0
  212. package/src/Graph3DUtils.ts +269 -0
  213. package/src/GraphUtils.ts +159 -0
  214. package/src/GroupTheory.ts +214 -0
  215. package/src/IntUtils.ts +200 -0
  216. package/src/Interval.ts +171 -0
  217. package/src/Lattice.ts +87 -0
  218. package/src/Logic.ts +38 -0
  219. package/src/MatrixMath.ts +326 -0
  220. package/src/NumberTheory.ts +228 -0
  221. package/src/Numerical.ts +390 -0
  222. package/src/Permutation.ts +148 -0
  223. package/src/Polygon.ts +229 -0
  224. package/src/PolynomialRing.ts +242 -0
  225. package/src/Quaternion.ts +125 -0
  226. package/src/Rational.ts +148 -0
  227. package/src/RealMath.ts +346 -0
  228. package/src/Rotor4.ts +440 -0
  229. package/src/SpecialFunctions.ts +152 -0
  230. package/src/SpecialOperator.ts +28 -0
  231. package/src/Statistics.ts +170 -0
  232. package/src/StringEvaluator.ts +208 -0
  233. package/src/Structure.ts +481 -0
  234. package/src/Symbolic.ts +4313 -0
  235. package/src/Type.ts +48 -0
  236. package/src/Utilities.ts +49 -0
  237. package/src/Vec4.ts +98 -0
  238. package/src/Vector.ts +189 -0
  239. package/src/VectorCalculus.ts +87 -0
  240. package/src/VectorUtils.ts +797 -0
  241. package/src/differentiation-rules.ts +73 -0
  242. package/src/index.ts +140 -0
@@ -0,0 +1,706 @@
1
+ import { Vector } from "./Vector.js";
2
+ export class VectorUtils {
3
+ // -- Section I.1: truth functions & comparison ---------------------------
4
+ static isVector(e) {
5
+ return e instanceof Vector;
6
+ }
7
+ static isNotVector(e) {
8
+ return !(e instanceof Vector);
9
+ }
10
+ /**
11
+ * True when the vector contains at least one element satisfying
12
+ * `vectorCriterion` (default: is a Vector).
13
+ *
14
+ * Bug fix: the AS3 implementation returned true only when *every* element was
15
+ * a vector, contradicting the library's own glossary ("multi-dimensional … if
16
+ * it contains elements which are also vectors") and breaking {@link flatten}
17
+ * on ragged/mixed vectors. The documented semantics are used here.
18
+ */
19
+ static isMultiDimensional(vector, vectorCriterion = VectorUtils.isVector) {
20
+ for (const e of vector) {
21
+ if (vectorCriterion(e))
22
+ return true;
23
+ }
24
+ return false;
25
+ }
26
+ /** True when `element` is present, optionally by a custom equality function. */
27
+ static contains(vector, element, equalityFunction) {
28
+ if (!equalityFunction)
29
+ return vector.lastIndexOf(element) !== -1;
30
+ for (const i of vector) {
31
+ if (equalityFunction(element, i))
32
+ return true;
33
+ }
34
+ return false;
35
+ }
36
+ /** The longer of two vectors; ties return the first. */
37
+ static longer(alpha, beta) {
38
+ return alpha.length >= beta.length ? alpha : beta;
39
+ }
40
+ /** The shorter of two vectors; ties return the second. */
41
+ static shorter(alpha, beta) {
42
+ return alpha.length >= beta.length ? beta : alpha;
43
+ }
44
+ static isNotMultiDimensional(vector, vectorCriterion) {
45
+ return !VectorUtils.isMultiDimensional(vector, vectorCriterion ?? VectorUtils.isVector);
46
+ }
47
+ static isFlat(vector, vectorCriterion) {
48
+ return VectorUtils.isNotMultiDimensional(vector, vectorCriterion);
49
+ }
50
+ // -- Section I.2: constructors -------------------------------------------
51
+ /** Arithmetic sequence `seed, seed+step, …` bounded by `limit`. */
52
+ static arithmeticSequence(seed = 0, limit = 100, step = 1) {
53
+ const out = new Vector();
54
+ let value = seed;
55
+ if (step > 0) {
56
+ if (limit < value)
57
+ limit = value;
58
+ while (value <= limit) {
59
+ out.push(value);
60
+ value += step;
61
+ }
62
+ }
63
+ else if (step < 0) {
64
+ if (limit > value)
65
+ limit = value;
66
+ while (value >= limit) {
67
+ out.push(value);
68
+ value += step;
69
+ }
70
+ }
71
+ else {
72
+ out.push(value);
73
+ }
74
+ return out;
75
+ }
76
+ /** `size` equally-spaced steps from `lower` to `upper` (inclusive). */
77
+ static arithmeticBounds(lower, upper, size) {
78
+ return VectorUtils.arithmeticSequence(lower, upper, (upper - lower) / size);
79
+ }
80
+ /** Geometric sequence `seed, seed*step, …` bounded by `|limit|`. */
81
+ static geometricSequence(seed = 1, limit = 1000, step = 2) {
82
+ const out = new Vector();
83
+ let value = seed;
84
+ if (Math.abs(step) > 1) {
85
+ if (Math.abs(limit) < Math.abs(value))
86
+ limit = value;
87
+ while (value <= Math.abs(limit)) {
88
+ out.push(value);
89
+ value *= step;
90
+ }
91
+ }
92
+ else if (Math.abs(step) < 1 && step !== 0) {
93
+ if (Math.abs(limit) < Math.abs(value))
94
+ limit = value;
95
+ while (value >= Math.abs(limit)) {
96
+ out.push(value);
97
+ value *= step;
98
+ }
99
+ }
100
+ else {
101
+ out.push(value);
102
+ }
103
+ return out;
104
+ }
105
+ /** A vector of `length` copies of `e`. */
106
+ static constantVector(length = 1, e) {
107
+ const out = new Vector();
108
+ for (let i = 0; i < length; i++)
109
+ out.push(e);
110
+ return out;
111
+ }
112
+ /** Wrap an array into a Vector. */
113
+ static fromArray(array) {
114
+ return Vector.fromArray(array);
115
+ }
116
+ /**
117
+ * Merge two elements into a single vector. Vectors are concatenated; a
118
+ * non-vector is folded into a vector partner; two non-vectors become a pair.
119
+ */
120
+ static merge(vectorA = null, vectorB = null) {
121
+ if (vectorA instanceof Vector && vectorB instanceof Vector) {
122
+ return Vector.fromArray([...vectorA, ...vectorB]);
123
+ }
124
+ if (vectorA instanceof Vector) {
125
+ const copy = vectorA.clone();
126
+ copy.push(vectorB);
127
+ return copy;
128
+ }
129
+ if (vectorB instanceof Vector) {
130
+ const copy = vectorB.clone();
131
+ copy.addElement(vectorA, 0); // bug fix: prepend vectorA, not vectorB
132
+ return copy;
133
+ }
134
+ return Vector.fromArray([vectorA, vectorB]);
135
+ }
136
+ /**
137
+ * Build a sequence recursively. With `keep`, the growing result feeds itself;
138
+ * otherwise a fixed-length sliding window of `seeds` is used. Neither the
139
+ * caller's `seeds` array is mutated (a bug avoided from the AS3 original).
140
+ */
141
+ static recursiveSequence(seeds, formula, endCondition, keep = false) {
142
+ const out = Vector.fromArray(seeds);
143
+ if (keep) {
144
+ // Pass the accumulator directly (not a fresh copy each time): the
145
+ // "caller's seeds untouched" guarantee only needs to protect the
146
+ // original `seeds` array (already copied into `out` above), not this
147
+ // internal accumulator. Spreading `out` on every push made this loop
148
+ // quadratic for large results.
149
+ while (!endCondition(out))
150
+ out.push(formula(out));
151
+ }
152
+ else {
153
+ const window = [...seeds];
154
+ while (!endCondition(window)) {
155
+ out.push(formula(window));
156
+ window.shift();
157
+ window.push(out[out.length - 1]);
158
+ }
159
+ }
160
+ return out;
161
+ }
162
+ /** Wrap `element` inside `depth` nested vectors. Returns `element` if depth 0. */
163
+ static wrap(element, depth = 1) {
164
+ if (depth === 0)
165
+ return element;
166
+ const out = new Vector();
167
+ out.push(element);
168
+ return VectorUtils.wrap(out, depth - 1);
169
+ }
170
+ /**
171
+ * Placeholder for the AS3 On-Line Encyclopedia of Integer Sequences fetch,
172
+ * which was itself only a hard-coded stub (it "required an internet
173
+ * connection" but never actually made one).
174
+ */
175
+ static fromOEIS(selection = 1) {
176
+ let vectorString;
177
+ switch (selection) {
178
+ case 1:
179
+ vectorString = "1,2,3";
180
+ break;
181
+ case 2:
182
+ vectorString = "4,5,6";
183
+ break;
184
+ case 3:
185
+ vectorString = "7,8,9";
186
+ break;
187
+ default:
188
+ vectorString = "0,0,0";
189
+ }
190
+ return VectorUtils.transform(Vector.fromArray(vectorString.split(",")), (s) => parseInt(s, 10));
191
+ }
192
+ // -- Section I.3: transformations ----------------------------------------
193
+ /** Fill a length-`v.length` vector with `unary(i)` for each index. */
194
+ static fillByIndex(v, unaryOperation) {
195
+ const out = new Vector(v.length);
196
+ for (let i = 0; i < out.length; i++)
197
+ out[i] = unaryOperation(i);
198
+ return out;
199
+ }
200
+ /** Map `unaryOperation` over each element. */
201
+ static transform(vector, unaryOperation) {
202
+ const out = new Vector();
203
+ for (const e of vector)
204
+ out.push(unaryOperation(e));
205
+ return out;
206
+ }
207
+ /** Replace every element with `element`. */
208
+ static replace(vector, element) {
209
+ const out = new Vector();
210
+ for (let i = 0; i < vector.length; i++)
211
+ out.push(element);
212
+ return out;
213
+ }
214
+ /** Map `unaryOperation` over every end node (non-vector leaf), recursively. */
215
+ static transformEndNodes(vector, unaryOperation, endNodeCriterion = VectorUtils.isNotVector) {
216
+ const out = vector.clone();
217
+ for (let i = 0; i < out.length; i++) {
218
+ const el = out[i];
219
+ if (endNodeCriterion(el) || !(el instanceof Vector)) {
220
+ out[i] = unaryOperation(el);
221
+ }
222
+ else {
223
+ out[i] = VectorUtils.transformEndNodes(el, unaryOperation, endNodeCriterion);
224
+ }
225
+ }
226
+ return out;
227
+ }
228
+ /** Replace every end node with `element`, recursively. */
229
+ static replaceEndNodes(vector, element, endNodeCriterion = VectorUtils.isNotVector) {
230
+ const out = vector.clone();
231
+ for (let i = 0; i < out.length; i++) {
232
+ const el = out[i];
233
+ if (endNodeCriterion(el) || !(el instanceof Vector)) {
234
+ out[i] = element;
235
+ }
236
+ else {
237
+ out[i] = VectorUtils.replaceEndNodes(el, element, endNodeCriterion);
238
+ }
239
+ }
240
+ return out;
241
+ }
242
+ /** Remove `first` elements from the front and `last` from the back. */
243
+ static trim(vector, first = 0, last = 0) {
244
+ const out = vector.clone();
245
+ out.splice(vector.length - last, last);
246
+ out.splice(0, first);
247
+ return out;
248
+ }
249
+ /** Remove every occurrence of any of `remove` (strict equality). */
250
+ static removeElements(vector, ...remove) {
251
+ const out = vector.clone();
252
+ for (let i = 0; i < out.length; i++) {
253
+ if (remove.includes(out[i])) {
254
+ out.removeElement(i);
255
+ i--;
256
+ }
257
+ }
258
+ return out;
259
+ }
260
+ /** Keep the elements matching `matchCriterion`. */
261
+ static filter(vector, matchCriterion) {
262
+ const out = new Vector();
263
+ for (const e of vector)
264
+ if (matchCriterion(e))
265
+ out.push(e);
266
+ return out;
267
+ }
268
+ /** The most frequently occurring element(s). */
269
+ static modes(list) {
270
+ const modes = new Vector();
271
+ if (list.length === 0)
272
+ return modes;
273
+ // Single linear pass with a Map (SameValueZero equality, matching the old
274
+ // Array#includes-based lookup) instead of an O(n) `includes` scan plus an
275
+ // O(n) `count` rescan per unique value.
276
+ const counts = new Map();
277
+ const order = [];
278
+ for (const value of list) {
279
+ const occurences = counts.get(value);
280
+ if (occurences === undefined) {
281
+ counts.set(value, 1);
282
+ order.push(value);
283
+ }
284
+ else {
285
+ counts.set(value, occurences + 1);
286
+ }
287
+ }
288
+ let highCount = 0;
289
+ for (const value of order) {
290
+ const occurences = counts.get(value);
291
+ if (occurences > highCount)
292
+ highCount = occurences;
293
+ }
294
+ for (const value of order) {
295
+ if (counts.get(value) === highCount)
296
+ modes.push(value);
297
+ }
298
+ return modes;
299
+ }
300
+ /** Fully flatten a nested vector of arbitrary, possibly ragged depth. */
301
+ static flatten(vector) {
302
+ // A single depth-first pass into a fresh output vector. The previous
303
+ // implementation repeatedly spliced elements into/out of a shared vector
304
+ // in place (`removeElement`/`addElement` are O(n) each), making it
305
+ // severely superlinear; this walk visits each leaf exactly once.
306
+ const out = new Vector();
307
+ const walk = (v) => {
308
+ for (const el of v) {
309
+ if (el instanceof Vector) {
310
+ walk(el);
311
+ }
312
+ else {
313
+ out.push(el);
314
+ }
315
+ }
316
+ };
317
+ walk(vector);
318
+ return out;
319
+ }
320
+ /** Flatten one level of a vector whose elements share the same depth. */
321
+ static flattenSD(vector) {
322
+ if (vector.length === 0)
323
+ return new Vector();
324
+ if (!(vector[0] instanceof Vector))
325
+ return vector.clone();
326
+ // One linear pass, spreading each vector element's own elements straight
327
+ // into a fresh output vector (matching `merge`'s vector+scalar behavior
328
+ // for any non-vector siblings). The previous implementation repeatedly
329
+ // called `merge` + deep `clone` on the ever-growing accumulator, an O(n)
330
+ // operation per element, making the whole pass quadratic.
331
+ const out = new Vector();
332
+ for (const el of vector) {
333
+ if (el instanceof Vector) {
334
+ for (const e of el)
335
+ out.push(e);
336
+ }
337
+ else {
338
+ out.push(el);
339
+ }
340
+ }
341
+ return out;
342
+ }
343
+ /** Flatten a same-depth vector by `depth` levels (fully if `depth` is 0). */
344
+ static flattenSDLevels(vector, depth = 0) {
345
+ let out = vector.clone();
346
+ const level = depth > 0 ? depth : VectorUtils.nestedDepthSD(vector);
347
+ // Bug fix: this called `flatten` (unlimited, fully recursive), which made
348
+ // every `depth >= 1` produce the same fully-flat result on the first
349
+ // iteration — silently ignoring `depth`. `flattenSD` only peels one level
350
+ // per call, which is what "by `depth` levels" actually requires.
351
+ for (let i = 0; i < level; i++)
352
+ out = VectorUtils.flattenSD(out);
353
+ return out;
354
+ }
355
+ /** Replace end nodes with copies of the whole vector (one fractal step). */
356
+ static fractal(vector) {
357
+ return VectorUtils.replaceEndNodes(vector, vector.clone());
358
+ }
359
+ /** Apply {@link fractal} `level` times. */
360
+ static fractalLevels(vector, level = 0) {
361
+ let out = vector.clone();
362
+ for (let i = 0; i < level; i++)
363
+ out = VectorUtils.fractal(out);
364
+ return out;
365
+ }
366
+ // -- Section I.4: combinations -------------------------------------------
367
+ /** Insert the elements of `newVector` into `target` at `index`. */
368
+ static insert(target, newVector, index = -1) {
369
+ if (index < 0)
370
+ index = target.length;
371
+ const out = target.clone();
372
+ for (let i = 0; i < newVector.length; i++) {
373
+ out.splice(index + i, 0, newVector[i]);
374
+ }
375
+ return out;
376
+ }
377
+ /**
378
+ * Combine two vectors element-wise via `binaryOperation`. Where only one
379
+ * vector has an element, `defaultValue` is used if supplied, otherwise the
380
+ * present element. (Bug fix: presence is tested by index, not truthiness.)
381
+ */
382
+ static combine(alpha, beta, binaryOperation, defaultValue) {
383
+ const len = Math.max(alpha.length, beta.length);
384
+ const out = new Vector(len);
385
+ for (let i = 0; i < len; i++) {
386
+ const hasA = i < alpha.length;
387
+ const hasB = i < beta.length;
388
+ if (hasA && hasB) {
389
+ out[i] = binaryOperation(alpha[i], beta[i]);
390
+ }
391
+ else if (hasA) {
392
+ out[i] = defaultValue !== undefined ? defaultValue : alpha[i];
393
+ }
394
+ else {
395
+ out[i] = defaultValue !== undefined ? defaultValue : beta[i];
396
+ }
397
+ }
398
+ return out;
399
+ }
400
+ // -- Section I.5: reductions & queries -----------------------------------
401
+ static length(list) {
402
+ return list.length;
403
+ }
404
+ /** Reduce a vector to a single value via a binary operation (left fold). */
405
+ static collapse(vector, binaryOperation, defaultObject = null) {
406
+ const work = vector.clone();
407
+ if (work.length === 0)
408
+ return defaultObject;
409
+ let acc = work[0];
410
+ for (let i = 1; i < work.length; i++)
411
+ acc = binaryOperation(acc, work[i]);
412
+ return acc;
413
+ }
414
+ /** Count elements satisfying `matchCriterion`. */
415
+ static matches(vector, matchCriterion) {
416
+ let n = 0;
417
+ for (const e of vector)
418
+ if (matchCriterion(e))
419
+ n++;
420
+ return n;
421
+ }
422
+ /** Count occurrences of `matchElement` (strict equality). */
423
+ static count(vector, matchElement) {
424
+ return VectorUtils.matches(vector, (x) => x === matchElement);
425
+ }
426
+ /**
427
+ * Lengths of consecutive runs matching `matchCriterion`. Unlike the AS3
428
+ * original, a spurious trailing `0` (left over when the input ends on a
429
+ * non-matching run) is trimmed.
430
+ */
431
+ static consecutiveMatches(vector, matchCriterion) {
432
+ const appearences = [0];
433
+ for (const e of vector) {
434
+ if (matchCriterion(e)) {
435
+ appearences[appearences.length - 1]++;
436
+ }
437
+ else if (appearences[appearences.length - 1] !== 0) {
438
+ appearences.push(0);
439
+ }
440
+ }
441
+ if (appearences.length > 1 && appearences[appearences.length - 1] === 0)
442
+ appearences.pop();
443
+ return appearences;
444
+ }
445
+ /** Depth of a same-depth nested vector. */
446
+ static nestedDepthSD(vector, initialDepth = 0) {
447
+ if (!(vector[0] instanceof Vector))
448
+ return initialDepth;
449
+ return VectorUtils.nestedDepthSD(vector[0], initialDepth + 1);
450
+ }
451
+ // -- Section III: matrices -----------------------------------------------
452
+ /** Row separator used by {@link matrixString}. */
453
+ static RowSeperator = ",\r";
454
+ /** True when `vector` is a matrix (rows are equal-length vectors). */
455
+ static isMatrix(vector) {
456
+ if (!(vector[0] instanceof Vector))
457
+ return false;
458
+ const length = vector[0].length;
459
+ for (const v of vector) {
460
+ if (!(v instanceof Vector) || v.length !== length)
461
+ return false;
462
+ }
463
+ return true;
464
+ }
465
+ static width(vector) {
466
+ return vector[0].length;
467
+ }
468
+ static height(vector) {
469
+ return vector.length;
470
+ }
471
+ /** An `height`×`width` matrix filled with `e`. */
472
+ static constantMatrix(height = 1, width = 1, e) {
473
+ const out = new Vector();
474
+ for (let i = 0; i < height; i++) {
475
+ const row = new Vector();
476
+ for (let j = 0; j < width; j++)
477
+ row.push(e);
478
+ out.push(row);
479
+ }
480
+ return out;
481
+ }
482
+ /** Identity-like matrix with `one` on the diagonal and `zero` elsewhere. */
483
+ static generateIdentity(height = 1, width = 1, one, zero) {
484
+ const identity = VectorUtils.constantMatrix(height, width, zero);
485
+ return VectorUtils.fillMatrixByIndex(identity, (i, j) => (i === j ? one : zero));
486
+ }
487
+ /** Wrap a vector as a single-row matrix. */
488
+ static vectorToMatrixRow(vector) {
489
+ const out = new Vector();
490
+ out.push(vector);
491
+ return out;
492
+ }
493
+ /** Wrap a vector as a single-column matrix. */
494
+ static vectorToMatrixColumn(vector) {
495
+ return VectorUtils.transpose(VectorUtils.vectorToMatrixRow(vector));
496
+ }
497
+ /** Fill each cell of a matrix with `binaryOperation(i, j)`. */
498
+ static fillMatrixByIndex(m, binaryOperation) {
499
+ const out = m.clone();
500
+ for (let i = 0; i < VectorUtils.height(out); i++) {
501
+ for (let j = 0; j < VectorUtils.width(out); j++) {
502
+ out[i][j] = binaryOperation(i, j);
503
+ }
504
+ }
505
+ return out;
506
+ }
507
+ /** Replace every cell of a matrix with `element`. */
508
+ static replaceMatrix(m, element) {
509
+ const out = m.clone();
510
+ for (let i = 0; i < VectorUtils.height(out); i++) {
511
+ for (let j = 0; j < VectorUtils.width(out); j++)
512
+ out[i][j] = element;
513
+ }
514
+ return out;
515
+ }
516
+ /** Transpose a matrix. */
517
+ static transpose(vector) {
518
+ const out = new Vector();
519
+ for (let k = 0; k < VectorUtils.width(vector); k++)
520
+ out.push(new Vector(VectorUtils.height(vector)));
521
+ for (let i = 0; i < VectorUtils.height(vector); i++) {
522
+ for (let j = 0; j < VectorUtils.width(vector); j++) {
523
+ out[j][i] = vector[i][j];
524
+ }
525
+ }
526
+ return out;
527
+ }
528
+ /** Return the `index`-th row as a single-row matrix. */
529
+ static getRow(m, index = 0) {
530
+ return VectorUtils.wrap(m[index]);
531
+ }
532
+ /** Return the `index`-th column as a single-row matrix. */
533
+ static getColumn(m, index = 0) {
534
+ return VectorUtils.transpose(VectorUtils.getRow(VectorUtils.transpose(m), index));
535
+ }
536
+ static rowRemoved(m, index = 0) {
537
+ const out = m.clone();
538
+ out.removeElement(index);
539
+ return out;
540
+ }
541
+ static columnRemoved(m, index = 0) {
542
+ return VectorUtils.transpose(VectorUtils.rowRemoved(VectorUtils.transpose(m), index));
543
+ }
544
+ static rowInserted(target, inserted, index = -1) {
545
+ return VectorUtils.insert(target, VectorUtils.wrap(inserted), index);
546
+ }
547
+ static columnInserted(target, inserted, index = -1) {
548
+ return VectorUtils.transpose(VectorUtils.rowInserted(VectorUtils.transpose(target), inserted, index));
549
+ }
550
+ static mergeRows(vectorA, vectorB) {
551
+ return VectorUtils.merge(vectorA, vectorB);
552
+ }
553
+ static mergeColumns(vectorA, vectorB) {
554
+ return VectorUtils.transpose(VectorUtils.mergeRows(VectorUtils.transpose(vectorA), VectorUtils.transpose(vectorB)));
555
+ }
556
+ static rowSet(target, newVector, index = 0) {
557
+ const out = target.clone();
558
+ out.setElement(newVector, index);
559
+ return out;
560
+ }
561
+ static columnSet(target, newVector, index = 0) {
562
+ return VectorUtils.transpose(VectorUtils.rowSet(VectorUtils.transpose(target), newVector, index));
563
+ }
564
+ /** Overlay `block` onto `target` with its top-left corner at (i, j). */
565
+ static placeBlock(target, block, i, j) {
566
+ const out = target.clone();
567
+ for (let iPrime = 0; iPrime < VectorUtils.height(block); iPrime++) {
568
+ for (let jPrime = 0; jPrime < VectorUtils.width(block); jPrime++) {
569
+ const row = out[i + iPrime];
570
+ if (row && row.length > j + jPrime) {
571
+ row[j + jPrime] = block[iPrime][jPrime];
572
+ }
573
+ }
574
+ }
575
+ return out;
576
+ }
577
+ /** Expand a block matrix (matrix of matrices) into a flat matrix. */
578
+ static breakBlock(M) {
579
+ let newHeight = 0;
580
+ let newWidth = 0;
581
+ const h = VectorUtils.height(M);
582
+ const w = VectorUtils.width(M);
583
+ for (let k = 0; k < h; k++)
584
+ newHeight += VectorUtils.height(M[k][0]);
585
+ for (let k = 0; k < w; k++)
586
+ newWidth += VectorUtils.width(M[0][k]);
587
+ const broken = VectorUtils.constantMatrix(newHeight, newWidth, null);
588
+ let currentHeight = 0;
589
+ let currentWidth = 0;
590
+ let currentMatrix = M[0][0];
591
+ while (currentHeight < newHeight) {
592
+ for (let i = 0; i < h; i++) {
593
+ for (let j = 0; j < w; j++) {
594
+ currentMatrix = M[i][j];
595
+ for (let iPrime = 0; iPrime < VectorUtils.height(currentMatrix); iPrime++) {
596
+ for (let jPrime = 0; jPrime < VectorUtils.width(currentMatrix); jPrime++) {
597
+ broken[currentHeight + iPrime][currentWidth + jPrime] = currentMatrix[iPrime][jPrime];
598
+ }
599
+ }
600
+ currentWidth += VectorUtils.width(currentMatrix);
601
+ }
602
+ currentWidth = 0;
603
+ currentHeight += VectorUtils.height(currentMatrix);
604
+ }
605
+ }
606
+ return broken;
607
+ }
608
+ /** Pad a matrix with `element`, optionally interleaving and/or bordering. */
609
+ static pad(matrix, element = null, padRows = true, padCols = true, top = true, bottom = true, left = true, right = true) {
610
+ let out = matrix.clone();
611
+ let paddingVector;
612
+ if (padRows) {
613
+ let insertCount = 1;
614
+ while (insertCount < VectorUtils.height(out)) {
615
+ paddingVector = VectorUtils.constantVector(VectorUtils.width(out), element);
616
+ out = VectorUtils.rowInserted(out, paddingVector, insertCount);
617
+ insertCount += 2;
618
+ }
619
+ }
620
+ if (padCols) {
621
+ let insertCount = 1;
622
+ while (insertCount < VectorUtils.width(out)) {
623
+ paddingVector = VectorUtils.constantVector(VectorUtils.height(out), element);
624
+ out = VectorUtils.columnInserted(out, paddingVector, insertCount);
625
+ insertCount += 2;
626
+ }
627
+ }
628
+ if (top)
629
+ out = VectorUtils.rowInserted(out, VectorUtils.constantVector(VectorUtils.width(out), element), 0);
630
+ if (bottom)
631
+ out = VectorUtils.rowInserted(out, VectorUtils.constantVector(VectorUtils.width(out), element), -1);
632
+ if (left)
633
+ out = VectorUtils.columnInserted(out, VectorUtils.constantVector(VectorUtils.height(out), element), 0);
634
+ if (right)
635
+ out = VectorUtils.columnInserted(out, VectorUtils.constantVector(VectorUtils.height(out), element), -1);
636
+ return out;
637
+ }
638
+ /** The main (or `off`-set) diagonal of a matrix as a vector. */
639
+ static diagonal(M, off = 0) {
640
+ const diag = new Vector();
641
+ if (off >= 0) {
642
+ for (let i = 0; i < VectorUtils.width(M) - off; i++)
643
+ diag.push(M[i][i + off]);
644
+ }
645
+ else {
646
+ const o = -off;
647
+ for (let i = 0; i < VectorUtils.height(M) - o; i++)
648
+ diag.push(M[i + o][i]);
649
+ }
650
+ return diag;
651
+ }
652
+ /** The anti-diagonal (or `off`-set) of a matrix as a vector. */
653
+ static minorDiagonal(M, off = 0) {
654
+ const diag = new Vector();
655
+ if (off >= 0) {
656
+ for (let i = 0; i < VectorUtils.width(M) - off; i++) {
657
+ diag.push(M[i][VectorUtils.width(M) - i - 1 - off]);
658
+ }
659
+ }
660
+ else {
661
+ const o = -off;
662
+ for (let i = 0; i < VectorUtils.height(M) - o; i++) {
663
+ diag.push(M[i + o][VectorUtils.width(M) - i - 1]);
664
+ }
665
+ }
666
+ return diag;
667
+ }
668
+ /** Render a matrix as a nicely aligned multi-line string. */
669
+ static matrixString(vector, minSpace = 0, center = 0, seperator = ",", leftBracket = "[", rightBracket = "]", rowSeperator = ",", openingBracket = "[", closingBracket = "]") {
670
+ // Stringify cells (kept in a parallel structure so we don't mutate input).
671
+ const cells = [];
672
+ let space = minSpace;
673
+ for (let i = 0; i < VectorUtils.height(vector); i++) {
674
+ const row = [];
675
+ for (let j = 0; j < VectorUtils.width(vector); j++) {
676
+ const raw = vector[i][j];
677
+ const str = raw == null ? "null" : String(raw);
678
+ row.push(str);
679
+ if (minSpace > 0 && space < str.length)
680
+ space = str.length;
681
+ }
682
+ cells.push(row);
683
+ }
684
+ if (minSpace > 0) {
685
+ for (const row of cells) {
686
+ for (let j = 0; j < row.length; j++) {
687
+ const cell = row[j];
688
+ if (center !== 0) {
689
+ let addLeft = Math.ceil((space - cell.length) / 2);
690
+ let addRight = Math.floor((space - cell.length) / 2);
691
+ if (center < 0)
692
+ [addLeft, addRight] = [addRight, addLeft];
693
+ row[j] = " ".repeat(addLeft) + cell + " ".repeat(addRight);
694
+ }
695
+ else {
696
+ row[j] = " ".repeat(space - cell.length) + cell;
697
+ }
698
+ }
699
+ }
700
+ }
701
+ const rowStrings = cells.map((row) => leftBracket + row.join(seperator) + rightBracket);
702
+ const fullRowSep = `${rowSeperator}\r${" ".repeat(openingBracket.length)}`;
703
+ return openingBracket + rowStrings.join(fullRowSep) + closingBracket;
704
+ }
705
+ }
706
+ //# sourceMappingURL=VectorUtils.js.map