metanum 1.3.0 → 2.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.
package/test_mixed.js CHANGED
@@ -1,759 +1,1433 @@
1
- if (!this.MetaNum) MetaNum = require("metanum.js");
2
-
3
- function check(name, input, expectedArray) {
4
- try {
5
- var m = MetaNum(input);
6
- var arrStr = JSON.stringify(m.array);
7
- var expStr = JSON.stringify(expectedArray);
8
- var pass = arrStr === expStr;
9
- console.log((pass ? "PASS" : "FAIL") + " | " + name + " | " + input);
10
- if (!pass) {
11
- console.log(" Got: " + arrStr);
12
- console.log(" Expected: " + expStr);
13
- }
14
- } catch (e) {
15
- console.log("ERROR | " + name + " | " + input + " => " + e.message);
16
- }
17
- }
18
-
19
- function checkRT(name, input) {
20
- try {
21
- var m = MetaNum(input);
22
- var s = m.toString();
23
- var m2 = MetaNum(s);
24
- var pass = m.eq(m2);
25
- console.log((pass ? "PASS" : "FAIL") + " | RT " + name + " | " + input + " => " + s + " => " + m2.toString());
26
- if (!pass) console.log(" Got: " + m2.toString());
27
- } catch (e) {
28
- console.log("ERROR | RT " + name + " | " + input + " => " + e.message);
29
- }
30
- }
31
-
32
- console.log("\n=== 1-letter regression ===");
33
- checkRT("E308", "E308");
34
- checkRT("EE100", "EE100");
35
- checkRT("FE10", "E^9999999998 10000000000");
36
- checkRT("G10", "F^8 E^8 10000000000");
37
- checkRT("J1000", "I^998 H^8 G^8 F^8 E^8 10000000000");
38
- checkRT("Z10", "Y^8 X^8 W^8 V^8 U^8 T^8 S^8 R^8 Q^8 P^8 O^8 N^8 M^8 L^8 K^8 J^8 I^8 H^8 G^8 F^8 E^8 10000000000");
39
-
40
- console.log("\n=== 2-letter regression ===");
41
- checkRT("Aa10", "Aa10");
42
- checkRT("Ab5", "Ab5");
43
- checkRT("Ac100", "Ac100");
44
- checkRT("AaAa10", "AaAa10");
45
- checkRT("AbAb10", "AbAb10");
46
- checkRT("Ba10", "Ba10");
47
- checkRT("BaBa10", "BaBa10");
48
- checkRT("Bb10", "Bb10");
49
- checkRT("Bc10", "Bc10");
50
- checkRT("Bz10", "Bz10");
51
- checkRT("Ca10", "Ca10");
52
- checkRT("Zz10", "Zz10");
53
-
54
- console.log("\n=== 3-letter regression ===");
55
- checkRT("Aaa10", "Aaa10");
56
- checkRT("Aaa1000", "Aaa1000");
57
- checkRT("AaaAaa10", "AaaAaa10");
58
- checkRT("Aab10", "Aab10");
59
- checkRT("Aac10", "Aac10");
60
- checkRT("Aba10", "Aba10");
61
- checkRT("Abb10", "Abb10");
62
- checkRT("Aza10", "Aza10");
63
- checkRT("Baa10", "Baa10");
64
- checkRT("Zzz10", "Zzz10");
65
-
66
- console.log("\n=== 4-letter regression ===");
67
- checkRT("Aaaa10", "Aaaa10");
68
- checkRT("Aaaa1000", "Aaaa1000");
69
- checkRT("AaaaAaaa10", "AaaaAaaa10");
70
- checkRT("Aaab10", "Aaab10");
71
- checkRT("Aaba10", "Aaba10");
72
- checkRT("Abaa10", "Abaa10");
73
- checkRT("Baaa10", "Baaa10");
74
- checkRT("Zzzz10", "Zzzz10");
75
-
76
- console.log("\n=== symbol+letters regression ===");
77
- checkRT("!Aa10", "!Aa10"); //layer=1
78
- checkRT("!Abcd10", "!Abcd10"); //layer=1
79
- checkRT("@Ef10", "@Ef10"); //layer=2
80
- checkRT("#Gh100", "#Gh100"); //layer=3
81
- checkRT("1ε100", "1ε100"); //layer=100
82
- checkRT("1ε9007199254740991", "1ε9007199254740991"); //layer=MSI
83
-
84
- console.log("\n=== mixed token tests ===");
85
- check("BbBbAaGGGFFE100 array", "BbBbAaGGGFFE100", [[100, 1, 2, 3], [1,0,1],[2,1,2]]);
86
- check("QqQe308 array", "QqQe308", [[308], [1, 4, 17], [1, 16, 17]]);
87
- checkRT("BbBbAaGGGFFE100", "BbBbAaGGGFFE100");
88
- checkRT("QqQe308", "QqQe308");
89
-
90
- // ─────────────────────────────────────
91
- // hyperoperations test
92
- // ─────────────────────────────────────
93
-
94
- function checkOp(label, result, expectedVal, tol) {
95
- if (tol === undefined) tol = 0.01;
96
- try {
97
- var rn = result.toNumber ? result.toNumber() : result;
98
- if (Number.isNaN(rn) && Number.isNaN(expectedVal)) {
99
- console.log("PASS | " + label + " | NaN (expected)");
100
- return;
101
- }
102
- if (Number.isFinite(rn) && Number.isFinite(expectedVal)) {
103
- var ok = Math.abs(rn - expectedVal) <= tol;
104
- console.log((ok ? "PASS" : "FAIL") + " | " + label + " | got=" + (result.toString ? result.toString().slice(0,100) : result) + " expected=" + expectedVal);
105
- return;
106
- }
107
- console.log("PASS | " + label + " | " + (result.toString ? result.toString().slice(0,100) : result));
108
- } catch (e) {
109
- console.log("ERROR | " + label + " => " + e.message);
110
- }
111
- }
112
-
113
- function checkBool(label, result, expected) {
114
- try {
115
- var pass = result === expected;
116
- console.log((pass ? "PASS" : "FAIL") + " | " + label + " | got=" + result + " expected=" + expected);
117
- } catch (e) {
118
- console.log("ERROR | " + label + " => " + e.message);
119
- }
120
- }
121
-
122
- // ─────────────────────────────────────
123
- // big number (> MSI) vs small number (< MSI) all operations test
124
- // ─────────────────────────────────────
125
- var m0 = MetaNum(0);
126
- var m1 = MetaNum(1);
127
- var m2 = MetaNum(2);
128
- var m3 = MetaNum(3);
129
- var m4 = MetaNum(4);
130
- var mT = MetaNum.arrow(3,3,3);
131
- var MSI = 9007199254740991;
132
- var mSmall = MetaNum(1e6); // 1,000,000 < MSI
133
- var mSmall2 = MetaNum(1e9); // 1,000,000,000 < MSI
134
- var mBig = MetaNum(1e16); // 10,000,000,000,000,000 > MSI
135
- var mBig2 = MetaNum(1e20); // > MSI
136
-
137
-
138
- console.log("\n=== basic arithmetic (< MSI vs > MSI) ===");
139
- checkOp("add small", mSmall.add(5), 1000005, 0);
140
- checkBool("add big", mBig.add(5).toString() === "E16", true);
141
- checkOp("sub small", mSmall.sub(5), 999995, 0);
142
- checkBool("sub big", mBig.sub(5).toString() === "E16", true);
143
- checkOp("mul small", mSmall.mul(2), 2000000, 0);
144
- checkBool("mul big", mBig.mul(2).toString() === "E16.30103", true);
145
- checkOp("div small", mSmall.div(2), 500000, 0);
146
- checkBool("div big", mBig.div(2).toString() === "4999999999999999", true);
147
-
148
- console.log("\n=== power operations (< MSI vs > MSI) ===");
149
- checkOp("pow small", MetaNum(2).pow(10), 1024, 0);
150
- checkOp("pow big", MetaNum(2).pow(60), 1.15292150461e18, 0.01);
151
- checkOp("exp small", MetaNum(2).exp(), 7.38905609893065, 1e-8);
152
- checkOp("exp big", MetaNum(40).exp(), 2.35385266837e17, 0.01);
153
-
154
- console.log("\n=== roots (< MSI vs > MSI) ===");
155
- checkOp("sqrt small", MetaNum(1e6).sqrt(), 1000, 0);
156
- checkOp("sqrt big", mBig.sqrt(), 100000000, 0);
157
- checkOp("cbrt small", MetaNum(1e9).cbrt(), 1000, 0.01);
158
- checkOp("cbrt big", mBig.cbrt(), 215443.469, 0.01);
159
- checkOp("root small", MetaNum(1e9).root(3), 1000, 0.01);
160
- checkOp("root big 4th", mBig.root(4), 10000, 0);
161
- checkOp("root big 10th", mBig2.root(10), 100, 0);
162
-
163
- console.log("\n=== logarithms (< MSI vs > MSI) ===");
164
- checkOp("log10 small", mSmall.log10(), 6, 0);
165
- checkOp("log10 big 1e20", mBig2.log10(), 20, 0);
166
- checkOp("log10 big 1e16", mBig.log10(), 16, 0);
167
- checkOp("log small", mSmall.log(100), 3, 0.01);
168
- checkOp("log big", mBig.log(100), 8, 0.01);
169
- checkOp("ln small", mSmall.ln(), Math.log(1e6), 1e-6);
170
- checkOp("ln big", mBig.ln(), Math.log(1e16), 1e-6);
171
-
172
- console.log("\n=== factorial, gamma and Lambert W (< MSI vs > MSI) ===");
173
- checkOp("fact small", MetaNum(5).fact(), 120, 0);
174
- checkOp("fact big", MetaNum(20).fact(), 2.43290200817664e18, 0.01);
175
- checkOp("gamma small", MetaNum(0.5).gamma(), Math.sqrt(Math.PI), 1e-6);
176
- checkOp("gamma big", MetaNum(20).gamma(), 1.21645100408832e17, 0.01);
177
- checkOp("lambertw small", MetaNum(1).lambertw(), 0.5671432904097838, 1e-6);
178
- checkOp("lambertw big", MetaNum(1e16).lambertw(), 33.334760768448184, 1e-6);
179
-
180
- console.log("\n=== rounding and modulus (< MSI vs > MSI) ===");
181
- checkOp("floor small", MetaNum(3.7).floor(), 3, 0);
182
- checkBool("floor big", MetaNum(1e16 + 0.5).floor().toString() === "E16", true);
183
- checkOp("ceil small", MetaNum(3.2).ceil(), 4, 0);
184
- checkBool("ceil big", MetaNum(1e16 + 0.5).ceil().toString() === "E16", true);
185
- checkOp("round small", MetaNum(3.5).round(), 4, 0);
186
- checkBool("round big", MetaNum(1e16 + 0.5).round().toString() === "E16", true);
187
- checkOp("mod small", MetaNum(10).mod(3), 1, 0);
188
- checkOp("mod big", MetaNum(1e16).mod(3), 1, 0);
189
-
190
- console.log("\n=== other unary operations (< MSI vs > MSI) ===");
191
- checkOp("abs small", MetaNum(-5).abs(), 5, 0);
192
- checkBool("abs big", MetaNum(-1e16).abs().toString() === "E16", true);
193
- checkOp("neg small", MetaNum(5).neg(), -5, 0);
194
- checkBool("neg big", MetaNum(1e16).neg().toString() === "-E16", true);
195
- checkOp("rec small", MetaNum(4).rec(), 0.25, 0);
196
- checkOp("rec big", MetaNum(1e16).rec(), 1e-16, 1e-20);
197
-
198
- console.log("\n=== hyperoperation base (< MSI vs > MSI) ===");
199
- checkOp("tetr small", MetaNum(2).tetr(3), 16, 0);
200
- checkBool("tetr big", MetaNum(1e16).tetr(3).toString() === "EEE17.20412", true);
201
- checkOp("pent small", MetaNum(2).pent(2), 4, 0);
202
- checkBool("pent big", MetaNum(1e16).pent(3).toString() === "FFE16", true);
203
- checkOp("arrow small", MetaNum(2).arrow(2)(3), 16, 0);
204
- checkBool("arrow big", MetaNum(1e16).arrow(3)(4).toString() === "FFFE16", true);
205
- checkBool("chain small", MetaNum(2).chain(4, 3).toString() === "E^65532 19727.7804056", true);
206
- checkBool("chain big", MetaNum(1e16).chain(4, 3).toString() === "FFFE16", true);
207
- checkOp("ssrt small", MetaNum(27).ssrt(), 3, 0.01);
208
- checkOp("ssrt big", MetaNum(1e16).ssrt(), 13.97, 0.01);
209
- checkOp("slog small", MetaNum(16).slog(2), 3, 0.01);
210
- checkOp("slog big", MetaNum(1e16).slog(2), 4.41, 0.01);
211
- checkOp("linear_sroot small", MetaNum(100).linear_sroot(3), 2.2128, 0.01);
212
- checkOp("linear_sroot big", MetaNum(1e16).linear_sroot(3), 3.09, 0.01);
213
- checkOp("layeradd small", MetaNum(10).layeradd(), 1e10, 0.01);
214
- checkBool("layeradd big", MetaNum(1e16).layeradd().toString() === "EE16", true);
215
- checkOp("layeradd10 small", MetaNum(10).layeradd10(), 1e10, 0.01);
216
- checkBool("layeradd10 big", MetaNum(1e16).layeradd10().toString() === "EE16", true);
217
-
218
- // ─────────────────────────────────────
219
- // (pentate_log/root)
220
- // ─────────────────────────────────────
221
- console.log("\n=== pentate_log/root ===");
222
-
223
- // pentate_log: if pentate(a,b)=c then pentate_log(c,a)=b
224
- checkOp("pent_log semantic 2^3", MetaNum.pentate(2,3).pentate_log(2), 3, 0.1);
225
- checkOp("pent_log semantic 3^2", MetaNum.pentate(3,2).pentate_log(3), 2, 0.1);
226
-
227
- // pentate_root: if pentate(a,b)=c then pentate_root(c,b)≈a
228
- checkOp("pent_root semantic b=2", MetaNum.pentate_root(MetaNum.pentate(3,2), 2), 3, 0.1);
229
- checkOp("pent_root semantic b=3", MetaNum.pentate_root(MetaNum.pentate(2,3), 3), 2, 0.1);
230
-
231
- //hyperoperation definition from https://googology.fandom.com/wiki/Template:ExtendedOps
232
-
233
- // ─── 1. aperiote (ω): x{y}x = arrow(x,y,x), arrow(y)(a,a)=a↑^y a ───
234
- // arrow(0): multiplication → 2*2=4, 3*3=9
235
- // arrow(1): exponentiation → 2^2=4, 3^3=27
236
- // arrow(2): tetration → 2↑↑2=4, 3↑↑3=3^27=7625597484987
237
- console.log("\n=== 1. aperiote (ω) ===");
238
- checkOp("aper(3,0)", m3.aperiote(0), 9, 0);
239
- checkOp("aper(3,1)", m3.aperiote(1), 27, 0);
240
- checkOp("aper(3,2)", m3.aperiote(2), 7625597484987, 0);
241
- checkOp("aper(3,4)", m3.aperiote(4)); //3↑↑↑↑3
242
- checkOp("aper(4,3)", m4.aperiote(3)); //4↑↑↑4
243
- checkBool("aper NaN", MetaNum.aperiote(m3, MetaNum.NaN).isNaN(), true);
244
- checkBool("aper inv NaN", MetaNum.inv_aperiote(m3, MetaNum.NaN).isNaN(), true);
245
-
246
- // ─── 2. expande (ω+1): x{{1}}y ───
247
- // expande: iterated aperiote, x{{1}}y=x{x{...}x}x where there are y x's from the center out
248
- // e.g. 3{{1}}2=3{3}3=3↑↑↑3
249
- console.log("\n=== 2. expande (ω+1) ===");
250
- checkOp("expa(3,1)", m3.expande(1), 3, 0);
251
- checkOp("expa(3,2)", m3.expande(2)); //3↑↑↑3
252
- checkOp("expa(3,4)", m3.expande(4)); //3{3{3{3}3}3}3
253
- checkOp("expa(4,3)", m4.expande(3)); //4{4{4}4}4
254
- checkBool("expa y=0 NaN", m3.expande(0).isNaN(), true);
255
- checkBool("expa NaN", MetaNum.expande(m3, MetaNum.NaN).isNaN(), true);
256
-
257
- // ─── 3. multiexpande (ω+2): x{{2}}y ───
258
- // multiexpande: iterated expande, x{{2}}y=x{{1}}x{{1}}... with y x's
259
- // e.g. 3{{2}}2=3{{1}}3=3{3{3}3}3=3↑…(3↑↑↑3 arrows)…↑3
260
- console.log("\n=== 3. multiexpande (ω+2) ===");
261
- checkOp("muea(3,4)", m3.multiexpande(4));
262
- checkOp("muea(4,3)", m4.multiexpande(3));
263
- checkBool("muea y=0 NaN", m3.multiexpande(0).isNaN(), true);
264
- checkBool("muea NaN", MetaNum.multiexpande(m3, MetaNum.NaN).isNaN(), true);
265
-
266
- // ─── 4. powerexpande (ω+3): x{{3}}y ───
267
- // powerexpande: iterated multiexpande, x{{3}}y=x{{2}}x{{2}}... with y x's
268
- // e.g. 3{{3}}2=3{{2}}3=3{{1}}3{{1}}3
269
- console.log("\n=== 4. powerexpande (ω+3) ===");
270
- checkOp("poea(3,4)", m3.powerexpande(4));
271
- checkOp("poea(4,3)", m4.powerexpande(3));
272
- checkBool("poea y=0 NaN", m3.powerexpande(0).isNaN(), true);
273
- checkBool("poea NaN", MetaNum.powerexpande(m3, MetaNum.NaN).isNaN(), true);
274
-
275
- // ─── 5. aperioexpande (ω*2): x{{y}}x ───
276
- // aperioexpande: diagonalization of ω+y, x{{y}}x
277
- // e.g. 3{{10}}3=3{{9}}3{{9}}3
278
- console.log("\n=== 5. aperioexpande (ω*2) ===");
279
- checkOp("apea(3,4)", m3.aperioexpande(4));
280
- checkOp("apea(4,3)", m4.aperioexpande(3));
281
- checkBool("apea NaN", MetaNum.aperioexpande(m3, MetaNum.NaN).isNaN(), true);
282
-
283
- // ─── 6. explode (ω*2+1): x{{{1}}}y ───
284
- console.log("\n=== 6. explode (ω*2+1) ===");
285
- checkOp("expl(3,4)", m3.explode(4));
286
- checkOp("expl(4,3)", m4.explode(3));
287
- checkBool("expl y=0 NaN", m3.explode(0).isNaN(), true);
288
- checkBool("expl NaN", MetaNum.explode(m3, MetaNum.NaN).isNaN(), true);
289
-
290
- // ─── 7. multiexplode (ω*2+2): x{{{2}}}y ───
291
- console.log("\n=== 7. multiexplode (ω*2+2) ===");
292
- checkOp("muel(3,4)", m3.multiexplode(4));
293
- checkOp("muel(4,3)", m4.multiexplode(3));
294
- checkBool("muel y=0 NaN", m3.multiexplode(0).isNaN(), true);
295
- checkBool("muel NaN", MetaNum.multiexplode(m3, MetaNum.NaN).isNaN(), true);
296
-
297
- // ─── 8. aperioexplode (ω*3): x{{{y}}}x ───
298
- console.log("\n=== 8. aperioexplode (ω*3) ===");
299
- checkOp("apel(3,4)", m3.aperioexplode(4));
300
- checkOp("apel(4,3)", m4.aperioexplode(3));
301
- checkBool("apel NaN", MetaNum.aperioexplode(m3, MetaNum.NaN).isNaN(), true);
302
-
303
- // ─── 9. detonate (ω*3+1): x{{{{1}}}}y ───
304
- console.log("\n=== 9. detonate (ω*3+1) ===");
305
- checkOp("deto(3,4)", m3.detonate(4));
306
- checkOp("deto(4,3)", m4.detonate(3));
307
- checkBool("deto y=0 NaN", m3.detonate(0).isNaN(), true);
308
- checkBool("deto NaN", MetaNum.detonate(m3, MetaNum.NaN).isNaN(), true);
309
-
310
- // ─── 10. aperiodetonate (ω*4): x{{{{y}}}}x ───
311
- console.log("\n=== 10. aperiodetonate (ω*4) ===");
312
- checkOp("apdt(3,4)", m3.aperiodetonate(4));
313
- checkOp("apdt(4,3)", m4.aperiodetonate(3));
314
- checkBool("apdt NaN", MetaNum.aperiodetonate(m3, MetaNum.NaN).isNaN(), true);
315
-
316
- // ─── 11. aperionate (ω^2): diagonalization of ω*y ───
317
- console.log("\n=== 11. aperionate (ω^2) ===");
318
- checkOp("apeo(3,4)", m3.aperionate(4));
319
- checkOp("apeo(4,3)", m4.aperionate(3));
320
- checkBool("apeo NaN", MetaNum.aperionate(m3, MetaNum.NaN).isNaN(), true);
321
-
322
- // ─── 12. megote (ω^2+1): 迭代 ω^2 ───
323
- console.log("\n=== 12. megote (ω^2+1) ===");
324
- checkOp("mego(3,4)", m3.megote(4));
325
- checkOp("mego(4,3)", m4.megote(3));
326
- checkBool("mego y=0 NaN", m3.megote(0).isNaN(), true);
327
- checkBool("mego NaN", MetaNum.megote(m3, MetaNum.NaN).isNaN(), true);
328
-
329
- // ─── 13. multimegote (ω^2+2): 迭代 ω^2+1 ───
330
- console.log("\n=== 13. multimegote (ω^2+2) ===");
331
- checkOp("mume(3,4)", m3.multimegote(4));
332
- checkOp("mume(4,3)", m4.multimegote(3));
333
- checkBool("mume y=0 NaN", m3.multimegote(0).isNaN(), true);
334
- checkBool("mume NaN", MetaNum.multimegote(m3, MetaNum.NaN).isNaN(), true);
335
-
336
- // ─── 14. aperimegote (ω^2+ω): 对角化 ω^2+y ───
337
- console.log("\n=== 14. aperimegote (ω^2+ω) ===");
338
- checkOp("apmg(3,4)", m3.aperimegote(4));
339
- checkOp("apmg(4,3)", m4.aperimegote(3));
340
- checkBool("apmg NaN", MetaNum.aperimegote(m3, MetaNum.NaN).isNaN(), true);
341
-
342
- // ─── 15. megoexpande (ω^2+ω+1): 迭代 ω^2+ω ───
343
- console.log("\n=== 15. megoexpande (ω^2+ω+1) ===");
344
- checkOp("mgea(3,4)", m3.megoexpande(4));
345
- checkOp("mgea(4,3)", m4.megoexpande(3));
346
- checkBool("mgea y=0 NaN", m3.megoexpande(0).isNaN(), true);
347
- checkBool("mgea NaN", MetaNum.megoexpande(m3, MetaNum.NaN).isNaN(), true);
348
-
349
- // ─── 16. aperimegoexpande (ω^2+ω*2): 对角化 ω^2+ω+y ───
350
- console.log("\n=== 16. aperimegoexpande (ω^2+ω*2) ===");
351
- checkOp("apme(3,4)", m3.aperimegoexpande(4));
352
- checkOp("apme(4,3)", m4.aperimegoexpande(3));
353
- checkBool("apme NaN", MetaNum.aperimegoexpande(m3, MetaNum.NaN).isNaN(), true);
354
-
355
- // ─── 17. megoaperionate (ω^2*2): 对角化 ω^2+ω*y ───
356
- console.log("\n=== 17. megoaperionate (ω^2*2) ===");
357
- checkOp("mgao(3,4)", m3.megoaperionate(4));
358
- checkOp("mgao(4,3)", m4.megoaperionate(3));
359
- checkBool("mgao NaN", MetaNum.megoaperionate(m3, MetaNum.NaN).isNaN(), true);
360
-
361
- // ─── 18. gigote (ω^2*2+1): 迭代 ω^2*2 ───
362
- console.log("\n=== 18. gigote (ω^2*2+1) ===");
363
- checkOp("gigo(3,4)", m3.gigote(4));
364
- checkOp("gigo(4,3)", m4.gigote(3));
365
- checkBool("gigo y=0 NaN", m3.gigote(0).isNaN(), true);
366
- checkBool("gigo NaN", MetaNum.gigote(m3, MetaNum.NaN).isNaN(), true);
367
-
368
- // ─── 19. aperigigote (ω^2*2+ω): 对角化 ω^2*2+y ───
369
- console.log("\n=== 19. aperigigote (ω^2*2+ω) ===");
370
- checkOp("apgg(3,4)", m3.aperigigote(4));
371
- checkOp("apgg(4,3)", m4.aperigigote(3));
372
- checkBool("apgg NaN", MetaNum.aperigigote(m3, MetaNum.NaN).isNaN(), true);
373
-
374
- // ─── 20. gigoaperionate (ω^2*3): 对角化 ω^2*2+ω*y ───
375
- console.log("\n=== 20. gigoaperionate (ω^2*3) ===");
376
- checkOp("ggap(3,4)", m3.gigoaperionate(4));
377
- checkOp("ggap(4,3)", m4.gigoaperionate(3));
378
- checkBool("ggap y=0 NaN", m3.gigoaperionate(0).isNaN(), true);
379
- checkBool("ggap NaN", MetaNum.gigoaperionate(m3, MetaNum.NaN).isNaN(), true);
380
-
381
- // ─── 21. aperiatote (ω^3): 对角化 ω^2*y ───
382
- console.log("\n=== 21. aperiatote (ω^3) ===");
383
- checkOp("apat(3,4)", m3.aperiatote(4));
384
- checkOp("apat(4,3)", m4.aperiatote(3));
385
- checkBool("apat NaN", MetaNum.aperiatote(m3, MetaNum.NaN).isNaN(), true);
386
-
387
- // ─── 22. powiainate (ω^3+1): 迭代 ω^3 ───
388
- console.log("\n=== 22. powiainate (ω^3+1) ===");
389
- checkOp("pwan(3,4)", m3.powiainate(4));
390
- checkOp("pwan(4,3)", m4.powiainate(3));
391
- checkBool("pwan y=0 NaN", m3.powiainate(0).isNaN(), true);
392
- checkBool("pwan NaN", MetaNum.powiainate(m3, MetaNum.NaN).isNaN(), true);
393
-
394
- // ─── 23. expandainate (ω^3+ω): ω级别迭代 powiainate ───
395
- console.log("\n=== 23. expandainate (ω^3+ω) ===");
396
- checkOp("epan(3,4)", m3.expandainate(4));
397
- checkOp("epan(4,3)", m4.expandainate(3));
398
- checkBool("epan NaN", MetaNum.expandainate(m3, MetaNum.NaN).isNaN(), true);
399
-
400
- // ─── 24. megodainate (ω^3+ω^2): 迭代 ω^3+ω ───
401
- console.log("\n=== 24. megodainate (ω^3+ω^2) ===");
402
- checkOp("mgan(3,4)", m3.megodainate(4));
403
- checkOp("mgan(4,3)", m4.megodainate(3));
404
- checkBool("mgan y=0 NaN", m3.megodainate(0).isNaN(), true);
405
- checkBool("mgan NaN", MetaNum.megodainate(m3, MetaNum.NaN).isNaN(), true);
406
-
407
- // ─── 25. powiairate (ω^3*2) ───
408
- console.log("\n=== 25. powiairate (ω^3*2) ===");
409
- checkOp("pwar(3,4)", m3.powiairate(4));
410
- checkOp("pwar(4,3)", m4.powiairate(0).isNaN(), true);
411
- checkBool("pwar NaN", MetaNum.powiairate(m3, MetaNum.NaN).isNaN(), true);
412
-
413
- // ─── 26. aperioguate (ω^4): 对角化 ω^3*y ───
414
- console.log("\n=== 26. aperioguate (ω^4) ===");
415
- checkOp("apgu(3,4)", m3.aperioguate(4));
416
- checkOp("apgu(4,3)", m4.aperioguate(3));
417
- checkBool("apgu NaN", MetaNum.aperioguate(m3, MetaNum.NaN).isNaN(), true);
418
-
419
- // ─── 27. iter (ω^ω): 对角化 ω^x ───
420
- console.log("\n=== 27. iter (ω^ω) ===");
421
- checkOp("ite(3,4)", m3.iter(4));
422
- checkOp("ite(4,3)", m4.iter(3));
423
- checkBool("ite y=0 NaN", m3.iter(0).isNaN(), true);
424
- checkBool("ite NaN", MetaNum.iter(m3, MetaNum.NaN).isNaN(), true);
425
-
426
- // ─── 28. itermult (ω^ω+1): 迭代 ω^ω ───
427
- console.log("\n=== 28. itermult (ω^ω+1) ===");
428
- checkOp("itmu(3,4)", m3.itermult(4));
429
- checkOp("itmu(4,3)", m4.itermult(3));
430
- checkBool("itmu y=0 NaN", m3.itermult(0).isNaN(), true);
431
- checkBool("itmu NaN", MetaNum.itermult(m3, MetaNum.NaN).isNaN(), true);
432
-
433
- // ─── 29. cuboiter (ω^ω*2) ───
434
- console.log("\n=== 29. cuboiter (ω^ω*2) ===");
435
- checkOp("cube(3,4)", m3.cuboiter(4));
436
- checkOp("cube(4,3)", m4.cuboiter(3));
437
- checkBool("cube NaN", MetaNum.cuboiter(m3, MetaNum.NaN).isNaN(), true);
438
-
439
- // ─── 30. expoiter (ω^(ω+1)) ───
440
- console.log("\n=== 30. expoiter (ω^(ω+1)) ===");
441
- checkOp("expo(3,4)", m3.expoiter(4));
442
- checkOp("expo(4,3)", m4.expoiter(3));
443
- checkBool("expo NaN", MetaNum.expoiter(m3, MetaNum.NaN).isNaN(), true);
444
-
445
- // ─── 31. trioterate (ω^(ω*2)) ───
446
- console.log("\n=== 31. trioterate (ω^(ω*2)) ===");
447
- checkOp("tria(3,4)", m3.trioterate(4));
448
- checkOp("tria(4,3)", m4.trioterate(3));
449
- checkBool("tria NaN", MetaNum.trioterate(m3, MetaNum.NaN).isNaN(), true);
450
-
451
- // ─── 32. trixxate (ω^(ω^2)) ───
452
- console.log("\n=== 32. trixxate (ω^(ω^2)) ===");
453
- checkOp("trix(3,4)", m3.trixxate(4));
454
- checkOp("trix(4,3)", m4.trixxate(3));
455
- checkBool("trix NaN", MetaNum.trixxate(m3, MetaNum.NaN).isNaN(), true);
456
-
457
- // ─── 33. aperixxate (ω^(ω^ω)) ───
458
- console.log("\n=== 33. aperixxate (ω^(ω^ω)) ===");
459
- checkOp("apix(3,4)", m3.aperixxate(4));
460
- checkOp("apix(4,3)", m4.aperixxate(3));
461
- checkBool("apix NaN", MetaNum.aperixxate(m3, MetaNum.NaN).isNaN(), true);
462
-
463
- // ─── 34. epsilonate (ε₀) ───
464
- console.log("\n=== 34. epsilonate (ε₀) ===");
465
- checkOp("epsl(3,4)", m3.epsilonate(4));
466
- checkOp("epsl(4,3)", m4.epsilonate(3));
467
- checkBool("epsl NaN", MetaNum.epsilonate(m3, MetaNum.NaN).isNaN(), true);
468
-
469
- // Same-value tests: op(x,1) produces reasonable results
470
- var ops = [
471
- "aperiote","expande","multiexpande","powerexpande","aperioexpande",
472
- "explode","multiexplode","aperioexplode","detonate","aperiodetonate",
473
- "aperionate","megote","multimegote","aperimegote","megoexpande",
474
- "aperimegoexpande","megoaperionate","gigote","aperigigote","gigoaperionate",
475
- "aperiatote","powiainate","expandainate","megodainate","powiairate","aperioguate","iteration",
476
- "itermult","cuboiter","expoiter","trioterate","trixxate","aperixxate","epsilonate"
477
- ];
478
-
479
- console.log("\n=== all hyperoperations x=1, y=3 test ===");
480
- for (var oi = 0; oi < ops.length; oi++) {
481
- try {
482
- var res = m1[ops[oi]](3);
483
- if (res.eq(1)) console.log("PASS | " + ops[oi] + "(1,3) | " + res.toString().slice(0,100));
484
- else console.log("FAIL | " + ops[oi] + "(1,3) => " + res.toString().slice(0,100));
485
- } catch (e) {
486
- console.log("ERROR | " + ops[oi] + "(1,3) => " + e.message);
487
- }
488
- }
489
-
490
- console.log("\n=== all hyperoperations x=3, y=1 test ===");
491
- for (var oi = 0; oi < ops.length; oi++) {
492
- try {
493
- var res = m3[ops[oi]](1);
494
- console.log("PASS | " + ops[oi] + "(3,1) | " + res.toString().slice(0,100));
495
- } catch (e) {
496
- console.log("ERROR | " + ops[oi] + "(3,1) => " + e.message);
497
- }
498
- }
499
-
500
- // 逆运算 roundtrip: op(10,x) → inv → 应该 ≈ x
501
- console.log("\n=== inv hyperoperations roundtrip test ===");
502
- var m10 = MetaNum(10);
503
- for (var oi = 0; oi < ops.length; oi++) {
504
- var opname = ops[oi];
505
- try {
506
- var fwd = m10[opname](3);
507
- var invname = "inv_" + opname;
508
- var back = fwd[invname](m10);
509
- if(back.eq(m3)) console.log("PASS | " + invname + " | fwd=" + fwd.toString().slice(0,100) + " back=" + back.toString().slice(0,100));
510
- else console.log("FAIL | " + invname + " | fwd=" + fwd.toString().slice(0,100) + " back=" + back.toString().slice(0,100));
511
- } catch (e) {
512
- console.log("ERROR | inv_" + opname + " => " + e.message);
513
- }
514
- }
515
-
516
- console.log("\n=== hyperoperation (x > MSI) (not fully implemented) ===");
517
- var mBigBase = MetaNum(1e16);
518
- var hyperOps = [
519
- "aperiote","expande","multiexpande","powerexpande","aperioexpande",
520
- "explode","multiexplode","aperioexplode","detonate","aperiodetonate",
521
- "aperionate","megote","multimegote","aperimegote","megoexpande",
522
- "aperimegoexpande","megoaperionation","gigote","aperigigote","gigoaperionate",
523
- "aperiatote","powiainate","expandainate","megodainate","powiairate","aperioguate","iteration",
524
- "itermult","cuboiter","expoiter","trioterate","trixxate","aperixxate","epsilonate"
525
- ];
526
- for (var oi = 0; oi < hyperOps.length; oi++) {
527
- try {
528
- var res = mBigBase[hyperOps[oi]](1);
529
- console.log("PASS | " + hyperOps[oi] + "(1e16,3) | " + res.toString().slice(0,100));
530
- } catch (e) {
531
- console.log("FAIL | " + hyperOps[oi] + "(1e16,3) => " + e.message);
532
- }
533
- }
534
-
535
- console.log("\n=== hyperoperation (y > MSI) ===");
536
- for (var oi = 0; oi < hyperOps.length; oi++) {
537
- try {
538
- var res = mBigBase[hyperOps[oi]](2);
539
- console.log("PASS | " + hyperOps[oi] + "(3,1e16) | " + res.toString().slice(0,100));
540
- } catch (e) {
541
- console.log("FAIL | " + hyperOps[oi] + "(3,1e16) => " + e.message);
542
- }
543
- }
544
-
545
- console.log("\n=== inverse operation (> MSI) roundtrip ===");
546
- var invOps = [
547
- "inv_aperiote","inv_expande","inv_multiexpande","inv_powerexpande","inv_aperioexpande",
548
- "inv_explode","inv_multiexplode","inv_aperioexplode","inv_detonate","inv_aperiodetonate",
549
- "inv_aperionate","inv_megote","inv_multimegote","inv_aperimegote","inv_megoexpande",
550
- "inv_aperimegoexpande","inv_megoaperionate","inv_gigote","inv_aperigigote","inv_gigoaperionate",
551
- "inv_aperiatote","inv_powiainate","inv_expandainate","inv_megodainate","inv_powiairate","inv_aperioguate","inv_iteration",
552
- "inv_itermult","inv_cuboiter","inv_expoiter","inv_trioterate","inv_trixxate","inv_aperixxate","inv_epsilonate"
553
- ];
554
- for (var oi = 0; oi < invOps.length; oi++) {
555
- try {
556
- var fwd = mBigBase[hyperOps[oi]](2);
557
- var back = fwd[invOps[oi]](fwd);
558
- console.log("PASS | " + invOps[oi] + " | fwd=" + fwd.toString().slice(0,100) + " back=" + back.toString().slice(0,100));
559
- } catch (e) {
560
- console.log("FAIL | " + invOps[oi] + " => " + e.message);
561
- }
562
- }
563
-
564
- // ─────────────────────────────────────
565
- // hyperoperation iteration tests (嵌套超运算)
566
- // ─────────────────────────────────────
567
- console.log("\n=== hyperoperation iteration tests (not fully implemented) ===");
568
-
569
- // aperiote (ω): x{y}x nested
570
- checkOp("aper(3,aper(3,0))", m3.aperiote(m3.aperiote(0).toNumber()), m3.aperiote(9));
571
- checkOp("aper(3,aper(3,1))", m3.aperiote(m3.aperiote(1).toNumber()), m3.aperiote(27));
572
- checkOp("aper(3,aper(3,2))", m3.aperiote(m3.aperiote(2)));
573
-
574
- // expande (ω+1): x{{1}}y nested
575
- checkOp("expa(3,expa(3,1))", m3.expande(m3.expande(1)));
576
- checkOp("expa(3,expa(3,2))", m3.expande(m3.expande(2)));
577
- checkOp("expa(4,expa(4,1))", m4.expande(m4.expande(1)));
578
-
579
- // multiexpande (ω+2): x{{2}}y nested
580
- checkOp("muea(3,muea(3,1))", m3.multiexpande(m3.multiexpande(1)));
581
- checkOp("muea(3,muea(3,2))", m3.multiexpande(m3.multiexpande(2)));
582
- checkOp("muea(4,muea(4,1))", m4.multiexpande(m4.multiexpande(1)));
583
-
584
- // powerexpande (ω+3): x{{3}}y nested
585
- checkOp("poea(3,poea(3,1))", m3.powerexpande(m3.powerexpande(1)));
586
- checkOp("poea(3,poea(3,2))", m3.powerexpande(m3.powerexpande(2)));
587
- checkOp("poea(4,poea(4,1))", m4.powerexpande(m4.powerexpande(1)));
588
-
589
- // aperioexpande (ω*2): x{{y}}x nested
590
- checkOp("apea(3,apea(3,1))", m3.aperioexpande(m3.aperioexpande(1)));
591
- checkOp("apea(3,apea(3,2))", m3.aperioexpande(m3.aperioexpande(2)));
592
- checkOp("apea(4,apea(4,1))", m4.aperioexpande(m4.aperioexpande(1)));
593
-
594
- // explode (ω*2+1): x{{{1}}}y nested
595
- checkOp("expl(3,expl(3,1))", m3.explode(m3.explode(1)));
596
- checkOp("expl(3,expl(3,2))", m3.explode(m3.explode(2)));
597
- checkOp("expl(4,expl(4,1))", m4.explode(m4.explode(1)));
598
-
599
- // multiexplode (ω*2+2): x{{{2}}}y nested
600
- checkOp("muel(3,muel(3,1))", m3.multiexplode(m3.multiexplode(1)));
601
- checkOp("muel(3,muel(3,2))", m3.multiexplode(m3.multiexplode(2)));
602
- checkOp("muel(4,muel(4,1))", m4.multiexplode(m4.multiexplode(1)));
603
-
604
- // aperioexplode (ω*3): x{{{y}}}x nested
605
- checkOp("apel(3,apel(3,1))", m3.aperioexplode(m3.aperioexplode(1)));
606
- checkOp("apel(3,apel(3,2))", m3.aperioexplode(m3.aperioexplode(2)));
607
- checkOp("apel(4,apel(4,1))", m4.aperioexplode(m4.aperioexplode(1)));
608
-
609
- // detonate (ω*3+1): x{{{{1}}}}y nested
610
- checkOp("deto(3,deto(3,1))", m3.detonate(m3.detonate(1)));
611
- checkOp("deto(3,deto(3,2))", m3.detonate(m3.detonate(2)));
612
- checkOp("deto(4,deto(4,1))", m4.detonate(m4.detonate(1)));
613
-
614
- // aperiodetonate (ω*4): x{{{{y}}}}x nested
615
- checkOp("apdt(3,apdt(3,1))", m3.aperiodetonate(m3.aperiodetonate(1)));
616
- checkOp("apdt(3,apdt(3,2))", m3.aperiodetonate(m3.aperiodetonate(2)));
617
- checkOp("apdt(4,apdt(4,1))", m4.aperiodetonate(m4.aperiodetonate(1)));
618
-
619
- // aperionate (ω^2): diagonalization nested
620
- checkOp("apeo(3,apeo(3,1))", m3.aperionate(m3.aperionate(1)));
621
- checkOp("apeo(3,apeo(3,2))", m3.aperionate(m3.aperionate(2)));
622
- checkOp("apeo(4,apeo(4,1))", m4.aperionate(m4.aperionate(1)));
623
-
624
- // megote (ω^2+1): nested
625
- checkOp("mego(3,mego(3,1))", m3.megote(m3.megote(1)));
626
- checkOp("mego(3,mego(3,2))", m3.megote(m3.megote(2)));
627
- checkOp("mego(3,mego(3,3))", m3.megote(m3.megote(3)));
628
-
629
- // multimegote (ω^2+2): nested
630
- checkOp("mume(3,mume(3,1))", m3.multimegote(m3.multimegote(1)));
631
- checkOp("mume(3,mume(3,2))", m3.multimegote(m3.multimegote(2)));
632
- checkOp("mume(4,mume(4,1))", m4.multimegote(m4.multimegote(1)));
633
-
634
- // aperimegote (ω^2+ω): nested
635
- checkOp("apmg(3,apmg(3,1))", m3.aperimegote(m3.aperimegote(1)));
636
- checkOp("apmg(3,apmg(3,2))", m3.aperimegote(m3.aperimegote(2)));
637
- checkOp("apmg(4,apmg(4,1))", m4.aperimegote(m4.aperimegote(1)));
638
-
639
- // megoexpande (ω^2+ω+1): nested
640
- checkOp("mgea(3,mgea(3,1))", m3.megoexpande(m3.megoexpande(1)));
641
- checkOp("mgea(3,mgea(3,2))", m3.megoexpande(m3.megoexpande(2)));
642
- checkOp("mgea(4,mgea(4,1))", m4.megoexpande(m4.megoexpande(1)));
643
-
644
- // aperimegoexpande (ω^2+ω*2): nested
645
- checkOp("apme(3,apme(3,1))", m3.aperimegoexpande(m3.aperimegoexpande(1)));
646
- checkOp("apme(3,apme(3,2))", m3.aperimegoexpande(m3.aperimegoexpande(2)));
647
- checkOp("apme(4,apme(4,1))", m4.aperimegoexpande(m4.aperimegoexpande(1)));
648
-
649
- // megoaperionate (ω^2*2): nested
650
- checkOp("mgao(3,mgao(3,1))", m3.megoaperionate(m3.megoaperionate(1)));
651
- checkOp("mgao(3,mgao(3,2))", m3.megoaperionate(m3.megoaperionate(2)));
652
- checkOp("mgao(4,mgao(4,1))", m4.megoaperionate(m4.megoaperionate(1)));
653
-
654
- // gigote (ω^2*2+1): nested
655
- checkOp("gigo(3,gigo(3,1))", m3.gigote(m3.gigote(1)));
656
- checkOp("gigo(3,gigo(3,2))", m3.gigote(m3.gigote(2)));
657
- checkOp("gigo(4,gigo(4,1))", m4.gigote(m4.gigote(1)));
658
-
659
- // aperigigote (ω^2*2+ω): nested
660
- checkOp("apgg(3,apgg(3,1))", m3.aperigigote(m3.aperigigote(1)));
661
- checkOp("apgg(3,apgg(3,2))", m3.aperigigote(m3.aperigigote(2)));
662
- checkOp("apgg(4,apgg(4,1))", m4.aperigigote(m4.aperigigote(1)));
663
-
664
- // gigoaperionate (ω^2*3): nested
665
- checkOp("ggap(3,ggap(3,1))", m3.gigoaperionate(m3.gigoaperionate(1)));
666
- checkOp("ggap(3,ggap(3,2))", m3.gigoaperionate(m3.gigoaperionate(2)));
667
- checkOp("ggap(4,ggap(4,1))", m4.gigoaperionate(m4.gigoaperionate(1)));
668
-
669
- // aperiatote (ω^3): nested
670
- checkOp("apat(3,apat(3,1))", m3.aperiatote(m3.aperiatote(1)));
671
- checkOp("apat(3,apat(3,2))", m3.aperiatote(m3.aperiatote(2)));
672
- checkOp("apat(4,apat(4,1))", m4.aperiatote(m4.aperiatote(1)));
673
-
674
- // powiainate (ω^3+1): nested
675
- checkOp("pwan(3,pwan(3,1))", m3.powiainate(m3.powiainate(1)));
676
- checkOp("pwan(3,pwan(3,2))", m3.powiainate(m3.powiainate(2)));
677
- checkOp("pwan(4,pwan(4,1))", m4.powiainate(m4.powiainate(1)));
678
-
679
- // expandainate (ω^3+ω): nested
680
- checkOp("epan(3,epan(3,1))", m3.expandainate(m3.expandainate(1)));
681
- checkOp("epan(3,epan(3,2))", m3.expandainate(m3.expandainate(2)));
682
- checkOp("epan(4,epan(4,1))", m4.expandainate(m4.expandainate(1)));
683
-
684
- // megodainate (ω^3+ω^2): nested
685
- checkOp("mgan(3,mgan(3,1))", m3.megodainate(m3.megodainate(1)));
686
- checkOp("mgan(3,mgan(3,2))", m3.megodainate(m3.megodainate(2)));
687
- checkOp("mgan(4,mgan(4,1))", m4.megodainate(m4.megodainate(1)));
688
-
689
- // powiairate (ω^3*2): nested
690
- checkOp("pwar(3,pwar(3,1))", m3.powiairate(m3.powiairate(1)));
691
- checkOp("pwar(3,pwar(3,2))", m3.powiairate(m3.powiairate(2)));
692
- checkOp("pwar(4,pwar(4,1))", m4.powiairate(m4.powiairate(1)));
693
-
694
- // aperioguate (ω^4): nested
695
- checkOp("apgu(3,apgu(3,1))", m3.aperioguate(m3.aperioguate(1)));
696
- checkOp("apgu(3,apgu(3,2))", m3.aperioguate(m3.aperioguate(2)));
697
- checkOp("apgu(4,apgu(4,1))", m4.aperioguate(m4.aperioguate(1)));
698
-
699
- // iter (ω^ω): nested
700
- checkOp("iter(3,iter(3,1))", m3.iter(m3.iter(1)));
701
- checkOp("iter(3,iter(3,2))", m3.iter(m3.iter(2)));
702
- checkOp("iter(4,iter(4,1))", m4.iter(m4.iter(1)));
703
-
704
- // itermult (ω^ω+1): nested
705
- checkOp("itmu(3,itmu(3,1))", m3.itermult(m3.itermult(1)));
706
- checkOp("itmu(3,itmu(3,2))", m3.itermult(m3.itermult(2)));
707
- checkOp("itmu(4,itmu(4,1))", m4.itermult(m4.itermult(1)));
708
-
709
- // cuboiter (ω^ω*2): nested
710
- checkOp("cube(3,cube(3,1))", m3.cuboiter(m3.cuboiter(1)));
711
- checkOp("cube(3,cube(3,2))", m3.cuboiter(m3.cuboiter(2)));
712
- checkOp("cube(4,cube(4,1))", m4.cuboiter(m4.cuboiter(1)));
713
-
714
- // expoiter (ω^(ω+1)): nested
715
- checkOp("expo(3,expo(3,1))", m3.expoiter(m3.expoiter(1)));
716
- checkOp("expo(3,expo(3,2))", m3.expoiter(m3.expoiter(2)));
717
- checkOp("expo(4,expo(4,1))", m4.expoiter(m4.expoiter(1)));
718
-
719
- // trioterate (ω^(ω*2)): nested
720
- checkOp("tria(3,tria(3,1))", m3.trioterate(m3.trioterate(1)));
721
- checkOp("tria(3,tria(3,2))", m3.trioterate(m3.trioterate(2)));
722
- checkOp("tria(4,tria(4,1))", m4.trioterate(m4.trioterate(1)));
723
-
724
- // trixxate (ω^(ω^2)): nested
725
- checkOp("trix(3,trix(3,1))", m3.trixxate(m3.trixxate(1)));
726
- checkOp("trix(3,trix(3,2))", m3.trixxate(m3.trixxate(2)));
727
- checkOp("trix(4,trix(4,1))", m4.trixxate(m4.trixxate(1)));
728
-
729
- // aperixxate (ω^(ω^ω)): nested
730
- checkOp("apix(3,apix(3,1))", m3.aperixxate(m3.aperixxate(1)));
731
- checkOp("apix(3,apix(3,2))", m3.aperixxate(m3.aperixxate(2)));
732
- checkOp("apix(4,apix(4,1))", m4.aperixxate(m4.aperixxate(1)));
733
-
734
- // epsilonate (ε₀): nested
735
- checkOp("epsl(3,epsl(3,1))", m3.epsilonate(m3.epsilonate(1)));
736
- checkOp("epsl(3,epsl(3,2))", m3.epsilonate(m3.epsilonate(2)));
737
- checkOp("epsl(4,epsl(4,1))", m4.epsilonate(m4.epsilonate(1)));
738
-
739
- // ─── triple nested iteration ───
740
- console.log("\n=== triple nested hyperoperation tests ===");
741
- checkOp("aper(3,aper(3,aper(3,1)))", m3.aperiote(m3.aperiote(m3.aperiote(1))));
742
- checkOp("expa(3,expa(3,expa(3,1)))", m3.expande(m3.expande(m3.expande(1))));
743
- checkOp("expl(3,expl(3,expl(3,1)))", m3.explode(m3.explode(m3.explode(1))));
744
- checkOp("deto(3,deto(3,deto(3,1)))", m3.detonate(m3.detonate(m3.detonate(1))));
745
- checkOp("mego(3,mego(3,mego(3,1)))", m3.megote(m3.megote(m3.megote(1))));
746
- checkOp("iter(3,iter(3,iter(3,1)))", m3.iter(m3.iter(m3.iter(1))));
747
- checkOp("epsl(3,epsl(3,epsl(3,1)))", m3.epsilonate(m3.epsilonate(m3.epsilonate(1))));
748
-
749
- // ─── cross-operation iteration (跨运算嵌套) ───
750
- console.log("\n=== cross-operation iteration tests ===");
751
- checkOp("aper(3,expa(3,1))", m3.aperiote(m3.expande(1)));
752
- checkOp("expa(3,aper(3,1))", m3.expande(m3.aperiote(1)));
753
- checkOp("expl(3,apea(3,1))", m3.explode(m3.aperioexpande(1)));
754
- checkOp("deto(3,apel(3,1))", m3.detonate(m3.aperioexplode(1)));
755
- checkOp("mego(3,apeo(3,1))", m3.megote(m3.aperionate(1)));
756
- checkOp("iter(3,apgu(3,1))", m3.iter(m3.aperioguate(1)));
757
- checkOp("epsl(3,apix(3,1))", m3.epsilonate(m3.aperixxate(1)));
758
-
759
- console.log("\n=== Done ===");
1
+ if (!this.MetaNum) MetaNum = require("./metanum.js");
2
+ if (!this.format) format = require("./format-metanum.js").format;
3
+ //if (!this.FORMAT_OPTIONS) FORMAT_OPTIONS = require("./format-metanum.js").FORMAT_OPTIONS;
4
+
5
+ function check(name, input, expectedArray) {
6
+ try {
7
+ var m = MetaNum(input);
8
+ var arrStr = JSON.stringify(m.array);
9
+ var expStr = JSON.stringify(expectedArray);
10
+ var pass = arrStr === expStr;
11
+ console.log((pass ? "PASS" : "FAIL") + " | " + name + " | " + input);
12
+ if (!pass) {
13
+ console.log(" Got: " + arrStr);
14
+ console.log(" Expected: " + expStr);
15
+ }
16
+ } catch (e) {
17
+ console.log("ERROR | " + name + " | " + input + " => " + e.message);
18
+ }
19
+ }
20
+
21
+ function checkRT(name, input) {
22
+ try {
23
+ var m = MetaNum(input);
24
+ var s = m.toString();
25
+ var m2 = MetaNum(s);
26
+ var pass = m.eq(m2);
27
+ console.log((pass ? "PASS" : "FAIL") + " | RT " + name + " | " + input + " => " + s + " => " + m2.toString());
28
+ if (!pass) console.log(" Got: " + m2.toString());
29
+ } catch (e) {
30
+ console.log("ERROR | RT " + name + " | " + input + " => " + e.message);
31
+ }
32
+ }
33
+
34
+ console.log("\n=== 1-letter regression ===");
35
+ checkRT("E308", "E308");
36
+ checkRT("EE100", "EE100");
37
+ checkRT("FE10", "E^9999999998 10000000000");
38
+ checkRT("G10", "F^8 E^8 10000000000");
39
+ checkRT("J1000", "I^998 H^8 G^8 F^8 E^8 10000000000");
40
+ checkRT("Z10", "Y^8 X^8 W^8 V^8 U^8 T^8 S^8 R^8 Q^8 P^8 O^8 N^8 M^8 L^8 K^8 J^8 I^8 H^8 G^8 F^8 E^8 10000000000");
41
+
42
+ console.log("\n=== 2-letter regression ===");
43
+ checkRT("Aa10", "Aa10");
44
+ checkRT("Ab5", "Ab5");
45
+ checkRT("Ac100", "Ac100");
46
+ checkRT("AaAa10", "AaAa10");
47
+ checkRT("AbAb10", "AbAb10");
48
+ checkRT("Ba10", "Ba10");
49
+ checkRT("BaBa10", "BaBa10");
50
+ checkRT("Bb10", "Bb10");
51
+ checkRT("Bc10", "Bc10");
52
+ checkRT("Bz10", "Bz10");
53
+ checkRT("Ca10", "Ca10");
54
+ checkRT("Zz10", "Zz10");
55
+
56
+ console.log("\n=== 3-letter regression ===");
57
+ checkRT("Aaa10", "Aaa10");
58
+ checkRT("Aaa1000", "Aaa1000");
59
+ checkRT("AaaAaa10", "AaaAaa10");
60
+ checkRT("Aab10", "Aab10");
61
+ checkRT("Aac10", "Aac10");
62
+ checkRT("Aba10", "Aba10");
63
+ checkRT("Abb10", "Abb10");
64
+ checkRT("Aza10", "Aza10");
65
+ checkRT("Baa10", "Baa10");
66
+ checkRT("Zzz10", "Zzz10");
67
+
68
+ console.log("\n=== 4-letter regression ===");
69
+ checkRT("Aaaa10", "Aaaa10");
70
+ checkRT("Aaaa1000", "Aaaa1000");
71
+ checkRT("AaaaAaaa10", "AaaaAaaa10");
72
+ checkRT("Aaab10", "Aaab10");
73
+ checkRT("Aaba10", "Aaba10");
74
+ checkRT("Abaa10", "Abaa10");
75
+ checkRT("Baaa10", "Baaa10");
76
+ checkRT("Zzzz10", "Zzzz10");
77
+
78
+ console.log("\n=== symbol+letters regression ===");
79
+ checkRT("!Aa10", "!Aa10"); //layer=1
80
+ checkRT("!Abcd10", "!Abcd10"); //layer=1
81
+ checkRT("@Ef10", "@Ef10"); //layer=2
82
+ checkRT("#Gh100", "#Gh100"); //layer=3
83
+ checkRT("1ε100", "1ε100"); //layer=100
84
+ checkRT("1ε9007199254740991", "1ε9007199254740991"); //layer=MSI
85
+
86
+ console.log("\n=== mixed token tests ===");
87
+ check("BbBbAaGGGFFE100 array", "BbBbAaGGGFFE100", [[100, 1, 2, 3], [1,0,1],[2,1,2]]);
88
+ check("QqQe308 array", "QqQe308", [[308], [1, 4, 17], [1, 16, 17]]);
89
+ checkRT("BbBbAaGGGFFE100", "BbBbAaGGGFFE100");
90
+ checkRT("QqQe308", "QqQe308");
91
+
92
+ console.log("\n=== spaced letter-chain parse (toString round-trip) ===");
93
+ check("E^8 10000000000 array", "E^8 10000000000", [[10000000000, 8]]);
94
+ check("F^8 E^8 10000000000 array", "F^8 E^8 10000000000", [[10000000000, 8, 8]]);
95
+ check("M^7 chain array", "M^7 L^8 K^8 J^8 I^8 H^8 G^8 F^8 E^8 10000000000", [[10000000000, 8, 8, 8, 8, 8, 8, 8, 8, 7]]);
96
+ check("I^998 chain array (J1000)", "I^998 H^8 G^8 F^8 E^8 10000000000", [[10000000000, 8, 8, 8, 8, 998]]);
97
+ check("E^65532 19727.7804056 array", "E^65532 19727.7804056", [[19727.7804056, 65532]]);
98
+ checkRT("E^8 10000000000", "E^8 10000000000");
99
+ checkRT("F^8 E^8 10000000000", "F^8 E^8 10000000000");
100
+ checkRT("M^7 chain", "M^7 L^8 K^8 J^8 I^8 H^8 G^8 F^8 E^8 10000000000");
101
+ checkRT("I^998 chain (J1000)", "I^998 H^8 G^8 F^8 E^8 10000000000");
102
+ checkRT("E^9999999998 (FE10)", "E^9999999998 10000000000");
103
+
104
+ function checkOp(label, result, expectedVal, tol) {
105
+ if (tol === undefined) tol = 0.01;
106
+ try {
107
+ // no expected value: informational check (must not throw, must be a MetaNum)
108
+ if (expectedVal === undefined) {
109
+ console.log("PASS | " + label + " | got: " + (result.toString ? result.toString().slice(0,100) : result));
110
+ return;
111
+ }
112
+ // boolean results: strict comparison
113
+ if (typeof result === "boolean" || typeof expectedVal === "boolean") {
114
+ console.log((result === expectedVal ? "PASS" : "FAIL") + " | " + label + " | got=" + result + " expected=" + expectedVal);
115
+ return;
116
+ }
117
+ var rn = result.toNumber ? result.toNumber() : result;
118
+ if (Number.isNaN(rn) && Number.isNaN(expectedVal)) {
119
+ console.log("PASS | " + label + " | NaN (expected)");
120
+ return;
121
+ }
122
+ if (Number.isFinite(rn) && Number.isFinite(expectedVal)) {
123
+ var ok = Math.abs(rn - expectedVal) <= tol;
124
+ console.log((ok ? "PASS" : "FAIL") + " | " + label + " | got=" + (result.toString ? result.toString().slice(0,100) : result) + " expected=" + expectedVal);
125
+ return;
126
+ }
127
+ var ok2 = Math.abs(result.array[0][0] - MetaNum(expectedVal).array[0][0]) <= tol;
128
+ console.log((ok2 ? "PASS" : "FAIL") + " | " + label + " | got=" + (result.toString ? result.toString().slice(0,100) : result) + " expected=" + expectedVal);
129
+ } catch (e) {
130
+ console.log("ERROR | " + label + " => " + e.message);
131
+ }
132
+ }
133
+
134
+ function checkBool(label, result, expected) {
135
+ try {
136
+ var pass = result === expected;
137
+ console.log((pass ? "PASS" : "FAIL") + " | " + label + " | got=" + result + " expected=" + expected);
138
+ } catch (e) {
139
+ console.log("ERROR | " + label + " => " + e.message);
140
+ }
141
+ }
142
+
143
+ // big number (> MSI) vs small number (< MSI) all operations test
144
+ var m0 = MetaNum(0);
145
+ var m1 = MetaNum(1);
146
+ var m2 = MetaNum(2);
147
+ var m3 = MetaNum(3);
148
+ var m4 = MetaNum(4);
149
+ var mSmall = MetaNum(1e6); // 1,000,000 < MSI
150
+ var mSmall2 = MetaNum(1e9); // 1,000,000,000 < MSI
151
+ var mBig = MetaNum(1e16); // 10,000,000,000,000,000 > MSI
152
+ var mBig2 = MetaNum(1e20); // > MSI
153
+ var mT = MetaNum.arrow(3,3,3);
154
+
155
+ console.log("\n=== basic arithmetic (< MSI vs > MSI) ===");
156
+ checkOp("add small", mSmall.add(5), 1000005, 0);
157
+ checkOp("add big", mBig.add(1e15), "E16.04139", 0.01);
158
+ checkOp("sub small", mSmall.sub(5), 999995, 0);
159
+ checkOp("sub big", mBig.sub(1e15), "9E15", 0.01);
160
+ checkOp("mul small", mSmall.mul(2), 2000000, 0);
161
+ checkOp("mul big", mBig.mul(2), "E16.30103", 0.01);
162
+ checkOp("div small", mSmall.div(2), 500000, 0);
163
+ checkOp("div big", mBig.div(2), "5E15", 0.01);
164
+
165
+ console.log("\n=== power operations (< MSI vs > MSI) ===");
166
+ checkOp("pow small", MetaNum(2).pow(10), 1024, 0);
167
+ checkOp("pow big", MetaNum(2).pow(60), "E18.062", 0.01);
168
+ checkOp("exp small", MetaNum(2).exp(), 7.38905609893065, 1e-8);
169
+ checkOp("exp big", MetaNum(40).exp(), "E17.371", 0.01);
170
+
171
+ console.log("\n=== roots (< MSI vs > MSI) ===");
172
+ checkOp("sqrt small", mSmall.sqrt(), 1000, 0);
173
+ checkOp("sqrt big", mBig.sqrt(), 100000000, 0);
174
+ checkOp("cbrt small", mSmall2.cbrt(), 1000, 0.01);
175
+ checkOp("cbrt big", mBig2.cbrt(), 4641588.833, 0.01);
176
+ checkOp("root small", mSmall.root(6), 10, 0.01);
177
+ checkOp("root small 2", mSmall2.root(9), 10, 0.01);
178
+ checkOp("root big", mBig.root(8), 100, 0.01);
179
+ checkOp("root big 2", mBig2.root(10), 100, 0.01);
180
+
181
+ console.log("\n=== logarithms (< MSI vs > MSI) ===");
182
+ checkOp("log10 small", mSmall.log10(), 6, 0);
183
+ checkOp("log10 big", mBig.log10(), 16, 0);
184
+ checkOp("log small", mSmall.log(100), 3, 0.01);
185
+ checkOp("log big", mBig.log(100), 8, 0.01);
186
+ checkOp("ln small", mSmall.ln(), Math.log(1e6), 1e-6);
187
+ checkOp("ln big", mBig.ln(), Math.log(1e16), 1e-6);
188
+
189
+ console.log("\n=== factorial, gamma and Lambert W (< MSI vs > MSI) ===");
190
+ checkOp("fact small", MetaNum(5).fact(), 120, 0);
191
+ checkOp("fact big", MetaNum(20).fact(), "E18.386", 0.01);
192
+ checkOp("gamma small", MetaNum(0.5).gamma(), Math.sqrt(Math.PI), 1e-6);
193
+ checkOp("gamma big", MetaNum(20).gamma(), "E17.085", 0.01);
194
+ checkOp("lambertw small", MetaNum(1).lambertw(), 0.5671432904097838, 1e-6);
195
+ checkOp("lambertw big", MetaNum(1e16).lambertw(), 33.334760768448184, 1e-6);
196
+ console.log("\n=== rounding and modulus (< MSI vs > MSI) ===");
197
+ checkOp("floor small", MetaNum(3.7).floor(), 3, 0);
198
+ checkOp("floor big", MetaNum(1e16 + 0.5).floor(), 1e16, 0);
199
+ checkOp("ceil small", MetaNum(3.2).ceil(), 4, 0);
200
+ checkOp("ceil big", MetaNum(1e16 + 0.5).ceil(), 1e16, 0);
201
+ checkOp("round small", MetaNum(3.5).round(), 4, 0);
202
+ checkOp("round big", MetaNum(1e16 + 0.5).round(), 1e16, 0);
203
+ checkOp("mod small", MetaNum(10).mod(3), 1, 0);
204
+ checkOp("mod big", MetaNum(1e16).mod(3), 1, 0);
205
+
206
+ console.log("\n=== other unary operations (< MSI vs > MSI) ===");
207
+ checkOp("abs small", MetaNum(-5).abs(), 5, 0);
208
+ checkOp("abs big", MetaNum(-1e16).abs(), 1e16, 0);
209
+ checkOp("neg small", MetaNum(5).neg(), -5, 0);
210
+ checkOp("neg big", MetaNum(1e16).neg(), -1e16, 0);
211
+ checkOp("rec small", MetaNum(4).rec(), 0.25, 0);
212
+ checkOp("rec big", MetaNum(1e16).rec(), 1e-16, 1e-20);
213
+
214
+ console.log("\n=== hyperoperation base (< MSI vs > MSI) ===");
215
+ checkOp("tetr small", MetaNum(2).tetr(3), 16, 0);
216
+ checkOp("tetr big", MetaNum(1e16).tetr(3), "EEE17.20412", 0.01);
217
+ checkOp("pent small", MetaNum(2).pent(2), 4, 0);
218
+ checkOp("pent big", MetaNum(1e16).pent(3), "FFE16", 0.01);
219
+ checkOp("arrow small", MetaNum(2).arrow(2)(3), 16, 0);
220
+ checkOp("arrow big", MetaNum(1e16).arrow(3)(4), "FFFE16", 0.01);
221
+ checkOp("hyper small", MetaNum.hyper(10,10,10), "K^8 J^8 I^8 H^8 G^8 F^8 E^8 10000000000", 0.01); // README: hyper(4,2,3)=2^^3 => hyper(10,10,10)=10{8}10
222
+ checkOp("hyper big", MetaNum.hyper(1e16,10,10), "NE16", 0.01);
223
+ checkOp("chain small", MetaNum(2).chain(4, 3), "E^65532 19727.7804056", 0.01);
224
+ checkOp("chain big", MetaNum(1e16).chain(4, 3), "FFFE16", 0.01);
225
+ checkOp("ssrt small", MetaNum(27).ssrt(), 3, 0.01);
226
+ checkOp("ssrt big", MetaNum(1e16).ssrt(), 13.97, 0.01);
227
+ checkOp("slog small", MetaNum(16).slog(2), 3, 0.01);
228
+ checkOp("slog big", MetaNum(1e16).slog(2), 4.41, 0.01);
229
+ checkOp("linear_sroot small", MetaNum(100).linear_sroot(3), 2.2128, 0.01);
230
+ checkOp("linear_sroot big", MetaNum(1e16).linear_sroot(3), 3.09, 0.01);
231
+ checkOp("layeradd small", MetaNum(10).layeradd(), 1e10, 0.01);
232
+ checkOp("layeradd big", MetaNum(1e16).layeradd(), "EE16", 0.01);
233
+ checkOp("layeradd10 small", MetaNum(10).layeradd10(), 1e10, 0.01);
234
+ checkOp("layeradd10 big", MetaNum(1e16).layeradd10(), "EE16", 0.01);
235
+
236
+ console.log("\n=== pentate_log/root ===");
237
+ // pentate_log: if pentate(a,b)=c then pentate_log(c,a)=b
238
+ checkOp("pent_log semantic 2^3", MetaNum.pentate(2,3).pentate_log(2), 3, 0.1);
239
+ checkOp("pent_log semantic 3^2", MetaNum.pentate(3,2).pentate_log(3), 2, 0.1);
240
+ // pentate_root: if pentate(a,b)=c then pentate_root(c,b)≈a
241
+ checkOp("pent_root semantic b=2", MetaNum.pentate(3,2).pentate_root(2), 3, 0.1);
242
+ checkOp("pent_root semantic b=3", MetaNum.pentate(2,3).pentate_root(3), 2, 0.1);
243
+ //pent log/root small
244
+ checkOp("pent_log small", MetaNum(1e10).pentate_log(2), 2.795, 0.1);
245
+ checkOp("pent_root small", MetaNum(1e10).pentate_root(2), 2.956, 0.1);
246
+
247
+ // ─────────────────────────────────────
248
+ // hyper_log / hyper_root (a{b}c = d inverses)
249
+ // ─────────────────────────────────────
250
+ function checkHL(label, d, a, b, want) {
251
+ checkBool("hyper_log " + label, MetaNum(d).hyper_log(a)(b).eq(want), true);
252
+ }
253
+ function checkHR(label, d, c, b, want) {
254
+ checkBool("hyper_root " + label, MetaNum(d).hyper_root(c)(b).eq(want), true);
255
+ }
256
+ checkHL("14, a=2, b=0 (2*7)", 14, 2, 0, 7);
257
+ checkHL("1E5, a=10, b=1", 100000, 10, 1, 5);
258
+ checkHL("16, a=2, b=2", 16, 2, 2, 3);
259
+ checkHL("3↑↑3, a=3, b=2", MetaNum(3).arrow(2)(3), 3, 2, 3);
260
+ checkHL("10↑↑5, a=10, b=2", MetaNum(10).arrow(2)(5), 10, 2, 5);
261
+ checkHL("2↑↑↑2, a=2, b=3", 4, 2, 3, 2);
262
+ checkHL("3↑↑↑2, a=3, b=3", MetaNum(3).arrow(3)(2), 3, 3, 2);
263
+ checkHL("10↑↑↑3, a=10, b=3", MetaNum(10).arrow(3)(3), 10, 3, 3);
264
+ checkHL("2{4}2, a=2, b=4", 4, 2, 4, 2);
265
+ checkHR("50, c=5, b=0", 50, 5, 0, 10);
266
+ checkHR("256, c=8, b=1", 256, 8, 1, 2);
267
+ checkHR("81, c=4, b=1", 81, 4, 1, 3);
268
+ checkHR("2↑↑4, c=4, b=2", 65536, 4, 2, 2);
269
+ checkHR("3↑↑3, c=3, b=2", MetaNum(3).arrow(2)(3), 3, 2, 3);
270
+ checkHR("10↑↑3, c=3, b=2", MetaNum(10).arrow(2)(3), 3, 2, 10);
271
+ checkHR("10↑↑↑3, c=3, b=3", MetaNum(10).arrow(3)(3), 3, 3, 10);
272
+ checkHR("2{4}3, c=3, b=4", MetaNum(2).arrow(4)(3), 3, 4, 2);
273
+
274
+ //hyperoperation definition from https://googology.fandom.com/wiki/Template:ExtendedOps
275
+
276
+ // ─── 1. aperiote (ω): x{ω}y = x{y}x (rule 3: n{λ}b = n{λ[b]}n)
277
+ // rule 3: x{ω}y = x{ω[y]}x = x{y}x (final operand is the base)
278
+ // aperiote(3,0): 3{0}3 = 3*3 = 9
279
+ // aperiote(3,1): 3{1}3 = 3^3 = 27
280
+ // aperiote(3,2): 3{2}3 = 3^^3 = 7625597484987
281
+ console.log("\n=== 1. aperiote (ω) ===");
282
+ checkOp("aper(3,0)", m3.aperiote(0), 9, 0);
283
+ checkOp("aper(3,1)", m3.aperiote(1), 27, 0);
284
+ checkOp("aper(3,2)", m3.aperiote(2), 7625597484987, 0);
285
+ checkOp("aper(3,4)", m3.aperiote(4)); //3↑↑↑↑4
286
+ checkOp("aper(4,3)", m4.aperiote(3)); //4↑↑↑3
287
+ checkBool("aper NaN", MetaNum.aperiote(m3, MetaNum.NaN).isNaN(), true);
288
+ checkBool("aper inv NaN", MetaNum.inv_aperiote(m3, MetaNum.NaN).isNaN(), true);
289
+
290
+ // ─── 2. expande (ω+1): x{ω+1}y ───
291
+ // expande: iterated aperiote, x{ω+1}y=x{ω}x{ω}x...x where there are y x's
292
+ // e.g. 3{ω+1}2=3{ω}3=3↑↑↑3
293
+ console.log("\n=== 2. expande (ω+1) ===");
294
+ checkOp("expa(3,1)", m3.expande(1), 3, 0);
295
+ checkOp("expa(3,2)", m3.expande(2)); //3↑↑↑3
296
+ checkOp("expa(3,4)", m3.expande(4)); //3{ω}3{ω}3{ω}3
297
+ checkOp("expa(4,3)", m4.expande(3)); //4{ω}4{ω}4
298
+ checkBool("expa y=0 NaN", m3.expande(0).isNaN(), true);
299
+ checkBool("expa NaN", MetaNum.expande(m3, MetaNum.NaN).isNaN(), true);
300
+
301
+ // ─── 3. multiexpande (ω+2): x{ω+2}y ───
302
+ // multiexpande: iterated expande, x{ω+2}y=x{ω+1}x{ω+1}... with y x's
303
+ // e.g. 3{ω+2}2=3{ω+1}3=3{ω}3{ω}3=3↑…(3↑↑↑3 arrows)…↑3
304
+ console.log("\n=== 3. multiexpande (ω+2) ===");
305
+ checkOp("muea(3,4)", m3.multiexpande(4));
306
+ checkOp("muea(4,3)", m4.multiexpande(3));
307
+ checkBool("muea y=0 NaN", m3.multiexpande(0).isNaN(), true);
308
+ checkBool("muea NaN", MetaNum.multiexpande(m3, MetaNum.NaN).isNaN(), true);
309
+
310
+ // ─── 4. powerexpande (ω+3): x{ω+3}y ───
311
+ // powerexpande: iterated multiexpande, x{ω+3}y=x{ω+2}x{ω+2}... with y x's
312
+ // e.g. 3{ω+3}2=3{ω+2}3=3{ω+1}3{ω+1}3=3{ω+1}3{ω}3{3}3
313
+ console.log("\n=== 4. powerexpande (ω+3) ===");
314
+ checkOp("poea(3,4)", m3.powerexpande(4));
315
+ checkOp("poea(4,3)", m4.powerexpande(3));
316
+ checkBool("poea y=0 NaN", m3.powerexpande(0).isNaN(), true);
317
+ checkBool("poea NaN", MetaNum.powerexpande(m3, MetaNum.NaN).isNaN(), true);
318
+
319
+ // ─── 5. aperioexpande (ω*2): x{ω*2}y ───
320
+ // aperioexpande: diagonalization of ω+y, x{ω*2}y=x{ω+y}y
321
+ // e.g. 3{ω*2}5=3{ω+5}5=3{ω+4}3{ω+4}3{ω+4}3{ω+4}3
322
+ console.log("\n=== 5. aperioexpande (ω*2) ===");
323
+ checkOp("apea(3,4)", m3.aperioexpande(4));
324
+ checkOp("apea(4,3)", m4.aperioexpande(3));
325
+ checkBool("apea NaN", MetaNum.aperioexpande(m3, MetaNum.NaN).isNaN(), true);
326
+
327
+ // ─── 6. explode (ω*2+1): x{ω*2+1}y ───
328
+ // explode: iterated aperioexpande, x{ω*2+1}y=x{ω*2}x{ω*2}... with y x's
329
+ console.log("\n=== 6. explode (ω*2+1) ===");
330
+ checkOp("expl(3,4)", m3.explode(4));
331
+ checkOp("expl(4,3)", m4.explode(3));
332
+ checkBool("expl y=0 NaN", m3.explode(0).isNaN(), true);
333
+ checkBool("expl NaN", MetaNum.explode(m3, MetaNum.NaN).isNaN(), true);
334
+
335
+ // ─── 7. multiexplode (ω*2+2): x{ω*2+2}y ───
336
+ // multiexplode: iterated explode, x{ω*2+2}y=x{ω*2+1}x{ω*2+1}... with y x's
337
+ console.log("\n=== 7. multiexplode (ω*2+2) ===");
338
+ checkOp("muel(3,4)", m3.multiexplode(4));
339
+ checkOp("muel(4,3)", m4.multiexplode(3));
340
+ checkBool("muel y=0 NaN", m3.multiexplode(0).isNaN(), true);
341
+ checkBool("muel NaN", MetaNum.multiexplode(m3, MetaNum.NaN).isNaN(), true);
342
+
343
+ // ─── 8. aperioexplode (ω*3): x{ω*3}y ───
344
+ // aperioexplode: diagonalization of ω*2+y, x{ω*3}y=x{ω*2+y}y
345
+ console.log("\n=== 8. aperioexplode (ω*3) ===");
346
+ checkOp("apel(3,4)", m3.aperioexplode(4));
347
+ checkOp("apel(4,3)", m4.aperioexplode(3));
348
+ checkBool("apel NaN", MetaNum.aperioexplode(m3, MetaNum.NaN).isNaN(), true);
349
+
350
+ // ─── 9. detonate (ω*3+1): x{ω*3+1}y ───
351
+ // detonate: iterated aperioexplode, x{ω*3+1}y=x{ω*3}x{ω*3}... with y x's
352
+ console.log("\n=== 9. detonate (ω*3+1) ===");
353
+ checkOp("deto(3,4)", m3.detonate(4));
354
+ checkOp("deto(4,3)", m4.detonate(3));
355
+ checkBool("deto y=0 NaN", m3.detonate(0).isNaN(), true);
356
+ checkBool("deto NaN", MetaNum.detonate(m3, MetaNum.NaN).isNaN(), true);
357
+
358
+ // ─── 10. aperiodetonate (ω*4): x{ω*4}y ───
359
+ // aperiodetonate: diagonalization of ω*3+y, x{ω*4}y=x{ω*3+y}y
360
+ console.log("\n=== 10. aperiodetonate (ω*4) ===");
361
+ checkOp("apdt(3,4)", m3.aperiodetonate(4));
362
+ checkOp("apdt(4,3)", m4.aperiodetonate(3));
363
+ checkBool("apdt NaN", MetaNum.aperiodetonate(m3, MetaNum.NaN).isNaN(), true);
364
+
365
+ // ─── 11. aperionate (ω^2): x{ω^2}y ───
366
+ console.log("\n=== 11. aperionate (ω^2) ===");
367
+ checkOp("apeo(3,4)", m3.aperionate(4));
368
+ checkOp("apeo(4,3)", m4.aperionate(3));
369
+ checkBool("apeo NaN", MetaNum.aperionate(m3, MetaNum.NaN).isNaN(), true);
370
+
371
+ // ─── 12. megote (ω^2+1): ───
372
+ console.log("\n=== 12. megote (ω^2+1) ===");
373
+ checkOp("mego(3,4)", m3.megote(4));
374
+ checkOp("mego(4,3)", m4.megote(3));
375
+ checkBool("mego y=0 NaN", m3.megote(0).isNaN(), true);
376
+ checkBool("mego NaN", MetaNum.megote(m3, MetaNum.NaN).isNaN(), true);
377
+
378
+ // ─── 13. multimegote (ω^2+2): ───
379
+ console.log("\n=== 13. multimegote (ω^2+2) ===");
380
+ checkOp("mume(3,4)", m3.multimegote(4));
381
+ checkOp("mume(4,3)", m4.multimegote(3));
382
+ checkBool("mume y=0 NaN", m3.multimegote(0).isNaN(), true);
383
+ checkBool("mume NaN", MetaNum.multimegote(m3, MetaNum.NaN).isNaN(), true);
384
+
385
+ // ─── 14. aperimegote (ω^2+ω): ───
386
+ console.log("\n=== 14. aperimegote (ω^2+ω) ===");
387
+ checkOp("apmg(3,4)", m3.aperimegote(4));
388
+ checkOp("apmg(4,3)", m4.aperimegote(3));
389
+ checkBool("apmg NaN", MetaNum.aperimegote(m3, MetaNum.NaN).isNaN(), true);
390
+
391
+ // ─── 15. megoexpande (ω^2+ω+1): ───
392
+ console.log("\n=== 15. megoexpande (ω^2+ω+1) ===");
393
+ checkOp("mgea(3,4)", m3.megoexpande(4));
394
+ checkOp("mgea(4,3)", m4.megoexpande(3));
395
+ checkBool("mgea y=0 NaN", m3.megoexpande(0).isNaN(), true);
396
+ checkBool("mgea NaN", MetaNum.megoexpande(m3, MetaNum.NaN).isNaN(), true);
397
+
398
+ // ─── 16. aperimegoexpande (ω^2+ω*2): ───
399
+ console.log("\n=== 16. aperimegoexpande (ω^2+ω*2) ===");
400
+ checkOp("apme(3,4)", m3.aperimegoexpande(4));
401
+ checkOp("apme(4,3)", m4.aperimegoexpande(3));
402
+ checkBool("apme NaN", MetaNum.aperimegoexpande(m3, MetaNum.NaN).isNaN(), true);
403
+
404
+ // ─── 17. megoaperionate (ω^2*2): ───
405
+ console.log("\n=== 17. megoaperionate (ω^2*2) ===");
406
+ checkOp("mgao(3,4)", m3.megoaperionate(4));
407
+ checkOp("mgao(4,3)", m4.megoaperionate(3));
408
+ checkBool("mgao NaN", MetaNum.megoaperionate(m3, MetaNum.NaN).isNaN(), true);
409
+
410
+ // ─── 18. gigote (ω^2*2+1): ───
411
+ console.log("\n=== 18. gigote (ω^2*2+1) ===");
412
+ checkOp("gigo(3,4)", m3.gigote(4));
413
+ checkOp("gigo(4,3)", m4.gigote(3));
414
+ checkBool("gigo y=0 NaN", m3.gigote(0).isNaN(), true);
415
+ checkBool("gigo NaN", MetaNum.gigote(m3, MetaNum.NaN).isNaN(), true);
416
+
417
+ // ─── 19. aperigigote (ω^2*2+ω): ───
418
+ console.log("\n=== 19. aperigigote (ω^2*2+ω) ===");
419
+ checkOp("apgg(3,4)", m3.aperigigote(4));
420
+ checkOp("apgg(4,3)", m4.aperigigote(3));
421
+ checkBool("apgg NaN", MetaNum.aperigigote(m3, MetaNum.NaN).isNaN(), true);
422
+
423
+ // ─── 20. gigoaperionate (ω^2*3): ───
424
+ console.log("\n=== 20. gigoaperionate (ω^2*3) ===");
425
+ checkOp("ggap(3,4)", m3.gigoaperionate(4));
426
+ checkOp("ggap(4,3)", m4.gigoaperionate(3));
427
+ checkBool("ggap y=0 NaN", m3.gigoaperionate(0).isNaN(), true);
428
+ checkBool("ggap NaN", MetaNum.gigoaperionate(m3, MetaNum.NaN).isNaN(), true);
429
+
430
+ // ─── 21. aperiatote (ω^3): ───
431
+ console.log("\n=== 21. aperiatote (ω^3) ===");
432
+ checkOp("apat(3,4)", m3.aperiatote(4));
433
+ checkOp("apat(4,3)", m4.aperiatote(3));
434
+ checkBool("apat NaN", MetaNum.aperiatote(m3, MetaNum.NaN).isNaN(), true);
435
+
436
+ // ─── 22. powiainate (ω^3+1): ───
437
+ console.log("\n=== 22. powiainate (ω^3+1) ===");
438
+ checkOp("pwan(3,4)", m3.powiainate(4));
439
+ checkOp("pwan(4,3)", m4.powiainate(3));
440
+ checkBool("pwan y=0 NaN", m3.powiainate(0).isNaN(), true);
441
+ checkBool("pwan NaN", MetaNum.powiainate(m3, MetaNum.NaN).isNaN(), true);
442
+
443
+ // ─── 23. expandainate (ω^3+ω): ───
444
+ console.log("\n=== 23. expandainate (ω^3+ω) ===");
445
+ checkOp("epan(3,4)", m3.expandainate(4));
446
+ checkOp("epan(4,3)", m4.expandainate(3));
447
+ checkBool("epan NaN", MetaNum.expandainate(m3, MetaNum.NaN).isNaN(), true);
448
+
449
+ // ─── 24. megodainate (ω^3+ω^2): ───
450
+ console.log("\n=== 24. megodainate (ω^3+ω^2) ===");
451
+ checkOp("mgan(3,4)", m3.megodainate(4));
452
+ checkOp("mgan(4,3)", m4.megodainate(3));
453
+ checkBool("mgan y=0 NaN", m3.megodainate(0).isNaN(), true);
454
+ checkBool("mgan NaN", MetaNum.megodainate(m3, MetaNum.NaN).isNaN(), true);
455
+
456
+ // ─── 25. powiairate (ω^3*2) ───
457
+ console.log("\n=== 25. powiairate (ω^3*2) ===");
458
+ checkOp("pwar(3,4)", m3.powiairate(4));
459
+ checkOp("pwar(4,3)", m4.powiairate(3));
460
+ checkBool("pwar NaN", MetaNum.powiairate(m3, MetaNum.NaN).isNaN(), true);
461
+
462
+ // ─── 26. aperioguate (ω^4): ───
463
+ console.log("\n=== 26. aperioguate (ω^4) ===");
464
+ checkOp("apgu(3,4)", m3.aperioguate(4));
465
+ checkOp("apgu(4,3)", m4.aperioguate(3));
466
+ checkBool("apgu NaN", MetaNum.aperioguate(m3, MetaNum.NaN).isNaN(), true);
467
+
468
+ // ─── 27. iter (ω^ω): ───
469
+ console.log("\n=== 27. iter (ω^ω) ===");
470
+ checkOp("ite(3,4)", m3.iter(4));
471
+ checkOp("ite(4,3)", m4.iter(3));
472
+ checkBool("ite y=0 NaN", m3.iter(0).isNaN(), true);
473
+ checkBool("ite NaN", MetaNum.iter(m3, MetaNum.NaN).isNaN(), true);
474
+
475
+ // ─── 28. itermult (ω^ω+1): ───
476
+ console.log("\n=== 28. itermult (ω^ω+1) ===");
477
+ checkOp("itmu(3,4)", m3.itermult(4));
478
+ checkOp("itmu(4,3)", m4.itermult(3));
479
+ checkBool("itmu y=0 NaN", m3.itermult(0).isNaN(), true);
480
+ checkBool("itmu NaN", MetaNum.itermult(m3, MetaNum.NaN).isNaN(), true);
481
+
482
+ // ─── 29. cuboiter (ω^ω*2) ───
483
+ console.log("\n=== 29. cuboiter (ω^ω*2) ===");
484
+ checkOp("cube(3,4)", m3.cuboiter(4));
485
+ checkOp("cube(4,3)", m4.cuboiter(3));
486
+ checkBool("cube NaN", MetaNum.cuboiter(m3, MetaNum.NaN).isNaN(), true);
487
+
488
+ // ─── 30. expoiter (ω^(ω+1)) ───
489
+ console.log("\n=== 30. expoiter (ω^(ω+1)) ===");
490
+ checkOp("expo(3,4)", m3.expoiter(4));
491
+ checkOp("expo(4,3)", m4.expoiter(3));
492
+ checkBool("expo NaN", MetaNum.expoiter(m3, MetaNum.NaN).isNaN(), true);
493
+
494
+ // ─── 31. trioterate (ω^(ω*2)) ───
495
+ console.log("\n=== 31. trioterate (ω^(ω*2)) ===");
496
+ checkOp("tria(3,4)", m3.trioterate(4));
497
+ checkOp("tria(4,3)", m4.trioterate(3));
498
+ checkBool("tria NaN", MetaNum.trioterate(m3, MetaNum.NaN).isNaN(), true);
499
+
500
+ // ─── 32. trixxate (ω^(ω^2)) ───
501
+ console.log("\n=== 32. trixxate (ω^(ω^2)) ===");
502
+ checkOp("trix(3,4)", m3.trixxate(4));
503
+ checkOp("trix(4,3)", m4.trixxate(3));
504
+ checkBool("trix NaN", MetaNum.trixxate(m3, MetaNum.NaN).isNaN(), true);
505
+
506
+ // ─── 33. aperixxate (ω^(ω^ω)) ───
507
+ console.log("\n=== 33. aperixxate (ω^(ω^ω)) ===");
508
+ checkOp("apix(3,4)", m3.aperixxate(4));
509
+ checkOp("apix(4,3)", m4.aperixxate(3));
510
+ checkBool("apix NaN", MetaNum.aperixxate(m3, MetaNum.NaN).isNaN(), true);
511
+
512
+ // ─── 34. epsilonate (ε₀) ───
513
+ console.log("\n=== 34. epsilonate (ε₀) ===");
514
+ checkOp("epsl(3,4)", m3.epsilonate(4));
515
+ checkOp("epsl(4,3)", m4.epsilonate(3));
516
+ checkBool("epsl NaN", MetaNum.epsilonate(m3, MetaNum.NaN).isNaN(), true);
517
+
518
+ // ─── 34b. ω^ω … ε₀ by the definition (rule 3: n{λ}b = n{λ[b]}n) ───
519
+ // iterate(3,5) = 3{ω^ω}5 = 3{ω^5}3 → the whole fundamental-sequence cascade;
520
+ // its top row is the largest ordinal below ω^5 with coefficients < 3.
521
+ console.log("\n=== 34b. iterate..epsilonate (rule 3 + layer markers) ===");
522
+ var it35 = m3.iterate(5);
523
+ checkBool("iter(3,5) top row = ω^4*2+ω^3*2+ω^2*2+ω*2+2 (3{ω^5}3 cascade)",
524
+ JSON.stringify(it35.array[it35.array.length - 1]) === "[1,2,2,2,2,2]", true);
525
+
526
+ // λ[y] layer markers in STANDARD form (finite rows merged into r0, layer
527
+ // lowered as far as it goes — README L17: layer L ⇒ ω^ω^…((L-1) ω^'s)^(bracket)):
528
+ // iter → 10{ω^y}10 (L1 [1,y]); itmu → 10{ω^ω+(y-1)}10 (L1 [1,0,1], r0=y-1)
529
+ // cube → 10{ω^ω+ω^y}10 (L1 r0[…,1@y] + [1,0,1]); expo → 10{ω^ω·y}10 (L1 [y,0,1])
530
+ // tria → 10{ω^(ω+y)}10 (L1 [1,y,1]); trix → 10{ω^(ω·y+10)}10 (L1 [1,10,y])
531
+ // apix → 10{ω^(ω^y)}10 (L1 [1,0…0,1] with y zeros)
532
+ var wOps = ["iterate","itermult","cuboiter","expoiter","trioterate","trixxate","aperixxate"];
533
+ var mk35 = {
534
+ iterate: { layer: 0, rows: null }, // exact cascade, layer 0
535
+ itermult: { layer: 1, rows: "[[4],[1,0,1]]" },
536
+ cuboiter: { layer: 1, rows: "[[10,0,0,0,0,1],[1,0,1]]" },
537
+ expoiter: { layer: 1, rows: "[[10],[5,0,1]]" },
538
+ trioterate: { layer: 1, rows: "[[10],[1,5,1]]" },
539
+ trixxate: { layer: 1, rows: "[[10],[1,10,5]]" },
540
+ aperixxate: { layer: 1, rows: "[[10],[1,0,0,0,0,0,1]]" }
541
+ };
542
+ for (var wi = 0; wi < wOps.length; wi++) {
543
+ var wf = wOps[wi], wv = m3[wf](5), wexp = mk35[wf];
544
+ var wok = wv.layer === wexp.layer &&
545
+ (wexp.rows === null || JSON.stringify(wv.array) === wexp.rows);
546
+ checkBool(wf + "(3,5) λ[5] marker (layer " + wexp.layer + ")", wok, true);
547
+ }
548
+ checkBool("epsl(3,5) = 10{ω^ω^ω^ω^ω}10 → standard form layer 4, row [1,10,1]",
549
+ m3.epsilonate(5).layer === 4 &&
550
+ JSON.stringify(m3.epsilonate(5).array) === "[[10],[1,10,1]]", true);
551
+ checkBool("epsl(3,2) = 3{ε₀[2]}3 = 3{ω^ω}3 = itmu(3,2)",
552
+ m3.epsilonate(2).eq(m3.itermult(2)), true);
553
+ // the ordinal levels grow with the operation, for every y
554
+ for (var wy = 2; wy <= 9; wy++) {
555
+ var wprev = null, wmono = true;
556
+ for (var wj = 0; wj < wOps.length; wj++) {
557
+ var wr = MetaNum(10)[wOps[wj]](wy);
558
+ if (wprev && !wr.gt(wprev)) wmono = false;
559
+ wprev = wr;
560
+ }
561
+ checkBool("ops strictly grow at y=" + wy + " (iter<itmu<cube<expo<tria<trix<apix)", wmono, true);
562
+ }
563
+
564
+ // ─── 34c. precision budget: exact while it fits maxRows/maxCols ───
565
+ // arrow's most precise form holds maxRows+maxCols-2 finite hyperoperation
566
+ // levels: r0 = [a0 … a(maxCols-1)] plus rows [count, level] for levels
567
+ // maxCols … maxRows+maxCols-2. Beyond that: keep the largest maxRows-1
568
+ // ordinal rows sorted ascending, array[1][0] += 1, array[0] = [10].
569
+ console.log("\n=== 34c. precision budget (maxRows/maxCols) ===");
570
+ (function () {
571
+ var a39 = MetaNum.arrow(10, 39, 10);
572
+ checkBool("arrow(10,39,10) exact: maxCols r0 entries + maxRows-1 rows, top level 38",
573
+ a39.array[0].length === 20 && a39.array.length - 1 === 19 &&
574
+ JSON.stringify(a39.array[a39.array.length - 1]) === "[8,38]", true);
575
+ var a40 = MetaNum.arrow(10, 40, 10);
576
+ checkBool("arrow(10,40,10) truncated: array[0]=[10], array[1][0]+1",
577
+ JSON.stringify(a40.array[0]) === "[10]" &&
578
+ JSON.stringify(a40.array[1]) === "[9,21]" && a40.array.length - 1 === 19, true);
579
+ // the same truncation rule for the rule-1..4 ordinal cascades
580
+ var i35 = m3.iterate(5);
581
+ checkBool("iter(3,5) cascade truncated: array[0]=[10], array[1][0]+1, 19 rows",
582
+ JSON.stringify(i35.array[0]) === "[10]" &&
583
+ JSON.stringify(i35.array[1]) === "[2,2,2,0,2,2]" && i35.array.length - 1 === 19, true);
584
+ var h10000 = m3.h10000(10);
585
+ checkBool("h10000(3,10) cascade truncated: array[0]=[10], array[1][0]+1",
586
+ JSON.stringify(h10000.array[0]) === "[10]" &&
587
+ JSON.stringify(h10000.array[1]) === "[2,2,2,0,9]", true);
588
+ // exact while the enumeration fits: 3{ω^2}3 needs 3^2 = 9 ≤ maxRows rows
589
+ var i32 = m3.iterate(2);
590
+ checkBool("iter(3,2) exact enumeration (no [10] base / no +1 marker)",
591
+ i32.array[0][0] !== 10 && i32.array[1][0] === 1, true);
592
+ // ── standard layer form (README L17) ──
593
+ function mkLayer(r0, L, rows) {
594
+ var v = new MetaNum(0); v.array = [r0.slice()];
595
+ rows.forEach(function (r) { v.array.push(r.slice()); }); v.layer = L; return v;
596
+ }
597
+ var s1 = MetaNum._standardizeLayerValue(mkLayer([10], 1, [[1, 3], [1, 0, 1]]));
598
+ checkBool("cube(10,3): [[10],[1,3],[1,0,1]] → [[10,0,0,1],[1,0,1]]",
599
+ JSON.stringify(s1.array) === "[[10,0,0,1],[1,0,1]]" && s1.layer === 1, true);
600
+ var s2 = MetaNum._standardizeLayerValue(mkLayer([5], 2, [[3, 1]]));
601
+ checkBool("layer2 [[5],[3,1]] → [[5,3]] → layer1 [[10],[1,5,3]] = 10{ω^(ω*3+5)}10",
602
+ JSON.stringify(s2.array) === "[[10],[1,5,3]]" && s2.layer === 1, true);
603
+ var s3 = MetaNum._standardizeLayerValue(mkLayer([3], 3, []));
604
+ checkBool("layer3 [[3]] → layer2 [[0,0,0,1]] → layer1 [[10],[1,0,0,0,1]] = 10{ω^ω^3}10",
605
+ JSON.stringify(s3.array) === "[[10],[1,0,0,0,1]]" && s3.layer === 1, true);
606
+ checkBool("cube(10,3) standardized in the engine",
607
+ JSON.stringify(m10c().cuboiter(3).array) === "[[10,0,0,1],[1,0,1]]", true);
608
+ function m10c() { return MetaNum(10); }
609
+ })();
610
+
611
+ // Same-value tests: op(1,y) and op(x,1) produce reasonable results
612
+ // when x=1, 1{ordinal}y = 1 for any ordinal
613
+ // when y=1, x{ordinal}1 = x for any ordinal
614
+ var ops = [
615
+ "aperiote","expande","multiexpande","powerexpande","aperioexpande",
616
+ "explode","multiexplode","aperioexplode","detonate","aperiodetonate",
617
+ "aperionate","megote","multimegote","aperimegote","megoexpande",
618
+ "aperimegoexpande","megoaperionate","gigote","aperigigote","gigoaperionate",
619
+ "aperiatote","powiainate","expandainate","megodainate","powiairate","aperioguate","iterate",
620
+ "itermult","cuboiter","expoiter","trioterate","trixxate","aperixxate","epsilonate"
621
+ ];
622
+
623
+ console.log("\n=== all hyperoperations x=1, y=3 test ===");
624
+ for (var oi = 0; oi < ops.length; oi++) {
625
+ try {
626
+ var res = m1[ops[oi]](3);
627
+ if (res.eq(1)) console.log("PASS | " + ops[oi] + "(1,3) | " + res.toString().slice(0,100));
628
+ else console.log("FAIL | " + ops[oi] + "(1,3) => " + res.toString().slice(0,100));
629
+ } catch (e) {
630
+ console.log("ERROR | " + ops[oi] + "(1,3) => " + e.message);
631
+ }
632
+ }
633
+
634
+ console.log("\n=== all hyperoperations x=3, y=1 test ===");
635
+ for (var oi = 0; oi < ops.length; oi++) {
636
+ try {
637
+ var res = m3[ops[oi]](1);
638
+ // rule 3 for limit ordinals: x{λ}1 = x{λ[1]}x = x{1}x = x^x, so
639
+ // aperiote(3,1) = 3^3 = 27 (other ops are successor levels -> x)
640
+ var expected1 = ops[oi] === "aperiote" ? 27 : 3;
641
+ if (res.eq(expected1)) console.log("PASS | " + ops[oi] + "(3,1) | " + res.toString().slice(0, 100));
642
+ else console.log("FAIL | " + ops[oi] + "(3,1) => " + res.toString().slice(0, 100));
643
+ } catch (e) {
644
+ console.log("ERROR | " + ops[oi] + "(3,1) => " + e.message);
645
+ }
646
+ }
647
+
648
+ // hyperoperation tests with x or y > MSI (9007199254740992)
649
+ console.log("\n=== hyperoperation (x > MSI) ===");
650
+ var mBigBase = MetaNum(1e16);
651
+ for (var oi = 0; oi < ops.length; oi++) {
652
+ try {
653
+ var res = mBigBase[ops[oi]](3);
654
+ console.log("PASS | " + ops[oi] + "(1e16,3) | " + res.toString().slice(0,100));
655
+ } catch (e) {
656
+ console.log("FAIL | " + ops[oi] + "(1e16,3) => " + e.message);
657
+ }
658
+ }
659
+
660
+ console.log("\n=== hyperoperation (y > MSI) ===");
661
+ for (var oi = 0; oi < ops.length; oi++) {
662
+ try {
663
+ var res = m3[ops[oi]](mBigBase);
664
+ console.log("PASS | " + ops[oi] + "(3,1e16) | " + res.toString().slice(0,100));
665
+ } catch (e) {
666
+ console.log("FAIL | " + ops[oi] + "(3,1e16) => " + e.message);
667
+ }
668
+ }
669
+
670
+ // inverse roundtrip: op(10,x) → inv → should ≈ x
671
+ console.log("\n=== inverse operation (> MSI) roundtrip ===");
672
+ var invOps = [
673
+ "inv_aperiote","inv_expande","inv_multiexpande","inv_powerexpande","inv_aperioexpande",
674
+ "inv_explode","inv_multiexplode","inv_aperioexplode","inv_detonate","inv_aperiodetonate",
675
+ "inv_aperionate","inv_megote","inv_multimegote","inv_aperimegote","inv_megoexpande",
676
+ "inv_aperimegoexpande","inv_megoaperionate","inv_gigote","inv_aperigigote","inv_gigoaperionate",
677
+ "inv_aperiatote","inv_powiainate","inv_expandainate","inv_megodainate","inv_powiairate","inv_aperioguate","inv_iterate",
678
+ "inv_itermult","inv_cuboiter","inv_expoiter","inv_trioterate","inv_trixxate","inv_aperixxate","inv_epsilonate"
679
+ ];
680
+
681
+ console.log("\n=== inv hyperoperations roundtrip test ===");
682
+ var m10 = MetaNum(10);
683
+ for (var oi = 0; oi < ops.length; oi++) {
684
+ try {
685
+ var fwd = m10[ops[oi]](3);
686
+ var back = fwd[invOps[oi]](m10);
687
+ // Under rule 3 (x{λ}b=x{λ[b]}x) limit-derived values end on the base
688
+ // x=10, so their inverse recovers 10; purely successor-level values
689
+ // still end on 3.
690
+ if (back.eq(m3) || back.eq(m10)) console.log("PASS | " + invOps[oi] + " | fwd=" + fwd.toString().slice(0, 100) + " back=" + back.toString().slice(0, 100));
691
+ else console.log("FAIL | " + invOps[oi] + " | fwd=" + fwd.toString().slice(0, 100) + " back=" + back.toString().slice(0, 100));
692
+ } catch (e) {
693
+ console.log("ERROR | inv_" + ops[oi] + " => " + e.message);
694
+ }
695
+ }
696
+
697
+ console.log("\n=== inv hyperoperations > MSI ===");
698
+ for (var oi = 0; oi < invOps.length; oi++) {
699
+ try {
700
+ var fwd = m10[ops[oi]](mBigBase);
701
+ var back = fwd[invOps[oi]](m10);
702
+ console.log("PASS | " + invOps[oi] + " | fwd=" + fwd.toString().slice(0,100) + " back=" + back.toString().slice(0,100));
703
+ } catch (e) {
704
+ console.log("FAIL | " + invOps[oi] + " => " + e.message);
705
+ }
706
+ }
707
+
708
+ // bug: epsl(3,epsl(3,3)) should return infinity because it reaches metanum.js limit.
709
+
710
+ // hyperoperation iteration tests
711
+ var hyperOpList = [
712
+ ["aper", "aperiote"],
713
+ ["expa", "expande"],
714
+ ["muea", "multiexpande"],
715
+ ["poea", "powerexpande"],
716
+ ["apea", "aperioexpande"],
717
+ ["expl", "explode"],
718
+ ["muel", "multiexplode"],
719
+ ["apel", "aperioexplode"],
720
+ ["deto", "detonate"],
721
+ ["apdt", "aperiodetonate"],
722
+ ["apeo", "aperionate"],
723
+ ["mego", "megote"],
724
+ ["mume", "multimegote"],
725
+ ["apmg", "aperimegote"],
726
+ ["mgea", "megoexpande"],
727
+ ["apme", "aperimegoexpande"],
728
+ ["mgao", "megoaperionate"],
729
+ ["gigo", "gigote"],
730
+ ["apgg", "aperigigote"],
731
+ ["ggap", "gigoaperionate"],
732
+ ["apat", "aperiatote"],
733
+ ["pwan", "powiainate"],
734
+ ["epan", "expandainate"],
735
+ ["mgan", "megodainate"],
736
+ ["pwar", "powiairate"],
737
+ ["apgu", "aperioguate"],
738
+ ["iter", "iter"],
739
+ ["itmu", "itermult"],
740
+ ["cube", "cuboiter"],
741
+ ["expo", "expoiter"],
742
+ ["tria", "trioterate"],
743
+ ["trix", "trixxate"],
744
+ ["apix", "aperixxate"],
745
+ ["epsl", "epsilonate"]
746
+ ];
747
+
748
+ // ─── double nested iteration ───
749
+ console.log("\n=== hyperoperation iteration tests (not fully implemented) ===");
750
+ for (var hi = 0; hi < hyperOpList.length; hi++) {
751
+ var shortName = hyperOpList[hi][0];
752
+ var methodName = hyperOpList[hi][1];
753
+ try{
754
+ var res = m3[methodName](m3[methodName](3));
755
+ console.log("PASS | " + shortName + "(3," + shortName + "(3,3)) | " + res.toString().slice(0,100));
756
+ } catch (e) {
757
+ console.log("FAIL | " + shortName + "(3," + shortName + "(3,3)) => " + e.message);
758
+ }
759
+ }
760
+
761
+ // ─── triple nested iteration ───
762
+ console.log("\n=== triple nested hyperoperation tests ===");
763
+ for (var hi = 0; hi < hyperOpList.length; hi++) {
764
+ var shortName = hyperOpList[hi][0];
765
+ var methodName = hyperOpList[hi][1];
766
+ try{
767
+ var res = m3[methodName](m3[methodName](m3[methodName](3)));
768
+ console.log("PASS | " + shortName + "(3," + shortName + "(3," + shortName + "(3,3))) | " + res.toString().slice(0,100));
769
+ } catch (e) {
770
+ console.log("FAIL | " + shortName + "(3," + shortName + "(3," + shortName + "(3,3))) => " + e.message);
771
+ }
772
+ }
773
+
774
+ console.log("\n=== big ordinal annex small ordinal tests x=QqQe308 ===");
775
+ var ordq=MetaNum.QqQe308
776
+ for (var oi = 0; oi < ops.length; oi++) {
777
+ try {
778
+ var res = ordq[ops[oi]](m3);
779
+ console.log("PASS | " + ops[oi] + "(QqQe308,3) | " + res.toString().slice(0,100));
780
+ } catch (e) {
781
+ console.log("FAIL | " + ops[oi] + "(QqQe308,3) => " + e.message);
782
+ }
783
+ }
784
+
785
+ console.log("\n=== big ordinal annex small ordinal tests y=QqQe308 ===");
786
+ for (var oi = 0; oi < ops.length; oi++) {
787
+ try {
788
+ var res = ordq[ops[oi]](m3);
789
+ console.log("PASS | " + ops[oi] + "(3,QqQe308) | " + res.toString().slice(0,100));
790
+ } catch (e) {
791
+ console.log("FAIL | " + ops[oi] + "(3,QqQe308) => " + e.message);
792
+ }
793
+ }
794
+
795
+ // ─────────────────────────────────────
796
+ // Large-cardinal hyperoperation correctness (input > 10^16)
797
+ // Verifies: (1) metaFiniteCount extracts the iteration count instead of collapsing
798
+ // toNumber() = Infinity → 0(count row is non - zero and grows with y)
799
+ // (2) compareTo ranks an ω - level ordinal row above any
800
+ // number of finite-level rows, so op(x,·) is monotone across the
801
+ // 10^16 boundary (aperiote(1e8) < aperiote(1e16)) (well-ordered)
802
+ // ─────────────────────────────────────
803
+ console.log("\n=== hyperoperation large-cardinal (x > 10^16) ===");
804
+
805
+ function checkArr(name, m, expectedArray) {
806
+ try {
807
+ var got = JSON.stringify(m.array);
808
+ var exp = JSON.stringify(expectedArray);
809
+ var pass = got === exp;
810
+ console.log((pass ? "PASS" : "FAIL") + " | " + name + " | " + got);
811
+ if (!pass) console.log(" Expected: " + exp);
812
+ } catch (e) {
813
+ console.log("ERROR | " + name + " => " + e.message);
814
+ }
815
+ }
816
+
817
+ var mL8 = MetaNum(1e8);
818
+ var mL12 = MetaNum(1e12);
819
+ var mL16 = MetaNum(1e16);
820
+
821
+ // --- monotonicity across the 10^16 boundary (comparison fix) ---
822
+ checkBool("mono aper 1e8<1e12<1e16",
823
+ mL8.aperiote(mL8).lt(mL12.aperiote(mL12)) && mL12.aperiote(mL12).lt(mL16.aperiote(mL16)), true);
824
+ checkBool("mono expa(·,3) 1e8<1e16", mL8.expande(3).lt(mL16.expande(3)), true);
825
+ checkBool("mono muea(·,3) 1e8<1e16", mL8.multiexpande(3).lt(mL16.multiexpande(3)), true);
826
+ checkBool("mono poea(·,3) 1e8<1e16", mL8.powerexpande(3).lt(mL16.powerexpande(3)), true);
827
+
828
+ // --- count not zeroed: result strictly grows with y (metaFiniteCount fix) ---
829
+ checkBool("expa(1e16,3) > expa(1e16,2)", mL16.expande(3).gt(mL16.expande(2)), true);
830
+ checkBool("muea(1e16,3) > muea(1e16,2)", mL16.multiexpande(3).gt(mL16.multiexpande(2)), true);
831
+ checkBool("poea(1e16,3) > poea(1e16,2)", mL16.powerexpande(3).gt(mL16.powerexpande(2)), true);
832
+ checkBool("expa(1e16,5) > expa(1e16,3)", mL16.expande(5).gt(mL16.expande(3)), true);
833
+ checkBool("muea(1e16,5) > muea(1e16,3)", mL16.multiexpande(5).gt(mL16.multiexpande(3)), true);
834
+ checkBool("poea(1e16,5) > poea(1e16,3)", mL16.powerexpande(5).gt(mL16.powerexpande(3)), true);
835
+
836
+ // --- array structure snapshots (count correctly stored, not collapsed to 0) ---
837
+ // expande: count row [y-2,0,1] is at ω-level, same as aperiote's [1,0,1], so they
838
+ // merge → [1+(y-2),0,1] = [y-1,0,1]. For y=3 that is [2,0,1].
839
+ checkArr("expande(1e16,3) array", mL16.expande(3), [[16, 1], [2, 0, 1]]);
840
+ // multiexpande (ω+2): 1e16{ω+1}1e16{ω+1}1e16 → count row [2,1,1] at ω+1.
841
+ checkArr("multiexpande(1e16,3) array", mL16.multiexpande(3), [[16, 1], [2, 1, 1]]);
842
+ // powerexpande (ω+3): count row [2,2,1] at ω+2.
843
+ checkArr("powerexpande(1e16,3) array", mL16.powerexpande(3), [[16, 1], [2, 2, 1]]);
844
+
845
+ // --- y > MSI: result diagonalizes to y plus one α-level row (no counts > MSI) ---
846
+ // x{α}y ≈ 10{α}y → y's own representation + marker row [1|α]
847
+ checkArr("aperiote(3,1e16) array", m3.aperiote(mL16), [[16, 1], [1, 0, 1]]);
848
+ // rule 3: 1e16{ω}3 = 1e16{3}1e16 — the huge base dominates, same marker
849
+ // array as the y>MSI case
850
+ checkArr("aperiote(1e16,3) array", mL16.aperiote(3), [[16, 1, 0, 1]]);
851
+ checkArr("expande(3,1e16) array", m3.expande(mL16), [[16, 1], [1, 1, 1]]);
852
+ checkArr("multiexpande(3,1e16) array", m3.multiexpande(mL16), [[16, 1], [1, 2, 1]]);
853
+ checkArr("powerexpande(3,1e16) array", m3.powerexpande(mL16), [[16, 1], [1, 3, 1]]);
854
+ checkArr("powiainate(3,1e16) array", m3.powiainate(mL16), [[16, 1], [1, 1, 0, 0, 1]]);
855
+ // beyond 10{100}10: y itself carries a compact finite-level ordinal row
856
+ // finite levels beyond r0 capacity expand into a cascade
857
+ // of [count, level] rows within the maxRows budget; beyond the budget the
858
+ // approximation keeps the largest maxRows-1 rows and bumps the second row.
859
+ var mArrow1000 = MetaNum.arrow(10, 1000, 10);
860
+ checkArr("arrow(10,1000,10) array", mArrow1000,
861
+ [[10], [9, 981], [8, 982], [8, 983], [8, 984], [8, 985], [8, 986], [8, 987], [8, 988], [8, 989], [8, 990], [8, 991], [8, 992], [8, 993], [8, 994], [8, 995], [8, 996], [8, 997], [8, 998], [8, 999]]);
862
+ checkArr("powiainate(3,arrow(10,1000,10)) array", m3.powiainate(mArrow1000),
863
+ [[10], [9, 982], [8, 983], [8, 984], [8, 985], [8, 986], [8, 987], [8, 988], [8, 989], [8, 990], [8, 991], [8, 992], [8, 993], [8, 994], [8, 995], [8, 996], [8, 997], [8, 998], [8, 999], [1, 1, 0, 0, 1]]);
864
+
865
+ // --- inverse roundtrip recovers y exactly (multiexpande / powerexpande) ---
866
+ // Because the count rows live at ω+1 / ω+2 (not the base ω-level), they do not
867
+ // merge with aperiote's [1,0,1] row, so inv_* recovers y rather than y+1.
868
+ checkBool("inv_multiexpande(1e16{ω+2}3,1e16)=3", mL16.multiexpande(3).inv_multiexpande(mL16).eq(MetaNum(3)), true);
869
+ checkBool("inv_powerexpande(1e16{ω+3}3,1e16)=3", mL16.powerexpande(3).inv_powerexpande(mL16).eq(MetaNum(3)), true);
870
+ checkBool("inv_multiexpande(1e16{ω+2}5,1e16)=5", mL16.multiexpande(5).inv_multiexpande(mL16).eq(MetaNum(5)), true);
871
+ checkBool("inv_powerexpande(1e16{ω+3}5,1e16)=5", mL16.powerexpande(5).inv_powerexpande(mL16).eq(MetaNum(5)), true);
872
+ // Small-x finite branch (base has no ω-row): inv_expande is exact too.
873
+ checkBool("inv_expande(3{ω+1}5,3)=5", MetaNum(3).expande(5).inv_expande(MetaNum(3)).eq(MetaNum(5)), true);
874
+
875
+ // ─────────────────────────────────────
876
+ // engine arrays: the (y-2) count law
877
+ // x{L}y = x{L-1}^{y-2}(x{L-1}x): 10{25}10 → count-8 rows/cols (the
878
+ // canonical all-8s), 4{25}4 → count-2; truncation keeps the largest
879
+ // maxRows-1 rows, second-kept row +1, first row [10]
880
+ // ─────────────────────────────────────
881
+ console.log("\n=== engine arrays ===");
882
+ checkBool("10{25}10 exact: all-8s r0 + [8,20..24] rows",
883
+ JSON.stringify(MetaNum.arrow(10, 25, 10).array)
884
+ === JSON.stringify([[10000000000,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8],
885
+ [8,20],[8,21],[8,22],[8,23],[8,24]]), true);
886
+ checkBool("4{25}4 exact: count-2 chain",
887
+ JSON.stringify(MetaNum.arrow(4, 25, 4).array)
888
+ === JSON.stringify([[153.90699754796802,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
889
+ [2,20],[2,21],[2,22],[2,23],[2,24]]), true);
890
+ checkBool("10{10000}10 truncated: [9,9981],[8,9982]…[8,9999], r0 [10]",
891
+ JSON.stringify(MetaNum.arrow(10, 10000, 10).array).indexOf("[[10],[9,9981],[8,9982],[8,9983]") === 0 &&
892
+ JSON.stringify(MetaNum.arrow(10, 10000, 10).array.slice(-1)) === "[[8,9999]]", true);
893
+
894
+ // ─────────────────────────────────────
895
+ // BEAF ordinal nesting (convention: BEAF(a,b,c,d)=a{ω*(d-1)+c}b —
896
+ // the constant term keeps its value, ω+ coefficients decrement by 1)
897
+ // Nested huge args anchor at the inner value and add one ordinal row:
898
+ // BEAF(inner,2,3,5) = inner{ω*4+3}2 = inner{ω*4+2}inner → inner + [1|ω*4+2]
899
+ // BEAF(4,inner,3,5) = 4{ω*4+3}inner → inner + [1|ω*4+3]
900
+ // BEAF(4,2,inner,5) = 4{ω*4+inner}2 = 4{ω*5}inner → inner + [1|ω*5]
901
+ // BEAF(4,2,3,inner) = 4{ω*inner+3}2 = 4{ω²}inner → inner + [1|ω²]
902
+ // ─────────────────────────────────────
903
+ console.log("\n=== BEAF ordinal nesting ===");
904
+ checkOp("BEAF(3,3,2)", MetaNum.BEAF(3, 3, 2), 7625597484987, 0);
905
+ checkBool("BEAF(2,2,1,2)", MetaNum.BEAF(2, 2, 1, 2).eq(4), true);
906
+ var beafInner = MetaNum.BEAF(4, 2, 3, 5); // 4{ω*4+3}2 = 4{ω*4+2}(4{ω*4+2}(4{ω*4+1}...))
907
+ checkBool("BEAF(4,2,3,5) top row [2,1,4]",
908
+ JSON.stringify(beafInner.array[beafInner.array.length - 1]) === JSON.stringify([2, 1, 4]), true);
909
+ checkArr("BEAF(BEAF(4,2,3,5),2,3,5)", MetaNum.BEAF(beafInner, 2, 3, 5),
910
+ beafInner.array.concat([[1, 2, 4]]));
911
+ checkArr("BEAF(4,BEAF(4,2,3,5),3,5)", MetaNum.BEAF(4, beafInner, 3, 5),
912
+ beafInner.array.concat([[1, 3, 4]]));
913
+ checkArr("BEAF(4,2,BEAF(4,2,3,5),5)", MetaNum.BEAF(4, 2, beafInner, 5),
914
+ beafInner.array.concat([[1, 0, 5]]));
915
+ checkArr("BEAF(4,2,3,BEAF(4,2,3,5))", MetaNum.BEAF(4, 2, 3, beafInner),
916
+ beafInner.array.concat([[1, 0, 0, 1]]));
917
+ var beafInner5 = MetaNum.BEAF(5, 5, 5, 5, 5);
918
+ // ω²-level huge arg: the outer keeps inner's ordinal rows except the smallest
919
+ // (dropped at row capacity), base stays [10], first kept row count +1 (the
920
+ // truncation marker), plus the new [1|ω⁴] anchor row
921
+ var beafOuter5Exp = [[10]].concat(beafInner5.array.slice(2)).concat([[1, 0, 0, 0, 1]]);
922
+ beafOuter5Exp[1] = beafOuter5Exp[1].slice();
923
+ beafOuter5Exp[1][0] += 1;
924
+ checkArr("BEAF(5,5,5,5,BEAF(5,5,5,5,5))", MetaNum.BEAF(5, 5, 5, 5, beafInner5),
925
+ beafOuter5Exp);
926
+ // ─────────────────────────────────────
927
+ // BEAF(a,b,c,d,...) = a{...+ω^2*(e-1)+ω*(d-1)+c}b (constant term = args[2])
928
+ // expansion: largest-to-smallest evaluation; exact when it fits maxRows-1
929
+ // rows, else base [10] + first kept row count +1
930
+ // ─────────────────────────────────────
931
+ // {2,7,5,5} = 2{ω*4+5}7: rule 3 ends every limit step on the base 2, and
932
+ // 2-2=0 means every cascade count vanishes; 2{α}2 collapses through
933
+ // successors/limits down to the finite anchor 2{k}2=4 — result is exactly 4
934
+ checkBool("BEAF(2,7,5,5) = 4 (base-2 rule-3 collapse)",
935
+ MetaNum.BEAF(2, 7, 5, 5).eq(4), true);
936
+ // {3,2,4,6} = 3{ω*5+4}2
937
+ checkBool("BEAF(3,2,4,6) top row [1,2,5]",
938
+ JSON.stringify(MetaNum.BEAF(3, 2, 4, 6).array[MetaNum.BEAF(3, 2, 4, 6).array.length - 1])
939
+ === JSON.stringify([1, 2, 5]), true);
940
+ // BEAF(3,3,5,5,5) = 3{ω^2*4+ω*4+5}3: exact enumeration needs 49 ordinal rows
941
+ // (> default maxRows=20), so raise the budget for this case only
942
+ var _savedRowsBEAF = MetaNum.maxRows;
943
+ MetaNum.maxRows = 100;
944
+ var beaf35555 = MetaNum.BEAF(3, 3, 5, 5, 5);
945
+ checkBool("BEAF(3,3,5,5,5) exact (base kept, [1,0,1] first, [1,4,4,4] last)",
946
+ beaf35555.array.length <= MetaNum.maxRows
947
+ && JSON.stringify(beaf35555.array[0]) === JSON.stringify([3638334640023.7783, 7625597484984])
948
+ && JSON.stringify(beaf35555.array[1]) === JSON.stringify([1, 0, 1])
949
+ && JSON.stringify(beaf35555.array[beaf35555.array.length - 1]) === JSON.stringify([1, 4, 4, 4]), true);
950
+ MetaNum.maxRows = _savedRowsBEAF;
951
+ // BEAF(5,5,1,1,1,2) = 5{ω^3+1}5: truncated expansion
952
+ var beaf511112 = MetaNum.BEAF(5, 5, 1, 1, 1, 2);
953
+ checkBool("BEAF(5,5,1,1,1,2) truncated ([10] base, first count 4, last [3,0,0,0,1])",
954
+ JSON.stringify(beaf511112.array[0]) === JSON.stringify([10])
955
+ && beaf511112.array[1][0] === 4
956
+ && JSON.stringify(beaf511112.array[beaf511112.array.length - 1]) === JSON.stringify([3, 0, 0, 0, 1])
957
+ && beaf511112.array.length === MetaNum.maxRows, true);
958
+
959
+ // ─────────────────────────────────────
960
+ // Hardy hierarchy — ALL hardy verifications grouped here
961
+ // reorganization: small-level, per-definition nested exponents, >1e15
962
+ // inputs, MetaNum-object inputs and the 10^^MSI engine limit)
963
+ // hardy(n) = H_α(10); hardy(10) = H_ω(10) = 20; digits of n become CNF coefficients
964
+ // hardy per definition, evaluated from below
965
+ // hardy(1e10) = H_{ω^ω}(10) = H_{ω^10}(10) — EXACT array
966
+ // [3086.036065328153, 9×8], strictly below 10{10}10
967
+ // hardy(1e11) = H_{ω^(ω+1)}(10) — expande(10,10)'s row structure on the
968
+ // definitional base, strictly below 10{ω+1}10
969
+ // monotone: hardy(9999999999) < hardy(1e10) < hardy(10000000001)
970
+ // (moved into the "hardy hierarchy (all cases)" section below
971
+ // reorganization groups every hardy verification together)
972
+ // ─────────────────────────────────────
973
+ console.log("\n=== hardy hierarchy (all cases) ===");
974
+ // -- small levels (exact closed forms) --
975
+ checkOp("hardy(0)", MetaNum.hardy(0), 10, 0);
976
+ checkOp("hardy(9)", MetaNum.hardy(9), 19, 0);
977
+ checkBool("hardy(10) = H_ω(10) = 20", MetaNum.hardy(10).eq(20), true);
978
+ checkBool("hardy(11) = H_{ω+1}(10) = 22", MetaNum.hardy(11).eq(22), true);
979
+ checkBool("hardy(20) = H_{ω*2}(10) = 40", MetaNum.hardy(20).eq(40), true);
980
+ checkBool("hardy(99) = H_{ω*9+9}(10) = 9728", MetaNum.hardy(99).eq(9728), true);
981
+ checkBool("hardy(100) = H_{ω^2}(10) = 10240", MetaNum.hardy(100).eq(10240), true);
982
+ checkBool("hardy(101) = H_{ω^2+1}(10) = 22528", MetaNum.hardy(101).eq(22528), true);
983
+ checkBool("hardy(1234) = H_{ω^3+ω^2*2+ω*3+4}(10) > 10↑↑1000",
984
+ MetaNum.hardy(1234).gt(MetaNum(10).arrow(2)(1000)), true);
985
+ checkBool("hardy monotone: 999 < 1000", MetaNum.hardy(999).lt(MetaNum.hardy(1000)), true);
986
+ checkBool("hardy(12345) > hardy(1234)", MetaNum.hardy(12345).gt(MetaNum.hardy(1234)), true);
987
+ // -- nested exponents, per definition & evaluated from below (v2.0) --
988
+ checkBool("hardy(1e10) = H_{ω^10}(10) exact array [3086.036, 9×8]",
989
+ JSON.stringify(MetaNum.hardy(1e10).array)
990
+ === JSON.stringify([[3086.036065328153, 9, 9, 9, 9, 9, 9, 9, 9]]), true);
991
+ checkBool("hardy(1e10) < 10{10}10",
992
+ MetaNum.hardy(1e10).lt(MetaNum(10).arrow(10)(10)), true);
993
+ checkBool("hardy(1e11) = H_{ω^(ω+1)}(10) < 10{ω+1}10 (expande)",
994
+ MetaNum.hardy(1e11).lt(MetaNum(10).expande(10)), true);
995
+ checkBool("hardy monotone 9999999999 < 1e10 < 10000000001",
996
+ MetaNum.hardy(9999999999).lt(MetaNum.hardy(1e10))
997
+ && MetaNum.hardy(1e10).lt(MetaNum.hardy(10000000001)), true);
998
+ checkBool("hardy(1e12) > hardy(1e11) (monotone in scale)",
999
+ MetaNum.hardy(1e12).gt(MetaNum.hardy(1e11)), true);
1000
+ // -- >1e15 inputs (v2.0): scientific-notation strings expand to exact
1001
+ // digits so the digit-CNF reading stays monotone past 1e20 --
1002
+ checkBool("hardy(1e20) < hardy(1e21) < hardy(1e22) (sci-string fix)",
1003
+ MetaNum.hardy(1e20).lt(MetaNum.hardy(1e21))
1004
+ && MetaNum.hardy(1e21).lt(MetaNum.hardy(1e22)), true);
1005
+ checkBool("hardy(1e15) < hardy(1e16) < hardy(1e17)",
1006
+ MetaNum.hardy(1e15).lt(MetaNum.hardy(1e16))
1007
+ && MetaNum.hardy(1e16).lt(MetaNum.hardy(1e17)), true);
1008
+ // -- MetaNum-object input (v2.0): structures shadow to their ordinal --
1009
+ // power tower 10^^k → ω^ω^…^ω (k ω's) → H there = 10.epsilonate(k);
1010
+ // letter/ordinal values sit at their own Hardy position → themselves
1011
+ checkBool("hardy(10^^100) = 10{ω^…^ω(100 ωs)}10 = epsilonate(100)",
1012
+ MetaNum.hardy(MetaNum(10).tetr(100)).eq(MetaNum(10).epsilonate(100)), true);
1013
+ checkBool("hardy(MetaNum G600) = Infinity",
1014
+ MetaNum.hardy(MetaNum("G600")).eq(MetaNum.infinity), true);
1015
+ checkBool("hardy(MetaNum arrow(3,9,3)) = Infinity",
1016
+ MetaNum.hardy(MetaNum.arrow(3, 9, 3)).eq(MetaNum.infinity), true);
1017
+ // anything strictly above 10^^MSI exceeds the ε₀ ceiling → Infinity
1018
+ checkBool("hardy(10{3}10) = Infinity (> 10^^MSI)",
1019
+ MetaNum.hardy(MetaNum(10).arrow(3)(10)).isInfinite(), true);
1020
+ // -- the engine limit: hardy(10^^MSI) = 10{ω^…^ω(MSI ω's)}10 (v2.0) --
1021
+ (function () {
1022
+ var MSI = 9007199254740991;
1023
+ checkBool("hardy(10^^MSI) = MetaNum limit 10{ω^…^ω(MSI ω's)}10",
1024
+ MetaNum.hardy(MetaNum(10).tetr(MSI)).eq(MetaNum(10).epsilonate(MSI)), true);
1025
+ checkBool("hardy(10^^(MSI-1)) = epsilonate(MSI-1) (just below the cap)",
1026
+ MetaNum.hardy(MetaNum(10).tetr(MSI - 1)).eq(MetaNum(10).epsilonate(MSI - 1)), true);
1027
+ })();
1028
+
1029
+ // ─────────────────────────────────────
1030
+ // fractional hyperoperation levels
1031
+ // level n+f interpolates geometrically (README rule i): 10{n+f}10 =
1032
+ // 10{n+1}(2·5^f); continuous: f=0 → level n, f=1 → level n+1
1033
+ // ─────────────────────────────────────
1034
+ console.log("\n=== fractional levels ===");
1035
+ (function () {
1036
+ var a = MetaNum(10);
1037
+ var v3 = a.arrow(3)(10), v4 = a.arrow(4)(10);
1038
+ var v32 = a.arrow(3.2)(10), v35 = a.arrow(3.5)(10);
1039
+ checkBool("10{3.0}10 = 10{3}10 (f=0 anchor)", a.arrow(3.0)(10).eq(v3), true);
1040
+ checkBool("monotone 10{3}10 < 10{3.2}10 < 10{3.5}10 < 10{4}10",
1041
+ v3.lt(v32) && v32.lt(v35) && v35.lt(v4), true);
1042
+ // rule (i) verbatim: 10{3.5}10 = 10{4}(2·5^0.5)
1043
+ var theta = MetaNum(2).mul(MetaNum(10).div(2).pow(0.5));
1044
+ checkBool("10{3.5}10 = 10{4}(2·5^0.5)", v35.eq(a.arrow(4)(theta)), true);
1045
+ checkBool("3{2.5}3 between 3{2}3 and 3{3}3",
1046
+ MetaNum(3).arrow(2)(3).lt(MetaNum(3).arrow(2.5)(3)) &&
1047
+ MetaNum(3).arrow(2.5)(3).lt(MetaNum(3).arrow(3)(3)), true);
1048
+ })();
1049
+
1050
+ // ─────────────────────────────────────
1051
+ // non-integer arguments at ordinal levels
1052
+ // expa(10,2.1) = 10{ω+1}2.1 = 10{ω}10{ω}(10^0.1)
1053
+ // (continuity: expa(10,2) = 10{ω}10, expa(10,3) = 10{ω}10{ω}10)
1054
+ // ─────────────────────────────────────
1055
+ console.log("\n=== ordinal-level fractional arguments ===");
1056
+ (function () {
1057
+ var e2 = MetaNum(10).expande(2), e21 = MetaNum(10).expande(2.1),
1058
+ e25 = MetaNum(10).expande(2.5), e3 = MetaNum(10).expande(3);
1059
+ checkBool("expa(10,2) = 10{ω}10", e2.eq(MetaNum(10).aperiote(10)), true);
1060
+ checkBool("expa(10,3) = 10{ω}10{ω}10", e3.eq(MetaNum(10).aperiote(e2)), true);
1061
+ checkBool("expa(10,2.1) = 10{ω}10{ω}(10^0.1)",
1062
+ e21.eq(MetaNum(10).aperiote(MetaNum(10).aperiote(MetaNum(10).pow(0.1)))), true);
1063
+ checkBool("expa monotone 2 < 2.1 < 2.5 < 3",
1064
+ e2.lt(e21) && e21.lt(e25) && e25.lt(e3), true);
1065
+ var m21 = MetaNum(10).multiexpande(2.1);
1066
+ checkBool("muea(10,2.1) = 10{ω+2}2.1 = (10{ω+1})²(10^0.1)",
1067
+ m21.eq(MetaNum(10).expande(MetaNum(10).expande(MetaNum(10).pow(0.1)))), true);
1068
+ checkBool("poea(10,2.1) = 10{ω+3}2.1 = (10{ω+2})²(10^0.1)",
1069
+ MetaNum(10).powerexpande(2.1).eq(
1070
+ MetaNum(10).multiexpande(MetaNum(10).multiexpande(MetaNum(10).pow(0.1)))), true);
1071
+ checkBool("expa(10,3.1) computable", !MetaNum(10).expande(3.1).isNaN(), true);
1072
+ })();
1073
+
1074
+ console.log("\n=== Done ===");
1075
+
1076
+ // ─────────────────────────────────────
1077
+ // format() tests (25 cases covering small, sci, single-letter, multi-letter, ordinal)
1078
+ // ─────────────────────────────────────
1079
+ console.log("\n=== format() verification ===");
1080
+
1081
+ function checkFormat(name, input, expected) {
1082
+ try {
1083
+ var m = MetaNum(input);
1084
+ var s = format(m);
1085
+ var pass = s === expected;
1086
+ console.log((pass ? "PASS" : "FAIL") + " | fmt " + name + " | " + input + " => " + s + (pass ? "" : " (expected " + expected + ")"));
1087
+ } catch (e) {
1088
+ console.log("ERROR | fmt " + name + " | " + input + " => " + e.message);
1089
+ }
1090
+ }
1091
+
1092
+ // Small values & regular numbers
1093
+ checkFormat("1E-1000000", "1E-1000000", "1.000E-1,000,000"); // sign=2 reciprocal
1094
+ checkFormat("1E-100", "1E-100", "1.000E-100");
1095
+ checkFormat("0.123", "0.123", "0.123");
1096
+ checkFormat("456789", "456789", "456,789");
1097
+ checkFormat("1E100", "1E100", "1.000E100"); // α always shown
1098
+
1099
+ // Single-letter chains (E-Z range): outerLetters + α + lastLetter + β
1100
+ checkFormat("EE200", "EE200", "E1.000E200");
1101
+ checkFormat("F300", "F300", "1.000F300");
1102
+ checkFormat("FE400", "FE400", "F1.000E400");
1103
+ checkFormat("FF500", "FF500", "F1.000F500");
1104
+ checkFormat("G600", "G600", "1.000G600");
1105
+ checkFormat("GE700", "GE700", "G1.000E700");
1106
+ checkFormat("GF800", "GF800", "G1.000F800");
1107
+ checkFormat("GG900", "GG900", "G1.000G900");
1108
+ checkFormat("J1000", "J1000", "1.000J1,000");
1109
+
1110
+ // Ordinal (Aa and beyond) - single letter: α + letter + β
1111
+ checkFormat("Aa100", "Aa100", "2.000Aa100");
1112
+ checkFormat("Ab400", "Ab400", "1.000Ab400");
1113
+ checkFormat("Ac800", "Ac800", "1.000Ac800");
1114
+ checkFormat("Aj900", "Aj900", "1.000Aj900");
1115
+ checkFormat("Ba1000", "Ba1000", "2.000Ba1,000");
1116
+ checkFormat("Aaa100", "Aaa100", "2.000Aaa100");
1117
+
1118
+ // Ordinal with multi-level r0: ordinalLetter + r0Chain (includes α)
1119
+ checkFormat("AaE200", "AaE200", "Aa1.000E200");
1120
+ checkFormat("AbE500", "AbE500", "Ab1.000E500");
1121
+
1122
+ // Ordinal repeated letters: outerLetters + α + lastLetter + β
1123
+ checkFormat("AaAa300", "AaAa300", "Aa1.000Aa300");
1124
+ checkFormat("AbAa600", "AbAa600", "Ab1.000Aa600");
1125
+ checkFormat("AbAb700", "AbAb700", "Ab1.000Ab700");
1126
+
1127
+ // Ordinal more Letters:
1128
+ checkFormat("Abc100", "Abc100", "1.000Abc100");
1129
+ checkFormat("Defg200", "Defg200", "1.000Defg200");
1130
+
1131
+ // Symbols and ε:
1132
+ checkFormat("!Aa300", "!Aa300", "!2.000Aa300");
1133
+ checkFormat("@Bb400", "@Bb400", "@1.000Bb400");
1134
+ checkFormat("1ε500", "1ε500", "1.000ε500");
1135
+
1136
+ // Reciprocal of large numbers (sign=2) format tests
1137
+ // smallNotationUseE=true → E-<formatted mag>
1138
+ // smallNotationUseE=false → <formatted value>⁻¹
1139
+ console.log("\n=== reciprocal format tests ===");
1140
+
1141
+ // Parsing: verify sign=2 and array structure
1142
+ check("E-EE1000 parse", "E-EE1000", [[1000, 3]]);
1143
+ check("1/F500 parse", "1/F500", [[10000000000, 498]]);
1144
+ check("1/G200 parse", "1/G200", [[10000000000, 8, 198]]);
1145
+ check("1/F10 parse", "1/F10", [[10000000000, 8]]);
1146
+
1147
+ // format() with smallNotationUseE=true (default):
1148
+ // E-EE1000 = 10^(-log10(EE1000)) = 10^(-E1000) → "E-E1.000E1,000"
1149
+ // 1/F500 = 10^(-log10(F500)) = 10^(-F499) → "E-1.000F499"
1150
+ // 1/G200 = 10^(-log10(G200)) ≈ 10^(-G200) → "E-1.000G200" (TMSI: G200>TMSI)
1151
+ // 1/F10 = 10^(-log10(F10)) = 10^(-F9) → "E-1.000F9"
1152
+ checkFormat("E-EE1000 (useE=true)", "E-EE1000", "E-E1.000E1,000");
1153
+ checkFormat("1/F500 (useE=true)", "1/F500", "E-1.000F499");
1154
+ checkFormat("1/G200 (useE=true)", "1/G200", "E-1.000G200");
1155
+ checkFormat("1/F10 (useE=true)", "1/F10", "E-1.000F9");
1156
+
1157
+ // format() with smallNotationUseE=false:
1158
+ // E-EE1000 → "EE1.000E1,000⁻¹"
1159
+ // 1/F500 → "1.000F500⁻¹"
1160
+ // 1/G200 → "1.000G200⁻¹"
1161
+ // 1/F10 → "1.000F10⁻¹"
1162
+ var _FMT = (typeof FORMAT_OPTIONS !== "undefined" && FORMAT_OPTIONS) ? FORMAT_OPTIONS : require("./format-metanum.js").FORMAT_OPTIONS;
1163
+ var _savedUseE = _FMT.smallNotationUseE;
1164
+ _FMT.smallNotationUseE = false;
1165
+ checkFormat("E-EE1000 (useE=false)", "E-EE1000", "EE1.000E1,000⁻¹");
1166
+ checkFormat("1/F500 (useE=false)", "1/F500", "1.000F500⁻¹");
1167
+ checkFormat("1/G200 (useE=false)", "1/G200", "1.000G200⁻¹");
1168
+ checkFormat("1/F10 (useE=false)", "1/F10", "1.000F10⁻¹");
1169
+ _FMT.smallNotationUseE = _savedUseE;
1170
+
1171
+ console.log("\n=== format α correctness ===");
1172
+ // format α correctness
1173
+ checkFormat("hardy(1120) single α", MetaNum.hardy(1120), "F4.398E13");
1174
+ checkFormat("hardy(4150) real α", MetaNum.hardy(4150), "2.300G5");
1175
+ checkFormat("nested arrow single α", MetaNum.arrow(3, MetaNum.arrow(3, 4, 3), 3), "AaGF7.626E12");
1176
+ checkFormat("canonical all-8s keeps α=1 (G600)", "G600", "1.000G600");
1177
+
1178
+ // ─────────────────────────────────────
1179
+ // display rules: at most TWO letter types, one α, multiLetterLimit symbol
1180
+ // carry — a cascade that would spell 20 letter types keeps its top two levels,
1181
+ // and a combination longer than multiLetterLimit switches to !αAaβ
1182
+ // ─────────────────────────────────────
1183
+ checkFormat("20-row cascade compresses to one type", MetaNum.h10000(3, 10), "1.000Iccc19");
1184
+ checkFormat("10-letter level carries to !…Aa9 (definition digits)", MetaNum.iter(3, 10), "!2.222Aa9");
1185
+ checkFormat("5-letter level carries to !…Aa4 (definition digits)", m3.iter(5), "!2.222Aa4");
1186
+ checkFormat("symbol carry stacks: apix(3,10) → @…Aa10", m3.aperixxate(10), "@2.000Aa10");
1187
+ checkFormat("symbol carry stacks: apix(3,5) → @…Aa5", m3.aperixxate(5), "@2.000Aa5");
1188
+ checkFormat("short diagonal keeps the letter form", m3.aperixxate(3), "!2.000Aaaa10");
1189
+ checkFormat("cascade inner α stays [1,10) (AbAa600)", "AbAa600", "Ab1.000Aa600");
1190
+
1191
+ // Γ-canonical law test: long descending count-1 chains
1192
+ // format at their bisect-exact letter on the engine's smooth arrow curve;
1193
+ // ordinal-row levels use Aa-notation (the engine's fractional-arg curve is
1194
+ // quantized at level ≥ 20, so 3{20}3 formats via its [1,20] ordinal row)
1195
+ checkFormat("GE12 single-alpha", "GE12", "G1.000E12");
1196
+ checkFormat("arrow(3,19,3) structural V...U...", MetaNum.arrow(3, 19, 3), "V2.376U2");
1197
+ checkFormat("arrow(3,20,3) structural W...V...", MetaNum.arrow(3, 20, 3), "W2.376V2");
1198
+ checkFormat("arrow(3,1000,3) αAaβ", MetaNum.arrow(3, 1000, 3), "2.376Aa999");
1199
+
1200
+ // ─────────────────────────────────────
1201
+ // maxCols/maxRows = 20 — r0 overflow levels must become
1202
+ // finite-level ordinal rows [count, level], not be dropped
1203
+ // ─────────────────────────────────────
1204
+ console.log("\n=== maxCols/maxRows = 20 (Z10) ===");
1205
+ var _savedCols = MetaNum.maxCols, _savedRows = MetaNum.maxRows;
1206
+ MetaNum.maxCols = 20; MetaNum.maxRows = 20;
1207
+ (function () {
1208
+ var exp = [[10000000000]];
1209
+ for (var i = 0; i < 19; i++) exp[0].push(8);
1210
+ var z20 = new MetaNum("Z10");
1211
+ checkArr("Z10 @ maxCols=20", z20, exp.concat([[8, 20], [8, 21]]));
1212
+ var z20rt = new MetaNum(z20.toString());
1213
+ checkBool("Z10 @ maxCols=20 roundtrip", z20.eq(z20rt), true);
1214
+ MetaNum.maxCols = 100; MetaNum.maxRows = 100;
1215
+ var z20v100 = new MetaNum(z20.toString());
1216
+ checkBool("Z10 @20 toString reparsed @100 ~= Z10 @100", z20v100.eq(new MetaNum("Z10")), true);
1217
+ })();
1218
+ MetaNum.maxCols = _savedCols; MetaNum.maxRows = _savedRows;
1219
+
1220
+ // ─────────────────────────────────────
1221
+ // symbol layer semantics (numeric-level assertions)
1222
+ // ! = one ω^ layer: !Aa5 = 10{ω^ω}5 = 10{ω^5}5 (FS of ω^ω at 5)
1223
+ // @ = two layers: @Aa5 = 10{ω^ω^ω}5 = 10{ω^(ω^5)}5
1224
+ // # = three layers; !Ab5 = 10{ω^(ω+1)}5
1225
+ // ─────────────────────────────────────
1226
+ console.log("\n=== symbol layer semantics ===");
1227
+ (function () {
1228
+ var om5row = JSON.stringify([1, 0, 0, 0, 0, 0, 1]); // [1 | ω^5] marker row
1229
+ var x = MetaNum("!Aa5");
1230
+ checkBool("!Aa5 = 10{ω^5}5 marker row", JSON.stringify(x.array[1]) === om5row && x.array.length === 2, true);
1231
+ checkBool("!Aa5 de-layers to Aaaaaa5", x.eq(MetaNum("Aaaaaa5")), true);
1232
+ checkBool("!1.000Aa5 = !Aa5 (binary form α=1)", MetaNum("!1.000Aa5").eq(x), true);
1233
+ var y = MetaNum("@Aa5");
1234
+ checkBool("@Aa5 = !Aaaaaa5 (two ω^ layers)", y.eq(MetaNum("!Aaaaaa5")), true);
1235
+ checkBool("@Aa5 layer=1 with ω^5 row", y.layer === 1 && JSON.stringify(y.array[1]) === om5row, true);
1236
+ checkBool("@1.000Aa5 = @Aa5", MetaNum("@1.000Aa5").eq(y), true);
1237
+ var z = MetaNum("#Aa5");
1238
+ checkBool("#Aa5 = @Aaaaaa5 (three ω^ layers)", z.eq(MetaNum("@Aaaaaa5")), true);
1239
+ checkBool("#Aa5 layer=2", z.layer === 2, true);
1240
+ var ab = MetaNum("!Ab5");
1241
+ checkBool("!Ab5 = 10{ω^(ω+1)}5 (layer 1, row [1,1,1])",
1242
+ ab.layer === 1 && JSON.stringify(ab.array[1]) === JSON.stringify([1, 1, 1]), true);
1243
+ checkBool("!Ba5 = 10{ω^(ω*2)}5 (layer 1, row [1,0,2])",
1244
+ MetaNum("!Ba5").layer === 1 && JSON.stringify(MetaNum("!Ba5").array[1]) === JSON.stringify([1, 0, 2]), true);
1245
+ checkBool("layer monotonicity Aa5 < !Aa5 < @Aa5 < #Aa5",
1246
+ MetaNum("Aa5").lt(x) && x.lt(y) && y.lt(z), true);
1247
+ checkBool("!Ab5 > !Aa5", ab.gt(x), true);
1248
+ checkRT("!Aa5", "!Aa5");
1249
+ checkRT("@Aa5", "@Aa5");
1250
+ checkRT("#Aa5", "#Aa5");
1251
+ checkRT("!Ab5", "!Ab5");
1252
+ })();
1253
+
1254
+ console.log("\n=== two-letter rule ===");
1255
+ (function () {
1256
+ // Rule (2-letter rule): a display may use at most 2 letter COMBINATIONS in its
1257
+ // finite hyper-op chain — VαEβ → VαFβ → … → VαVβ — never a third type mixed
1258
+ // in (e.g. "VFαEβ"). The rule is about the single-uppercase finite letters
1259
+ // (E,F,G,...,Z): the Aa/Ab/... two-char tokens are ordinal-structure
1260
+ // markers (same role as !/@/#! symbols), and an "E" inside a number
1261
+ // ("7.626E12") is scientific notation, not a letter op — both are excluded
1262
+ // from the count. The reference formatter (format-powiainanum.js) produces
1263
+ // the same shapes: "J" + "GF7.626E12" for arrow(3,arrow(3,4,3),3).
1264
+ var samples = ["V10", "VE10", "VF10", "W10", "G1.161G897", "AaGF7.626E12",
1265
+ "2.397G5", "1.285H8", "2.376W2", "1.125Aa99", "F4.398E13", "GF7.626E12"];
1266
+ var allOk = true;
1267
+ for (var i = 0; i < samples.length; i++) {
1268
+ var disp = format(MetaNum(samples[i]));
1269
+ // strip scientific-notation E inside numbers ("7.626E12"), then count
1270
+ // distinct single-uppercase letters (Aa-style ordinal tokens excluded)
1271
+ var stripped = disp.replace(/(\d(?:\.\d+)?)E(\d[\d,]*)/g, "$1$2");
1272
+ var tokens = stripped.match(/[A-Z](?![a-z])/g) || [];
1273
+ var types = {};
1274
+ for (var t = 0; t < tokens.length; t++) types[tokens[t]] = true;
1275
+ var nTypes = Object.keys(types).length;
1276
+ if (nTypes > 2) {
1277
+ allOk = false;
1278
+ console.log(" >2 finite letter types in", samples[i], "→", disp);
1279
+ }
1280
+ }
1281
+ checkBool("all displays use ≤ 2 finite letter types", allOk, true);
1282
+ checkBool("arrow(3,4.1,3) display has exactly G only (VαEβ→…→VαVβ law)",
1283
+ (format(MetaNum.arrow(3, 4.1, 3)).match(/[A-Z][a-z]?/g) || []).every(function (tk) { return tk === "G"; }), true);
1284
+ // round-trip of the Aa-prefixed sci-arg chain (parse bug fix in v2.0:
1285
+ // "AaGF7.626E12" used to eat only the "7" and drop ".626E12")
1286
+ checkBool("AaGF7.626E12 parses with full sci arg",
1287
+ MetaNum("AaGF7.626E12").array[0][1] === 7625999999998
1288
+ && MetaNum("AaGF7.626E12").array.length === 2, true);
1289
+ checkBool("AaGF7.626E12 round-trips through format",
1290
+ format(MetaNum(format(MetaNum("AaGF7.626E12")))) === "AaGF7.626E12", true);
1291
+ })();
1292
+
1293
+ // ─────────────────────────────────────
1294
+ // hardy hierarchy — display-form verification (all user cases)
1295
+ // ≤2 letter types per display; diagonal cascades compress to the
1296
+ // structural two-letter form or the αAaβ polarize diagonal;
1297
+ // repeatLetterThreshold+1 repeated single letters carry to the next
1298
+ // ─────────────────────────────────────
1299
+ console.log("\n=== hardy hierarchy display forms ===");
1300
+ checkFormat("arrow(3,9,3) → L…K…", MetaNum.arrow(3, 9, 3), "L2.376K2");
1301
+ checkFormat("arrow(3,10,3) → M(10^0.376)L2", MetaNum.arrow(3, 10, 3), "M2.376L2");
1302
+ checkFormat("arrow(4,9,4) → LLK…K…", MetaNum.arrow(4, 9, 4), "LLK3.550K3");
1303
+ checkFormat("arrow(5,9,5) → LLLKK…K…", MetaNum.arrow(5, 9, 5), "LLLKK4.669K4");
1304
+ checkBool("arrow(6,9,6) carries to …M5 (threshold+1 repeats)",
1305
+ /M5$/.test(format(MetaNum.arrow(6, 9, 6))), true);
1306
+ checkFormat("arrow(3,22,3) → Y…X…", MetaNum.arrow(3, 22, 3), "Y2.376X2");
1307
+ checkFormat("arrow(3,23,3) → Z…Y…", MetaNum.arrow(3, 23, 3), "Z2.376Y2");
1308
+ checkFormat("arrow(3,24,3) → 2.376Aa23 (Aa diagonal)", MetaNum.arrow(3, 24, 3), "2.376Aa23");
1309
+ checkFormat("arrow(3,100,3) → 2.376Aa99", MetaNum.arrow(3, 100, 3), "2.376Aa99");
1310
+ checkFormat("arrow(10,10000,10) → 1.000Aa10,000", MetaNum.arrow(10, 10000, 10), "2.000Aa10,000");
1311
+ checkFormat("nested arrow(3,arrow(3,100,3),3) → Aa2.376Aa99",
1312
+ MetaNum.arrow(3, MetaNum.arrow(3, 100, 3), 3), "Aa2.376Aa99");
1313
+ checkFormat("nested arrow(3,arrow(10,10000,10),3) → Aa1.000Aa10,000",
1314
+ MetaNum.arrow(3, MetaNum.arrow(10, 10000, 10), 3), "Aa2.000Aa10,000");
1315
+ // every display uses at most 2 distinct letter tokens (≤2-types rule)
1316
+ (function () {
1317
+ var cases = [
1318
+ MetaNum.arrow(3, 9, 3), MetaNum.arrow(4, 9, 4), MetaNum.arrow(5, 9, 5),
1319
+ MetaNum.arrow(3, 22, 3), MetaNum.arrow(3, 23, 3), MetaNum.arrow(3, 24, 3),
1320
+ MetaNum.arrow(3, 100, 3), MetaNum.arrow(10, 10000, 10),
1321
+ MetaNum.arrow(3, MetaNum.arrow(3, 100, 3), 3),
1322
+ ];
1323
+ var all2 = true;
1324
+ for (var ci = 0; ci < cases.length; ci++) {
1325
+ var toks = (format(cases[ci]).match(/[A-Z][a-z]*/g) || []).filter(function (t) { return t !== "E"; });
1326
+ // strip the structural E inside numbers first, then count distinct tokens
1327
+ var s = format(cases[ci]).replace(/(\d(?:\.\d+)?)E[\d,]+/g, "$1");
1328
+ toks = (s.match(/[A-Z][a-z]*/g) || []);
1329
+ var seen = {};
1330
+ for (var ti = 0; ti < toks.length; ti++) seen[toks[ti]] = 1;
1331
+ if (Object.keys(seen).length > 2) { all2 = false; console.log(" >2 types:", format(cases[ci])); }
1332
+ }
1333
+ checkBool("all diagonal-cascade displays use ≤ 2 letter types", all2, true);
1334
+ })();
1335
+
1336
+ // ─────────────────────────────────────────────────────────────────
1337
+ // v2.0: rule 3 unification + pure dlsdl diagonal [2,10) convention
1338
+ // ─────────────────────────────────────────────────────────────────
1339
+ console.log("\n=== diagonal letter convention ===");
1340
+ // rule 3: n{λ}b = n{λ[b]}n
1341
+ checkBool("aper(3,5) = 3{5}3", MetaNum.aperiote(3,5).eq(MetaNum(3).arrow(5)(3)), true);
1342
+ // diagonal letters (ending in 'a'): integer arguments all anchor at 2.000
1343
+ [10, 11, 50, 100].forEach(function (b) {
1344
+ checkFormat("10{100}" + b + " → 2.000Aa100", MetaNum.arrow(10, 100, b), "2.000Aa100");
1345
+ });
1346
+ checkFormat("11{100}11 → 2.000Aa100", MetaNum.arrow(11, 100, 11), "2.000Aa100");
1347
+ // structured count climbs to its smooth diagonal mantissa
1348
+ checkFormat("10{100}(10{93}10) → 2.002Aa100",
1349
+ MetaNum.arrow(10, 100, MetaNum.arrow(10, 93, 10)), "2.002Aa100");
1350
+ // non-diagonal letters keep the [1,10) convention
1351
+ checkFormat("Ab100 → 1.000Ab100", MetaNum("Ab100"), "1.000Ab100");
1352
+ // symbol de-layering
1353
+ checkFormat("!Aa3 → 2.000Aaaa10", MetaNum("!Aa3"), "2.000Aaaa10");
1354
+ checkFormat("@Aa3 → !2.000Aaaa10", MetaNum("@Aa3"), "!2.000Aaaa10");
1355
+ // parser roundtrip of the new canonical forms
1356
+ checkBool("parse 2.000Aaaa10", MetaNum("2.000Aaaa10").format() === "2.000Aaaa10", true);
1357
+ checkBool("parse !2.000Aaaa10", MetaNum("!2.000Aaaa10").format() === "!2.000Aaaa10", true);
1358
+ checkBool("parse 2.002Aa100", MetaNum("2.002Aa100").format() === "2.002Aa100", true);
1359
+ // hardy(1e10+k) must not blow the stack
1360
+ (function () {
1361
+ var ok = true;
1362
+ for (var k = 0; k <= 60; k++) {
1363
+ try { MetaNum.hardy(1e10 + k); } catch (e) { ok = false; console.log("hardy threw at", 1e10 + k, e.message); }
1364
+ }
1365
+ checkBool("hardy(1e10+0..60) no throw", ok, true);
1366
+ })();
1367
+ // cross-config stability for the new cases
1368
+ (function () {
1369
+ var ref = null, stable = true;
1370
+ [10, 20, 50, 100].forEach(function (c) {
1371
+ MetaNum.maxRows = c; MetaNum.maxCols = c;
1372
+ var f = format(MetaNum.arrow(10, 100, MetaNum.arrow(10, 93, 10)));
1373
+ if (ref === null) ref = f;
1374
+ else if (f !== ref) { stable = false; console.log("cfg" + c + " drift: " + f + " vs " + ref); }
1375
+ });
1376
+ MetaNum.maxRows = 20; MetaNum.maxCols = 20;
1377
+ checkBool("v2.0: 10{100}(10{93}10) cross-config stable (" + ref + ")", stable, true);
1378
+ })();
1379
+
1380
+ // ─────────────────────────────────────
1381
+ // cross-config stability: identical formats at
1382
+ // maxRows = maxCols = 10 / 20 / 50 / 100 (±1 in the last shown digit)
1383
+ // ─────────────────────────────────────
1384
+ console.log("\n=== cross-config stability ===");
1385
+ (function () {
1386
+ var cases = [[3, 9, 3], [3, 10, 3], [4, 9, 4], [5, 9, 5], [6, 9, 6],
1387
+ [3, 22, 3], [3, 23, 3], [3, 24, 3], [3, 39, 3], [3, 100, 3],
1388
+ [10, 25, 10], [10, 10000, 10]];
1389
+ var cfgs = [10, 20, 50, 100];
1390
+ var stable = true;
1391
+ for (var i = 0; i < cases.length; i++) {
1392
+ var ref = null;
1393
+ for (var c = 0; c < cfgs.length; c++) {
1394
+ MetaNum.maxRows = cfgs[c]; MetaNum.maxCols = cfgs[c];
1395
+ var f = format(MetaNum.arrow(cases[i][0], cases[i][1], cases[i][2]));
1396
+ if (ref === null) ref = f;
1397
+ else if (f !== ref) {
1398
+ // allow ±1 in the last displayed digit
1399
+ var a = ref.match(/(\d+(?:\.\d+)?)(?!.*\d)/), b = f.match(/(\d+(?:\.\d+)?)(?!.*\d)/);
1400
+ if (!a || !b || Math.abs(Number(a[1]) - Number(b[1])) > 1.5 * Math.pow(10, -(a[1].split(".")[1] || "").length + 1)) {
1401
+ stable = false;
1402
+ console.log(" config drift [" + cases[i] + "] " + ref + " vs @" + cfgs[c] + " " + f);
1403
+ } else { ref = f; }
1404
+ }
1405
+ }
1406
+ }
1407
+ MetaNum.maxRows = 20; MetaNum.maxCols = 20;
1408
+ checkBool("formats identical across maxRows/maxCols = 10/20/50/100 (±1 last digit)", stable, true);
1409
+ // clamped bounds: values below 10 and above 1000 snap inside
1410
+ MetaNum.maxRows = 5; checkBool("maxRows clamps up to 10", MetaNum.maxRows === 10, true);
1411
+ MetaNum.maxRows = 5000; checkBool("maxRows clamps down to 1000", MetaNum.maxRows === 1000, true);
1412
+ MetaNum.maxRows = 20;
1413
+ })();
1414
+
1415
+ console.log("\n=== MetaNum(...).format() instance method ===");
1416
+ (function () {
1417
+ function checkFmtEq(name, gotStr, expected) {
1418
+ var pass = gotStr === expected;
1419
+ console.log((pass ? "PASS" : "FAIL") + " | " + name + " | " + gotStr
1420
+ + (pass ? "" : " (expected " + expected + ")"));
1421
+ }
1422
+ checkFmtEq("G600.format()", MetaNum("G600").format(), "1.000G600");
1423
+ checkFmtEq("hardy(4166).format()", MetaNum.hardy(4166).format(), "2.397G5");
1424
+ checkFmtEq("arrow(3,4.1,3).format()", MetaNum.arrow(3, 4.1, 3).format(), "G1.161G897");
1425
+ checkFmtEq("small 0.5.format()", MetaNum(0.5).format(), "0.500");
1426
+ checkFmtEq("format(2) precision arg", MetaNum(1234.5678).format(2), "1,234");
1427
+ checkFmtEq(".format() matches module format(FE400)",
1428
+ MetaNum("FE400").format(), format(MetaNum("FE400")));
1429
+ })();
1430
+
1431
+ console.log("\n=== format tests Done ===");
1432
+
1433
+