metanum 2.0.1 → 2.0.2
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/README.md +149 -228
- package/format-metanum.js +249 -79
- package/metanum.js +413 -61
- package/package.json +1 -1
- package/test-interface.html +1 -0
- package/test_mixed.js +739 -42
package/test_mixed.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
if (!this.MetaNum) MetaNum = require("./metanum.js");
|
|
2
2
|
if (!this.format) format = require("./format-metanum.js").format;
|
|
3
3
|
//if (!this.FORMAT_OPTIONS) FORMAT_OPTIONS = require("./format-metanum.js").FORMAT_OPTIONS;
|
|
4
4
|
|
|
@@ -244,9 +244,7 @@ checkOp("pent_root semantic b=3", MetaNum.pentate(2,3).pentate_root(3), 2, 0.1);
|
|
|
244
244
|
checkOp("pent_log small", MetaNum(1e10).pentate_log(2), 2.795, 0.1);
|
|
245
245
|
checkOp("pent_root small", MetaNum(1e10).pentate_root(2), 2.956, 0.1);
|
|
246
246
|
|
|
247
|
-
|
|
248
|
-
// hyper_log / hyper_root (a{b}c = d inverses)
|
|
249
|
-
// ─────────────────────────────────────
|
|
247
|
+
console.log("\n=== hyper_log/root ===");
|
|
250
248
|
function checkHL(label, d, a, b, want) {
|
|
251
249
|
checkBool("hyper_log " + label, MetaNum(d).hyper_log(a)(b).eq(want), true);
|
|
252
250
|
}
|
|
@@ -272,7 +270,7 @@ checkHR("10↑↑↑3, c=3, b=3", MetaNum(10).arrow(3)(3), 3, 3, 10);
|
|
|
272
270
|
checkHR("2{4}3, c=3, b=4", MetaNum(2).arrow(4)(3), 3, 4, 2);
|
|
273
271
|
|
|
274
272
|
//hyperoperation definition from https://googology.fandom.com/wiki/Template:ExtendedOps
|
|
275
|
-
|
|
273
|
+
console.log("\n=== hyperoperation definition ===")
|
|
276
274
|
// ─── 1. aperiote (ω): x{ω}y = x{y}x (rule 3: n{λ}b = n{λ[b]}n)
|
|
277
275
|
// rule 3: x{ω}y = x{ω[y]}x = x{y}x (final operand is the base)
|
|
278
276
|
// aperiote(3,0): 3{0}3 = 3*3 = 9
|
|
@@ -515,20 +513,13 @@ checkOp("epsl(3,4)", m3.epsilonate(4));
|
|
|
515
513
|
checkOp("epsl(4,3)", m4.epsilonate(3));
|
|
516
514
|
checkBool("epsl NaN", MetaNum.epsilonate(m3, MetaNum.NaN).isNaN(), true);
|
|
517
515
|
|
|
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
516
|
// λ[y] layer markers in STANDARD form (finite rows merged into r0, layer
|
|
527
517
|
// lowered as far as it goes — README L17: layer L ⇒ ω^ω^…((L-1) ω^'s)^(bracket)):
|
|
528
518
|
// iter → 10{ω^y}10 (L1 [1,y]); itmu → 10{ω^ω+(y-1)}10 (L1 [1,0,1], r0=y-1)
|
|
529
519
|
// cube → 10{ω^ω+ω^y}10 (L1 r0[…,1@y] + [1,0,1]); expo → 10{ω^ω·y}10 (L1 [y,0,1])
|
|
530
520
|
// tria → 10{ω^(ω+y)}10 (L1 [1,y,1]); trix → 10{ω^(ω·y+10)}10 (L1 [1,10,y])
|
|
531
521
|
// apix → 10{ω^(ω^y)}10 (L1 [1,0…0,1] with y zeros)
|
|
522
|
+
console.log("\n=== λ[y] layer markers in STANDARD form ===");
|
|
532
523
|
var wOps = ["iterate","itermult","cuboiter","expoiter","trioterate","trixxate","aperixxate"];
|
|
533
524
|
var mk35 = {
|
|
534
525
|
iterate: { layer: 0, rows: null }, // exact cascade, layer 0
|
|
@@ -561,12 +552,12 @@ for (var wy = 2; wy <= 9; wy++) {
|
|
|
561
552
|
checkBool("ops strictly grow at y=" + wy + " (iter<itmu<cube<expo<tria<trix<apix)", wmono, true);
|
|
562
553
|
}
|
|
563
554
|
|
|
564
|
-
//
|
|
555
|
+
// precision budget: exact while it fits maxRows/maxCols
|
|
565
556
|
// arrow's most precise form holds maxRows+maxCols-2 finite hyperoperation
|
|
566
557
|
// levels: r0 = [a0 … a(maxCols-1)] plus rows [count, level] for levels
|
|
567
558
|
// maxCols … maxRows+maxCols-2. Beyond that: keep the largest maxRows-1
|
|
568
559
|
// ordinal rows sorted ascending, array[1][0] += 1, array[0] = [10].
|
|
569
|
-
console.log("\n===
|
|
560
|
+
console.log("\n=== precision budget (maxRows/maxCols) ===");
|
|
570
561
|
(function () {
|
|
571
562
|
var a39 = MetaNum.arrow(10, 39, 10);
|
|
572
563
|
checkBool("arrow(10,39,10) exact: maxCols r0 entries + maxRows-1 rows, top level 38",
|
|
@@ -746,7 +737,7 @@ var hyperOpList = [
|
|
|
746
737
|
];
|
|
747
738
|
|
|
748
739
|
// ─── double nested iteration ───
|
|
749
|
-
console.log("\n=== hyperoperation iteration tests
|
|
740
|
+
console.log("\n=== hyperoperation iteration tests ===");
|
|
750
741
|
for (var hi = 0; hi < hyperOpList.length; hi++) {
|
|
751
742
|
var shortName = hyperOpList[hi][0];
|
|
752
743
|
var methodName = hyperOpList[hi][1];
|
|
@@ -1027,26 +1018,74 @@ checkBool("h31(10,5.1) < h31(10,5.5) < h31(10,5.9) < h31(10,6)",
|
|
|
1027
1018
|
MetaNum(10).h31(5.1).lt(MetaNum(10).h31(5.5)) &&
|
|
1028
1019
|
MetaNum(10).h31(5.5).lt(MetaNum(10).h31(5.9)) &&
|
|
1029
1020
|
MetaNum(10).h31(5.9).lt(MetaNum(10).h31(6)), true);
|
|
1030
|
-
// the expanded form keeps the count law
|
|
1031
|
-
//
|
|
1032
|
-
//
|
|
1021
|
+
// the expanded form keeps the count law with INTEGER counts (only array[0][0]
|
|
1022
|
+
// may be fractional): every row below the top one carries x-2 = 8 and the α-1
|
|
1023
|
+
// row carries ceil(y)-2; the fraction lives in the cascade depth, so 2+ε starts
|
|
1024
|
+
// with the shallowest cascade and 3-ε has the full 10{ω*2}10 cascade
|
|
1033
1025
|
(function () {
|
|
1034
1026
|
var ok = true;
|
|
1035
1027
|
for (var k = 0; k < 6; k++) {
|
|
1036
1028
|
var fy = [2.001, 2.1, 2.5, 3.5, 10.25, 100.75][k];
|
|
1037
1029
|
var rr = MetaNum(10).h21(fy).array.slice(1);
|
|
1038
1030
|
for (var i = 0; i < rr.length - 1; i++) if (rr[i][0] !== 8) ok = false;
|
|
1039
|
-
if (
|
|
1031
|
+
if (rr[rr.length - 1][0] !== Math.ceil(fy) - 2) ok = false;
|
|
1040
1032
|
}
|
|
1041
|
-
checkBool("h21(10, fractional): lower rows =
|
|
1042
|
-
// the endpoints: 2+ε is
|
|
1043
|
-
checkBool("h21(10,2+1e-15) =
|
|
1044
|
-
MetaNum(10).h21(2 + 1e-15).array.length ===
|
|
1045
|
-
MetaNum(10).h21(2 + 1e-15).array[
|
|
1033
|
+
checkBool("h21(10, fractional): lower rows = 8, ω*2 row = ceil(y)-2 (integer)", ok, true);
|
|
1034
|
+
// the endpoints: 2+ε is just above h21(10,2) = 10{ω*2}10, 3-ε → h21(10,3)
|
|
1035
|
+
checkBool("h21(10,2+1e-15) = shallowest cascade + one ω*2 row, above h21(10,2)",
|
|
1036
|
+
MetaNum(10).h21(2 + 1e-15).array.length === 3 &&
|
|
1037
|
+
JSON.stringify(MetaNum(10).h21(2 + 1e-15).array[2]) === "[1,0,2]" &&
|
|
1038
|
+
MetaNum(10).h21(2 + 1e-15).gt(MetaNum(10).h21(2)), true);
|
|
1046
1039
|
checkBool("h21(10,2.999999) → h21(10,3) from below",
|
|
1047
1040
|
MetaNum(10).h21(2.999999).lt(MetaNum(10).h21(3)) &&
|
|
1048
1041
|
MetaNum(10).h21(2.999999).gt(MetaNum(10).h21(2)), true);
|
|
1049
1042
|
})();
|
|
1043
|
+
// the CONTRACT for fractional operands: only array[0][0] may be non-integer —
|
|
1044
|
+
// every row count, every row coefficient and every other r0 entry is an integer
|
|
1045
|
+
// (exactly like MetaNum.arrow with a fractional level/argument)
|
|
1046
|
+
(function () {
|
|
1047
|
+
var bad = [], n = 0;
|
|
1048
|
+
var fOps = ["h11","h13","h20","h21","h31","h100","h101","h1001","iterate",
|
|
1049
|
+
"cuboiter","trioterate","epsilonate"];
|
|
1050
|
+
for (var f of fOps) {
|
|
1051
|
+
for (var b = 0; b < 3; b++) {
|
|
1052
|
+
var bx = [3, 10, 100][b];
|
|
1053
|
+
for (var k = 0; k < 3; k++) {
|
|
1054
|
+
var by = [2.1, 3.5, 100.75][k];
|
|
1055
|
+
n++;
|
|
1056
|
+
var arr = MetaNum(bx)[f](by).array;
|
|
1057
|
+
for (var i = 0; i < arr.length; i++) {
|
|
1058
|
+
for (var j = 0; j < arr[i].length; j++) {
|
|
1059
|
+
if (i === 0 && j === 0) continue;
|
|
1060
|
+
var c = arr[i][j];
|
|
1061
|
+
if (typeof c !== "number" || !isFinite(c) || c !== Math.floor(c)) {
|
|
1062
|
+
if (bad.length < 4) bad.push(f + "(" + bx + "," + by + ") [" + i + "][" + j + "]=" + c);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
checkBool("only array[0][0] is fractional (" + n + " results checked)", bad.length === 0,
|
|
1070
|
+
true, bad.join(" | "));
|
|
1071
|
+
// arrow() itself obeys the same contract
|
|
1072
|
+
var bad2 = 0;
|
|
1073
|
+
for (var b2 = 0; b2 < 3; b2++) {
|
|
1074
|
+
var bx2 = [3, 10, 100][b2];
|
|
1075
|
+
for (var k2 = 0; k2 < 7; k2++) {
|
|
1076
|
+
var lv = [1.5, 2.1, 2.5, 3.5, 10.25, 100.75, 1e9 + 0.4][k2];
|
|
1077
|
+
var arr2 = MetaNum(bx2).arrow(lv)(10).array;
|
|
1078
|
+
for (var i2 = 0; i2 < arr2.length; i2++) {
|
|
1079
|
+
for (var j2 = 0; j2 < arr2[i2].length; j2++) {
|
|
1080
|
+
if (i2 === 0 && j2 === 0) continue;
|
|
1081
|
+
if (arr2[i2][j2] !== Math.floor(arr2[i2][j2])) bad2++;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
checkBool("arrow() with fractional levels: only array[0][0] is fractional", bad2 === 0, true);
|
|
1087
|
+
})();
|
|
1088
|
+
|
|
1050
1089
|
// row coefficients stay integer (a fractional constant is carried to the base)
|
|
1051
1090
|
(function () {
|
|
1052
1091
|
var ok = true;
|
|
@@ -1243,8 +1282,12 @@ checkBool("hardy(1e15) < hardy(1e16) < hardy(1e17)",
|
|
|
1243
1282
|
// -- MetaNum-object input (v2.0): structures shadow to their ordinal --
|
|
1244
1283
|
// power tower 10^^k → ω^ω^…^ω (k ω's) → H there = 10.epsilonate(k);
|
|
1245
1284
|
// letter/ordinal values sit at their own Hardy position → themselves
|
|
1246
|
-
checkBool("hardy(10^^100) =
|
|
1247
|
-
|
|
1285
|
+
checkBool("hardy(10^^100) = H_{ω^…^ω(100 ωs)}(10), layer 100-2 = 98 (one per 10^ level)",
|
|
1286
|
+
(function () {
|
|
1287
|
+
var v = MetaNum.hardy(MetaNum(10).tetr(100));
|
|
1288
|
+
return v.layer === 98 &&
|
|
1289
|
+
JSON.stringify(v.array) === JSON.stringify(MetaNum.hardy(1e10).array);
|
|
1290
|
+
})(), true);
|
|
1248
1291
|
checkBool("hardy(MetaNum G600) = Infinity",
|
|
1249
1292
|
MetaNum.hardy(MetaNum("G600")).eq(MetaNum.infinity), true);
|
|
1250
1293
|
checkBool("hardy(MetaNum arrow(3,9,3)) = Infinity",
|
|
@@ -1255,12 +1298,533 @@ checkBool("hardy(10{3}10) = Infinity (> 10^^MSI)",
|
|
|
1255
1298
|
// -- the engine limit: hardy(10^^MSI) = 10{ω^…^ω(MSI ω's)}10 (v2.0) --
|
|
1256
1299
|
(function () {
|
|
1257
1300
|
var MSI = 9007199254740991;
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
MetaNum.hardy(MetaNum(10).tetr(MSI
|
|
1301
|
+
// the tower height k caps the Hardy hierarchy: layer = k - 2 (one per 10^)
|
|
1302
|
+
checkBool("hardy(10^^MSI) = the MetaNum limit (layer MSI-2, base rows kept)",
|
|
1303
|
+
MetaNum.hardy(MetaNum(10).tetr(MSI)).layer === MSI - 2 &&
|
|
1304
|
+
JSON.stringify(MetaNum.hardy(MetaNum(10).tetr(MSI)).array) ===
|
|
1305
|
+
JSON.stringify(MetaNum.hardy(1e10).array), true);
|
|
1306
|
+
checkBool("hardy(10^^(MSI-1)) is just below the cap",
|
|
1307
|
+
MetaNum.hardy(MetaNum(10).tetr(MSI - 1)).lt(MetaNum.hardy(MetaNum(10).tetr(MSI))), true);
|
|
1308
|
+
})();
|
|
1309
|
+
|
|
1310
|
+
// ─────────────────────────────────────
|
|
1311
|
+
// v2.0.2 hardy fixes:
|
|
1312
|
+
// - a plain number beyond the double range is NOT a power tower: read its
|
|
1313
|
+
// decimal expansion (hardy("1.8e308") stays layer 0 with the ordinary
|
|
1314
|
+
// digit path, last row [8,7,0,3] like hardy("1.79e308"))
|
|
1315
|
+
// - ee10 / eee10 / eeee10 map to ω-towers of DIFFERENT heights (layers
|
|
1316
|
+
// 2/3/4), no longer the same value
|
|
1317
|
+
// - fractional n: the ordinal comes from the integer part, the base
|
|
1318
|
+
// argument becomes 10+f (H_ω(10.38) = 10.38·2 = 20.76)
|
|
1319
|
+
// ─────────────────────────────────────
|
|
1320
|
+
console.log("\n=== v2.0.2 hardy fixes ===");
|
|
1321
|
+
checkBool("hardy(\"1.8e308\") layer 0, top row [1,8,0,3] (ω^(ω²·3+8), one application)",
|
|
1322
|
+
(function () {
|
|
1323
|
+
var h = MetaNum.hardy(MetaNum("1.8e308"));
|
|
1324
|
+
return h.layer === 0 &&
|
|
1325
|
+
JSON.stringify(h.array[h.array.length - 1]) === "[1,8,0,3]";
|
|
1326
|
+
})(), true);
|
|
1327
|
+
// (the row budget resolves differences down to ~1e307 here, so the pair is
|
|
1328
|
+
// 1.7e308/1.8e308 — one exponent step apart, not one hundredth of one)
|
|
1329
|
+
checkBool("hardy(\"1.7e308\") < hardy(\"1.8e308\") (monotone over the double limit)",
|
|
1330
|
+
MetaNum.hardy(MetaNum("1.7e308")).lt(MetaNum.hardy(MetaNum("1.8e308"))), true);
|
|
1331
|
+
checkBool("hardy(ee10) < hardy(eee10) < hardy(eeee10) (distinct tower heights)",
|
|
1332
|
+
MetaNum.hardy(MetaNum("ee10")).lt(MetaNum.hardy(MetaNum("eee10"))) &&
|
|
1333
|
+
MetaNum.hardy(MetaNum("eee10")).lt(MetaNum.hardy(MetaNum("eeee10"))), true);
|
|
1334
|
+
checkBool("hardy(ee10)/eee10/eeee10 sit at layers 1/2/3 (one layer per 10^ level)",
|
|
1335
|
+
MetaNum.hardy(MetaNum("ee10")).layer === 1 &&
|
|
1336
|
+
MetaNum.hardy(MetaNum("eee10")).layer === 2 &&
|
|
1337
|
+
MetaNum.hardy(MetaNum("eeee10")).layer === 3, true);
|
|
1338
|
+
checkBool("hardy(10.38) = 20.76 (H_ω(10.38) = 10.38·2)",
|
|
1339
|
+
MetaNum.hardy(10.38).eq(MetaNum(20.76)), true);
|
|
1340
|
+
checkBool("hardy(100.1) = 11084.709858935355 (H_{ω²}(10.1) = 10.1·2^10.1)",
|
|
1341
|
+
MetaNum.hardy(100.1).eq(MetaNum(11084.709858935355)), true);
|
|
1342
|
+
checkBool("hardy(10) < hardy(10.38) < hardy(11) (continuous in n)",
|
|
1343
|
+
MetaNum.hardy(10).lt(MetaNum.hardy(10.38)) &&
|
|
1344
|
+
MetaNum.hardy(10.38).lt(MetaNum.hardy(11)), true);
|
|
1345
|
+
checkBool("hardy(100) < hardy(100.1) < hardy(101)",
|
|
1346
|
+
MetaNum.hardy(100).lt(MetaNum.hardy(100.1)) &&
|
|
1347
|
+
MetaNum.hardy(100.1).lt(MetaNum.hardy(101)), true);
|
|
1348
|
+
// ─────────────────────────────────────
|
|
1349
|
+
// non-integer inputs above 1000: the fundamental-sequence step writes the
|
|
1350
|
+
// running base n into a coefficient, so a coefficient can turn FRACTIONAL —
|
|
1351
|
+
// the old "-1" step then went negative and left no positive term at all
|
|
1352
|
+
// (hardy(1000.5) threw "Cannot read properties of undefined (reading 'gt')").
|
|
1353
|
+
// 0 < c_j < 1 is now a PARTIAL step: ω^j·f contributes ω^(j-1)·(n·f).
|
|
1354
|
+
// ─────────────────────────────────────
|
|
1355
|
+
(function () {
|
|
1356
|
+
var vals = [1000.5, 1000.1, 1000.9999, 1001.1, 10000.5, 1000000.75, 1e10 + 0.5, 1e15 + 0.5];
|
|
1357
|
+
var bad = [], nan = 0;
|
|
1358
|
+
for (var i = 0; i < vals.length; i++) {
|
|
1359
|
+
var v;
|
|
1360
|
+
try { v = MetaNum.hardy(vals[i]); } catch (e) { bad.push(vals[i] + " threw " + e.message.slice(0, 40)); continue; }
|
|
1361
|
+
if (v.isNaN()) nan++;
|
|
1362
|
+
}
|
|
1363
|
+
checkBool("hardy(non-integer > 1000) does not throw", bad.length === 0 && nan === 0, true,
|
|
1364
|
+
bad.join(" | "));
|
|
1365
|
+
// monotone in the integer and in the fraction
|
|
1366
|
+
var mono = true;
|
|
1367
|
+
for (var m = 0; m < 5; m++) {
|
|
1368
|
+
var base = [1000, 1001, 10000, 12345, 99999][m];
|
|
1369
|
+
for (var k = 0; k < 5; k++) {
|
|
1370
|
+
var f = [0.001, 0.25, 0.5, 0.75, 0.999][k];
|
|
1371
|
+
if (!(MetaNum.hardy(base + f).gte(MetaNum.hardy(base + f - 0.0001)) &&
|
|
1372
|
+
MetaNum.hardy(base + 1).gte(MetaNum.hardy(base + f)))) mono = false;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
checkBool("hardy(n) monotone across non-integer n > 1000", mono, true);
|
|
1376
|
+
checkBool("hardy(1000) < hardy(1000.5) < hardy(1001)",
|
|
1377
|
+
MetaNum.hardy(1000).lt(MetaNum.hardy(1000.5)) &&
|
|
1378
|
+
MetaNum.hardy(1000.5).lt(MetaNum.hardy(1001)), true);
|
|
1379
|
+
checkBool("hardy(10000) < hardy(10000.5) < hardy(10001)",
|
|
1380
|
+
MetaNum.hardy(10000).lt(MetaNum.hardy(10000.5)) &&
|
|
1381
|
+
MetaNum.hardy(10000.5).lt(MetaNum.hardy(10001)), true);
|
|
1382
|
+
// the array contract still holds for those results
|
|
1383
|
+
var cbad = 0;
|
|
1384
|
+
for (var b2 = 0; b2 < 4; b2++) {
|
|
1385
|
+
var bv = [1000, 10000, 1e6, 1e10][b2];
|
|
1386
|
+
for (var k2 = 0; k2 < 3; k2++) {
|
|
1387
|
+
var arr = MetaNum.hardy(bv + [0.1, 0.5, 0.9][k2]).array;
|
|
1388
|
+
for (var i2 = 0; i2 < arr.length; i2++) {
|
|
1389
|
+
for (var j2 = 0; j2 < arr[i2].length; j2++) {
|
|
1390
|
+
if (i2 === 0 && j2 === 0) continue;
|
|
1391
|
+
if (arr[i2][j2] !== Math.floor(arr[i2][j2])) cbad++;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
checkBool("hardy(non-integer > 1000): only array[0][0] is fractional", cbad === 0, true);
|
|
1397
|
+
})();
|
|
1398
|
+
|
|
1399
|
+
// ─────────────────────────────────────
|
|
1400
|
+
// hardy above 1e10 with a non-zero "rest": the from-below base is H_{ω^n1}(n1),
|
|
1401
|
+
// whose tower sits at level n1-1 — array[0] holds n1 entries, so the step-by-step
|
|
1402
|
+
// expansion only fits while n1 ≤ maxCols. Above that the coefficients the limit
|
|
1403
|
+
// steps write turn structured and the expansion collapsed into a destroyed base
|
|
1404
|
+
// (array[0] = [1]) with a bogus row: hardy(1e10+11) was [[1],[2,20]].
|
|
1405
|
+
// The engine value 10{n1-1}(n1+1) is used there instead.
|
|
1406
|
+
// ─────────────────────────────────────
|
|
1407
|
+
console.log("\n=== hardy(n ≥ 1e10) : base & cascade ===");
|
|
1408
|
+
(function () {
|
|
1409
|
+
// H_{ω^ω+ω+1}(10) = H_{ω^ω}(22): the exact tower [c0, 21×20] no longer fits
|
|
1410
|
+
// maxCols = 20, so the TRUNCATED cascade [3086.036…, 21×19] is kept — the
|
|
1411
|
+
// [非整数, 21, 21, …, 21] single-row shape (was the engine value
|
|
1412
|
+
// 10{20}22 = [[1e10,8×19],[21,20]]).
|
|
1413
|
+
var v11 = MetaNum.hardy(1e10 + 11); // H_{ω^ω+ω+1}(10) = H_{ω^ω}(22)
|
|
1414
|
+
checkBool("hardy(1e10+11): single truncated tower [c0, 21×19] — [非整数,21,21,…]",
|
|
1415
|
+
v11.array.length === 1 && v11.array[0].length === MetaNum.maxCols &&
|
|
1416
|
+
v11.array[0][1] === 21 && v11.array[0][MetaNum.maxCols - 1] === 21 &&
|
|
1417
|
+
v11.array[0][0] > 1 && v11.array[0][0] !== Math.floor(v11.array[0][0]), true);
|
|
1418
|
+
checkBool("hardy(1e10+11) < 10{21}23 (from below on the ω^22 tower)",
|
|
1419
|
+
v11.lt(MetaNum.arrow(10, 21, 23)), true);
|
|
1420
|
+
// the same at the top of the range: H_{ω^ω}(48) → level 47
|
|
1421
|
+
var v22 = MetaNum.hardy(1e10 + 22);
|
|
1422
|
+
checkFormat("hardy(1e10+22) = H_{ω^ω+ω*2+2}(10) → X49", v22, "X49");
|
|
1423
|
+
checkBool("hardy(1e10+22): single truncated tower [c0, 47×19]",
|
|
1424
|
+
v22.array.length === 1 && v22.array[0][1] === 47 &&
|
|
1425
|
+
v22.array[0][MetaNum.maxCols - 1] === 47, true);
|
|
1426
|
+
checkBool("hardy(1e10+10) < hardy(1e10+11) < hardy(1e10+22)",
|
|
1427
|
+
MetaNum.hardy(1e10 + 10).lt(MetaNum.hardy(1e10 + 11)) &&
|
|
1428
|
+
MetaNum.hardy(1e10 + 11).lt(MetaNum.hardy(1e10 + 22)), true);
|
|
1429
|
+
// the whole 1e10+m family keeps growing, and never collapses again
|
|
1430
|
+
var broke = 0, collapsed = 0;
|
|
1431
|
+
for (var m = 0; m <= 30; m++) {
|
|
1432
|
+
var vm = MetaNum.hardy(1e10 + m);
|
|
1433
|
+
if (m > 0 && !vm.gt(MetaNum.hardy(1e10 + m - 1))) broke++;
|
|
1434
|
+
if (vm.array[0].length === 1 && vm.array[0][0] === 1) collapsed++;
|
|
1435
|
+
}
|
|
1436
|
+
checkBool("hardy(1e10+0..30) is strictly monotone", broke === 0, true);
|
|
1437
|
+
checkBool("hardy(1e10+0..30) never collapses array[0] to [1]", collapsed === 0, true);
|
|
1438
|
+
})();
|
|
1439
|
+
|
|
1440
|
+
// The leading term ω^β·dk is dk APPLICATIONS of H_{ω^β}, one after the other on
|
|
1441
|
+
// the running value, and an application is a row [1, β] — never a bump of the
|
|
1442
|
+
// ω-row count ([9,0,1] / [16,0,1] conflated dk with the rest-part):
|
|
1443
|
+
// hardy(1.1e11) = H_{ω^(ω+1)}(H_{ω^ω}(10)) = [3086.036,9×8] [1,1,1]
|
|
1444
|
+
// hardy(2e11) = H_{ω^(ω+1)}(H_{ω^(ω+1)}(10)) = [3086.036,9×8] [8,0,1] [1,1,1]
|
|
1445
|
+
(function () {
|
|
1446
|
+
var a = MetaNum.hardy(1e11), b = MetaNum.hardy(1.1e11), c = MetaNum.hardy(2e11);
|
|
1447
|
+
var base9 = "[3086.036065328153,9,9,9,9,9,9,9,9]";
|
|
1448
|
+
checkBool("hardy(1e11) = base + [8,0,1] (one H_{ω^(ω+1)}, from below)",
|
|
1449
|
+
JSON.stringify(a.array) === "[" + base9 + ",[8,0,1]]", true);
|
|
1450
|
+
checkBool("hardy(1.1e11) = [3086.036,9×8] [1,1,1] (H_{ω^ω} then H_{ω^(ω+1)})",
|
|
1451
|
+
JSON.stringify(b.array) === "[" + base9 + ",[1,1,1]]", true);
|
|
1452
|
+
checkBool("hardy(2e11) = [3086.036,9×8] [8,0,1] [1,1,1] (H_{ω^(ω+1)} twice)",
|
|
1453
|
+
JSON.stringify(c.array) === "[" + base9 + ",[8,0,1],[1,1,1]]", true);
|
|
1454
|
+
checkBool("hardy(3e11) = … [8,0,1] [2,1,1] (three applications)",
|
|
1455
|
+
JSON.stringify(MetaNum.hardy(3e11).array) === "[" + base9 + ",[8,0,1],[2,1,1]]", true);
|
|
1456
|
+
checkBool("hardy(1e11) < hardy(1.1e11) < hardy(2e11) < hardy(3e11)",
|
|
1457
|
+
a.lt(b) && b.lt(c) && c.lt(MetaNum.hardy(3e11)), true);
|
|
1458
|
+
var ok = true;
|
|
1459
|
+
for (var dk = 1; dk <= 9; dk++) {
|
|
1460
|
+
var vd = MetaNum.hardy(dk * 1e11);
|
|
1461
|
+
if (dk > 1 && !vd.gt(MetaNum.hardy((dk - 1) * 1e11))) ok = false;
|
|
1462
|
+
}
|
|
1463
|
+
checkBool("hardy(dk·1e11) strictly monotone in dk = 1..9", ok, true);
|
|
1464
|
+
// the same at ω+2: hardy(1.1e12) = H_{ω^(ω+2)}(H_{ω^(ω+1)}(10))
|
|
1465
|
+
checkBool("hardy(1.1e12) = [3086.036,9×8] [8,0,1] [1,2,1]",
|
|
1466
|
+
JSON.stringify(MetaNum.hardy(1.1e12).array) === "[" + base9 + ",[8,0,1],[1,2,1]]", true);
|
|
1467
|
+
})();
|
|
1468
|
+
|
|
1469
|
+
// hardy("1e100000") and above: 10^v is a PLAIN number (a power tower has the
|
|
1470
|
+
// same r0 = [v,1] shape but v ≥ 1e10), so the digit path must be taken — the
|
|
1471
|
+
// old "exponent < 1e5" guard pushed it into the tower branch (layer 1).
|
|
1472
|
+
(function () {
|
|
1473
|
+
var h100k = MetaNum.hardy("1e100000");
|
|
1474
|
+
checkBool("hardy(\"1e100000\") = H_{ω^(ω^5)}(10), layer 0", h100k.layer === 0, true);
|
|
1475
|
+
checkBool("hardy(\"1e100000\"): top row is the ω^5 cascade [8,9,9,9,9,9]",
|
|
1476
|
+
JSON.stringify(h100k.array[h100k.array.length - 1]) === "[8,9,9,9,9,9]", true);
|
|
1477
|
+
checkBool("hardy(\"1e10000\") top row = [8,9,9,9,9] (ω^4 cascade)",
|
|
1478
|
+
JSON.stringify(MetaNum.hardy("1e10000").array[19]) === "[8,9,9,9,9]", true);
|
|
1479
|
+
checkBool("hardy(\"1e1000\") top row = [8,9,9,9] (ω^3 cascade)",
|
|
1480
|
+
JSON.stringify(MetaNum.hardy("1e1000").array[19]) === "[8,9,9,9]", true);
|
|
1481
|
+
checkBool("hardy(1e100) top row = [8,9,9] (ω^2 cascade)",
|
|
1482
|
+
JSON.stringify(MetaNum.hardy(1e100).array[19]) === "[8,9,9]", true);
|
|
1483
|
+
checkBool("hardy(1e100) < hardy(\"1e1000\") < hardy(\"1e10000\") < hardy(\"1e100000\")",
|
|
1484
|
+
MetaNum.hardy(1e100).lt(MetaNum.hardy("1e1000")) &&
|
|
1485
|
+
MetaNum.hardy("1e1000").lt(MetaNum.hardy("1e10000")) &&
|
|
1486
|
+
MetaNum.hardy("1e10000").lt(MetaNum.hardy("1e100000")), true);
|
|
1487
|
+
// ee6..ee9: the ordinal is read off the value itself (10^W → ω^ord(W)),
|
|
1488
|
+
// so these are layer-0 cascades with ordinal rows that follow the input;
|
|
1489
|
+
// ee10 (W = 1e10 exactly) is the height-3 band → layerUp(hardy(1e10))
|
|
1490
|
+
checkBool("hardy(ee6..ee9) stay layer 0 with ordinal rows; ee10 → layer 1",
|
|
1491
|
+
(function () {
|
|
1492
|
+
for (var k = 6; k <= 9; k++) {
|
|
1493
|
+
var v = MetaNum.hardy("ee" + k);
|
|
1494
|
+
if (v.layer !== 0 || v.array.length - 1 !== 19) return false;
|
|
1495
|
+
}
|
|
1496
|
+
var v10 = MetaNum.hardy("ee10");
|
|
1497
|
+
return v10.layer === 1 && v10.array.length === 1;
|
|
1498
|
+
})(), true);
|
|
1499
|
+
checkBool("hardy(ee6) < hardy(ee7) < … < hardy(ee10) (rows follow the input)",
|
|
1500
|
+
(function () {
|
|
1501
|
+
for (var k = 7; k <= 10; k++) {
|
|
1502
|
+
if (!MetaNum.hardy("ee" + (k - 1)).lt(MetaNum.hardy("ee" + k))) return false;
|
|
1503
|
+
}
|
|
1504
|
+
return true;
|
|
1505
|
+
})(), true);
|
|
1506
|
+
checkBool("hardy(ee10) = layerUp(hardy(1e10)): the same rows at layer 1",
|
|
1507
|
+
MetaNum.hardy("ee10").layer === 1 &&
|
|
1508
|
+
JSON.stringify(MetaNum.hardy("ee10").array) ===
|
|
1509
|
+
JSON.stringify(MetaNum.hardy(1e10).array), true);
|
|
1510
|
+
// just above ee10 the level no longer fits into rows → layer 1
|
|
1511
|
+
checkBool("hardy(10^(1e10+1)) = H_{ω^(ω^ω+1)}(10) → layer 1",
|
|
1512
|
+
MetaNum.hardy(MetaNum(10).pow(MetaNum(1e10).add(MetaNum(1)))).layer === 1, true);
|
|
1513
|
+
checkBool("hardy(ee10) < hardy(10^(1e10+1)) < hardy(ee20)",
|
|
1514
|
+
MetaNum.hardy("ee10").lt(MetaNum.hardy(MetaNum(10).pow(MetaNum(1e10).add(MetaNum(1))))) &&
|
|
1515
|
+
MetaNum.hardy(MetaNum(10).pow(MetaNum(1e10).add(MetaNum(1)))).lt(MetaNum.hardy("ee20")), true);
|
|
1516
|
+
checkBool("hardy(ee10) < hardy(ee20) < hardy(ee100) < hardy(eee5) < hardy(eee10)",
|
|
1517
|
+
MetaNum.hardy("ee10").lt(MetaNum.hardy("ee20")) &&
|
|
1518
|
+
MetaNum.hardy("ee20").lt(MetaNum.hardy("ee100")) &&
|
|
1519
|
+
MetaNum.hardy("ee100").lt(MetaNum.hardy("eee5")) &&
|
|
1520
|
+
MetaNum.hardy("eee5").lt(MetaNum.hardy("eee10")), true);
|
|
1521
|
+
checkBool("above eee10 the layer is 2, above eeee10 it is 3 (one per 10^)",
|
|
1522
|
+
MetaNum.hardy("eee20").layer === 2 && MetaNum.hardy("eeee10").layer === 3 &&
|
|
1523
|
+
MetaNum.hardy("eeeee10").layer === 4, true);
|
|
1524
|
+
checkBool("hardy(eee10) < hardy(eee20) < hardy(eeee10) < hardy(eeeee10)",
|
|
1525
|
+
MetaNum.hardy("eee10").lt(MetaNum.hardy("eee20")) &&
|
|
1526
|
+
MetaNum.hardy("eee20").lt(MetaNum.hardy("eeee10")) &&
|
|
1527
|
+
MetaNum.hardy("eeee10").lt(MetaNum.hardy("eeeee10")), true);
|
|
1528
|
+
})();
|
|
1529
|
+
|
|
1530
|
+
// ─────────────────────────────────────
|
|
1531
|
+
// A number beyond Number.MAX_VALUE is stored as 10^v; the reconstructed mantissa
|
|
1532
|
+
// carries a rounding tail (2e1000 → 10^1000.301029995664 → 10^0.301… =
|
|
1533
|
+
// 1.9999999999… instead of 2), which used to spell "19999…9" and made hardy
|
|
1534
|
+
// read a garbage "rest" — hardy("2e1000") returned Infinity.
|
|
1535
|
+
(function () {
|
|
1536
|
+
var vals = ["2e1000", "5e1001", "9e999", "3.5e500"];
|
|
1537
|
+
var bad = 0;
|
|
1538
|
+
for (var i = 0; i < vals.length; i++) {
|
|
1539
|
+
var v = MetaNum.hardy(vals[i]);
|
|
1540
|
+
if (v.isNaN() || v.array[0].length === 1 && v.array[0][0] === null) bad++;
|
|
1541
|
+
}
|
|
1542
|
+
checkBool("hardy(\"2e1000\")/\"5e1001\"/… are finite (no rounding-tail Infinity)",
|
|
1543
|
+
bad === 0, true);
|
|
1544
|
+
checkBool("hardy(\"9e999\") < hardy(\"1e1000\") < hardy(\"2e1000\") monotone",
|
|
1545
|
+
MetaNum.hardy("9e999").lt(MetaNum.hardy("1e1000")) &&
|
|
1546
|
+
MetaNum.hardy("1e1000").lt(MetaNum.hardy("2e1000")), true);
|
|
1547
|
+
checkBool("hardy(\"2e1000\") top row follows the input (ω^1000 cascade)",
|
|
1548
|
+
MetaNum.hardy("2e1000").layer === 0 &&
|
|
1549
|
+
MetaNum.hardy("2e1000").array.length - 1 === 19, true);
|
|
1550
|
+
})();
|
|
1551
|
+
|
|
1552
|
+
// ─────────────────────────────────────
|
|
1553
|
+
// Levels above the letter grid (ω*2+100, ω*50, ω²*50, …) read as level-arg:
|
|
1554
|
+
// the snapped level with the fundamental-sequence index that recovers the
|
|
1555
|
+
// ordinal — the LARGEST coefficient was used before, which collapsed
|
|
1556
|
+
// [100,100,50], [100,100,60] and [100,100,100] into one string.
|
|
1557
|
+
(function () {
|
|
1558
|
+
var pairs = [
|
|
1559
|
+
[[100, 100, 50], "2.000Aaaa51"],
|
|
1560
|
+
[[100, 100, 60], "2.000Aaaa61"],
|
|
1561
|
+
[[100, 100, 100], "2.000Aaaa101"],
|
|
1562
|
+
[[100, 100, 200], "2.000Aaaa201"],
|
|
1563
|
+
[[100, 30], "2.000Aaa31"],
|
|
1564
|
+
[[100, 50], "2.000Aaa51"],
|
|
1565
|
+
[[100, 2], "2.000Ca100"]
|
|
1566
|
+
]
|
|
1567
|
+
var ok = true, seen = {}
|
|
1568
|
+
for (var i = 0; i < pairs.length; i++) {
|
|
1569
|
+
var f = format(MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), pairs[i][0]))
|
|
1570
|
+
if (f !== pairs[i][1]) { ok = false; console.log(" " + f + " ≠ " + pairs[i][1]) }
|
|
1571
|
+
if (seen[f]) { ok = false; console.log(" collision: " + f) }
|
|
1572
|
+
seen[f] = true
|
|
1573
|
+
}
|
|
1574
|
+
checkBool("unnamed levels keep distinct level-args", ok, true)
|
|
1575
|
+
// the ω+c / ω*N families must not collide either
|
|
1576
|
+
var ok2 = true, seen2 = {}
|
|
1577
|
+
var fam = [[100, 3], [100, 4], [100, 5], [0, 40], [100, 40]]
|
|
1578
|
+
for (var j = 0; j < fam.length; j++) {
|
|
1579
|
+
var g = format(MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), fam[j]))
|
|
1580
|
+
if (seen2[g]) { ok2 = false; console.log(" collision: " + g + " " + JSON.stringify(fam[j])) }
|
|
1581
|
+
seen2[g] = true
|
|
1582
|
+
}
|
|
1583
|
+
checkBool("ω+c / ω*N families keep distinct level-args", ok2, true)
|
|
1584
|
+
})();
|
|
1585
|
+
|
|
1586
|
+
// The carried !αAaβ form takes the ω-EXPONENT as β (README: !αAaβ = ω^β plus
|
|
1587
|
+
// the digits of α). ω³*50+… snaps to ω⁴, whose letter "Aaaaa" (5) exceeds
|
|
1588
|
+
// multiLetterLimit(4), so it reads "!2.000Aa4" — "!2.000Aa51" would claim the
|
|
1589
|
+
// ω⁵¹ level.
|
|
1590
|
+
(function () {
|
|
1591
|
+
var deep = format(MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), [100, 100, 100, 50]))
|
|
1592
|
+
checkFormat("ω³*50+… → !1.000H51 (single-letter carried form)",
|
|
1593
|
+
MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), [100, 100, 100, 50]), "!1.000H51")
|
|
1594
|
+
checkFormat("ω³*100+… → !1.000H101",
|
|
1595
|
+
MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), [100, 100, 100, 100]), "!1.000H101")
|
|
1596
|
+
checkFormat("ω³*200+… → !1.000H201",
|
|
1597
|
+
MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), [100, 100, 100, 200]), "!1.000H201")
|
|
1598
|
+
checkBool("the level-arg index is not used as the !-form exponent",
|
|
1599
|
+
deep.indexOf("Aa51") < 0, true)
|
|
1262
1600
|
})();
|
|
1263
1601
|
|
|
1602
|
+
// ─────────────────────────────────────
|
|
1603
|
+
// format: repeatLetterThreshold caps how many times ONE letter repeats — an
|
|
1604
|
+
// inner level must not promote to the outer letter (3{3}6 = FFF(E^7.6e12) is
|
|
1605
|
+
// "FFFEEE9.007E15", not "FFFF7.626E12"), and the saturated form is followed by
|
|
1606
|
+
// the next-letter (G) form.
|
|
1607
|
+
(function () {
|
|
1608
|
+
checkFormat("arrow(3,3,5) spells three F", MetaNum.arrow(3, 3, 5), "FFF7.626E12");
|
|
1609
|
+
// a fourth F would break repeatLetterThreshold, so the value renders at the
|
|
1610
|
+
// next letter by its real argument — not a saturated FFFEEE{…} form
|
|
1611
|
+
checkFormat("arrow(3,3,6) → 2.045G5 (next letter, real argument)",
|
|
1612
|
+
MetaNum.arrow(3, 3, 6), "2.045G5");
|
|
1613
|
+
checkFormat("arrow(3,3,7) → 2.045G6", MetaNum.arrow(3, 3, 7), "2.045G6");
|
|
1614
|
+
checkFormat("arrow(3,3,8) → 2.045G7", MetaNum.arrow(3, 3, 8), "2.045G7");
|
|
1615
|
+
for (var an = 3; an <= 8; an++) {
|
|
1616
|
+
var fs = format(MetaNum.arrow(3, 3, an))
|
|
1617
|
+
if (/(.)\1{3}/.test(fs.replace(/[\d,.]/g, ''))) {
|
|
1618
|
+
checkBool("arrow(3,3," + an + ") keeps within repeatLetterThreshold(3)", false, true)
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
checkBool("no more than repeatLetterThreshold(3) copies of one letter", true, true)
|
|
1622
|
+
})();
|
|
1623
|
+
|
|
1624
|
+
// A diagonal letter (name ending in "a": Aa, Ba, Ca, Aaa, …) carries the
|
|
1625
|
+
// mantissa α = 2·5^f ∈ [2,10) — never the [1,10) of the other letters.
|
|
1626
|
+
(function () {
|
|
1627
|
+
var diag = ["2.000Ca100", "2.000Aaa100", "2.000Aaaa101", "2.000Ba100"];
|
|
1628
|
+
var got = [
|
|
1629
|
+
format(MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), [100, 2])),
|
|
1630
|
+
format(MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), [0, 100])),
|
|
1631
|
+
format(MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(1000), [100, 100, 100])),
|
|
1632
|
+
format(MetaNum(10).aperioexpande(100))
|
|
1633
|
+
];
|
|
1634
|
+
var ok = true;
|
|
1635
|
+
for (var i = 0; i < diag.length; i++) {
|
|
1636
|
+
if (got[i] !== diag[i]) { ok = false; console.log(" " + got[i] + " ≠ " + diag[i]); }
|
|
1637
|
+
var m = parseFloat(got[i]);
|
|
1638
|
+
if (!(m >= 2 && m < 10)) ok = false;
|
|
1639
|
+
}
|
|
1640
|
+
checkBool("diagonal-letter mantissa stays in [2,10)", ok, true);
|
|
1641
|
+
})();
|
|
1642
|
+
|
|
1643
|
+
// Truncation must keep hardy's definitional from-below base top as array[0][0],
|
|
1644
|
+
// not collapse it to the [10] marker (the string "1e16+1e13" form used to parse
|
|
1645
|
+
// to 0 → hardy(0) = 10 → the bare [10] base).
|
|
1646
|
+
(function () {
|
|
1647
|
+
var baseTop = 3086.036065328153;
|
|
1648
|
+
checkBool("hardy(1e10+22): truncated tower keeps the base top 3086.036…, not [10]",
|
|
1649
|
+
MetaNum.hardy(1e10 + 22).array[0][0] === baseTop, true);
|
|
1650
|
+
checkBool("hardy(1e10+40): truncated tower keeps the base top 3086.036…, not [10]",
|
|
1651
|
+
MetaNum.hardy(1e10 + 40).array[0][0] === baseTop, true);
|
|
1652
|
+
checkBool("hardy(\"1e16+1e13\"): the string form keeps the base and rows",
|
|
1653
|
+
(function () {
|
|
1654
|
+
var v = MetaNum.hardy("1e16+1e13");
|
|
1655
|
+
return v.array[0][0] === baseTop &&
|
|
1656
|
+
JSON.stringify(v.array.slice(1)) === "[[8,0,1],[8,1,1],[8,2,1],[1,6,1]]";
|
|
1657
|
+
})(), true);
|
|
1658
|
+
var n10 = 0, mono = true, prev = null;
|
|
1659
|
+
for (var m = 0; m <= 40; m++) {
|
|
1660
|
+
var vm = MetaNum.hardy(1e10 + m);
|
|
1661
|
+
if (vm.array[0].length === 1 && vm.array[0][0] === 10) n10++;
|
|
1662
|
+
if (prev && !vm.gt(prev)) mono = false;
|
|
1663
|
+
prev = vm;
|
|
1664
|
+
}
|
|
1665
|
+
checkBool("hardy(1e10+0..40): never a [10] base", n10 === 0, true);
|
|
1666
|
+
checkBool("hardy(1e10+0..40): strictly monotone across the truncation point", mono, true);
|
|
1667
|
+
checkBool("hardy(\"1e100000\") keeps the base too",
|
|
1668
|
+
JSON.stringify(MetaNum.hardy("1e100000").array[0]) === "[3086.036065328153,9,9,9,9,9,9,9,9]", true);
|
|
1669
|
+
})();
|
|
1670
|
+
|
|
1671
|
+
// hardy(1e16+1e13) = H_{ω^(ω+6)+ω^(ω+3)}(10): the plain number is stored as 10^v
|
|
1672
|
+
// from 1e16 on, and the way back through the double lost the low digits
|
|
1673
|
+
// (10010000000000000 → 10010000000000014), which made the digit path read 14
|
|
1674
|
+
// instead of 1e13 as the "rest" — the base then collapsed to [1].
|
|
1675
|
+
(function () {
|
|
1676
|
+
var v = MetaNum.hardy(1e16 + 1e13);
|
|
1677
|
+
checkBool("hardy(1e16+1e13): array[0] is a real base, not the [1] marker",
|
|
1678
|
+
v.array[0].length > 1, true);
|
|
1679
|
+
checkBool("hardy(1e16+1e13) = H_{ω^(ω+6)}(H_{ω^(ω+3)}(10)) → … [8,2,1] [1,6,1]",
|
|
1680
|
+
JSON.stringify(v.array.slice(1)) ===
|
|
1681
|
+
"[[8,0,1],[8,1,1],[8,2,1],[1,6,1]]", true);
|
|
1682
|
+
checkBool("hardy(1e16) < hardy(1e16+1e13) < hardy(2e16)",
|
|
1683
|
+
MetaNum.hardy(1e16).lt(v) && v.lt(MetaNum.hardy(2e16)), true);
|
|
1684
|
+
})();
|
|
1685
|
+
|
|
1686
|
+
// ─────────────────────────────────────
|
|
1687
|
+
// v2.0.2 hardy(n > 1e10) round 2:
|
|
1688
|
+
// 1. fractional inputs 1e10+f collapse into ONE plain row (the fractional
|
|
1689
|
+
// hyper-operation result) and stay monotone across the integers;
|
|
1690
|
+
// 2. n1 > maxCols+1 keeps the truncated exact tower [c0, (n1-1)×(maxCols-1)]
|
|
1691
|
+
// instead of the engine value;
|
|
1692
|
+
// 3. "AeB+C" strings parse to the exact sum (hardy("1e16+1e13") is no longer
|
|
1693
|
+
// hardy(0) = 10);
|
|
1694
|
+
// 4. for 1e10 ≤ x < e1e10, hardy(10^x) = layerUp(hardy(x)) — one layer apart,
|
|
1695
|
+
// same array rows.
|
|
1696
|
+
// ─────────────────────────────────────
|
|
1697
|
+
console.log("\n=== v2.0.2 hardy(n > 1e10) round 2 ===");
|
|
1698
|
+
(function () {
|
|
1699
|
+
// 1. single-row fractional results
|
|
1700
|
+
checkBool("hardy(1e10) < hardy(1e10+0.5) < hardy(1e10+1), all single-row",
|
|
1701
|
+
(function () {
|
|
1702
|
+
var a = MetaNum.hardy(1e10), b = MetaNum.hardy("1e10+0.5"), c = MetaNum.hardy(1e10 + 1);
|
|
1703
|
+
return a.lt(b) && b.lt(c) &&
|
|
1704
|
+
a.array.length === 1 && b.array.length === 1 && c.array.length === 1;
|
|
1705
|
+
})(), true);
|
|
1706
|
+
checkBool("hardy(1e10+0.5).array[0][0] is the fractional hyper-op result",
|
|
1707
|
+
(function () {
|
|
1708
|
+
var b = MetaNum.hardy("1e10+0.5").array[0][0];
|
|
1709
|
+
return b > 3086.036 && b < 6785.435 && b !== Math.floor(b);
|
|
1710
|
+
})(), true);
|
|
1711
|
+
checkBool("hardy(1e10+k+0.5) single-row and monotone for k = 0..9",
|
|
1712
|
+
(function () {
|
|
1713
|
+
var prev = MetaNum.hardy(1e10);
|
|
1714
|
+
for (var k = 0; k <= 9; k++) {
|
|
1715
|
+
var v = MetaNum.hardy(1e10 + k + 0.5);
|
|
1716
|
+
if (v.array.length !== 1) return false;
|
|
1717
|
+
if (!v.gt(prev)) return false;
|
|
1718
|
+
prev = v;
|
|
1719
|
+
var vi = MetaNum.hardy(1e10 + k + 1);
|
|
1720
|
+
if (!vi.gt(v)) return false;
|
|
1721
|
+
prev = vi;
|
|
1722
|
+
}
|
|
1723
|
+
return true;
|
|
1724
|
+
})(), true);
|
|
1725
|
+
// 2. truncated towers
|
|
1726
|
+
checkBool("hardy(1e10+11) < hardy(1e10+11.5) ≤ hardy(1e10+12) (fraction keeps order)",
|
|
1727
|
+
MetaNum.hardy("1e10+11").lt(MetaNum.hardy("1e10+11.5")) &&
|
|
1728
|
+
MetaNum.hardy("1e10+11.5").lt(MetaNum.hardy(1e10 + 12)), true);
|
|
1729
|
+
checkBool("hardy(1e10+m) tower level = hardy(m)-1 for m = 12..40",
|
|
1730
|
+
(function () {
|
|
1731
|
+
for (var m = 12; m <= 40; m += 7) {
|
|
1732
|
+
var lv = MetaNum.hardy(1e10 + m).array[0][1];
|
|
1733
|
+
if (lv !== MetaNum.hardy(m).toNumber() - 1) return false;
|
|
1734
|
+
}
|
|
1735
|
+
return true;
|
|
1736
|
+
})(), true);
|
|
1737
|
+
// 3. the string sum form
|
|
1738
|
+
checkBool("M(\"1e10+0.5\") parses to the exact 10000000000.5",
|
|
1739
|
+
JSON.stringify(MetaNum("1e10+0.5").array) === "[[10000000000.5]]", true);
|
|
1740
|
+
checkBool("M(\"1e10+11\") parses to the exact 10000000011",
|
|
1741
|
+
JSON.stringify(MetaNum("1e10+11").array) === "[[10000000011]]", true);
|
|
1742
|
+
checkBool("hardy(\"1e10+11\") = hardy(10000000011) (string = number form)",
|
|
1743
|
+
JSON.stringify(MetaNum.hardy("1e10+11").array) ===
|
|
1744
|
+
JSON.stringify(MetaNum.hardy(10000000011).array), true);
|
|
1745
|
+
checkBool("hardy(\"1e10+22\") format X49 (level 47 chain, promoted)",
|
|
1746
|
+
MetaNum.hardy("1e10+22").format() === "X49", true);
|
|
1747
|
+
// 4. the tower layer rule: every extra 10^ level adds ONE layer, the array
|
|
1748
|
+
// rows stay those of the innermost readable expansion
|
|
1749
|
+
checkBool("hardy(e1e10) = layerUp(hardy(1e10))",
|
|
1750
|
+
(function () {
|
|
1751
|
+
var a = MetaNum.hardy("e1e10"), b = MetaNum.hardy(1e10);
|
|
1752
|
+
return a.layer === b.layer + 1 &&
|
|
1753
|
+
JSON.stringify(a.array) === JSON.stringify(b.array);
|
|
1754
|
+
})(), true);
|
|
1755
|
+
checkBool("hardy(1e308) = layer 0, the digit-path cascade (…[8,6,0,3],[8,7,0,3])",
|
|
1756
|
+
(function () {
|
|
1757
|
+
var v = MetaNum.hardy("1e308");
|
|
1758
|
+
return v.layer === 0 && v.array.length > 2 &&
|
|
1759
|
+
JSON.stringify(v.array[v.array.length - 2]) === "[8,6,0,3]" &&
|
|
1760
|
+
JSON.stringify(v.array[v.array.length - 1]) === "[8,7,0,3]";
|
|
1761
|
+
})(), true);
|
|
1762
|
+
checkBool("hardy(e1e308)/ee1e308/eee1e308 = the same rows at layers 1/2/3",
|
|
1763
|
+
(function () {
|
|
1764
|
+
var v0 = MetaNum.hardy("1e308");
|
|
1765
|
+
var chain = ["e1e308", "ee1e308", "eee1e308"];
|
|
1766
|
+
for (var i = 0; i < chain.length; i++) {
|
|
1767
|
+
var v = MetaNum.hardy(chain[i]);
|
|
1768
|
+
if (v.layer !== i + 1) return false;
|
|
1769
|
+
if (JSON.stringify(v.array) !== JSON.stringify(v0.array)) return false;
|
|
1770
|
+
}
|
|
1771
|
+
return true;
|
|
1772
|
+
})(), true);
|
|
1773
|
+
checkBool("hardy(10^^100) keeps the rows: layer 98 over hardy(1e10)'s array",
|
|
1774
|
+
(function () {
|
|
1775
|
+
var v = MetaNum.hardy(MetaNum(10).tetr(100));
|
|
1776
|
+
return v.layer === 98 &&
|
|
1777
|
+
JSON.stringify(v.array) === JSON.stringify(MetaNum.hardy(1e10).array);
|
|
1778
|
+
})(), true);
|
|
1779
|
+
checkBool("hardy(10^x) = layerUp(hardy(x)) for x = 1e10+1, 2e10, 1e11, 1e15",
|
|
1780
|
+
(function () {
|
|
1781
|
+
var xs = [1e10 + 1, 2e10, 1e11, 1e15];
|
|
1782
|
+
for (var i = 0; i < xs.length; i++) {
|
|
1783
|
+
var hx = MetaNum.hardy(xs[i]);
|
|
1784
|
+
var htx = MetaNum.hardy(MetaNum(10).pow(MetaNum(xs[i])));
|
|
1785
|
+
if (htx.layer !== hx.layer + 1) return false;
|
|
1786
|
+
if (JSON.stringify(htx.array) !== JSON.stringify(hx.array)) return false;
|
|
1787
|
+
}
|
|
1788
|
+
return true;
|
|
1789
|
+
})(), true);
|
|
1790
|
+
checkBool("hardy(10^x) monotone in x across the height-3 band",
|
|
1791
|
+
(function () {
|
|
1792
|
+
var xs = [2e10, 5e10, 1e11, 1e12, 1e15, 1e18];
|
|
1793
|
+
for (var i = 1; i < xs.length; i++) {
|
|
1794
|
+
if (!MetaNum.hardy(MetaNum(10).pow(MetaNum(xs[i - 1])))
|
|
1795
|
+
.lt(MetaNum.hardy(MetaNum(10).pow(MetaNum(xs[i]))))) return false;
|
|
1796
|
+
}
|
|
1797
|
+
return true;
|
|
1798
|
+
})(), true);
|
|
1799
|
+
checkBool("hardy(eee10) keeps the definitional base in its layer-1 marker",
|
|
1800
|
+
JSON.stringify(MetaNum.hardy("eee10").array[0]) ===
|
|
1801
|
+
"[3086.036065328153,9,9,9,9,9,9,9,9]", true);
|
|
1802
|
+
})();
|
|
1803
|
+
|
|
1804
|
+
// ─────────────────────────────────────
|
|
1805
|
+
// v2.0.2 unnamed-level format: a level whose coefficients exceed the letter
|
|
1806
|
+
// grid (ω*2+100, ω*100, ω²*100+ω*100+100, …) rounds UP to the next nameable
|
|
1807
|
+
// level and reads as level-arg — never a wrapped/wrong letter, never the
|
|
1808
|
+
// summed repeat count
|
|
1809
|
+
// ─────────────────────────────────────
|
|
1810
|
+
console.log("\n=== v2.0.2 unnamed-level format ===");
|
|
1811
|
+
// a diagonal letter ("Ca", "Ba", "Aaa", …) carries α = 2·5^f ∈ [2,10)
|
|
1812
|
+
checkFormat("10{ω*2+100}100 → 2.000Ca100",
|
|
1813
|
+
MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), [100, 2]), "2.000Ca100");
|
|
1814
|
+
checkFormat("10{ω*100}100 → 2.000Aaa100",
|
|
1815
|
+
MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), [0, 100]), "2.000Aaa100");
|
|
1816
|
+
checkFormat("10{ω²*100+ω*100+100}1000 → 2.000Aaaa101",
|
|
1817
|
+
MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(1000), [100, 100, 100]), "2.000Aaaa101");
|
|
1818
|
+
checkFormat("h20(10,1000) → 2.000Ba1,000 (ω*2 with y=1000)",
|
|
1819
|
+
MetaNum(10).h20(1000), "2.000Ba1,000");
|
|
1820
|
+
checkFormat("h100(10,1000) → 2.000Aaa1,000 (ω² with y=1000)",
|
|
1821
|
+
MetaNum(10).h100(1000), "2.000Aaa1,000");
|
|
1822
|
+
checkFormat("h30(10,100) → 2.000Ca100 (ω*3 with y=100)",
|
|
1823
|
+
MetaNum(10).h30(100), "2.000Ca100");
|
|
1824
|
+
// nameable levels keep their ordinary cascade display
|
|
1825
|
+
checkFormat("h21(10,1000) → Bb999 (nameable top row, unchanged)",
|
|
1826
|
+
MetaNum(10).h21(1000), "1.000Bb999");
|
|
1827
|
+
|
|
1264
1828
|
// ─────────────────────────────────────
|
|
1265
1829
|
// fractional hyperoperation levels
|
|
1266
1830
|
// level n+f interpolates geometrically (README rule i): 10{n+f}10 =
|
|
@@ -1282,6 +1846,44 @@ console.log("\n=== fractional levels ===");
|
|
|
1282
1846
|
MetaNum(3).arrow(2.5)(3).lt(MetaNum(3).arrow(3)(3)), true);
|
|
1283
1847
|
})();
|
|
1284
1848
|
|
|
1849
|
+
// ─────────────────────────────────────
|
|
1850
|
+
// arrow(x,y,y): level and argument move together, so the interpolation anchor
|
|
1851
|
+
// θ0 (the c with x{n+1}c = x{n}y) has to be a CONTINUOUS inverse — the integer
|
|
1852
|
+
// bisection of hyper_log overshoots it (2 instead of 1.0414), which makes the
|
|
1853
|
+
// geometric step y/θ0 < 1 run backwards and breaks monotonicity.
|
|
1854
|
+
// ─────────────────────────────────────
|
|
1855
|
+
(function () {
|
|
1856
|
+
var ys = [1, 1.1, 1.5, 1.9, 2];
|
|
1857
|
+
for (var b = 0; b < 2; b++) {
|
|
1858
|
+
var bx = [3, 10][b], prev = null, ok = true, firstBad = "";
|
|
1859
|
+
for (var i = 0; i < ys.length; i++) {
|
|
1860
|
+
var v = MetaNum.arrow(bx, ys[i], ys[i]);
|
|
1861
|
+
if (prev && !v.gte(prev)) { ok = false; if (!firstBad) firstBad = "y=" + ys[i]; }
|
|
1862
|
+
prev = v;
|
|
1863
|
+
}
|
|
1864
|
+
checkBool("arrow(" + bx + ",y,y) monotone for y = 1, 1.1, 1.5, 1.9, 2", ok, true,
|
|
1865
|
+
ok ? "" : " first break: " + firstBad);
|
|
1866
|
+
}
|
|
1867
|
+
// fine sweep across the whole 1 → 3 range, both endpoints included
|
|
1868
|
+
var fine = [1, 1.01, 1.25, 1.5, 1.75, 1.99, 2, 2.1, 2.5, 2.9, 3];
|
|
1869
|
+
for (var b2 = 0; b2 < 2; b2++) {
|
|
1870
|
+
var bx2 = [3, 10][b2], p2 = null, ok2 = true;
|
|
1871
|
+
for (var j = 0; j < fine.length; j++) {
|
|
1872
|
+
var v2 = MetaNum.arrow(bx2, fine[j], fine[j]);
|
|
1873
|
+
if (p2 && !v2.gte(p2)) ok2 = false;
|
|
1874
|
+
p2 = v2;
|
|
1875
|
+
}
|
|
1876
|
+
checkBool("arrow(" + bx2 + ",y,y) monotone over y = 1 … 3", ok2, true);
|
|
1877
|
+
}
|
|
1878
|
+
// the ends of an interval meet the neighbouring integers
|
|
1879
|
+
checkBool("10{1.99}1.99 < 10{2}2 = 10^^2",
|
|
1880
|
+
MetaNum.arrow(10, 1.99, 1.99).lt(MetaNum.arrow(10, 2, 2)), true);
|
|
1881
|
+
checkBool("10{2}2 < 10{2.1}2.1",
|
|
1882
|
+
MetaNum.arrow(10, 2, 2).lt(MetaNum.arrow(10, 2.1, 2.1)), true);
|
|
1883
|
+
checkBool("3{1.99}1.99 < 3{2}2 = 27",
|
|
1884
|
+
MetaNum.arrow(3, 1.99, 1.99).lt(MetaNum.arrow(3, 2, 2)), true);
|
|
1885
|
+
})();
|
|
1886
|
+
|
|
1285
1887
|
// ─────────────────────────────────────
|
|
1286
1888
|
// non-integer arguments at ordinal levels
|
|
1287
1889
|
// expa(10,2.1) = 10{ω+1}2.1 = 10{ω}10{ω}(10^0.1)
|
|
@@ -1325,7 +1927,8 @@ function checkFormat(name, input, expected) {
|
|
|
1325
1927
|
}
|
|
1326
1928
|
|
|
1327
1929
|
// Small values & regular numbers
|
|
1328
|
-
|
|
1930
|
+
// β = 1e6 ≥ 10^sciDecimalThreshold(3) → α keeps only its integer part
|
|
1931
|
+
checkFormat("1E-1000000", "1E-1000000", "1E-1,000,000"); // sign=2 reciprocal
|
|
1329
1932
|
checkFormat("1E-100", "1E-100", "1.000E-100");
|
|
1330
1933
|
checkFormat("0.123", "0.123", "0.123");
|
|
1331
1934
|
checkFormat("456789", "456789", "456,789");
|
|
@@ -1366,7 +1969,7 @@ checkFormat("Defg200", "Defg200", "1.000Defg200");
|
|
|
1366
1969
|
// Symbols and ε:
|
|
1367
1970
|
checkFormat("!Aa300", "!Aa300", "!2.000Aa300");
|
|
1368
1971
|
checkFormat("@Bb400", "@Bb400", "@1.000Bb400");
|
|
1369
|
-
checkFormat("1ε500", "1ε500", "1.
|
|
1972
|
+
checkFormat("1ε500", "1ε500", "1.000000ε500"); // epsilonSignificantDigits = 6
|
|
1370
1973
|
|
|
1371
1974
|
// Reciprocal of large numbers (sign=2) format tests
|
|
1372
1975
|
// smallNotationUseE=true → E-<formatted mag>
|
|
@@ -1384,7 +1987,7 @@ check("1/F10 parse", "1/F10", [[10000000000, 8]]);
|
|
|
1384
1987
|
// 1/F500 = 10^(-log10(F500)) = 10^(-F499) → "E-1.000F499"
|
|
1385
1988
|
// 1/G200 = 10^(-log10(G200)) ≈ 10^(-G200) → "E-1.000G200" (TMSI: G200>TMSI)
|
|
1386
1989
|
// 1/F10 = 10^(-log10(F10)) = 10^(-F9) → "E-1.000F9"
|
|
1387
|
-
checkFormat("E-EE1000 (useE=true)", "E-EE1000", "E-
|
|
1990
|
+
checkFormat("E-EE1000 (useE=true)", "E-EE1000", "E-E1E1,000"); // β=1e6 ≥ 10^sciDecimalThreshold → integer α
|
|
1388
1991
|
checkFormat("1/F500 (useE=true)", "1/F500", "E-1.000F499");
|
|
1389
1992
|
checkFormat("1/G200 (useE=true)", "1/G200", "E-1.000G200");
|
|
1390
1993
|
checkFormat("1/F10 (useE=true)", "1/F10", "E-1.000F9");
|
|
@@ -1397,7 +2000,7 @@ checkFormat("1/F10 (useE=true)", "1/F10", "E-1.000F9");
|
|
|
1397
2000
|
var _FMT = (typeof FORMAT_OPTIONS !== "undefined" && FORMAT_OPTIONS) ? FORMAT_OPTIONS : require("./format-metanum.js").FORMAT_OPTIONS;
|
|
1398
2001
|
var _savedUseE = _FMT.smallNotationUseE;
|
|
1399
2002
|
_FMT.smallNotationUseE = false;
|
|
1400
|
-
checkFormat("E-EE1000 (useE=false)", "E-EE1000", "
|
|
2003
|
+
checkFormat("E-EE1000 (useE=false)", "E-EE1000", "EE1E1,000⁻¹"); // integer α (sciDecimalThreshold)
|
|
1401
2004
|
checkFormat("1/F500 (useE=false)", "1/F500", "1.000F500⁻¹");
|
|
1402
2005
|
checkFormat("1/G200 (useE=false)", "1/G200", "1.000G200⁻¹");
|
|
1403
2006
|
checkFormat("1/F10 (useE=false)", "1/F10", "1.000F10⁻¹");
|
|
@@ -1416,10 +2019,12 @@ checkFormat("canonical all-8s keeps α=1 (G600)", "G600", "1.000G600");
|
|
|
1416
2019
|
// and a combination longer than multiLetterLimit switches to !αAaβ
|
|
1417
2020
|
// ─────────────────────────────────────
|
|
1418
2021
|
checkFormat("20-row cascade compresses to two letter types", MetaNum.h10000(3, 10), "Iccc1.000Iccb10");
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
checkFormat("
|
|
1422
|
-
checkFormat("
|
|
2022
|
+
// a level whose letter name is longer than multiLetterLimit carries to the
|
|
2023
|
+
// SINGLE-letter form !αΓβ — "!" adds one ω^ layer on top of the level Γ names
|
|
2024
|
+
checkFormat("10-letter level carries to !1.000M9", MetaNum.iter(3, 10), "!1.000M9");
|
|
2025
|
+
checkFormat("5-letter level carries to !1.000H4", m3.iter(5), "!1.000H4");
|
|
2026
|
+
checkFormat("symbol carry stacks: apix(3,10) → @1.000N10", m3.aperixxate(10), "@1.000N10");
|
|
2027
|
+
checkFormat("symbol carry stacks: apix(3,5) → @1.000I10", m3.aperixxate(5), "@1.000I10");
|
|
1423
2028
|
checkFormat("short diagonal keeps the letter form", m3.aperixxate(3), "!2.000Aaaa10");
|
|
1424
2029
|
checkFormat("cascade inner α stays [1,10) (AbAa600)", "AbAa600", "Ab1.000Aa600");
|
|
1425
2030
|
|
|
@@ -1456,9 +2061,10 @@ for (var si = 0; si < stacked.length; si++) {
|
|
|
1456
2061
|
checkFormat("apea^3(1e16) nests further", p3, "BaBaBa1.000E16");
|
|
1457
2062
|
checkBool("apea stacking is strictly monotone", p2.gt(p1) && p3.gt(p2), true);
|
|
1458
2063
|
})();
|
|
1459
|
-
// a row coefficient above
|
|
1460
|
-
// letter
|
|
1461
|
-
|
|
2064
|
+
// a row coefficient above the grid (ω+81..99 from a ω*2 fundamental sequence)
|
|
2065
|
+
// has no letter — the level rounds UP to the next nameable one and the value
|
|
2066
|
+
// reads as level-arg: 10{ω*2}100 → Ba with the operation's own argument 100
|
|
2067
|
+
checkFormat("ω*2 level reads Ba (no coefficient wrap)", MetaNum(10).aperioexpande(100), "2.000Ba100");
|
|
1462
2068
|
|
|
1463
2069
|
// Γ-canonical law test: long descending count-1 chains
|
|
1464
2070
|
// format at their bisect-exact letter on the engine's smooth arrow curve;
|
|
@@ -1700,6 +2306,97 @@ console.log("\n=== MetaNum(...).format() instance method ===");
|
|
|
1700
2306
|
MetaNum("FE400").format(), format(MetaNum("FE400")));
|
|
1701
2307
|
})();
|
|
1702
2308
|
|
|
2309
|
+
// ─────────────────────────────────────
|
|
2310
|
+
// FORMAT_OPTIONS: every option must take effect. Each check flips the option
|
|
2311
|
+
// and asserts the display changes along the option's documented meaning.
|
|
2312
|
+
// ─────────────────────────────────────
|
|
2313
|
+
console.log("\n=== FORMAT_OPTIONS take effect ===");
|
|
2314
|
+
(function () {
|
|
2315
|
+
var OPT = _FMT;
|
|
2316
|
+
var saved = {};
|
|
2317
|
+
function set(k, v) { if (!(k in saved)) saved[k] = OPT[k]; OPT[k] = v; }
|
|
2318
|
+
function restore() { for (var k in saved) OPT[k] = saved[k]; saved = {}; }
|
|
2319
|
+
function after(name, fn) {
|
|
2320
|
+
var r;
|
|
2321
|
+
try { r = fn(); } catch (e) { r = "threw " + e.message.slice(0, 40); }
|
|
2322
|
+
restore();
|
|
2323
|
+
checkBool(name, r === true, true, typeof r === "string" ? r : "");
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
after("opt smallNotationUseE: ⁻¹ when false, E- when true", function () {
|
|
2327
|
+
set("smallNotationThreshold", 4);
|
|
2328
|
+
set("smallNotationUseE", false); var a = format(MetaNum(1e-10));
|
|
2329
|
+
set("smallNotationUseE", true); var b = format(MetaNum(1e-10));
|
|
2330
|
+
return a.indexOf("⁻¹") >= 0 && b.indexOf("E-") >= 0;
|
|
2331
|
+
});
|
|
2332
|
+
after("opt smallNotationThreshold moves the small-value boundary", function () {
|
|
2333
|
+
set("smallNotationThreshold", 3); var a = /E-4|⁻¹/.test(format(MetaNum(1e-4)));
|
|
2334
|
+
set("smallNotationThreshold", 5); var b = /E-4|⁻¹/.test(format(MetaNum(1e-4)));
|
|
2335
|
+
return a && !b;
|
|
2336
|
+
});
|
|
2337
|
+
after("opt decimalPlaces: 0 → '1', 2 → '1.40'", function () {
|
|
2338
|
+
set("decimalPlaces", 0); var a = format(MetaNum(1.4));
|
|
2339
|
+
set("decimalPlaces", 2); var b = format(MetaNum(1.4));
|
|
2340
|
+
return a === "1" && b === "1.40";
|
|
2341
|
+
});
|
|
2342
|
+
after("opt decimalThreshold: decimals drop past 10^n", function () {
|
|
2343
|
+
set("decimalThreshold", 3); var a = format(MetaNum(1234.56)).indexOf(".") < 0;
|
|
2344
|
+
set("decimalThreshold", 5); var b = format(MetaNum(1234.56)).indexOf(".") >= 0;
|
|
2345
|
+
return a && b;
|
|
2346
|
+
});
|
|
2347
|
+
after("opt useCommas toggles grouping", function () {
|
|
2348
|
+
set("useCommas", true); var a = format(MetaNum(1234567));
|
|
2349
|
+
set("useCommas", false); var b = format(MetaNum(1234567));
|
|
2350
|
+
return a === "1,234,567" && b === "1234567";
|
|
2351
|
+
});
|
|
2352
|
+
after("opt sciThreshold moves the E boundary", function () {
|
|
2353
|
+
set("sciThreshold", 9); var a = /E/.test(format(MetaNum(1e11)));
|
|
2354
|
+
set("sciThreshold", 12); var b = /E/.test(format(MetaNum(1e11)));
|
|
2355
|
+
return a && !b;
|
|
2356
|
+
});
|
|
2357
|
+
after("opt sciSignificantDigits: 1 → 1.2E10", function () {
|
|
2358
|
+
set("sciSignificantDigits", 1);
|
|
2359
|
+
return /^1\.2E/.test(format(MetaNum(1.2345e10)));
|
|
2360
|
+
});
|
|
2361
|
+
after("opt sciDecimalThreshold: β ≥ 10^n → integer α", function () {
|
|
2362
|
+
set("sciDecimalThreshold", 3); var a = /^1E100,000$/.test(format(MetaNum("1e100000")));
|
|
2363
|
+
set("sciDecimalThreshold", 9); var b = /^1\.000E100,000$/.test(format(MetaNum("1e100000")));
|
|
2364
|
+
return a && b;
|
|
2365
|
+
});
|
|
2366
|
+
after("opt singleLetterDigits: 1 → 2.0G, 3 → 2.045G", function () {
|
|
2367
|
+
set("singleLetterDigits", 1); var a = /^2\.0G/.test(format(MetaNum.arrow(3, 3, 7)));
|
|
2368
|
+
set("singleLetterDigits", 3); var b = /^2\.045G/.test(format(MetaNum.arrow(3, 3, 7)));
|
|
2369
|
+
return a && b;
|
|
2370
|
+
});
|
|
2371
|
+
after("opt repeatLetterThreshold: 3 collapses arrow(3,3,6), 5 spells FFFF", function () {
|
|
2372
|
+
set("repeatLetterThreshold", 3); var a = format(MetaNum.arrow(3, 3, 6)) === "2.045G5";
|
|
2373
|
+
set("repeatLetterThreshold", 5); var b = /^FFFF/.test(format(MetaNum.arrow(3, 3, 6)));
|
|
2374
|
+
return a && b;
|
|
2375
|
+
});
|
|
2376
|
+
after("opt multiLetterDigits: 1 → 2.0Aa, 3 → 2.000Aa", function () {
|
|
2377
|
+
set("multiLetterDigits", 1); var a = /^2\.0Aa/.test(format(MetaNum(10).arrow(23)(MetaNum(10))));
|
|
2378
|
+
set("multiLetterDigits", 3); var b = /^2\.000Aa/.test(format(MetaNum(10).arrow(23)(MetaNum(10))));
|
|
2379
|
+
return a && b;
|
|
2380
|
+
});
|
|
2381
|
+
after("opt multiLetterRepeatThreshold: 2 collapses 3×Aa, 5 keeps it", function () {
|
|
2382
|
+
set("multiLetterRepeatThreshold", 2); var a = /^1\.841Ab/.test(format(MetaNum("AaAaAa100")));
|
|
2383
|
+
set("multiLetterRepeatThreshold", 5); var b = /^AaAa/.test(format(MetaNum("AaAaAa100")));
|
|
2384
|
+
return a && b;
|
|
2385
|
+
});
|
|
2386
|
+
after("opt multiLetterLimit: 4 keeps Aaaa, 3 carries to !", function () {
|
|
2387
|
+
var v = MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(100), [100, 100, 50]);
|
|
2388
|
+
set("multiLetterLimit", 4); var a = /Aaaa/.test(format(v));
|
|
2389
|
+
set("multiLetterLimit", 3); var b = format(v).indexOf("!") === 0;
|
|
2390
|
+
return a && b;
|
|
2391
|
+
});
|
|
2392
|
+
after("opt epsilonSignificantDigits: 6 → 1.000000ε12, 0 → 1ε12", function () {
|
|
2393
|
+
var v = MetaNum("!!!!!!!!!!!!2.000Aa10");
|
|
2394
|
+
set("epsilonSignificantDigits", 6); var a = format(v) === "1.000000ε12";
|
|
2395
|
+
set("epsilonSignificantDigits", 0); var b = format(v) === "1ε12";
|
|
2396
|
+
return a && b;
|
|
2397
|
+
});
|
|
2398
|
+
})();
|
|
2399
|
+
|
|
1703
2400
|
console.log("\n=== format tests Done ===");
|
|
1704
2401
|
|
|
1705
2402
|
|