metanum 2.0.0 → 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 +187 -172
- package/format-metanum.js +354 -141
- package/metanum.js +629 -247
- package/package.json +1 -1
- package/test-interface.html +1 -0
- package/test_mixed.js +1000 -31
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];
|
|
@@ -872,6 +863,289 @@ checkBool("inv_powerexpande(1e16{ω+3}5,1e16)=5", mL16.powerexpande(5).inv_power
|
|
|
872
863
|
// Small-x finite branch (base has no ω-row): inv_expande is exact too.
|
|
873
864
|
checkBool("inv_expande(3{ω+1}5,3)=5", MetaNum(3).expande(5).inv_expande(MetaNum(3)).eq(MetaNum(5)), true);
|
|
874
865
|
|
|
866
|
+
// ─────────────────────────────────────
|
|
867
|
+
// h11/h12/h13 (ω+1 / ω+2 / ω+3): the TOP row carries y-2 applications
|
|
868
|
+
// (rule 2: x{α}y = x{α-1}^(y-2)(x{α-1}x)), and every row BELOW it comes from
|
|
869
|
+
// decomposing x{α-1}x — whose operand is the BASE x — so it carries x-2,
|
|
870
|
+
// the same count the finite r0 coefficients carry.
|
|
871
|
+
// 10{ω+3}20 = 10{ω+2}^18 10{ω+1}^8 10{ω}^8 10{ω}10
|
|
872
|
+
// → [8,0,1] [8,1,1] [18,2,1] (not three 18-rows)
|
|
873
|
+
// ─────────────────────────────────────
|
|
874
|
+
console.log("\n=== h11/h12/h13 count law ===");
|
|
875
|
+
checkBool("h13(10,20) = 10{ω+3}20 → [8,0,1] [8,1,1] [18,2,1]",
|
|
876
|
+
JSON.stringify(MetaNum(10).h13(20).array.slice(1)) === "[[8,0,1],[8,1,1],[18,2,1]]", true);
|
|
877
|
+
checkBool("h12(10,20) = 10{ω+2}20 → [8,0,1] [18,1,1]",
|
|
878
|
+
JSON.stringify(MetaNum(10).h12(20).array.slice(1)) === "[[8,0,1],[18,1,1]]", true);
|
|
879
|
+
checkBool("h11(10,20) = 10{ω+1}20 → [18,0,1] (single row stays y-2)",
|
|
880
|
+
JSON.stringify(MetaNum(10).h11(20).array.slice(1)) === "[[18,0,1]]", true);
|
|
881
|
+
// the lower rows are the BASE's count (x-2) and never move with y
|
|
882
|
+
var hRows = { 3: 1, 5: 3, 10: 8 };
|
|
883
|
+
for (var hx in hRows) {
|
|
884
|
+
var lowC = hRows[hx];
|
|
885
|
+
for (var hy = 3; hy <= 20; hy++) {
|
|
886
|
+
var hr = MetaNum(Number(hx)).h13(hy).array.slice(1);
|
|
887
|
+
var hok = JSON.stringify(hr) === JSON.stringify(
|
|
888
|
+
[[lowC, 0, 1], [lowC, 1, 1], [hy - 2, 2, 1]]);
|
|
889
|
+
if (!hok) { checkBool("h13(" + hx + "," + hy + ") rows", false, true); break; }
|
|
890
|
+
}
|
|
891
|
+
checkBool("h13(" + hx + ",3..20): lower rows fixed at x-2=" + lowC + ", top row y-2", true, true);
|
|
892
|
+
}
|
|
893
|
+
// y-monotone and level-monotone on the enumeration path
|
|
894
|
+
for (var hy2 = 3; hy2 <= 20; hy2++) {
|
|
895
|
+
var hprev = null, hch = true;
|
|
896
|
+
for (var hi = 0; hi < 3; hi++) {
|
|
897
|
+
var hv = MetaNum(10)[["h11", "h12", "h13"][hi]](hy2);
|
|
898
|
+
if (hprev && !hv.gt(hprev)) hch = false;
|
|
899
|
+
hprev = hv;
|
|
900
|
+
}
|
|
901
|
+
if (!hch) { checkBool("h11<h12<h13 at y=" + hy2, false, true); break; }
|
|
902
|
+
}
|
|
903
|
+
checkBool("h11 < h12 < h13 for y = 3..20", true, true);
|
|
904
|
+
checkBool("inv_powerexpande(10{ω+3}20,10) = 20",
|
|
905
|
+
MetaNum(10).h13(20).inv_powerexpande(MetaNum(10)).eq(MetaNum(20)), true);
|
|
906
|
+
|
|
907
|
+
// ─────────────────────────────────────
|
|
908
|
+
// Every level from ω*2 up follows the same law:
|
|
909
|
+
// successor α = β+1 → rows of x{β}x, each x-2, + one β-row carrying y-2
|
|
910
|
+
// limit α → rule 3 turns y into the fundamental-sequence index, so
|
|
911
|
+
// EVERY row carries x-2 (stay expanded up to MSI)
|
|
912
|
+
// ─────────────────────────────────────
|
|
913
|
+
console.log("\n=== h20+ : expanded form & count law ===");
|
|
914
|
+
// successor h21 (ω*2+1): 10{ω*2+1}20 = the ω..ω+9 cascade (x-2 = 8) + ω*2 row y-2
|
|
915
|
+
checkBool("h21(10,20) = [8,0..9,1] rows + [18,0,2]",
|
|
916
|
+
JSON.stringify(MetaNum(10).h21(20).array.slice(1)) ===
|
|
917
|
+
"[[8,0,1],[8,1,1],[8,2,1],[8,3,1],[8,4,1],[8,5,1],[8,6,1],[8,7,1],[8,8,1],[8,9,1],[18,0,2]]", true);
|
|
918
|
+
// h22 (ω*2+2): one more row at ω*2 (x-2), top row ω*2+1 carries y-2
|
|
919
|
+
checkBool("h22(10,20) = cascade + [8,0,2] + [18,1,2]",
|
|
920
|
+
JSON.stringify(MetaNum(10).h22(20).array.slice(1)) ===
|
|
921
|
+
"[[8,0,1],[8,1,1],[8,2,1],[8,3,1],[8,4,1],[8,5,1],[8,6,1],[8,7,1],[8,8,1],[8,9,1],[8,0,2],[18,1,2]]", true);
|
|
922
|
+
// base-driven lower rows: x=3 → the cascade stops at ω+2 and every count is 1
|
|
923
|
+
checkBool("h21(3,20): lower rows carry x-2 = 1",
|
|
924
|
+
JSON.stringify(MetaNum(3).h21(20).array.slice(1)) === "[[1,0,1],[1,1,1],[1,2,1],[18,0,2]]", true);
|
|
925
|
+
// and the lower rows never move with y
|
|
926
|
+
(function () {
|
|
927
|
+
var lowRows = JSON.stringify(MetaNum(10).h21(3).array.slice(1, 11));
|
|
928
|
+
var ok = true;
|
|
929
|
+
for (var y = 4; y <= 20; y++) {
|
|
930
|
+
var r = MetaNum(10).h21(y).array.slice(1);
|
|
931
|
+
if (JSON.stringify(r.slice(0, 10)) !== lowRows || r[10][0] !== y - 2) ok = false;
|
|
932
|
+
}
|
|
933
|
+
checkBool("h21(10,3..20): lower rows fixed at 8, ω*2 row = y-2", ok, true);
|
|
934
|
+
})();
|
|
935
|
+
|
|
936
|
+
// limit ops stay EXPANDED for 100 < y ≤ MSI (no one-row marker)
|
|
937
|
+
(function () {
|
|
938
|
+
var MSI = 9007199254740991;
|
|
939
|
+
for (var i = 0; i < 3; i++) {
|
|
940
|
+
var lf = ["h20", "h30", "h100"][i];
|
|
941
|
+
for (var k = 0; k < 3; k++) {
|
|
942
|
+
var ly = [101, 1000, MSI][k];
|
|
943
|
+
var lr = MetaNum(10)[lf](ly);
|
|
944
|
+
// maxRows-1 ordinal rows, base collapsed to [10], first kept row marked +1
|
|
945
|
+
checkBool(lf + "(10," + ly + ") stays expanded (" + (lr.array.length - 1) + " rows)",
|
|
946
|
+
lr.array.length - 1 === MetaNum.maxRows - 1 && lr.array[0].length === 1 &&
|
|
947
|
+
lr.array[1][0] === 9, true);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
// top row carries the fundamental-sequence index y-1
|
|
951
|
+
checkBool("h20(10,1000) top row = ω+999",
|
|
952
|
+
JSON.stringify(MetaNum(10).h20(1000).array[19]) === "[8,999,1]", true);
|
|
953
|
+
checkBool("h20(10,MSI) top row = ω+(MSI-1)",
|
|
954
|
+
MetaNum(10).h20(MSI).array[19][1] === MSI - 1, true);
|
|
955
|
+
})();
|
|
956
|
+
|
|
957
|
+
// ─────────────────────────────────────
|
|
958
|
+
// Fractional y for every level from ω*2 up (README "Non-integer arguments"):
|
|
959
|
+
// a limit level takes its fundamental sequence at the FULL fractional index and
|
|
960
|
+
// the fractional coefficients resolve against the base x (ω^(k)·(c+f) =
|
|
961
|
+
// ω^(k)·c + ω^(k-1)·(x·f)); a leftover fractional constant becomes a fractional
|
|
962
|
+
// argument one level up: x{γ+f}x = x{γ+1}(2·(x/2)^f).
|
|
963
|
+
// ─────────────────────────────────────
|
|
964
|
+
console.log("\n=== h20+ with fractional y ===");
|
|
965
|
+
checkBool("10{ω*2}2.1 = 10{ω+3}(2*5^0.1)",
|
|
966
|
+
MetaNum(10).h20(2.1).eq(MetaNum(10).powerexpande(2 * Math.pow(5, 0.1))), true);
|
|
967
|
+
checkBool("3{ω*2}2.1 = 3{ω+3}(2*1.5^0.1)",
|
|
968
|
+
MetaNum(3).h20(2.1).eq(MetaNum(3).powerexpande(2 * Math.pow(1.5, 0.1))), true);
|
|
969
|
+
checkBool("10{ω^2}2.1 = 10{ω*2+1}10",
|
|
970
|
+
MetaNum(10).h100(2.1).eq(MetaNum(10).h21(10)), true);
|
|
971
|
+
checkBool("3{ω^2}2.1 = 3{ω*2+1}(2*1.5^0.3)",
|
|
972
|
+
MetaNum(3).h100(2.1).eq(MetaNum(3).h21(2 * Math.pow(1.5, 0.3))), true);
|
|
973
|
+
// 10{ω^ω}2.1 = 10{ω^2.1}10 = 10{ω^2*10^0.1}10 → ω^2+ω*2+5.8925… → next level
|
|
974
|
+
(function () {
|
|
975
|
+
var rf = MetaNum._resolveFracLevel([0, 0, Math.pow(10, 0.1)], 10);
|
|
976
|
+
var up = rf.ord.slice(); up[0] += 1;
|
|
977
|
+
checkBool("10{ω^ω}2.1 = 10{ω^2+ω*2+6}(2*5^0.8925…) (level " +
|
|
978
|
+
JSON.stringify(up) + ")",
|
|
979
|
+
JSON.stringify(up) === "[6,2,1]" &&
|
|
980
|
+
MetaNum(10).iterate(2.1).eq(
|
|
981
|
+
MetaNum._hyperopFromOrdinal(MetaNum(10), MetaNum(2 * Math.pow(5, rf.frac)), up)), true);
|
|
982
|
+
})();
|
|
983
|
+
// the fraction is not thrown away: y and floor(y) differ
|
|
984
|
+
checkBool("h20(10,2.1) != h20(10,2) and lies strictly between 2 and 3",
|
|
985
|
+
MetaNum(10).h20(2.1).gt(MetaNum(10).h20(2)) &&
|
|
986
|
+
MetaNum(10).h20(2.1).lt(MetaNum(10).h20(3)), true);
|
|
987
|
+
checkBool("h100(10,10.25) lies strictly between 10 and 11",
|
|
988
|
+
MetaNum(10).h100(10.25).gt(MetaNum(10).h100(10)) &&
|
|
989
|
+
MetaNum(10).h100(10.25).lt(MetaNum(10).h100(11)), true);
|
|
990
|
+
// monotone in y across the integers for the LIMIT levels
|
|
991
|
+
(function () {
|
|
992
|
+
var limOps = ["h20", "h30", "h100", "h110", "h1000", "h10000", "iterate"];
|
|
993
|
+
var bad = 0, firstBad = "";
|
|
994
|
+
for (var i = 0; i < limOps.length; i++) {
|
|
995
|
+
for (var b = 0; b < 2; b++) {
|
|
996
|
+
var bx = [3, 10][b];
|
|
997
|
+
for (var m = 2; m <= 10; m++) {
|
|
998
|
+
var a = MetaNum(bx)[limOps[i]](m), c = MetaNum(bx)[limOps[i]](m + 0.001);
|
|
999
|
+
var d = MetaNum(bx)[limOps[i]](m + 0.5), e = MetaNum(bx)[limOps[i]](m + 1);
|
|
1000
|
+
if (!(c.gte(a) && d.gte(c) && e.gte(d))) {
|
|
1001
|
+
bad++; if (!firstBad) firstBad = limOps[i] + "(" + bx + "," + m + ")";
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
checkBool("limit levels monotone across fractional y", bad === 0, true,
|
|
1007
|
+
bad === 0 ? "" : " first failure: " + firstBad);
|
|
1008
|
+
})();
|
|
1009
|
+
// the SUCCESSOR rule with a fractional argument is written in the same expanded
|
|
1010
|
+
// form: the α-1 row carries the m applications (ceil(y)-2 = m-1) and the cascade
|
|
1011
|
+
// below it is generated at the fundamental-sequence index x^f, so the value grows
|
|
1012
|
+
// with f inside the interval and converges to the next integer at f → 1
|
|
1013
|
+
checkBool("h21(10,2.001) < h21(10,2.5) < h21(10,2.99) < h21(10,3)",
|
|
1014
|
+
MetaNum(10).h21(2.001).lt(MetaNum(10).h21(2.5)) &&
|
|
1015
|
+
MetaNum(10).h21(2.5).lt(MetaNum(10).h21(2.99)) &&
|
|
1016
|
+
MetaNum(10).h21(2.99).lt(MetaNum(10).h21(3)), true);
|
|
1017
|
+
checkBool("h31(10,5.1) < h31(10,5.5) < h31(10,5.9) < h31(10,6)",
|
|
1018
|
+
MetaNum(10).h31(5.1).lt(MetaNum(10).h31(5.5)) &&
|
|
1019
|
+
MetaNum(10).h31(5.5).lt(MetaNum(10).h31(5.9)) &&
|
|
1020
|
+
MetaNum(10).h31(5.9).lt(MetaNum(10).h31(6)), true);
|
|
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
|
|
1025
|
+
(function () {
|
|
1026
|
+
var ok = true;
|
|
1027
|
+
for (var k = 0; k < 6; k++) {
|
|
1028
|
+
var fy = [2.001, 2.1, 2.5, 3.5, 10.25, 100.75][k];
|
|
1029
|
+
var rr = MetaNum(10).h21(fy).array.slice(1);
|
|
1030
|
+
for (var i = 0; i < rr.length - 1; i++) if (rr[i][0] !== 8) ok = false;
|
|
1031
|
+
if (rr[rr.length - 1][0] !== Math.ceil(fy) - 2) ok = false;
|
|
1032
|
+
}
|
|
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);
|
|
1039
|
+
checkBool("h21(10,2.999999) → h21(10,3) from below",
|
|
1040
|
+
MetaNum(10).h21(2.999999).lt(MetaNum(10).h21(3)) &&
|
|
1041
|
+
MetaNum(10).h21(2.999999).gt(MetaNum(10).h21(2)), true);
|
|
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
|
+
|
|
1089
|
+
// row coefficients stay integer (a fractional constant is carried to the base)
|
|
1090
|
+
(function () {
|
|
1091
|
+
var ok = true;
|
|
1092
|
+
for (var f of ["h21", "h22", "h31", "h101", "h111", "h1001"]) {
|
|
1093
|
+
for (var k = 0; k < 5; k++) {
|
|
1094
|
+
var fy = [2.001, 2.5, 3.5, 10.25, 100.75][k];
|
|
1095
|
+
var arr = MetaNum(10)[f](fy).array;
|
|
1096
|
+
for (var i = 1; i < arr.length; i++) {
|
|
1097
|
+
for (var j = 1; j < arr[i].length; j++) {
|
|
1098
|
+
if (arr[i][j] !== Math.floor(arr[i][j])) ok = false;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
checkBool("fractional y: every ordinal row coefficient is an integer", ok, true);
|
|
1104
|
+
})();
|
|
1105
|
+
|
|
1106
|
+
// no crash / NaN over the whole range with fractional operands
|
|
1107
|
+
(function () {
|
|
1108
|
+
var allOps = ["h20","h21","h22","h30","h31","h100","h101","h110","h111",
|
|
1109
|
+
"h1000","h1001","h10000","iterate"];
|
|
1110
|
+
var bad = 0;
|
|
1111
|
+
for (var i = 0; i < allOps.length; i++) {
|
|
1112
|
+
for (var b = 0; b < 4; b++) {
|
|
1113
|
+
var bx = [3, 10, 1e6, 1e16][b];
|
|
1114
|
+
for (var k = 0; k < 5; k++) {
|
|
1115
|
+
var by = [2.0001, 2.5, 3.5, 10.25, 1000.5][k];
|
|
1116
|
+
try {
|
|
1117
|
+
var v = MetaNum(bx)[allOps[i]](by);
|
|
1118
|
+
if (v.isNaN()) bad++;
|
|
1119
|
+
} catch (e) { bad++; }
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
checkBool("no throw/NaN for fractional y over h20..h10000 + iterate", bad === 0, true);
|
|
1124
|
+
})();
|
|
1125
|
+
|
|
1126
|
+
// inverse round-trip over the whole small-operand range, successors and limits
|
|
1127
|
+
(function () {
|
|
1128
|
+
var pairs = [["h11","inv_expande"],["h12","inv_multiexpande"],["h13","inv_powerexpande"],
|
|
1129
|
+
["h20","inv_aperioexpande"],["h21","inv_explode"],["h22","inv_multiexplode"],
|
|
1130
|
+
["h30","inv_aperioexplode"],["h31","inv_detonate"],["h100","inv_aperionate"],
|
|
1131
|
+
["h101","inv_megote"],["h110","inv_aperimegote"],["h111","inv_megoexpande"],
|
|
1132
|
+
["h1000","inv_aperiatote"],["h1001","inv_powiainate"]];
|
|
1133
|
+
var bad = 0, firstBad = "";
|
|
1134
|
+
for (var i = 0; i < pairs.length; i++) {
|
|
1135
|
+
for (var b = 0; b < 3; b++) {
|
|
1136
|
+
var bx = [3, 5, 10][b];
|
|
1137
|
+
for (var y = 3; y <= 20; y++) {
|
|
1138
|
+
var v = MetaNum(bx)[pairs[i][0]](y);
|
|
1139
|
+
if (!v[pairs[i][1]](MetaNum(bx)).eq(MetaNum(y))) {
|
|
1140
|
+
bad++; if (!firstBad) firstBad = pairs[i][0] + "(" + bx + "," + y + ")";
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
checkBool("inverse round-trip for h11..h1001 (x=3/5/10, y=3..20)", bad === 0,
|
|
1146
|
+
true, bad === 0 ? "" : " first failure: " + firstBad);
|
|
1147
|
+
})();
|
|
1148
|
+
|
|
875
1149
|
// ─────────────────────────────────────
|
|
876
1150
|
// engine arrays: the (y-2) count law
|
|
877
1151
|
// x{L}y = x{L-1}^{y-2}(x{L-1}x): 10{25}10 → count-8 rows/cols (the
|
|
@@ -1008,8 +1282,12 @@ checkBool("hardy(1e15) < hardy(1e16) < hardy(1e17)",
|
|
|
1008
1282
|
// -- MetaNum-object input (v2.0): structures shadow to their ordinal --
|
|
1009
1283
|
// power tower 10^^k → ω^ω^…^ω (k ω's) → H there = 10.epsilonate(k);
|
|
1010
1284
|
// letter/ordinal values sit at their own Hardy position → themselves
|
|
1011
|
-
checkBool("hardy(10^^100) =
|
|
1012
|
-
|
|
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);
|
|
1013
1291
|
checkBool("hardy(MetaNum G600) = Infinity",
|
|
1014
1292
|
MetaNum.hardy(MetaNum("G600")).eq(MetaNum.infinity), true);
|
|
1015
1293
|
checkBool("hardy(MetaNum arrow(3,9,3)) = Infinity",
|
|
@@ -1020,12 +1298,533 @@ checkBool("hardy(10{3}10) = Infinity (> 10^^MSI)",
|
|
|
1020
1298
|
// -- the engine limit: hardy(10^^MSI) = 10{ω^…^ω(MSI ω's)}10 (v2.0) --
|
|
1021
1299
|
(function () {
|
|
1022
1300
|
var MSI = 9007199254740991;
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
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);
|
|
1027
1397
|
})();
|
|
1028
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)
|
|
1600
|
+
})();
|
|
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
|
+
|
|
1029
1828
|
// ─────────────────────────────────────
|
|
1030
1829
|
// fractional hyperoperation levels
|
|
1031
1830
|
// level n+f interpolates geometrically (README rule i): 10{n+f}10 =
|
|
@@ -1047,6 +1846,44 @@ console.log("\n=== fractional levels ===");
|
|
|
1047
1846
|
MetaNum(3).arrow(2.5)(3).lt(MetaNum(3).arrow(3)(3)), true);
|
|
1048
1847
|
})();
|
|
1049
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
|
+
|
|
1050
1887
|
// ─────────────────────────────────────
|
|
1051
1888
|
// non-integer arguments at ordinal levels
|
|
1052
1889
|
// expa(10,2.1) = 10{ω+1}2.1 = 10{ω}10{ω}(10^0.1)
|
|
@@ -1090,7 +1927,8 @@ function checkFormat(name, input, expected) {
|
|
|
1090
1927
|
}
|
|
1091
1928
|
|
|
1092
1929
|
// Small values & regular numbers
|
|
1093
|
-
|
|
1930
|
+
// β = 1e6 ≥ 10^sciDecimalThreshold(3) → α keeps only its integer part
|
|
1931
|
+
checkFormat("1E-1000000", "1E-1000000", "1E-1,000,000"); // sign=2 reciprocal
|
|
1094
1932
|
checkFormat("1E-100", "1E-100", "1.000E-100");
|
|
1095
1933
|
checkFormat("0.123", "0.123", "0.123");
|
|
1096
1934
|
checkFormat("456789", "456789", "456,789");
|
|
@@ -1131,7 +1969,7 @@ checkFormat("Defg200", "Defg200", "1.000Defg200");
|
|
|
1131
1969
|
// Symbols and ε:
|
|
1132
1970
|
checkFormat("!Aa300", "!Aa300", "!2.000Aa300");
|
|
1133
1971
|
checkFormat("@Bb400", "@Bb400", "@1.000Bb400");
|
|
1134
|
-
checkFormat("1ε500", "1ε500", "1.
|
|
1972
|
+
checkFormat("1ε500", "1ε500", "1.000000ε500"); // epsilonSignificantDigits = 6
|
|
1135
1973
|
|
|
1136
1974
|
// Reciprocal of large numbers (sign=2) format tests
|
|
1137
1975
|
// smallNotationUseE=true → E-<formatted mag>
|
|
@@ -1149,7 +1987,7 @@ check("1/F10 parse", "1/F10", [[10000000000, 8]]);
|
|
|
1149
1987
|
// 1/F500 = 10^(-log10(F500)) = 10^(-F499) → "E-1.000F499"
|
|
1150
1988
|
// 1/G200 = 10^(-log10(G200)) ≈ 10^(-G200) → "E-1.000G200" (TMSI: G200>TMSI)
|
|
1151
1989
|
// 1/F10 = 10^(-log10(F10)) = 10^(-F9) → "E-1.000F9"
|
|
1152
|
-
checkFormat("E-EE1000 (useE=true)", "E-EE1000", "E-
|
|
1990
|
+
checkFormat("E-EE1000 (useE=true)", "E-EE1000", "E-E1E1,000"); // β=1e6 ≥ 10^sciDecimalThreshold → integer α
|
|
1153
1991
|
checkFormat("1/F500 (useE=true)", "1/F500", "E-1.000F499");
|
|
1154
1992
|
checkFormat("1/G200 (useE=true)", "1/G200", "E-1.000G200");
|
|
1155
1993
|
checkFormat("1/F10 (useE=true)", "1/F10", "E-1.000F9");
|
|
@@ -1162,7 +2000,7 @@ checkFormat("1/F10 (useE=true)", "1/F10", "E-1.000F9");
|
|
|
1162
2000
|
var _FMT = (typeof FORMAT_OPTIONS !== "undefined" && FORMAT_OPTIONS) ? FORMAT_OPTIONS : require("./format-metanum.js").FORMAT_OPTIONS;
|
|
1163
2001
|
var _savedUseE = _FMT.smallNotationUseE;
|
|
1164
2002
|
_FMT.smallNotationUseE = false;
|
|
1165
|
-
checkFormat("E-EE1000 (useE=false)", "E-EE1000", "
|
|
2003
|
+
checkFormat("E-EE1000 (useE=false)", "E-EE1000", "EE1E1,000⁻¹"); // integer α (sciDecimalThreshold)
|
|
1166
2004
|
checkFormat("1/F500 (useE=false)", "1/F500", "1.000F500⁻¹");
|
|
1167
2005
|
checkFormat("1/G200 (useE=false)", "1/G200", "1.000G200⁻¹");
|
|
1168
2006
|
checkFormat("1/F10 (useE=false)", "1/F10", "1.000F10⁻¹");
|
|
@@ -1180,14 +2018,54 @@ checkFormat("canonical all-8s keeps α=1 (G600)", "G600", "1.000G600");
|
|
|
1180
2018
|
// carry — a cascade that would spell 20 letter types keeps its top two levels,
|
|
1181
2019
|
// and a combination longer than multiLetterLimit switches to !αAaβ
|
|
1182
2020
|
// ─────────────────────────────────────
|
|
1183
|
-
checkFormat("20-row cascade compresses to
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
checkFormat("
|
|
1187
|
-
checkFormat("
|
|
2021
|
+
checkFormat("20-row cascade compresses to two letter types", MetaNum.h10000(3, 10), "Iccc1.000Iccb10");
|
|
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");
|
|
1188
2028
|
checkFormat("short diagonal keeps the letter form", m3.aperixxate(3), "!2.000Aaaa10");
|
|
1189
2029
|
checkFormat("cascade inner α stays [1,10) (AbAa600)", "AbAa600", "Ab1.000Aa600");
|
|
1190
2030
|
|
|
2031
|
+
// ─────────────────────────────────────
|
|
2032
|
+
// issue #14: stacking the SAME function must nest the letter — the rows are a
|
|
2033
|
+
// composition, so the top row leads and the row below it (which collapses from
|
|
2034
|
+
// its repeat count) keeps the single α and β:
|
|
2035
|
+
// poea(10,poea(10,100)) = Ad(Ad(99)) → "Ad1.000Ad99" (not "1.000Ad114")
|
|
2036
|
+
// ─────────────────────────────────────
|
|
2037
|
+
var stacked = [
|
|
2038
|
+
["expande (ω+1)", "expande", "2.398Ab99", "Ab2.398Ab99"],
|
|
2039
|
+
["multiexpande (ω+2)", "multiexpande", "1.000Ac99", "Ac1.000Ac99"],
|
|
2040
|
+
["powerexpande (ω+3)", "powerexpande", "1.000Ad99", "Ad1.000Ad99"],
|
|
2041
|
+
["explode (ω*2+1)", "explode", "1.000Bb99", "Bb1.000Bb99"],
|
|
2042
|
+
["multiexplode (ω*2+2)", "multiexplode", "1.000Bc99", "Bc1.000Bc99"],
|
|
2043
|
+
["megoexpande (ω²+1)", "megoexpande", "1.000Abb99", "Abb1.000Abb99"],
|
|
2044
|
+
["multimegote (ω²+2)", "multimegote", "1.000Aac99", "Aac1.000Aac99"],
|
|
2045
|
+
["powiainate (ω³+1)", "powiainate", "1.000Aaab99", "Aaab1.000Aaab99"]
|
|
2046
|
+
];
|
|
2047
|
+
for (var si = 0; si < stacked.length; si++) {
|
|
2048
|
+
var sf = stacked[si][1], s1 = MetaNum(10)[sf](100), s2 = MetaNum(10)[sf](s1), s3 = MetaNum(10)[sf](s2);
|
|
2049
|
+
checkFormat("stacked " + stacked[si][0] + " (1st)", s1, stacked[si][2]);
|
|
2050
|
+
checkFormat("stacked " + stacked[si][0] + " (x2)", s2, stacked[si][3]);
|
|
2051
|
+
checkBool("stacked " + stacked[si][0] + " grows and keeps nesting",
|
|
2052
|
+
s2.gt(s1) && s3.gt(s2) && format(s3).indexOf(format(s2).slice(0, 2)) === 0, true);
|
|
2053
|
+
}
|
|
2054
|
+
// apea (ω*2) with an operand above MSI: apea(apea(a)) must stay visible
|
|
2055
|
+
(function () {
|
|
2056
|
+
var p1 = MetaNum(10).aperioexpande(MetaNum(1e16));
|
|
2057
|
+
var p2 = MetaNum(10).aperioexpande(p1);
|
|
2058
|
+
var p3 = MetaNum(10).aperioexpande(p2);
|
|
2059
|
+
checkFormat("apea(1e16) (ω*2 level = Ba)", p1, "Ba1.000E16");
|
|
2060
|
+
checkFormat("apea(apea(1e16)) nests", p2, "BaBa1.000E16");
|
|
2061
|
+
checkFormat("apea^3(1e16) nests further", p3, "BaBaBa1.000E16");
|
|
2062
|
+
checkBool("apea stacking is strictly monotone", p2.gt(p1) && p3.gt(p2), true);
|
|
2063
|
+
})();
|
|
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");
|
|
2068
|
+
|
|
1191
2069
|
// Γ-canonical law test: long descending count-1 chains
|
|
1192
2070
|
// format at their bisect-exact letter on the engine's smooth arrow curve;
|
|
1193
2071
|
// ordinal-row levels use Aa-notation (the engine's fractional-arg curve is
|
|
@@ -1428,6 +2306,97 @@ console.log("\n=== MetaNum(...).format() instance method ===");
|
|
|
1428
2306
|
MetaNum("FE400").format(), format(MetaNum("FE400")));
|
|
1429
2307
|
})();
|
|
1430
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
|
+
|
|
1431
2400
|
console.log("\n=== format tests Done ===");
|
|
1432
2401
|
|
|
1433
2402
|
|