@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,194 @@
1
+ import { Permutation } from "./Permutation.js";
2
+ const contains = (arr, x, eq) => arr.some((y) => eq(x, y));
3
+ export class GroupTheory {
4
+ /** The Cayley (multiplication) table: `table[i][j] = op(elements[i], elements[j])`. */
5
+ static cayleyTable(elements, op) {
6
+ return elements.map((a) => elements.map((b) => op(a, b)));
7
+ }
8
+ /** True when the set is closed under `op`. */
9
+ static isClosed(elements, op, eq) {
10
+ for (const a of elements)
11
+ for (const b of elements)
12
+ if (!contains(elements, op(a, b), eq))
13
+ return false;
14
+ return true;
15
+ }
16
+ /** The identity element, or `null` if none exists. */
17
+ static findIdentity(elements, op, eq) {
18
+ for (const e of elements) {
19
+ if (elements.every((a) => eq(op(e, a), a) && eq(op(a, e), a)))
20
+ return e;
21
+ }
22
+ return null;
23
+ }
24
+ /** True when `op` is associative over the set (O(n³) check). */
25
+ static isAssociative(elements, op, eq) {
26
+ for (const a of elements)
27
+ for (const b of elements)
28
+ for (const c of elements)
29
+ if (!eq(op(op(a, b), c), op(a, op(b, c))))
30
+ return false;
31
+ return true;
32
+ }
33
+ /** True when every element has an inverse relative to `identity`. */
34
+ static hasInverses(elements, op, eq, identity) {
35
+ return elements.every((a) => elements.some((b) => eq(op(a, b), identity) && eq(op(b, a), identity)));
36
+ }
37
+ /** Verify all four group axioms (closure, associativity, identity, inverses). */
38
+ static isGroup(elements, op, eq) {
39
+ if (!GroupTheory.isClosed(elements, op, eq))
40
+ return false;
41
+ const id = GroupTheory.findIdentity(elements, op, eq);
42
+ if (id === null)
43
+ return false;
44
+ return GroupTheory.isAssociative(elements, op, eq) && GroupTheory.hasInverses(elements, op, eq, id);
45
+ }
46
+ /** True when the group is also abelian (commutative). */
47
+ static isAbelian(elements, op, eq) {
48
+ for (const a of elements)
49
+ for (const b of elements)
50
+ if (!eq(op(a, b), op(b, a)))
51
+ return false;
52
+ return true;
53
+ }
54
+ /** The order of an element: the least `k ≥ 1` with `elementᵏ = identity`. */
55
+ static elementOrder(element, op, eq, identity, max = 100000) {
56
+ let acc = element;
57
+ for (let k = 1; k <= max; k++) {
58
+ if (eq(acc, identity))
59
+ return k;
60
+ acc = op(acc, element);
61
+ }
62
+ throw new Error("Element order exceeded the search bound (is the group finite?).");
63
+ }
64
+ /**
65
+ * The subgroup generated by `generators`: the closure of the generators (and
66
+ * the identity) under `op`. `identity` may be supplied when it is not itself a
67
+ * generator; otherwise closure alone recovers it for a finite group — except
68
+ * when `generators` is empty, in which case there is nothing to multiply out
69
+ * and `identity` must be supplied explicitly to get the trivial subgroup
70
+ * `[identity]` back (omitting it returns `[]`, since no identity can be
71
+ * discovered from zero elements and `op` alone).
72
+ */
73
+ static closure(generators, op, eq, identity, cap = 100000) {
74
+ const elements = [];
75
+ if (identity !== undefined)
76
+ elements.push(identity);
77
+ for (const g of generators)
78
+ if (!contains(elements, g, eq))
79
+ elements.push(g);
80
+ let changed = true;
81
+ while (changed) {
82
+ changed = false;
83
+ for (let i = 0; i < elements.length; i++) {
84
+ for (const g of generators) {
85
+ const p = op(elements[i], g);
86
+ if (!contains(elements, p, eq)) {
87
+ elements.push(p);
88
+ changed = true;
89
+ if (elements.length > cap)
90
+ throw new Error("Closure exceeded the size cap.");
91
+ }
92
+ }
93
+ }
94
+ }
95
+ return elements;
96
+ }
97
+ /** True when `sub` is a subgroup of `group` under `op`. */
98
+ static isSubgroup(sub, group, op, eq) {
99
+ if (!sub.every((s) => contains(group, s, eq)))
100
+ return false;
101
+ return GroupTheory.isGroup(sub, op, eq);
102
+ }
103
+ /** The distinct left cosets `gH` of subgroup `H` in `group`. */
104
+ static leftCosets(subgroup, group, op, eq) {
105
+ const cosets = [];
106
+ const seen = [];
107
+ for (const g of group) {
108
+ if (contains(seen, g, eq))
109
+ continue;
110
+ const coset = subgroup.map((h) => op(g, h));
111
+ cosets.push(coset);
112
+ for (const c of coset)
113
+ if (!contains(seen, c, eq))
114
+ seen.push(c);
115
+ }
116
+ return cosets;
117
+ }
118
+ /** Lagrange index `[G : H] = |G| / |H|`. */
119
+ static index(group, subgroup) {
120
+ return group.length / subgroup.length;
121
+ }
122
+ /** The orbit of `x` under a group action, given the generators and the action map. */
123
+ static orbit(x, generators, action, eqX, cap = 100000) {
124
+ const orbit = [x];
125
+ let changed = true;
126
+ while (changed) {
127
+ changed = false;
128
+ for (let i = 0; i < orbit.length; i++) {
129
+ for (const g of generators) {
130
+ const y = action(g, orbit[i]);
131
+ if (!contains(orbit, y, eqX)) {
132
+ orbit.push(y);
133
+ changed = true;
134
+ if (orbit.length > cap)
135
+ throw new Error("Orbit exceeded the size cap.");
136
+ }
137
+ }
138
+ }
139
+ }
140
+ return orbit;
141
+ }
142
+ /** The cyclic group Zₙ as `{0, …, n-1}` under addition mod n. */
143
+ static cyclicGroup(n) {
144
+ return {
145
+ elements: Array.from({ length: n }, (_, i) => i),
146
+ op: (a, b) => (a + b) % n,
147
+ identity: 0,
148
+ };
149
+ }
150
+ /**
151
+ * The dihedral group Dₙ (order 2n): symmetries of a regular n-gon, as
152
+ * permutations of its n vertices `{0, …, n-1}`. n rotations `ρₖ: i ↦ (i+k)
153
+ * mod n` plus n reflections `σₖ: i ↦ (k-i) mod n` (reflecting through the
154
+ * axis fixing vertex k/2 when k is even, or the edge midpoint between
155
+ * ⌊k/2⌋ and ⌈k/2⌉ when k is odd). For n=3 this is exactly (element-for-
156
+ * element, not just isomorphic) {@link symmetricGroup}(3) — the two
157
+ * constructions coincide since S₃ has only 6 permutations total, matching
158
+ * D₃'s own order 2·3=6.
159
+ */
160
+ static dihedralGroup(n) {
161
+ const domain = Array.from({ length: n }, (_, i) => i);
162
+ const mod = (x) => ((x % n) + n) % n;
163
+ const rotations = Array.from({ length: n }, (_, k) => new Permutation(domain, domain.map((i) => mod(i + k))));
164
+ const reflections = Array.from({ length: n }, (_, k) => new Permutation(domain, domain.map((i) => mod(k - i))));
165
+ return [...rotations, ...reflections];
166
+ }
167
+ /**
168
+ * The stabilizer of `x` under a group action: the elements of `group`
169
+ * fixing `x`. Complements {@link orbit} — the orbit-stabilizer theorem
170
+ * (`|orbit(x)| · |stabilizer(x)| = |G|`) holds for any finite group action.
171
+ */
172
+ static stabilizer(x, group, action, eqX) {
173
+ return group.filter((g) => eqX(action(g, x), x));
174
+ }
175
+ /** The symmetric group Sₙ: every permutation of `{0, …, n-1}`. */
176
+ static symmetricGroup(n) {
177
+ const domain = Array.from({ length: n }, (_, i) => i);
178
+ const results = [];
179
+ const permute = (arr, k) => {
180
+ if (k === arr.length) {
181
+ results.push(new Permutation(domain, [...arr]));
182
+ return;
183
+ }
184
+ for (let i = k; i < arr.length; i++) {
185
+ [arr[k], arr[i]] = [arr[i], arr[k]];
186
+ permute(arr, k + 1);
187
+ [arr[k], arr[i]] = [arr[i], arr[k]];
188
+ }
189
+ };
190
+ permute([...domain], 0);
191
+ return results;
192
+ }
193
+ }
194
+ //# sourceMappingURL=GroupTheory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GroupTheory.js","sourceRoot":"","sources":["../src/GroupTheory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * IntUtils — convert integers (and numeric strings) into English words.
3
+ *
4
+ * Ported from Mallory's ActionScript `IntUtils`. The peculiar comma-joined
5
+ * grouping of the original output is preserved so behaviour is unchanged, but
6
+ * two spelling bugs are fixed: "fourty" → "forty" and "ninty" → "ninety".
7
+ *
8
+ * Passing a string lets you exceed JS's safe-integer range, exactly as the AS3
9
+ * version did to sidestep ActionScript's number limits.
10
+ */
11
+ export declare class IntUtils {
12
+ private static readonly ONES;
13
+ private static readonly TENS;
14
+ /** Accepted group suffixes (units, thousands, millions, …). */
15
+ static readonly ActualNames: string[];
16
+ /** Whimsical fall-back names once the real ones run out. */
17
+ static readonly FakeNames: string[];
18
+ private static toInt;
19
+ /** Words for the last three digits (0–999) of a number. */
20
+ static toWordsTriple(num?: number): string;
21
+ /** Suffix for the group at `index` (0 = units, 1 = thousands, …). */
22
+ static numberGroupNames(index?: number): string;
23
+ /** Convert an integer (or its string form) to English words. */
24
+ static toWords(num: number | string): string;
25
+ private static readonly ORDINAL_IRREGULARS;
26
+ /** Ordinal words: "twenty-first", "one-hundredth", "twentieth", "eighth", … */
27
+ static toWordsOrdinal(num: number | string): string;
28
+ /** Ordinal words with a leading "one-" stripped ("one-hundredth" → "hundredth"). */
29
+ static toWordsOrdinalLazy(num: number | string): string;
30
+ /** Convert a decimal number (or string) to English words. */
31
+ static toWordsDecimal(num: number | string): string | null;
32
+ }
33
+ //# sourceMappingURL=IntUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntUtils.d.ts","sourceRoot":"","sources":["../src/IntUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAqB1B;IAGF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAS1B;IAEF,+DAA+D;IAC/D,MAAM,CAAC,QAAQ,CAAC,WAAW,WAazB;IAEF,4DAA4D;IAC5D,MAAM,CAAC,QAAQ,CAAC,SAAS,WAAqD;IAE9E,OAAO,CAAC,MAAM,CAAC,KAAK;IAKpB,2DAA2D;IAC3D,MAAM,CAAC,aAAa,CAAC,GAAG,SAAI,GAAG,MAAM;IA0BrC,qEAAqE;IACrE,MAAM,CAAC,gBAAgB,CAAC,KAAK,SAAI,GAAG,MAAM;IAM1C,gEAAgE;IAChE,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAqC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CASxC;IAEF,+EAA+E;IAC/E,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAenD,oFAAoF;IACpF,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAMvD,6DAA6D;IAC7D,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI;CAsB3D"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * IntUtils — convert integers (and numeric strings) into English words.
3
+ *
4
+ * Ported from Mallory's ActionScript `IntUtils`. The peculiar comma-joined
5
+ * grouping of the original output is preserved so behaviour is unchanged, but
6
+ * two spelling bugs are fixed: "fourty" → "forty" and "ninty" → "ninety".
7
+ *
8
+ * Passing a string lets you exceed JS's safe-integer range, exactly as the AS3
9
+ * version did to sidestep ActionScript's number limits.
10
+ */
11
+ export class IntUtils {
12
+ static ONES = [
13
+ "zero",
14
+ "one",
15
+ "two",
16
+ "three",
17
+ "four",
18
+ "five",
19
+ "six",
20
+ "seven",
21
+ "eight",
22
+ "nine",
23
+ "ten",
24
+ "eleven",
25
+ "twelve",
26
+ "thirteen",
27
+ "fourteen",
28
+ "fifteen",
29
+ "sixteen",
30
+ "seventeen",
31
+ "eighteen",
32
+ "nineteen",
33
+ ];
34
+ // index 2..9 => tens words (forty/ninety fixed from AS3 "fourty"/"ninty").
35
+ static TENS = {
36
+ 2: "twenty",
37
+ 3: "thirty",
38
+ 4: "forty",
39
+ 5: "fifty",
40
+ 6: "sixty",
41
+ 7: "seventy",
42
+ 8: "eighty",
43
+ 9: "ninety",
44
+ };
45
+ /** Accepted group suffixes (units, thousands, millions, …). */
46
+ static ActualNames = [
47
+ "",
48
+ "-thousand",
49
+ "-million",
50
+ "-billion",
51
+ "-trillion",
52
+ "-quadrillion",
53
+ "-quintillion",
54
+ "-sextillion",
55
+ "-septillion",
56
+ "-octillion",
57
+ "-nonillion",
58
+ "-decillion",
59
+ ];
60
+ /** Whimsical fall-back names once the real ones run out. */
61
+ static FakeNames = ["ZILLION!!!", "-BAJILLION!!!", "-AGAZILLION!!!"];
62
+ static toInt(s) {
63
+ const n = Number.parseInt(s, 10);
64
+ return Number.isNaN(n) ? 0 : n;
65
+ }
66
+ /** Words for the last three digits (0–999) of a number. */
67
+ static toWordsTriple(num = 0) {
68
+ if (num < 20)
69
+ return IntUtils.ONES[num] ?? "";
70
+ const numString = num.toString();
71
+ const lowerPlace = IntUtils.toInt(numString.charAt(numString.length - 1));
72
+ const tensPlace = IntUtils.toInt(numString.charAt(numString.length - 2));
73
+ let intString = "";
74
+ if (lowerPlace !== 0) {
75
+ const tens = IntUtils.TENS[tensPlace];
76
+ if (tens)
77
+ intString = `${tens}-${IntUtils.toWordsTriple(lowerPlace)}`;
78
+ }
79
+ else {
80
+ intString = IntUtils.TENS[tensPlace] ?? "";
81
+ }
82
+ if (num < 100)
83
+ return intString;
84
+ const lastTwo = IntUtils.toInt(`${tensPlace}${lowerPlace}`);
85
+ const hundredsPlace = IntUtils.toInt(numString.charAt(numString.length - 3));
86
+ if (lastTwo !== 0) {
87
+ return `${IntUtils.toWordsTriple(hundredsPlace)}-hundred-${IntUtils.toWordsTriple(lastTwo)}`;
88
+ }
89
+ return `${IntUtils.toWordsTriple(hundredsPlace)}-hundred`;
90
+ }
91
+ /** Suffix for the group at `index` (0 = units, 1 = thousands, …). */
92
+ static numberGroupNames(index = 0) {
93
+ return index < IntUtils.ActualNames.length
94
+ ? IntUtils.ActualNames[index]
95
+ : IntUtils.FakeNames[0];
96
+ }
97
+ /** Convert an integer (or its string form) to English words. */
98
+ static toWords(num) {
99
+ let negative = false;
100
+ let value = num;
101
+ if (typeof value === "string") {
102
+ if (value.charAt(0) === "-") {
103
+ negative = true;
104
+ value = value.substring(1);
105
+ }
106
+ }
107
+ else if (value < 0) {
108
+ negative = true;
109
+ value = value * -1;
110
+ }
111
+ let numString = value.toString().split(",").join("");
112
+ const groups = [];
113
+ while (numString.length > 0) {
114
+ const take = numString.length > 2 ? 3 : numString.length > 1 ? 2 : 1;
115
+ groups.unshift(IntUtils.toInt(numString.substring(numString.length - take)));
116
+ numString = numString.substr(0, numString.length - take);
117
+ }
118
+ if (groups.length === 1) {
119
+ const single = IntUtils.toWordsTriple(groups[0]);
120
+ return negative ? `negative ${single}` : single;
121
+ }
122
+ const parts = groups
123
+ .map((g, i) => (g === 0 ? null : IntUtils.toWordsTriple(g) + IntUtils.numberGroupNames(groups.length - i - 1)))
124
+ .filter((p) => p !== null);
125
+ const joined = parts.join(",");
126
+ return negative ? `negative ${joined}` : joined;
127
+ }
128
+ // Irregular ordinal suffixes for the last word of a words-string (one..twelve
129
+ // don't all follow the plain "+th" rule: eight/nine/twelve drop a letter).
130
+ static ORDINAL_IRREGULARS = {
131
+ one: "first",
132
+ two: "second",
133
+ three: "third",
134
+ four: "fourth",
135
+ five: "fifth",
136
+ eight: "eighth",
137
+ nine: "ninth",
138
+ twelve: "twelfth",
139
+ };
140
+ /** Ordinal words: "twenty-first", "one-hundredth", "twentieth", "eighth", … */
141
+ static toWordsOrdinal(num) {
142
+ const originalString = IntUtils.toWords(num);
143
+ const lastHyphen = originalString.lastIndexOf("-");
144
+ const prefix = lastHyphen === -1 ? "" : originalString.substring(0, lastHyphen + 1);
145
+ const lastWord = lastHyphen === -1 ? originalString : originalString.substring(lastHyphen + 1);
146
+ const irregular = IntUtils.ORDINAL_IRREGULARS[lastWord];
147
+ if (irregular)
148
+ return `${prefix}${irregular}`;
149
+ // Tens words (twenty, thirty, … ninety) take "-ieth" in place of the "y".
150
+ if (lastWord.endsWith("y"))
151
+ return `${prefix}${lastWord.slice(0, -1)}ieth`;
152
+ return `${originalString}th`;
153
+ }
154
+ /** Ordinal words with a leading "one-" stripped ("one-hundredth" → "hundredth"). */
155
+ static toWordsOrdinalLazy(num) {
156
+ const ordinal = IntUtils.toWordsOrdinal(num);
157
+ if (ordinal.substring(0, 4) === "one-")
158
+ return ordinal.substring(4);
159
+ return ordinal;
160
+ }
161
+ /** Convert a decimal number (or string) to English words. */
162
+ static toWordsDecimal(num) {
163
+ const str = num.toString();
164
+ if (str.lastIndexOf(".") === -1)
165
+ return IntUtils.toWords(str);
166
+ const integer = str.split(".")[0] ?? "";
167
+ const decimal = str.split(".")[1] ?? "";
168
+ const pluralFraction = decimal.length > 0 && decimal.charAt(decimal.length - 1) !== "1";
169
+ let finalString;
170
+ if ((!integer || IntUtils.toWords(integer) === "zero") && decimal.length > 0) {
171
+ finalString = `${IntUtils.toWords(decimal)} ${IntUtils.toWordsOrdinalLazy(10 ** decimal.length)}`;
172
+ }
173
+ else if ((!decimal || IntUtils.toWords(decimal) === "zero") && integer.length > 0) {
174
+ finalString = IntUtils.toWords(integer);
175
+ }
176
+ else if (!(integer || decimal)) {
177
+ return null;
178
+ }
179
+ else {
180
+ finalString = `${IntUtils.toWords(integer)} and ${IntUtils.toWords(decimal)} ${IntUtils.toWordsOrdinalLazy(10 ** decimal.length)}`;
181
+ }
182
+ return pluralFraction ? `${finalString}s` : finalString;
183
+ }
184
+ }
185
+ //# sourceMappingURL=IntUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntUtils.js","sourceRoot":"","sources":["../src/IntUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Interval — rigorous interval arithmetic `[lo, hi]`. Operations return an
3
+ * interval guaranteed to contain every result of the corresponding operation on
4
+ * any pair of members, so a final interval bounds the true answer despite
5
+ * rounding — useful for reliable numerics and error tracking. Every
6
+ * operation that isn't provably exact (`negate`/`abs`/`hull`/`intersect`
7
+ * only move or compare existing endpoints) outward-rounds its result by
8
+ * one ULP per side via `outward()` above.
9
+ */
10
+ export declare class Interval {
11
+ readonly lo: number;
12
+ readonly hi: number;
13
+ constructor(lo: number, hi?: number);
14
+ static of(lo: number, hi: number): Interval;
15
+ /** A degenerate interval `[x, x]`. */
16
+ static point(x: number): Interval;
17
+ get width(): number;
18
+ get midpoint(): number;
19
+ get radius(): number;
20
+ contains(x: number): boolean;
21
+ overlaps(o: Interval): boolean;
22
+ add(o: Interval): Interval;
23
+ subtract(o: Interval): Interval;
24
+ /** Exact: IEEE-754 negation only flips the sign bit, no rounding. */
25
+ negate(): Interval;
26
+ multiply(o: Interval): Interval;
27
+ divide(o: Interval): Interval;
28
+ /** The tightest interval containing both (the convex hull / union). */
29
+ hull(o: Interval): Interval;
30
+ /** The overlap of two intervals, or `null` if they are disjoint. */
31
+ intersect(o: Interval): Interval | null;
32
+ abs(): Interval;
33
+ sqrt(): Interval;
34
+ exp(): Interval;
35
+ log(): Interval;
36
+ /** Integer power (handles even powers of intervals straddling zero). Exact when `n === 0` (every interval to the 0th power is the exact point 1). */
37
+ pow(n: number): Interval;
38
+ private extrema;
39
+ sin(): Interval;
40
+ cos(): Interval;
41
+ equals(o: Interval): boolean;
42
+ toString(): string;
43
+ }
44
+ //# sourceMappingURL=Interval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Interval.d.ts","sourceRoot":"","sources":["../src/Interval.ts"],"names":[],"mappings":"AAkCA;;;;;;;;GAQG;AACH,qBAAa,QAAQ;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;gBAER,EAAE,EAAE,MAAM,EAAE,EAAE,GAAE,MAAW;IAMvC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ;IAI3C,sCAAsC;IACtC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ;IAIjC,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,QAAQ,IAAI,MAAM,CAErB;IACD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;IAG5B,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO;IAI9B,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ;IAG1B,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ;IAG/B,qEAAqE;IACrE,MAAM,IAAI,QAAQ;IAIlB,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ;IAK/B,MAAM,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ;IAU7B,uEAAuE;IACvE,IAAI,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ;IAI3B,oEAAoE;IACpE,SAAS,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI;IAMvC,GAAG,IAAI,QAAQ;IAMf,IAAI,IAAI,QAAQ;IAIhB,GAAG,IAAI,QAAQ;IAGf,GAAG,IAAI,QAAQ;IAKf,qJAAqJ;IACrJ,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ;IASxB,OAAO,CAAC,OAAO;IASf,GAAG,IAAI,QAAQ;IAIf,GAAG,IAAI,QAAQ;IAKf,MAAM,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO;IAI5B,QAAQ,IAAI,MAAM;CAGnB"}
@@ -0,0 +1,165 @@
1
+ const F64 = new Float64Array(1);
2
+ const U64 = new BigUint64Array(F64.buffer);
3
+ /** The next representable double strictly greater than `value` (IEEE-754 nextafter toward +Infinity) -- JS has no built-in `Math.nextafter`, so this steps the raw 64-bit pattern by one ULP via a shared scratch buffer. */
4
+ function nextUp(value) {
5
+ if (Number.isNaN(value) || value === Infinity)
6
+ return value;
7
+ if (value === 0)
8
+ return Number.MIN_VALUE;
9
+ F64[0] = value;
10
+ U64[0] = U64[0] + (value > 0 ? 1n : -1n);
11
+ return F64[0];
12
+ }
13
+ /** The next representable double strictly less than `value` -- `-nextUp(-value)`, since stepping toward -Infinity from `x` is the mirror of stepping toward +Infinity from `-x`. */
14
+ function nextDown(value) {
15
+ return -nextUp(-value);
16
+ }
17
+ /**
18
+ * Widens `x` by one ULP on each side -- the outward-rounding every non-exact
19
+ * `Interval` operation below applies to its result. `Math.*` computes to
20
+ * the *nearest* representable double (`Math.sqrt` is correctly rounded to
21
+ * 0.5 ULP per IEEE-754; the other transcendentals/arithmetic are within
22
+ * ~1 ULP on every mainstream engine), which breaks the containment
23
+ * guarantee interval arithmetic exists to provide: `Interval.point(2).sqrt()`
24
+ * would otherwise return a degenerate `[s, s]` that provably does NOT
25
+ * contain the irrational `sqrt(2)`. One ULP of outward slack restores
26
+ * rigor, at the cost of a deliberately loose bound when a result happens
27
+ * to be exactly representable (e.g. `sqrt(4)` reports a width-2-ULP
28
+ * interval around 2 instead of the point `[2, 2]`).
29
+ */
30
+ function outward(x) {
31
+ return new Interval(nextDown(x.lo), nextUp(x.hi));
32
+ }
33
+ /**
34
+ * Interval — rigorous interval arithmetic `[lo, hi]`. Operations return an
35
+ * interval guaranteed to contain every result of the corresponding operation on
36
+ * any pair of members, so a final interval bounds the true answer despite
37
+ * rounding — useful for reliable numerics and error tracking. Every
38
+ * operation that isn't provably exact (`negate`/`abs`/`hull`/`intersect`
39
+ * only move or compare existing endpoints) outward-rounds its result by
40
+ * one ULP per side via `outward()` above.
41
+ */
42
+ export class Interval {
43
+ lo;
44
+ hi;
45
+ constructor(lo, hi = lo) {
46
+ if (lo > hi)
47
+ throw new Error(`Invalid interval: [${lo}, ${hi}]`);
48
+ this.lo = lo;
49
+ this.hi = hi;
50
+ }
51
+ static of(lo, hi) {
52
+ return new Interval(lo, hi);
53
+ }
54
+ /** A degenerate interval `[x, x]`. */
55
+ static point(x) {
56
+ return new Interval(x, x);
57
+ }
58
+ get width() {
59
+ return this.hi - this.lo;
60
+ }
61
+ get midpoint() {
62
+ return (this.lo + this.hi) / 2;
63
+ }
64
+ get radius() {
65
+ return this.width / 2;
66
+ }
67
+ contains(x) {
68
+ return this.lo <= x && x <= this.hi;
69
+ }
70
+ overlaps(o) {
71
+ return this.lo <= o.hi && o.lo <= this.hi;
72
+ }
73
+ add(o) {
74
+ return outward(new Interval(this.lo + o.lo, this.hi + o.hi));
75
+ }
76
+ subtract(o) {
77
+ return outward(new Interval(this.lo - o.hi, this.hi - o.lo));
78
+ }
79
+ /** Exact: IEEE-754 negation only flips the sign bit, no rounding. */
80
+ negate() {
81
+ return new Interval(-this.hi, -this.lo);
82
+ }
83
+ multiply(o) {
84
+ const p = [this.lo * o.lo, this.lo * o.hi, this.hi * o.lo, this.hi * o.hi];
85
+ return outward(new Interval(Math.min(...p), Math.max(...p)));
86
+ }
87
+ divide(o) {
88
+ if (o.contains(0))
89
+ throw new Error("Interval division by an interval containing zero.");
90
+ // The reciprocal bounds are themselves a rounded operation -- outward
91
+ // it before feeding into `multiply` (which outward-rounds its own
92
+ // result too), so neither step's rounding can silently eat the other's
93
+ // slack.
94
+ const reciprocal = outward(new Interval(1 / o.hi, 1 / o.lo));
95
+ return this.multiply(reciprocal);
96
+ }
97
+ /** The tightest interval containing both (the convex hull / union). */
98
+ hull(o) {
99
+ return new Interval(Math.min(this.lo, o.lo), Math.max(this.hi, o.hi));
100
+ }
101
+ /** The overlap of two intervals, or `null` if they are disjoint. */
102
+ intersect(o) {
103
+ const lo = Math.max(this.lo, o.lo);
104
+ const hi = Math.min(this.hi, o.hi);
105
+ return lo <= hi ? new Interval(lo, hi) : null;
106
+ }
107
+ abs() {
108
+ if (this.lo >= 0)
109
+ return this;
110
+ if (this.hi <= 0)
111
+ return this.negate();
112
+ return new Interval(0, Math.max(-this.lo, this.hi));
113
+ }
114
+ sqrt() {
115
+ if (this.lo < 0)
116
+ throw new Error("sqrt of an interval with negative values.");
117
+ return outward(new Interval(Math.sqrt(this.lo), Math.sqrt(this.hi)));
118
+ }
119
+ exp() {
120
+ return outward(new Interval(Math.exp(this.lo), Math.exp(this.hi)));
121
+ }
122
+ log() {
123
+ if (this.lo <= 0)
124
+ throw new Error("log of an interval with non-positive values.");
125
+ return outward(new Interval(Math.log(this.lo), Math.log(this.hi)));
126
+ }
127
+ /** Integer power (handles even powers of intervals straddling zero). Exact when `n === 0` (every interval to the 0th power is the exact point 1). */
128
+ pow(n) {
129
+ if (!Number.isInteger(n) || n < 0)
130
+ throw new Error("Interval.pow requires a non-negative integer.");
131
+ if (n === 0)
132
+ return Interval.point(1);
133
+ const a = this.lo ** n;
134
+ const b = this.hi ** n;
135
+ if (n % 2 === 0 && this.contains(0))
136
+ return outward(new Interval(0, Math.max(a, b)));
137
+ return outward(new Interval(Math.min(a, b), Math.max(a, b)));
138
+ }
139
+ extrema(f, criticalPeriodStart, period) {
140
+ const candidates = [f(this.lo), f(this.hi)];
141
+ // include critical points of the form `criticalPeriodStart + k·period` in range
142
+ const kStart = Math.ceil((this.lo - criticalPeriodStart) / period);
143
+ const kEnd = Math.floor((this.hi - criticalPeriodStart) / period);
144
+ for (let k = kStart; k <= kEnd; k++)
145
+ candidates.push(f(criticalPeriodStart + k * period));
146
+ return outward(new Interval(Math.min(...candidates), Math.max(...candidates)));
147
+ }
148
+ sin() {
149
+ if (this.width >= 2 * Math.PI)
150
+ return new Interval(-1, 1);
151
+ return this.extrema(Math.sin, Math.PI / 2, Math.PI);
152
+ }
153
+ cos() {
154
+ if (this.width >= 2 * Math.PI)
155
+ return new Interval(-1, 1);
156
+ return this.extrema(Math.cos, 0, Math.PI);
157
+ }
158
+ equals(o) {
159
+ return this.lo === o.lo && this.hi === o.hi;
160
+ }
161
+ toString() {
162
+ return `[${this.lo}, ${this.hi}]`;
163
+ }
164
+ }
165
+ //# sourceMappingURL=Interval.js.map