metanum 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/metanum.js CHANGED
@@ -1,14 +1,13 @@
1
- //Author: dlsdl v1.4
2
- //Support hyper operation >MSI and fix format-metanum bugs
1
+ //Author: dlsdl v2.0
2
+ //v2.0: Add hyper-root & hyper-log, hardy function, fractional hyperoperation inputs, fix BEAF operation level and format
3
3
  //Code snippets and templates from OmegaNum.js
4
4
 
5
5
  ;(function (globalScope) {
6
6
  "use strict";
7
7
 
8
8
  var MetaNum = {
9
- maxRows: 100,
10
- maxCols: 100,
11
- maxArrow: Number.MAX_SAFE_INTEGER,
9
+ maxRows: 20,
10
+ maxCols: 20,
12
11
  serializeMode: 0,
13
12
  debug: 0
14
13
  },
@@ -43,13 +42,14 @@
43
42
  R.NaN = NaN;
44
43
  R.POSITIVE_INFINITY = Infinity;
45
44
  R.NEGATIVE_INFINITY = -Infinity;
45
+ R.infinity = Infinity; // alias of POSITIVE_INFINITY
46
46
  R.E_MAX_SAFE_INTEGER = "E" + MAX_SAFE_INTEGER;
47
47
  R.EE_MAX_SAFE_INTEGER = "EE" + MAX_SAFE_INTEGER;
48
48
  R.TETRATED_MAX_SAFE_INTEGER = "F" + MAX_SAFE_INTEGER;
49
49
  R.PENTATED_MAX_SAFE_INTEGER = "G" + MAX_SAFE_INTEGER;
50
50
  R.TRITRI = "[[3638334640023.7783, 7625597484984]]";
51
51
  R.GRAHAMS_NUMBER = "[[3638334640023.7783,7625597484984,0,1],[63,0,1]]";
52
- R.TERR3 = "[[10],[1,374389,2],[1,374387,2],[1,374385,2],[1,374383,2],[1,374381,2],[1,374379,2],[1,374377,2],[1,374375,2],[1,374373,2],[1,374371,2]]"; //https://www.bilibili.com/video/BV1X94y1n7D1
52
+ R.TERR3 = "[[10],[1,374389,2],[1,374387,2],[1,374385,2],[1,374383,2],[1,374381,2],[1,374379,2],[1,374377,2],[1,374375,2],[1,374373,2],[1,374371,2]]";
53
53
  R.QqQe308 = "QqQe308";
54
54
 
55
55
  function cmpArr(a, b) {
@@ -352,12 +352,40 @@
352
352
  }
353
353
 
354
354
  if (x.array.length > MetaNum.maxRows) {
355
- x.array = x.array.slice(x.array.length - MetaNum.maxRows);
355
+ // Truncation keeps the base row and the largest maxRows-1 ordinal rows;
356
+ // only the smallest ordinal rows are sacrificed. The transient
357
+ // _ordTrunc flag lets the hyperoperation entry points detect the
358
+ // overflow and apply the issues.md truncation marker (array[1][0]+1,
359
+ // array[0] = [10]) — clone() does not copy it.
360
+ x._ordTrunc = true;
361
+ x.array = [x.array[0]].concat(x.array.slice(x.array.length - (MetaNum.maxRows - 1)));
356
362
  b = true;
357
363
  }
358
364
 
365
+ // r0 wider than maxCols: convert the overflow levels (>= maxCols) into
366
+ // finite-level ordinal rows [count, level] instead of dropping them.
367
+ // Deferred until the r0 cascade has settled so that high-level counts
368
+ // can still decompose into lower levels (e.g. "Z10" must fully expand
369
+ // into its level chain before levels >= maxCols freeze into rows).
370
+ if (r0.length > MetaNum.maxCols && !b) {
371
+ var r0Settled = !(r0[0] > MAX_SAFE_INTEGER)
372
+ && !(r0[1] && r0[0] < MAX_E)
373
+ && !(!r0[1] && r0.length > 2);
374
+ if (r0Settled) {
375
+ var pushedOverflow = false;
376
+ for (var ov = MetaNum.maxCols; ov < r0.length; ov++) {
377
+ if (r0[ov] > 0) {
378
+ x.array.push([r0[ov], ov]);
379
+ r0[ov] = 0;
380
+ pushedOverflow = true;
381
+ }
382
+ }
383
+ if (pushedOverflow) b = true;
384
+ }
385
+ }
386
+
359
387
  for (var i = 0; i < x.array.length; i++) {
360
- if (x.array[i].length > MetaNum.maxCols) {
388
+ if (i > 0 && x.array[i].length > MetaNum.maxCols) {
361
389
  x.array[i] = x.array[i].slice(0, MetaNum.maxCols);
362
390
  b = true;
363
391
  }
@@ -773,14 +801,6 @@
773
801
  x.array[0].length === 1 && isFinite(x.array[0][0]);
774
802
  }
775
803
 
776
- function computeLayer(arr) {
777
- // Layer represents ω^ nesting level above the ordinal represented by the array.
778
- // For all normal ordinal operations (up to ω^(maxcols-1) level), layer is 0.
779
- // Layer 1 = ω^(array ordinal), layer 2 = ω^ω^(array ordinal), etc.
780
- // Layer is managed explicitly by layerUp/layerDown, not computed from array.
781
- return 0;
782
- }
783
-
784
804
  function toNormalizedSign(s) {
785
805
  // Map sign=2/-2 to the corresponding normal sign for the array data
786
806
  return s === 2 ? 1 : s === -2 ? -1 : s;
@@ -794,7 +814,15 @@
794
814
  return new MetaNum([arr]);
795
815
  }
796
816
 
817
+ // Threshold values 10{n}val depend only on (n, val) and are only ever used
818
+ // in read-only comparisons — cache them: rebuilding an r0 of length n+1 on
819
+ // every arrow call cost ~1.8ms each (several per call, ~70% of the
820
+ // structured fast path).
821
+ var hyperLevelSafeCache = {};
797
822
  function hyperLevelSafe(n, val) {
823
+ var key = n + "|" + val;
824
+ var cached = hyperLevelSafeCache[key];
825
+ if (cached) return cached;
798
826
  var arr = new Array(n + 1);
799
827
  for (var i = 0; i <= n; i++) arr[i] = 0;
800
828
  arr[0] = val;
@@ -803,6 +831,7 @@
803
831
  MetaNum.maxCols = Math.max(oldMaxCols, n + 1);
804
832
  var r = new MetaNum([arr]);
805
833
  MetaNum.maxCols = oldMaxCols;
834
+ if (n >= 0 && n <= 100000) hyperLevelSafeCache[key] = r;
806
835
  return r;
807
836
  }
808
837
 
@@ -832,7 +861,6 @@
832
861
  // numbers (e.g. 10^16 stored as [[16,1]]) instead of Infinity. This is used
833
862
  // by hyperoperation functions (expande/multiexpande/powerexpande) to compute
834
863
  // iteration counts `count = y - 2` when y is a large-but-finite MetaNum.
835
- //
836
864
  // toNumber() returns Infinity whenever r0.length > 1 (E-notation) or the
837
865
  // array has ordinal rows, which is too conservative for count extraction:
838
866
  // 10^16 is a perfectly finite JS number. We only return Infinity for genuine
@@ -868,6 +896,11 @@
868
896
  if (x.isInfinite()) return x;
869
897
  if (other.isInfinite()) return other;
870
898
 
899
+ // Layer swallowing: an ω-tower plus a layer-0 value is the tower; two
900
+ // towers keep the larger one (ordinal addition, same layer).
901
+ var domAdd = layerDominant(x, other);
902
+ if (domAdd !== null) return domAdd.clone().normalize();
903
+
871
904
  // For simple numbers, use direct numeric addition
872
905
  if (isSimple(x) && isSimple(other)) {
873
906
  var directSum = x.toNumber() + other.toNumber();
@@ -973,6 +1006,11 @@
973
1006
 
974
1007
  if (x.max(other).gt(MetaNum.EE_MAX_SAFE_INTEGER)) return x.max(other);
975
1008
 
1009
+ // Layer swallowing: multiplying a tower (layer≥1) by any layer-0 value
1010
+ // leaves the tower unchanged; two towers keep the larger one.
1011
+ var domMul = layerDominant(x, other);
1012
+ if (domMul !== null) return domMul.clone().normalize();
1013
+
976
1014
  if (isSimple(x) && isSimple(other) && !isSmall(x) && !isSmall(other)) {
977
1015
  var nx = x.array[0][0];
978
1016
  var ny = other.array[0][0];
@@ -1795,11 +1833,243 @@
1795
1833
  return new MetaNum(x).pentate_root(height);
1796
1834
  };
1797
1835
 
1836
+ // Layer swallowing (README representation L17): a layer≥1 value is a
1837
+ // 10{ω^ω^…}10 tower and dominates every operation with a layer-0 operand
1838
+ // — the result keeps the tower's layer. Returns the dominating MetaNum,
1839
+ // or null when both operands carry the same layer>0.
1840
+ function layerDominant(a, b) {
1841
+ if (a.layer > 0 && b.layer === 0) return a;
1842
+ if (b.layer > 0 && a.layer === 0) return b;
1843
+ if (a.layer > b.layer) return a;
1844
+ if (b.layer > a.layer) return b;
1845
+ return null;
1846
+ }
1847
+
1848
+ // Fast construction of the diagonal chain D(L) = t{L}t for a plain finite
1849
+ // integer base t. The generic successor-rule recursion recomputes the whole
1850
+ // chain at every level (each level re-invokes t{n-1}(t)), which is ~O(n^3)
1851
+ // for plain diagonals (3{99}3 at maxCols=100 took ~5.5s). Unrolling rule 2
1852
+ // once builds the identical normalized array bottom-up:
1853
+ // D(1) = t{1}t ; D(n+1) = t{n}^{t-1}(t) = t{n}^{t-2}(D(n))
1854
+ // Each t{n}(D(n)) step is the engine's own structured-value fast path, so
1855
+ // the result is array-identical to the recursive evaluation, in O(L^2).
1856
+ function canFastDiagonal(t) {
1857
+ if (t.layer !== 0 || t.array.length !== 1) return false;
1858
+ var n = t.toNumber();
1859
+ if (!isFinite(n) || n < 1 || Math.floor(n) !== n) return false;
1860
+ return (n - 2) <= 1000;
1861
+ }
1862
+ function diagonalChain(t, L) {
1863
+ var repeat = Math.max(Math.floor(t.toNumber()) - 2, 0);
1864
+ var r = t.pow(t); // D(1) = t{1}t
1865
+ for (var n = 1; n < L; n++) {
1866
+ // D(n+1) = t{n}^{repeat}(D(n)) with repeat = t-2.
1867
+ // n=1,2 keep pow/tetr (their own structuralization). For n>=3 every
1868
+ // step is the engine's structured-value fast path verbatim
1869
+ // (0 + D(n), then one count at column n, normalize) — do it directly
1870
+ // instead of re-entering arrow() (whose threshold guards cost ~7ms).
1871
+ for (var k = 0; k < repeat; k++) {
1872
+ if (n >= 3) {
1873
+ var j = MetaNum.ZERO.add(r);
1874
+ if (j.array.length === 1) {
1875
+ while (j.array[0].length <= n) j.array[0].push(0);
1876
+ j.array[0][n] = (j.array[0][n] || 0) + 1;
1877
+ }
1878
+ j.normalize();
1879
+ r = j;
1880
+ } else {
1881
+ r = t.arrow(n)(r);
1882
+ }
1883
+ }
1884
+ }
1885
+ return r;
1886
+ }
1887
+
1888
+ // Convert a structured raw-application COUNT C at finite operation level n
1889
+ // ({n}^C(10)) to the dlsdl Aa-band smooth argument α (v = 10{n+2}(α)),
1890
+ // α ∈ [2,10). A count given canonically as 10{k}(t), t∈[1,10]:
1891
+ // t = 10 rewrites exactly to α-anchor 2 one level up (10{k}10=10{k+1}2);
1892
+ // each further level promotion is the geometric smooth-log step
1893
+ // f → 1 + log10(f) (the same step the low-level polarize produces).
1894
+ // Matches dlsdl rule (iii)-(v): {99}^{10{93}10}(10) = 10{101}(2.001607…).
1895
+ // Raw application COUNT C at operation level n ({n}^C(10)) -> the dlsdl
1896
+ // diagonal-letter smooth argument α in [2,10) with v = 10{n+2}(α).
1897
+ // Start from C=10{level}(t) (polarize: a scalar C starts at level 1 with
1898
+ // t=log10(C)), then each level promotion is the geometric smooth-log step
1899
+ // t → 1+log10(t) (exact t=10 rewrites to the α-anchor 2). The final value
1900
+ // lands in [1,2); the diagonal mantissa is α=1+t (2 at the anchor).
1901
+ function countToDiagonalAlpha(C, n, r0OfC, rowsOfC) {
1902
+ var t, level;
1903
+ if (r0OfC === undefined || r0OfC === null) {
1904
+ t = Math.log10(C); level = 1;
1905
+ } else {
1906
+ // Truncation marker normalization: when rows overflowed the budget the
1907
+ // base was reset to [10] and the LOWEST kept finite row got +1 over the
1908
+ // uniform per-level fill (xCnt). That +1 marks the dropped cascade —
1909
+ // read it as the same count as the next kept row so the count climb
1910
+ // matches the untruncated anchor across configs.
1911
+ var pr0 = r0OfC.slice();
1912
+ var prows = rowsOfC ? rowsOfC.slice() : [];
1913
+ if (pr0[0] === 10 && prows.length > 0) {
1914
+ var li = 0;
1915
+ for (var pi = 1; pi < prows.length; pi++) {
1916
+ if (prows[pi][1] < prows[li][1]) li = pi;
1917
+ }
1918
+ var sortedLv = prows.slice().sort(function (a, b) { return a[1] - b[1]; });
1919
+ var c0v = sortedLv[0][0] || 0;
1920
+ var c1v = sortedLv.length > 1 ? (sortedLv[1][0] || 0) : 0;
1921
+ if (c0v === c1v + 1) {
1922
+ prows[li] = [c1v, prows[li][1]];
1923
+ pr0[0] = 10000000000;
1924
+ }
1925
+ }
1926
+ var pol = polarizeLike(pr0, prows);
1927
+ if (!pol) return null;
1928
+ t = Math.log10(pol.bottom) + pol.repeation;
1929
+ level = pol.arrows + 1; // C = 10{level}(t)
1930
+ }
1931
+ while (level < n + 2) {
1932
+ t = (t >= 9.999999999) ? 2 : 1 + Math.log10(t);
1933
+ level++;
1934
+ if (!(t > 0)) return null;
1935
+ }
1936
+ if (t >= 9.999999999) t = 2;
1937
+ return t < 2 ? 1 + t : (t > 10 ? 10 : t);
1938
+ }
1939
+
1940
+ // Minimal local structural polarize (faithful port of format-metanum's
1941
+ // refPolarize) so the engine need not import the formatter: returns
1942
+ // {bottom, repeation, arrows} for an r0 + finite [count,level] rows chain,
1943
+ // i.e. the value behaves as 10{arrows+1}(log10(bottom)+repeation).
1944
+ function polarizeLike(r0, finiteRows) {
1945
+ var array = [r0[0]];
1946
+ for (var i = 1; i < r0.length; i++) if ((r0[i] || 0) > 0) array.push([i, r0[i], 1, 1]);
1947
+ if (finiteRows) for (i = 0; i < finiteRows.length; i++) {
1948
+ var fr0 = finiteRows[i];
1949
+ if (fr0 && fr0.length === 2 && (fr0[0] || 0) > 0) array.push([fr0[1], fr0[0], 1, 1]);
1950
+ }
1951
+ function arraySort() {
1952
+ array.sort(function (a, b) {
1953
+ if (typeof a == 'number') return
1954
+ else if (a[3] > b[3]) return -1
1955
+ else if (a[3] < b[3]) return 1
1956
+ else if (a[2] == 'x' && b[2] != 'x') return -1
1957
+ else if (a[2] != 'x' && b[2] == 'x') return 1
1958
+ else if (a[2] == 'x' && b[2] == 'x') return -1
1959
+ else if (a[2] > b[2]) return -1
1960
+ else if (a[2] < b[2]) return 1
1961
+ else if (a[0] == 'x' && b[0] != 'x') return -1
1962
+ else if (a[0] != 'x' && b[0] == 'x') return 1
1963
+ else if (a[0] == 'x' && b[0] == 'x') return -1
1964
+ else if (a[0] > b[0]) return -1
1965
+ else if (a[0] < b[0]) return 1
1966
+ else if (a[1] > b[1]) return -1
1967
+ else if (a[1] < b[1]) return 1
1968
+ return -1
1969
+ });
1970
+ }
1971
+ function arrayMerge() {
1972
+ var elemOffset = 0;
1973
+ for (var mi = 0; mi < array.length - 2; ++mi) {
1974
+ if (array[mi][0] == array[mi + 1][0] &&
1975
+ array[mi][2] == array[mi + 1][2] && array[mi][3] == array[mi + 1][3]) {
1976
+ array[mi][1] += array[mi + 1][1]
1977
+ array.splice(mi + 1, 1)
1978
+ --mi
1979
+ elemOffset++
1980
+ }
1981
+ }
1982
+ return elemOffset
1983
+ }
1984
+ arraySort(); arrayMerge();
1985
+ var ptr = array.length - 2
1986
+ var b = function () { return array[array.length - 1] }
1987
+ var c = function (x) { array[array.length - 1] = x }
1988
+ var repeatResult = 500000
1989
+ while (--repeatResult >= 0) {
1990
+ if (b() >= 10) {
1991
+ var a = Math.log10(b())
1992
+ array.push([1, 1, 1, 1]); ptr++; arraySort()
1993
+ var offset = arrayMerge(); ptr -= offset; c(a)
1994
+ } else {
1995
+ if (ptr == 0 && typeof array[ptr + 1] == 'number') break
1996
+ if (ptr != 0 && typeof array[ptr + 1] == 'number' && typeof array[ptr][0] == 'number' &&
1997
+ array[ptr][1] == 1 &&
1998
+ (array[ptr - 1][0] == 'x' || array[ptr - 1][2] > array[ptr][2] || array[ptr - 1][3] > array[ptr][3]) &&
1999
+ array[ptr][0] > 2 && (ptr != 0 || array[ptr - 1][0] == 'x')) {
2000
+ var arrow_count = array[ptr][0]
2001
+ var base = b()
2002
+ var Jx = arrow_count == 3 ? base : arrow_count - 1 + Math.log(base / 2) / Math.log(5)
2003
+ array[ptr][0] = 'x'
2004
+ c(Jx); arraySort(); var off2 = arrayMerge(); ptr -= off2
2005
+ }
2006
+ if (typeof array[ptr + 1] == 'number' && array[ptr][0] == 'x' && b() < 10 && ptr != 0) {
2007
+ var base2 = b()
2008
+ var JRepeation = array[ptr][1]
2009
+ var Kx = JRepeation + Math.log10(base2)
2010
+ array[ptr][1] = 1
2011
+ array[ptr][0] = 1
2012
+ array[ptr][2]++
2013
+ c(Kx); arraySort(); var off3 = arrayMerge(); ptr -= off3
2014
+ }
2015
+ if (((ptr == 0) || ptr != 0) && array[ptr][0] != 'x' && b() < 10) {
2016
+ if (b() == 1 && ptr > 0 && array[ptr - 1][0] > array[ptr][0] && array[ptr][1] == 1) {
2017
+ array[ptr][0] = array[ptr - 1][0]
2018
+ } else {
2019
+ var right = array[ptr][1] + Math.log10(b())
2020
+ array[ptr][0]++
2021
+ array[ptr][1] = 1
2022
+ c(right)
2023
+ }
2024
+ arraySort(); var off4 = arrayMerge(); ptr -= off4
2025
+ }
2026
+ }
2027
+ }
2028
+ if (typeof array[ptr][0] !== 'number' || !isFinite(b())) return null;
2029
+ return { bottom: b(), repeation: array[ptr][1], arrows: array[ptr][0] };
2030
+ }
2031
+
2032
+ // Canonical compact form of the smooth diagonal value 10{L}(α) with a
2033
+ // NUMERIC α in [1,10): r0=[1] plus one finite row [α, L-1]. The fractional
2034
+ // row count survives normalization (only r0 integer columns are floored)
2035
+ // and polarize climbs it straight back to t=α at level L-1, so the smooth
2036
+ // mantissa is preserved at arbitrary finite levels (used where the iterated
2037
+ // arrow loop would MSI-dump the fraction away).
2038
+ function compactSmoothValue(L, alpha) {
2039
+ var m = new MetaNum({ sign: 1, layer: 0, array: [[1], [alpha, L - 1]] });
2040
+ return m.normalize();
2041
+ }
2042
+
1798
2043
  // region >=ω level operations
1799
2044
  P.arrow = function (arrows) {
1800
2045
  var t = this.clone();
1801
2046
  arrows = new MetaNum(arrows);
1802
- if (!arrows.isint() || arrows.sign === -1 || arrows.sign === -2) return function () { return MetaNum.NaN.clone(); };
2047
+ if (arrows.sign === -1 || arrows.sign === -2) return function () { return MetaNum.NaN.clone(); };
2048
+ if (!arrows.isint()) {
2049
+ // Fractional hyperoperation level.
2050
+ // Geometric interpolation per README rule (i): level n+f acts as the (n+1)-level
2051
+ // op on a geometrically interpolated argument — for the canonical
2052
+ // diagonal 10{n+f}10 = 10{n+1}(2·5^f). General anchors: θ0 satisfies
2053
+ // x{n+1}θ0 = x{n}y (recovered via hyper_log), θ1 = y, θf = θ0·(y/θ0)^f,
2054
+ // so x{n+f}y = x{n+1}(θf), continuous in f with
2055
+ // x{n}y at f=0 and x{n+1}y at f=1.
2056
+ if (arrows.gte(MetaNum.ONE)) {
2057
+ var nLev = arrows.floor();
2058
+ var frac = arrows.sub(nLev);
2059
+ var self = t;
2060
+ return function (other) {
2061
+ other = new MetaNum(other);
2062
+ if (other.eq(MetaNum.ZERO)) return MetaNum.ONE.clone();
2063
+ if (other.eq(MetaNum.ONE)) return self.clone();
2064
+ if (frac.eq(MetaNum.ZERO)) return self.arrow(nLev)(other);
2065
+ var target = self.arrow(nLev)(other);
2066
+ var theta0 = target.hyper_log(self)(nLev.add(MetaNum.ONE));
2067
+ var theta = theta0.mul(other.div(theta0).pow(frac));
2068
+ return self.arrow(nLev.add(MetaNum.ONE))(theta);
2069
+ };
2070
+ }
2071
+ return function () { return MetaNum.NaN.clone(); };
2072
+ }
1803
2073
  if (arrows.eq(MetaNum.ZERO)) return function (other) { return t.mul(other); };
1804
2074
  if (arrows.eq(MetaNum.ONE)) return function (other) { return t.pow(other); };
1805
2075
  if (arrows.eq(2)) return function (other) { return t.tetr(other); };
@@ -1808,7 +2078,25 @@
1808
2078
  if (other.sign === -1 || other.sign === -2) return MetaNum.NaN.clone();
1809
2079
  if (other.eq(MetaNum.ZERO)) return MetaNum.ONE.clone();
1810
2080
  if (other.eq(MetaNum.ONE)) return t.clone();
1811
- if (other.eq(2)) return t.arrow(arrows.sub(MetaNum.ONE))(t);
2081
+ if (other.eq(2)) {
2082
+ var diagArrowsNum = arrows.toNumber();
2083
+ // Only build directly when the whole diagonal fits r0; at/above
2084
+ // maxCols the value must go through the truncating branch below
2085
+ // (base [10] + first-kept row count +1), reached via the ordinary
2086
+ // t{L-1}t call which itself reuses the fast diagonal for its tail.
2087
+ if (isFinite(diagArrowsNum) && diagArrowsNum >= 2 &&
2088
+ diagArrowsNum <= MetaNum.maxCols && canFastDiagonal(t)) {
2089
+ return diagonalChain(t, diagArrowsNum - 1);
2090
+ }
2091
+ return t.arrow(arrows.sub(MetaNum.ONE))(t);
2092
+ }
2093
+ // Layer swallowing: any ω-tower operand (layer≥1) dominates a layer-0
2094
+ // operand under every (finite or ordinal) hyperoperation; equal layers
2095
+ // take the supremum (higher ordinal rows win). The layer itself is the
2096
+ // ω^-tower height and must survive unchanged.
2097
+ var dom = layerDominant(t, other);
2098
+ if (dom !== null) return dom.clone().normalize();
2099
+ if (t.layer > 0) return t.max(other).normalize();
1812
2100
  var arrowsNum = arrows.toNumber();
1813
2101
  if (!isFinite(arrowsNum)) {
1814
2102
  // arrows is a huge MetaNum (ω-level): result inherits the largest structure
@@ -1817,17 +2105,45 @@
1817
2105
  j.normalize();
1818
2106
  return j;
1819
2107
  }
1820
- if (arrows.gte(MetaNum.maxArrow)) {
2108
+ if (arrows.gte(Number.MAX_SAFE_INTEGER)) {
1821
2109
  // arrows is very large but still a JS number; use approximate overflow
1822
2110
  var j = t.max(other).max(arrows).clone();
1823
2111
  j.array.push([1, 0, 1]);
1824
2112
  j.normalize();
1825
2113
  return j;
1826
2114
  }
2115
+ // Fractional argument exactly at the boundary level (L == maxCols):
2116
+ // 10{L}(α) with numeric α in (1,10) carries the smooth diagonal
2117
+ // mantissa directly (compact form). Levels beyond maxCols with a
2118
+ // numeric argument keep the structural integer cascade below.
2119
+ var yNumPre = other.toNumber();
2120
+ var boundaryFractional = isFinite(yNumPre) && yNumPre !== Math.floor(yNumPre);
2121
+ if (arrowsNum === MetaNum.maxCols && boundaryFractional) {
2122
+ return compactSmoothValue(arrowsNum, yNumPre);
2123
+ }
2124
+ // Structured finite argument at/below the boundary level
2125
+ // (e.g. 10{L}(10{k}10)): convert the raw application count to the
2126
+ // dlsdl smooth diagonal argument α and return 10{L+1}(α).
2127
+ var otherFiniteChain = other.layer === 0 &&
2128
+ other.array.slice(1).every(function (rr) { return rr.length === 2; });
2129
+ var otherHasChain = other.array[0].length >= 2 || other.array.length >= 2;
2130
+ if (arrowsNum >= MetaNum.maxCols &&
2131
+ otherFiniteChain && otherHasChain && !isFinite(yNumPre) &&
2132
+ t.layer === 0 && t.array.length === 1) {
2133
+ var alphaC = countToDiagonalAlpha(null, arrowsNum - 1,
2134
+ other.array[0], other.array.slice(1));
2135
+ if (alphaC !== null && alphaC >= 2) return compactSmoothValue(arrowsNum + 1, alphaC);
2136
+ }
1827
2137
  if (arrowsNum >= MetaNum.maxCols) {
1828
- // Compact ordinal-row representation: 10{1000}10 → [[10],[1,1000]].
1829
- // One [1|arrowsNum] row on top of the larger operand; finite arrow
1830
- // levels beyond r0 capacity no longer expand into a cascade of rows.
2138
+ // Finite arrow level beyond r0 capacity:
2139
+ // expand the level chain exactly as far as the array budget allows —
2140
+ // r0 filled to maxCols (levels 1..maxCols-1, the top one being the
2141
+ // anchor level L-1 col) + [count, level] rows for levels
2142
+ // maxCols..L-1 (maxRows-1 rows max; the top level L itself is the
2143
+ // 10{L}2 = 10{L-1}10 anchor and takes no row) —
2144
+ // and approximate beyond the budget: keep the LARGEST maxRows-1
2145
+ // ordinal rows, the ARRAY's second row (first-kept ordinal row) first column +1,
2146
+ // first row [10].
1831
2147
  // Swallowing: a finite level sits below any existing ω-level row.
1832
2148
  var j = t.max(other).clone();
1833
2149
  if (j.layer > 0) return j; // ω^ω-tower swallows any finite level
@@ -1836,23 +2152,124 @@
1836
2152
  var row = j.array[i];
1837
2153
  if (row && row.length >= 2 && (row[0] || 0) > 0) { idx = i; break; }
1838
2154
  }
1839
- if (idx < 0) {
1840
- j.array.push([1, arrowsNum]);
2155
+ // value below already carries an ordinal row: merge or swallow
2156
+ if (idx >= 0) {
2157
+ var belowRow = j.array[idx];
2158
+ var belowIsTower = belowRow.length >= 3;
2159
+ var belowLevel = belowIsTower ? Infinity : belowRow[1];
2160
+ if (belowIsTower || belowLevel > arrowsNum) { j.normalize(); return j; }
2161
+ if (belowLevel === arrowsNum) {
2162
+ belowRow[0] = Math.min((belowRow[0] || 0) + 1, MAX_SAFE_INTEGER);
2163
+ j.normalize();
2164
+ return j;
2165
+ }
2166
+ // belowLevel < arrowsNum: stack rows on top of the existing chain
2167
+ var rowBudgetA = MetaNum.maxRows - 1;
2168
+ var startA = Math.max(MetaNum.maxCols, belowLevel + 1);
2169
+ var endA = arrowsNum - 1;
2170
+ if (endA - startA + 1 <= rowBudgetA) {
2171
+ for (var la = startA; la <= endA; la++) j.array.push([1, la]);
2172
+ } else {
2173
+ var keptFromA = endA - rowBudgetA + 1;
2174
+ for (var lb = keptFromA; lb <= endA; lb++) {
2175
+ var cntA = (lb === endA) ? yCnt : xCnt;
2176
+ if (lb === keptFromA) cntA += 1;
2177
+ j.array.push([cntA, lb]);
2178
+ }
2179
+ j.array[0] = [10];
2180
+ }
2181
+ j.normalize();
2182
+ return j;
2183
+ }
2184
+ // plain finite base: expand the diagonal chain bottom-up.
2185
+ // Exact law (matches the engine's own low-level path and the
2186
+ // reference): x{L}y = x{L-1}^{y-2}(x{L-1}x), so the top level L-1
2187
+ // carries (y-2) ops and every level below — the x{L-1}x tail —
2188
+ // carries (x-2) ops:
2189
+ // 3{9}3 → 1 op/level, 4{9}4 → 2, 10{25}10 → 8 ops/level (the
2190
+ // canonical all-8s form). The top level L itself is the
2191
+ // 10{L}2 = 10{L-1}10 anchor and takes no row.
2192
+ var subDepth = MetaNum.maxCols - 1;
2193
+ var xBase = t.toNumber();
2194
+ var yBase = other.toNumber();
2195
+ var xCnt = isFinite(xBase) ? Math.min(Math.max(xBase - 2, 0), MAX_SAFE_INTEGER) : MAX_SAFE_INTEGER;
2196
+ // Top-of-chain count: x{L}y = x{L-1}^{y-1}(x), so every level below the
2197
+ // top carries (x-2) ops while level L-1 carries (y-2) ops for y>=3
2198
+ // (the y=2 anchor x{L}2=x{L-1}x carries x-2 there). This makes
2199
+ // 10{100}11 = 10{99}(10{100}10) exact (col 99 = 9, not 8).
2200
+ var topCnt;
2201
+ if (!isFinite(yBase)) topCnt = MAX_SAFE_INTEGER;
2202
+ else if (yBase <= 2) topCnt = xCnt;
2203
+ else topCnt = Math.min(Math.max(yBase - 2, 1), MAX_SAFE_INTEGER);
2204
+ // Base-2 with y≥3: 2{L-1}(2{L}2)=2{L-1}4 expands like a base-10 tail
2205
+ // (8 ops per level), with the fixed law level L-2 = 2 ops and
2206
+ // level L-1 = (y-3) ops (matches the exact main-loop arrays:
2207
+ // 2{100}3 -> cols 1..97=8, col98=2; 2{100}10 -> col99=7).
2208
+ var base2mode = (xCnt === 0 && isFinite(yBase) && yBase >= 3);
2209
+ var fillCnt = base2mode ? 8 : xCnt;
2210
+ function countAt(lv) {
2211
+ if (base2mode) {
2212
+ if (lv === arrowsNum - 2) return 2;
2213
+ if (lv === arrowsNum - 1) return Math.max(yBase - 3, 0);
2214
+ }
2215
+ return (lv === arrowsNum - 1) ? topCnt : fillCnt;
2216
+ }
2217
+ // base sub-chain: the tail's bottom x{subDepth}x
2218
+ var sub;
2219
+ if (subDepth >= 2 && subDepth < arrowsNum) {
2220
+ if (base2mode) sub = diagonalChain(MetaNum(10), subDepth);
2221
+ else sub = canFastDiagonal(t) ? diagonalChain(t, subDepth) : t.arrow(subDepth)(t);
1841
2222
  } else {
1842
- var top = j.array[idx].slice(1);
1843
- while (top.length > 0 && top[top.length - 1] === 0) top.pop();
1844
- var c = cmpCoeffsLevel([arrowsNum], top);
1845
- if (c > 0) {
1846
- j.array.push([1, arrowsNum]);
1847
- } else if (c === 0) {
1848
- j.array[idx][0] = Math.min((j.array[idx][0] || 0) + 1, MAX_SAFE_INTEGER);
2223
+ sub = t.max(other).clone();
2224
+ }
2225
+ if (sub.layer > 0) { sub.normalize(); return sub; }
2226
+ // top count at the anchor column (subDepth = L-1 when L == maxCols)
2227
+ if (sub.array.length === 1) {
2228
+ var wantLen = subDepth + 1;
2229
+ while (sub.array[0].length < wantLen) sub.array[0].push(0);
2230
+ if (arrowsNum === MetaNum.maxCols) {
2231
+ // no rows above: write the exact per-level counts into r0
2232
+ if (base2mode) {
2233
+ for (var bl = 1; bl <= arrowsNum - 3; bl++) sub.array[0][bl] = 8;
2234
+ sub.array[0][arrowsNum - 2] = 2;
2235
+ sub.array[0][arrowsNum - 1] = Math.max(yBase - 3, 0);
2236
+ if (sub.array[0][arrowsNum - 1] === 0) sub.array[0].pop();
2237
+ } else if (topCnt > 0) {
2238
+ sub.array[0][subDepth] = topCnt;
2239
+ }
2240
+ } else if (fillCnt > 0) {
2241
+ sub.array[0][subDepth] = (sub.array[0][subDepth] || 0) + fillCnt;
1849
2242
  }
1850
- // c < 0: swallowed by the larger ordinal structure already present
1851
2243
  }
1852
- j.normalize();
1853
- return j;
2244
+ // rows for levels maxCols..arrowsNum-1 within the budget
2245
+ var rowBudget = MetaNum.maxRows - 1;
2246
+ var startLv = subDepth + 1;
2247
+ var endLv = arrowsNum - 1; // top level L is the anchor, no row
2248
+ var nRows = endLv - startLv + 1;
2249
+ if (nRows > rowBudget) {
2250
+ // beyond budget: keep the largest rowBudget rows; the array's
2251
+ // SECOND row (= the first-kept ordinal row) gets its first column
2252
+ // +1 (the dropped lower chain collapses into one extra op there);
2253
+ // first row [10] (issues.md v2.1)
2254
+ var keptFrom = endLv - rowBudget + 1;
2255
+ for (var lv = keptFrom; lv <= endLv; lv++) {
2256
+ var cnt = countAt(lv);
2257
+ if (lv === keptFrom) cnt += 1;
2258
+ if (cnt > 0) sub.array.push([cnt, lv]);
2259
+ }
2260
+ sub.array[0] = [10];
2261
+ } else {
2262
+ for (var lv2 = startLv; lv2 <= endLv; lv2++) {
2263
+ var cnt2 = countAt(lv2);
2264
+ if (cnt2 > 0) sub.array.push([cnt2, lv2]);
2265
+ }
2266
+ }
2267
+ sub.normalize();
2268
+ return sub;
2269
+ }
2270
+ if (t.max(other).gt(hyperLevelSafe(arrowsNum + 1, MAX_SAFE_INTEGER))) {
2271
+ return t.max(other);
1854
2272
  }
1855
- if (t.max(other).gt(hyperLevelSafe(arrowsNum + 1, MAX_SAFE_INTEGER))) return t.max(other);
1856
2273
  if (t.gt(hyperLevelSafe(arrowsNum, MAX_SAFE_INTEGER)) || other.gt(MetaNum.MAX_SAFE_INTEGER)) {
1857
2274
  var r;
1858
2275
  if (t.gt(hyperLevelSafe(arrowsNum, MAX_SAFE_INTEGER))) {
@@ -1886,20 +2303,45 @@
1886
2303
  return j;
1887
2304
  }
1888
2305
  var y = other.toNumber();
1889
- if (arrowsNum >= 23 && y !== Math.floor(y)) {
2306
+ var fastDiag = isFinite(y) && Math.floor(y) === y && canFastDiagonal(t);
2307
+ if (arrowsNum >= 23 && y !== Math.floor(y) && Math.floor(y) > 2) {
2308
+ // Large integer part with a fractional tail at a high level: the tail
2309
+ // would be amplified by the many iterations (e.g. 10{69}69.6 ≈
2310
+ // 10{69}10), so use the discrete 10 anchor (accepted convention).
2311
+ // y with floor ≤ 2 keeps the smooth fractional path — the recursion
2312
+ // bottoms out numerically and carries the smooth Aa-diagonal mantissa
2313
+ // (e.g. 10{101}(2.001607)).
1890
2314
  y = 10;
2315
+ fastDiag = false;
1891
2316
  }
1892
2317
  var f = Math.floor(y);
1893
2318
  var arrows_m1 = arrows.sub(MetaNum.ONE);
1894
- var r = t.arrow(arrows_m1)(y - f);
1895
2319
  var initFloor = Math.floor(other.toNumber());
1896
- for (var i = 0; f !== 0 && r.lt(hyperLevelSafe(arrowsNum - 1, MAX_SAFE_INTEGER)) && i < 100; i++) {
1897
- if (f > 0) {
1898
- r = t.arrow(arrows_m1)(r);
1899
- f--;
2320
+ var r, i;
2321
+ if (fastDiag && arrowsNum >= 2 && f >= 2) {
2322
+ // x{L}y = x{L-1}^{y-1}(x) = x{L-1}^{y-2}(x{L-1}x): seed with the
2323
+ // diagonal D(L-1) built bottom-up and run the remaining successor
2324
+ // iterations — same loop/guard/dump semantics as the path below,
2325
+ // minus the two recomputed seed iterations.
2326
+ r = diagonalChain(t, arrowsNum - 1);
2327
+ f -= 2;
2328
+ for (i = 0; f !== 0 && r.lt(hyperLevelSafe(arrowsNum - 1, MAX_SAFE_INTEGER)) && i < 98; i++) {
2329
+ if (f > 0) {
2330
+ r = t.arrow(arrows_m1)(r);
2331
+ f--;
2332
+ }
1900
2333
  }
2334
+ if (i === 98) f = 0;
2335
+ } else {
2336
+ r = t.arrow(arrows_m1)(y - f);
2337
+ for (i = 0; f !== 0 && r.lt(hyperLevelSafe(arrowsNum - 1, MAX_SAFE_INTEGER)) && i < 100; i++) {
2338
+ if (f > 0) {
2339
+ r = t.arrow(arrows_m1)(r);
2340
+ f--;
2341
+ }
2342
+ }
2343
+ if (i === 100) f = 0;
1901
2344
  }
1902
- if (i === 100) f = 0;
1903
2345
  if (arrowsNum - 1 < MetaNum.maxCols) {
1904
2346
  if (f > 0) {
1905
2347
  r.array[0][arrowsNum - 1] = (r.array[0][arrowsNum - 1] || 0) + f;
@@ -1920,14 +2362,81 @@
1920
2362
  Q.arrow = function (x, arrows, y) {
1921
2363
  return new MetaNum(x).arrow(arrows)(y);
1922
2364
  };
2365
+
2366
+ // ==================== hyper_log / hyper_root ====================
2367
+ // Inverses of the hyperoperation a{b}c = d (arrow-style chained API):
2368
+ // d.hyper_log(a)(b) = c (recover the right operand / argument)
2369
+ // d.hyper_root(c)(b) = a (recover the base / left operand)
2370
+ // b = 0 and b = 1 use exact division and logarithms; b ≥ 2 bisects on the
2371
+ // monotone arrow engine (issues.md addition 2). Note: for levels b beyond
2372
+ // maxCols the forward arrow diagonalizes into one [1|b] marker row and the
2373
+ // argument is no longer recoverable — the bisection then returns the
2374
+ // smallest argument that reproduces d.
2375
+ function hyperBisect(f, target, bound) {
2376
+ // smallest integer x ≥ 1 with f(x) ≥ target (f monotone nondecreasing)
2377
+ var lo = MetaNum.ONE.clone();
2378
+ var hi = new MetaNum(2);
2379
+ var iters = 0;
2380
+ while (f(hi).lt(target)) {
2381
+ lo = hi.clone();
2382
+ hi = hi.mul(2);
2383
+ if (++iters > bound) return hi; // bracketing budget exhausted
2384
+ }
2385
+ iters = 0;
2386
+ while (hi.sub(lo).gt(MetaNum.ONE) && iters++ < bound) {
2387
+ var mid = lo.add(hi).div(2);
2388
+ if (mid.lte(lo)) mid = lo.add(MetaNum.ONE);
2389
+ if (mid.gte(hi)) mid = hi.sub(MetaNum.ONE);
2390
+ if (f(mid).lt(target)) lo = mid.clone();
2391
+ else hi = mid.clone();
2392
+ }
2393
+ return hi;
2394
+ }
2395
+
2396
+ P.hyper_log = function (a) {
2397
+ var d = this.clone();
2398
+ a = new MetaNum(a);
2399
+ return function (b) {
2400
+ b = new MetaNum(b);
2401
+ if (b.lt(MetaNum.ZERO) || d.lte(MetaNum.ZERO) || a.lte(MetaNum.ZERO) || a.eq(MetaNum.ONE)) {
2402
+ return MetaNum.NaN.clone();
2403
+ }
2404
+ if (b.eq(MetaNum.ZERO)) return d.div(a); // a·c = d
2405
+ if (b.eq(MetaNum.ONE)) return d.log10().div(a.log10()); // a^c = d
2406
+ return hyperBisect(function (x) { return a.arrow(b)(x); }, d, 200);
2407
+ };
2408
+ };
2409
+ Q.hyper_log = function (d, a, b) {
2410
+ return new MetaNum(d).hyper_log(a)(b);
2411
+ };
2412
+
2413
+ P.hyper_root = function (c) {
2414
+ var d = this.clone();
2415
+ c = new MetaNum(c);
2416
+ return function (b) {
2417
+ b = new MetaNum(b);
2418
+ if (b.lt(MetaNum.ZERO) || d.lte(MetaNum.ZERO) || c.lte(MetaNum.ZERO)) {
2419
+ return MetaNum.NaN.clone();
2420
+ }
2421
+ if (b.eq(MetaNum.ZERO)) return d.div(c); // a·c = d
2422
+ if (c.eq(MetaNum.ONE)) return d.clone(); // a{b}1 = a
2423
+ return hyperBisect(function (x) { return x.arrow(b)(c); }, d, 200);
2424
+ };
2425
+ };
2426
+ Q.hyper_root = function (d, c, b) {
2427
+ return new MetaNum(d).hyper_root(c)(b);
2428
+ };
1923
2429
  Q.chain = function (x, y, arrows) {
1924
2430
  return new MetaNum(x).arrow(arrows)(y);
1925
2431
  };
1926
2432
 
1927
- //calc level ω: x{ω}y = x{y}y (fundamental sequence ω[y] = y)
1928
- // aperiote(x,0) = x{0}0 = 0; aperiote(x,1) = x{1}1 = x; aperiote(x,2) = x{2}2 = x^x; ...
2433
+ // level ω, rule 3 with the fundamental sequence ω[y] = y:
2434
+ // x{ω}y = x{ω[y]}x = x{y}x
2435
+ // (the final operand is the base x, NOT the FS index y)
2436
+ // aperiote(3,0) = 3{0}3 = 9; aperiote(3,1) = 3{1}3 = 27;
2437
+ // aperiote(3,2) = 3{2}3 = 3^^3 = 7625597484987; ...
1929
2438
  P.aperiote = P.aper = P.h10 = function (y) {
1930
- return this.arrow(y)(y);
2439
+ return this.arrow(y)(this);
1931
2440
  };
1932
2441
  Q.aperiote = Q.aper = Q.h10 = function (x, y) {
1933
2442
  return new MetaNum(x).aperiote(y);
@@ -1977,7 +2486,8 @@
1977
2486
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
1978
2487
  var base = x.aperiote(x); // expande(x, 2) = x{x}x = x{ω}x
1979
2488
  if (y.eq(2)) return base.clone();
1980
- if (y.lt(2)) return base.clone(); // 1 < y < 2: the aperiote base
2489
+ // 1 < y < 2 follows the successor rule too: x{ω+1}y = x{ω} applied
2490
+ // floor(y) times to x^frac(y) (continuous with y=1 → x, y=2 → x{ω}x)
1981
2491
  return Q._hyperopFromOrdinal(x, y, [1, 1]);
1982
2492
  };
1983
2493
  Q.expande = Q.expa = Q.h11 = function (x, y) {
@@ -2027,7 +2537,7 @@
2027
2537
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
2028
2538
  var base = x.expande(x); // multiexpande(x, 2)
2029
2539
  if (y.eq(2)) return base.clone();
2030
- if (y.lt(2)) return base.clone(); // 1 < y < 2
2540
+ // 1 < y < 2 follows the successor rule (continuous with the integers)
2031
2541
  return Q._hyperopFromOrdinal(x, y, [2, 1]);
2032
2542
  };
2033
2543
  Q.multiexpande = Q.muea = Q.h12 = function (x, y) {
@@ -2075,7 +2585,7 @@
2075
2585
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
2076
2586
  var base = x.multiexpande(x); // powerexpande(x, 2)
2077
2587
  if (y.eq(2)) return base.clone();
2078
- if (y.lt(2)) return base.clone(); // 1 < y < 2
2588
+ // 1 < y < 2 follows the successor rule (continuous with the integers)
2079
2589
  return Q._hyperopFromOrdinal(x, y, [3, 1]);
2080
2590
  };
2081
2591
  Q.powerexpande = Q.poea = Q.h13 = function (x, y) {
@@ -2220,6 +2730,9 @@
2220
2730
  } else {
2221
2731
  var c = cmpCoeffsLevel(bt, rowToCoeffs(x.array[idx]));
2222
2732
  if (c > 0) {
2733
+ // Push the larger level; if this exceeds the row budget, normalize
2734
+ // keeps the base + the largest rows (the new row is never the one
2735
+ // dropped — it ranks among the largest)
2223
2736
  x.array.push([k].concat(bt));
2224
2737
  } else if (c === 0) {
2225
2738
  var cnt = (x.array[idx][0] || 0) + k;
@@ -2230,6 +2743,112 @@
2230
2743
  return x.normalize();
2231
2744
  };
2232
2745
 
2746
+ // issues.md truncation rule for ordinal expansions: when the expansion
2747
+ // reaches row capacity (maxRows-1 ordinal rows), the base defaults to [10]
2748
+ // and the first (smallest kept) ordinal row's count increments by 1 —
2749
+ // marking that the exact expansion was truncated to its largest ordinals.
2750
+ Q._applyExpansionTruncation = function (x) {
2751
+ x = x.normalize();
2752
+ var maxOrdinalRows = MetaNum.maxRows - 1;
2753
+ if (x.array.length >= 2 && x.array.length - 1 >= maxOrdinalRows) {
2754
+ x.array[0] = [10];
2755
+ x.array[1][0] = (x.array[1][0] || 0) + 1;
2756
+ if (x.array[1][0] > MAX_SAFE_INTEGER) x.array[1][0] = MAX_SAFE_INTEGER;
2757
+ }
2758
+ return x;
2759
+ };
2760
+
2761
+ // ---------------------------------------------------------------------------
2762
+ // Compact "layer marker" values for levels at or above ω^ω (README L17).
2763
+ // Such a level has no finite CNF coefficient row, so the result of x{α}y is
2764
+ // stored as the diagonal value of the reduced level (one rule-3 step):
2765
+ // layer L >= 1, rows [count, a1, …, ap] →
2766
+ // 10{ ω^ω^…((L-1) ω^'s)…^( Σ_i ω^(ord_i)·count_i + Σ_j ω^j·r_j ) }10
2767
+ // with ord_i = ω^(p-1)·ap + … + ω·a2 + a1.
2768
+ // Examples: 10{ω^y}10 = L1 [[0],[1,y]]; 10{ω^ω}10 = L1 [[0],[1,0,1]];
2769
+ // 10{ω^ω·y}10 = L1 [[0],[y,0,1]]; 10{ω^(ω+y)}10 = L1 [[0],[1,y,1]];
2770
+ // 10{ω^(ω·y)}10 = L2 [[0],[y,1]]; 10{ω^(ω^y)}10 = L3 [[y]];
2771
+ // 10{ω^ω^…^ω(y ω's)}10 = L_y [[0],[1,1]].
2772
+ // A marker is always stored in STANDARD FORM (Q._standardizeLayerValue):
2773
+ // finite-level rows merge into r0 and the layer drops as far as it can.
2774
+ // ---------------------------------------------------------------------------
2775
+ Q._layerMarker = function (r0, layer, rows) {
2776
+ var v = new MetaNum(0);
2777
+ v.array = [(r0 && r0.length) ? r0.slice() : [0]];
2778
+ for (var i = 0; i < (rows ? rows.length : 0); i++) {
2779
+ if (rows[i] && rows[i].length > 1) v.array.push(rows[i].slice());
2780
+ }
2781
+ v.layer = layer > 0 ? layer : 0;
2782
+ return Q._standardizeLayerValue(v);
2783
+ };
2784
+
2785
+ // Standard form of a layer >= 1 value (README L17). Two rewrites, both
2786
+ // preserving the encoded ordinal, applied until no longer possible:
2787
+ // (a) merge: an ordinal row [count, k] holds the finite level k, i.e. the
2788
+ // bracket term ω^k·count — the very term r0's own k-th entry spells
2789
+ // (Σ_j ω^j·r_j). So whenever k < maxCols the row folds into r0:
2790
+ // cube(10,3): [[10],[1,3],[1,0,1]] → [[10,0,0,1],[1,0,1]].
2791
+ // (b) de-layer: a layer-L value whose bracket is the finite ω-polynomial β
2792
+ // (no row above ω survives) equals the layer-(L-1) value carrying the
2793
+ // single row [1|β] (bracket ω^β, one ω^ less above it):
2794
+ // layer2 [[5],[3,1]] → layer2 [[5,3]] → layer1 [[10],[1,5,3]]
2795
+ // = 10{ω^(ω*3+5)}10;
2796
+ // layer3 [[3]] → layer2 [[0,0,0,1]] → layer1 [[10],[1,0,0,0,1]]
2797
+ // = 10{ω^ω^3}10.
2798
+ // Each de-layer step strictly lowers `layer`, so the loop terminates; the
2799
+ // innermost base is written as 10 (the 10{…}10 diagonal marker).
2800
+ function mergeFiniteRowsIntoR0(arr) {
2801
+ var r0 = arr[0];
2802
+ var keep = [];
2803
+ for (var i = 1; i < arr.length; i++) {
2804
+ var row = arr[i];
2805
+ if (row && row.length === 2 && row[1] >= 1 && row[1] < MetaNum.maxCols) {
2806
+ var k = row[1];
2807
+ while (r0.length <= k) r0.push(0);
2808
+ r0[k] += (row[0] || 0);
2809
+ continue;
2810
+ }
2811
+ keep.push(row);
2812
+ }
2813
+ arr.length = 1;
2814
+ for (var j = 0; j < keep.length; j++) arr.push(keep[j]);
2815
+ }
2816
+
2817
+ Q._standardizeLayerValue = function (v) {
2818
+ if (!v || v.layer < 1) return v.normalize();
2819
+ var L = v.layer;
2820
+ var arr = [v.array[0].slice()];
2821
+ for (var i = 1; i < v.array.length; i++) arr.push(v.array[i].slice());
2822
+ mergeFiniteRowsIntoR0(arr);
2823
+ while (L >= 2 && arr.length === 1) {
2824
+ var poly = arr[0].slice();
2825
+ while (poly.length > 0 && poly[poly.length - 1] === 0) poly.pop();
2826
+ if (poly.length === 0) break;
2827
+ var row = [1].concat(poly);
2828
+ if (row.length > MetaNum.maxCols) break; // row would not fit
2829
+ arr = [[0], row];
2830
+ L--;
2831
+ mergeFiniteRowsIntoR0(arr);
2832
+ }
2833
+ if ((arr[0][0] || 0) === 0) arr[0][0] = 10; // innermost base marker
2834
+ v.array = arr;
2835
+ v.layer = L;
2836
+ return v.normalize();
2837
+ };
2838
+
2839
+ // x{α}y when the operand y is itself an ordinal (or beyond MSI): the
2840
+ // iteration count is unrepresentable, so the engine convention applies —
2841
+ // "y plus one α-level marker row" (the supremum of the count-limited
2842
+ // iterations). `row` is the marker row of α at the given `layer`.
2843
+ Q._ordinalOperandOp = function (y, layer, row) {
2844
+ var v = y.clone();
2845
+ if (v.layer < layer) v.layer = layer;
2846
+ var bt = trimCoeffs((row || []).slice(1));
2847
+ var k = (row && row[0] > 0) ? row[0] : 1;
2848
+ if (bt.length === 0) return v.normalize();
2849
+ return Q._applyOrdinalRows(v, bt, k).normalize();
2850
+ };
2851
+
2233
2852
  Q._ordinalHyperop = function (x, y, coeffs, depth) {
2234
2853
  x = new MetaNum(x);
2235
2854
  y = new MetaNum(y);
@@ -2268,7 +2887,8 @@
2268
2887
  // the diagonalized single-row form (supremum of the iteration hierarchy).
2269
2888
  var hugeFs = yCnt > COEFF_BOUND && (pL >= 2 || (cf[1] || 0) > 1);
2270
2889
  if (hugeFs) return Q._applyOrdinalRows(x.max(y), cf, 1);
2271
- return Q._ordinalHyperop(x, y, fsCoeffs(cf, yCnt), depth + 1);
2890
+ // rule 3: x{λ}y = x{λ[y]}x — the final operand is the base x
2891
+ return Q._ordinalHyperop(x, x, fsCoeffs(cf, yCnt), depth + 1);
2272
2892
  };
2273
2893
 
2274
2894
  Q._iterateOrdinal = function (x, beta, V0, iters, depth) {
@@ -2296,7 +2916,7 @@
2296
2916
  // enumeration representation (one row per ordinal below α, count = y-2)
2297
2917
  // - everything else (any operand beyond MSI, x = 2, or enumeration too large):
2298
2918
  // unified ordinal engine (README rules 1-4)
2299
- Q._hyperopFromOrdinal = function (x, y, coeffs) {
2919
+ Q._hyperopFromOrdinalRaw = function (x, y, coeffs) {
2300
2920
  x = new MetaNum(x);
2301
2921
  y = new MetaNum(y);
2302
2922
  if (x.isNaN() || y.isNaN()) return MetaNum.NaN.clone();
@@ -2304,8 +2924,47 @@
2304
2924
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
2305
2925
  if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
2306
2926
  if (y.eq(MetaNum.ONE)) return x.clone();
2307
- var cf = trimCoeffs((coeffs || []).slice());
2308
- if (cf.length === 0) return x.mul(y); // rule 1: x{0}y = x*y
2927
+ var cf0 = trimCoeffs((coeffs || []).slice());
2928
+ if (cf0.length === 0) return x.mul(y); // rule 1: x{0}y = x*y
2929
+ // Non-integer argument at ordinal levels (issues.md addition 3):
2930
+ // successor level α (c0 > 0): x{α}(m+f) = x{α-1} applied m times to x^f
2931
+ // (e.g. expa(10,2.1) = 10{ω+1}2.1 = 10{ω}10{ω}(10^0.1); continuous at
2932
+ // the integers since x^0 = 1 and x{α-1}1 = x)
2933
+ // limit level λ (c0 = 0): fundamental sequence at m = floor(y)
2934
+ var yFracNum = y.toNumber();
2935
+ if (!y.isint() && y.gt(MetaNum.ONE) && y.array.length === 1 && isFinite(yFracNum)) {
2936
+ // Finite levels delegate to arrow()'s own fractional-argument machinery
2937
+ if (!coeffsHaveOmegaPart(cf0)) return x.arrow(cf0[0])(y);
2938
+ // ω level: match P.aperiote exactly (x{ω}y = x.arrow(y)(x)), so the
2939
+ // successor rule composes as expa(10,2.1) = 10{ω}10{ω}(10^0.1)
2940
+ if (cf0.length === 2 && cf0[1] === 1 && !(cf0[0] > 0)) return x.aperiote(y);
2941
+ var ym = Math.floor(yFracNum);
2942
+ // toPrecision(15) strips double-rounding noise in y - floor(y)
2943
+ // (2.1 - 2 = 0.10000000000000009), so x^frac(y) reproduces x.pow(0.1)
2944
+ // exactly and composition identities stay stable across paths
2945
+ var yf = new MetaNum(Number((yFracNum - ym).toPrecision(15)));
2946
+ if ((cf0[0] || 0) > 0) {
2947
+ if (ym <= 100000) {
2948
+ // successor rule: x{α}(m+f) = x{α-1} applied m times to x^f
2949
+ var succ = cf0.slice();
2950
+ succ[0] = succ[0] - 1;
2951
+ succ = trimCoeffs(succ);
2952
+ var v = x.pow(yf);
2953
+ for (var it = 0; it < ym; it++) v = Q._hyperopFromOrdinalRaw(x, v, succ);
2954
+ return v;
2955
+ }
2956
+ // Successor level with an iteration count beyond direct evaluation:
2957
+ // successors have no fundamental sequence, so fall through to the
2958
+ // engine's huge-y supremum convention (y + one α-row marker)
2959
+ return Q._ordinalHyperop(x, y, cf0);
2960
+ }
2961
+ if (ym >= 1) {
2962
+ // limit level: fundamental sequence at m = floor(y); rule 3 puts the
2963
+ // base x as the final operand: x{λ}y = x{λ[m]}x
2964
+ return Q._hyperopFromOrdinalRaw(x, x, fsCoeffs(cf0, ym));
2965
+ }
2966
+ }
2967
+ var cf = cf0;
2309
2968
  var deg = 0;
2310
2969
  for (var di = 1; di < cf.length; di++) if ((cf[di] || 0) !== 0) deg = di;
2311
2970
  if (deg >= 1 && x.array.length === 1 && x.layer === 0
@@ -2319,6 +2978,20 @@
2319
2978
  return Q._ordinalHyperop(x, y, cf);
2320
2979
  };
2321
2980
 
2981
+ // Public entry point of the ordinal-level hyperoperations. The expansion is
2982
+ // exact while it fits the array budget; once the rule-1..4 cascade overflows
2983
+ // maxRows the issues.md truncation rule applies (keep the largest maxRows-1
2984
+ // ordinal rows sorted ascending, array[1][0] += 1 as the truncation marker,
2985
+ // array[0] = [10]) — the same convention arrow() and BEAF already use.
2986
+ Q._hyperopFromOrdinal = function (x, y, coeffs) {
2987
+ var r = Q._hyperopFromOrdinalRaw(x, y, coeffs);
2988
+ if (r && r._ordTrunc) {
2989
+ delete r._ordTrunc;
2990
+ r = Q._applyExpansionTruncation(r);
2991
+ }
2992
+ return r;
2993
+ };
2994
+
2322
2995
  // Legacy (HEAD-compatible) enumeration-based hyperoperation for small operands.
2323
2996
  Q._enumHyperop = function (x, y, coeffs) {
2324
2997
  var xNum = x.toNumber();
@@ -2331,7 +3004,17 @@
2331
3004
  isFinite(yNum) ? Math.floor(yNum) : baseArrowLevel,
2332
3005
  maxRows);
2333
3006
  var result = baseResult.clone();
2334
- result.array = [baseResult.array[0].slice()];
3007
+ var maxOrdinalRows = maxRows - 1;
3008
+ if (rows.length > maxOrdinalRows) {
3009
+ // Truncation: keep the largest maxOrdinalRows rows (rows ascend), the
3010
+ // base defaults to [10] and the first kept row's count marks it with +1
3011
+ rows = rows.slice(rows.length - maxOrdinalRows);
3012
+ result.array = [[10]];
3013
+ rows[0][0] = (rows[0][0] || 0) + 1;
3014
+ if (rows[0][0] > MAX_SAFE_INTEGER) rows[0][0] = MAX_SAFE_INTEGER;
3015
+ } else {
3016
+ result.array = [baseResult.array[0].slice()];
3017
+ }
2335
3018
  for (var i = 0; i < rows.length; i++) result.array.push(rows[i]);
2336
3019
  if (result.array.length > 1) result.layer = 0;
2337
3020
  return result;
@@ -2505,8 +3188,10 @@
2505
3188
  if (row) allRows.push(row);
2506
3189
  }
2507
3190
 
2508
- var maxOrdinalRows = maxRows - 1;
2509
- if (allRows.length > maxOrdinalRows) {
3191
+ // When enumerating more rows than fit, keep the largest maxRows-1
3192
+ // ordinals (rows are sorted ascending, so drop from the front)
3193
+ if (allRows.length > maxRows - 1) {
3194
+ var maxOrdinalRows = maxRows - 1;
2510
3195
  allRows = allRows.slice(allRows.length - maxOrdinalRows);
2511
3196
  }
2512
3197
 
@@ -2909,78 +3594,59 @@
2909
3594
  // Hyperoperations from ω^ω up to ε₀
2910
3595
  // ---------------------------------------------------------------------------
2911
3596
 
2912
- // iter (ω^ω): diagonalizes ω^x operations
2913
- // k <= maxCols-2: layer 0, multi-index; k >= maxCols-1: layer 1
2914
- // e.g. iter(3,5)=3{ω^ω}5=3{ω^5}5=3{ω^4*4+ω^3*4+ω^2*4+ω*4+5}5=(3{ω^4*4+ω^3*4+ω^2*4+ω*4+4})^3...
2915
- // so iter(3,5) → layer=0, max array row=[3,4,4,4,4,4]
2916
- // for maxcol-1 <= k <= MSI, iter(3,k)=3{ω^ω}k=3{ω^k}k
2917
- // reference to README.md, when layer=1, array=[[0],[1,k]] represents 10{ω^k}10
2918
- // array [[1], [1,k]] represents 10{ω^k+1}10=10{ω^k}^9 10
2919
- // so iter(3,k)≈10{ω^k}10 → layer=1, max array row=[[0],[1,k]]
2920
- // for k > MSI, iter(3,k)≈10{ω^ω}MSI → layer=1, array=[[0],[1,0,1]], which represents 10{ω^ω}MSI
2921
- // 10{ω^ω+1}x (2<=x<=10, =10{ω^ω+1}(>MSI) if x=2) should be treated as 10{ω^ω+a}10, a=log5(x/2)
2922
- // iter(10,iter(10,10))=10{ω^ω}10{ω^ω}10=10{ω^ω+1}3→array=[[log5(3/2)],[1,0,1]]
2923
- P.iteration = P.iter = P.hww = function (y) {
3597
+ // ---------------------------------------------------------------------------
3598
+ // Hyperoperations from ω^ω up to ε₀ — README rules 1-4 with the unified
3599
+ // limit rule n{λ}b = n{λ[b]}n (the final operand is the BASE n, never b).
3600
+ // Levels ≥ ω^ω have no finite CNF coefficient row, so — except where the
3601
+ // reduced level λ[y] still fits a layer-0 ordinal row — the result is stored
3602
+ // as the compact layer marker of λ[y] (see Q._layerMarker).
3603
+ // ---------------------------------------------------------------------------
3604
+
3605
+ // iter (ω^ω): (ω^ω)[y] = ω^y → x{ω^ω}y = x{ω^y}x
3606
+ // e.g. iter(3,5) = 3{ω^5}3 = 3{ω^4*3}3 = … = 3{ω^4*2+ω^3*2+ω^2*2+ω*2+2}3…
3607
+ // (whole fundamental-sequence cascade → layer 0 multi-row array)
3608
+ // for y >= maxCols the ω^y row no longer fits → layer=1 marker [[r0],[1,y]]
3609
+ // (= 10{ω^y}10), and for y > MSI the operand is unrepresentable → the
3610
+ // ω^ω marker row [1,0,1] (= 10{ω^ω}10).
3611
+ P.iterate = P.iter = P.hww = function (y) {
2924
3612
  var x = this.clone();
2925
3613
  y = new MetaNum(y);
2926
3614
  if (x.isNaN() || y.isNaN()) return MetaNum.NaN.clone();
2927
3615
  if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
2928
3616
  if (y.eq(MetaNum.ONE)) return x.clone();
2929
3617
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
2930
-
2931
- if (y.layer === 0 && y.array.length <= 1) {
2932
- var yn = y.toNumber();
2933
- var maxLevel = MetaNum.maxCols - 1;
2934
- if (yn < maxLevel) {
2935
- // y fits within ordinal levels: create ω^y at layer 0
2936
- // Multi-index format: [1, 0, 0, ..., 0, 1] with yn zeros
2937
- var result = x.clone();
2938
- var row = [1];
2939
- for (var i = 0; i < yn; i++) row.push(0);
2940
- row.push(1);
2941
- result.layer = 0;
2942
- result.array.push(row);
2943
- result.normalize();
2944
- return result;
2945
- } else {
2946
- // y >= maxLevel: promote to layer 1, compact format [[x],[1,yn]]
2947
- // ordinal level ω^y needs a row longer than maxCols, so it is stored
2948
- // as layer=1 (level = ω^P with P = yn constant); cap at MSI
2949
- var result = x.clone();
2950
- result.layer = 1;
2951
- var yv = yn > MAX_SAFE_INTEGER ? MAX_SAFE_INTEGER : yn;
2952
- result.array.push([1, yv]);
2953
- result.normalize();
2954
- return result;
2955
- }
2956
- }
2957
-
2958
- // y is ordinal: iter on ordinal
2959
- // Promote: absorb y's ordinal rows into r0, add iter marker
2960
- // Layer promotion consumes one level: skip the first value
2961
- var result = y.clone();
2962
- var newR0 = x.array[0].slice();
2963
- // Absorb y's ordinal rows into r0 (skip count and first value)
2964
- for (var ir = 1; ir < y.array.length; ir++) {
2965
- var yrow = y.array[ir];
2966
- // Start from index 2 to skip count and first ordinal value
2967
- for (var jc = 2; jc < yrow.length; jc++) {
2968
- newR0.push(yrow[jc]);
2969
- }
2970
- }
2971
- result.array[0] = newR0;
2972
- result.array = [newR0];
2973
- // Add iter's own ordinal marker
2974
- result.array.push([1, 0, 1]);
2975
- result.layer = y.layer + 1;
2976
- result.normalize();
2977
- return result;
2978
- };
2979
- Q.iteration = Q.iter = Q.hww = function (x, y) {
2980
- return new MetaNum(x).iteration(y);
2981
- };
2982
3618
 
2983
- P.inv_iteration = P.inv_iter = P.iww = function (z) {
3619
+ // iterate(x,y) = x{ω^ω}y. Rule 3 with the fundamental sequence
3620
+ // (ω^ω)[y] = ω^y: x{ω^ω}y = x{ω^y}x — final operand is the base x.
3621
+ var yc = metaFiniteCount(y);
3622
+ if (yc === Math.floor(yc) && yc <= MAX_SAFE_INTEGER) {
3623
+ var m = Math.max(2, Math.floor(yc));
3624
+ if (m < MetaNum.maxCols) {
3625
+ // ω^y is a layer-0 ordinal (coeffs with 1 at index y): evaluate
3626
+ // x{ω^y}x through the unified rule-1..3 engine. E.g.
3627
+ // iterate(3,5) = 3{ω^5}3 = the full FS cascade (truncated when it
3628
+ // overflows the row budget).
3629
+ var coeffs = [];
3630
+ for (var ci = 0; ci < m; ci++) coeffs.push(0);
3631
+ coeffs.push(1);
3632
+ return Q._hyperopFromOrdinal(x, x, coeffs);
3633
+ }
3634
+ // y >= maxCols: ω^y needs a row longer than maxCols — store as the
3635
+ // layer-1 compact marker 10{ω^y}10, capped at MSI
3636
+ return Q._layerMarker([10], 1, [[1, m]]);
3637
+ }
3638
+ if (yc <= MAX_SAFE_INTEGER) {
3639
+ // fractional y: rule 3 takes the fundamental sequence at floor(y)
3640
+ return P.iterate.call(x, new MetaNum(Math.max(2, Math.floor(yc))));
3641
+ }
3642
+ // ordinal / out-of-range operand: y plus one ω^ω marker row
3643
+ return Q._ordinalOperandOp(y, 1, [1, 0, 1]);
3644
+ };
3645
+ Q.iterate = Q.iter = Q.hww = function (x, y) {
3646
+ return new MetaNum(x).iterate(y);
3647
+ };
3648
+
3649
+ P.inv_iterate = P.inv_iter = P.iww = function (z) {
2984
3650
  var x = this.clone();
2985
3651
  z = new MetaNum(z);
2986
3652
  if (x.isNaN() || z.isNaN()) return MetaNum.NaN.clone();
@@ -3029,14 +3695,17 @@
3029
3695
  }
3030
3696
  return z;
3031
3697
  };
3032
- Q.inv_iteration = Q.inv_iter = Q.iww = function (x, z) {
3033
- return new MetaNum(x).inv_iteration(z);
3698
+ Q.inv_iterate = Q.inv_iter = Q.iww = function (x, z) {
3699
+ return new MetaNum(x).inv_iterate(z);
3034
3700
  };
3035
3701
 
3036
- // itermult (ω^ω+1): iterates ω^ω level operations
3037
- // for k <= MSI, itmu(3,k)=3{ω^ω+1}k=3{ω^ω}3{ω^ω}...3 with k 3's
3038
- // ≈10{ω^ω+1}k → layer=1, array=[[n],[1,0,1]] (n=log5(k/2) if 2<=k<10, n=1 if k>=10)
3039
- // for k > MSI, itmu(3,k)≈10{ω^ω+1}MSI → layer=1, array=[[1],[1,0,1]]
3702
+ // itermult (ω^ω+1): successor level — x{ω^ω+1}y = x{ω^ω} applied y-1 times
3703
+ // to x (rule 2), i.e. itmu(3,k) = 3{ω^ω}3{ω^ω}…3 with k 3's.
3704
+ // k = 2 → x{ω^ω}x = iterate(x,x) exactly; 1 < k < 2 → x{ω^ω}(x^(k-1)).
3705
+ // k > 2 → layer=1 marker [[k-1],[1,0,1]] = 10{ω^ω+(k-1)}10: any finite
3706
+ // number of ω^ω applications stays strictly below ω^ω·2, so the count
3707
+ // lives in the constant term (ω^ω + n) — monotone in k and still below
3708
+ // cuboiter's ω^ω+ω^k.
3040
3709
  P.itermult = P.itmu = P.hw01 = function (y) {
3041
3710
  var x = this.clone();
3042
3711
  y = new MetaNum(y);
@@ -3044,24 +3713,20 @@
3044
3713
  if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
3045
3714
  if (y.eq(MetaNum.ONE)) return x.clone();
3046
3715
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
3047
- if (y.layer === 0 && y.array.length <= 1) {
3048
- var yn = y.toNumber();
3049
- var base = x.iter(x);
3050
- if (y.eq(2)) return base;
3051
- var result = base.clone();
3052
- result.layer = 1;
3053
- result.array = [base.array[0].slice()];
3054
- result.array[0] = [yn];
3055
- result.array.push([1, yn, 1]);
3056
- result.normalize();
3057
- return result;
3716
+ var yc = metaFiniteCount(y);
3717
+ if (yc <= MAX_SAFE_INTEGER) {
3718
+ if (yc <= 2) {
3719
+ // rule 2 with one iteration: x{ω^ω+1}k = x{ω^ω}(x^(k-1)) (x^1 = x)
3720
+ var f = y.sub(MetaNum.ONE);
3721
+ return f.eq(MetaNum.ZERO) ? x.iterate(x) : x.iterate(x.pow(f));
3722
+ }
3723
+ var n = Math.ceil(yc) - 1; // number of ω^ω applications
3724
+ if (n < 1) n = 1;
3725
+ if (n > MAX_SAFE_INTEGER) n = MAX_SAFE_INTEGER;
3726
+ return Q._layerMarker([n], 1, [[1, 0, 1]]);
3058
3727
  }
3059
- var result = y.clone();
3060
- result.layer = Math.max(result.layer, 1);
3061
- var base = x.iter(x);
3062
- result.array[0] = base.array[0].slice();
3063
- result.normalize();
3064
- return result;
3728
+ // ordinal / out-of-range operand: y plus one ω^ω marker row
3729
+ return Q._ordinalOperandOp(y, 1, [1, 0, 1]);
3065
3730
  };
3066
3731
  Q.itermult = Q.itmu = Q.hw01 = function (x, y) {
3067
3732
  return new MetaNum(x).itermult(y);
@@ -3071,13 +3736,24 @@
3071
3736
  var x = this.clone();
3072
3737
  z = new MetaNum(z);
3073
3738
  if (x.isNaN() || z.isNaN()) return MetaNum.NaN.clone();
3739
+ // marker [[n],[1,0,1]] = 10{ω^ω+n}10: the iteration count n sits in the
3740
+ // constant term, so y = n + 1 applications of the ω^ω level.
3741
+ if (x.layer >= 1) {
3742
+ for (var i = x.array.length - 1; i >= 1; i--) {
3743
+ var row = x.array[i];
3744
+ if (row.length === 3 && row[1] === 0 && row[2] === 1 && row[0] === 1) {
3745
+ var n = Math.round(x.array[0][0] || 0);
3746
+ return new MetaNum(n + 1);
3747
+ }
3748
+ }
3749
+ }
3074
3750
  if (x.array.length >= 2) {
3075
3751
  var result = x.clone();
3076
- for (var i = result.array.length - 1; i >= 1; i--) {
3077
- var row = result.array[i];
3078
- if (row.length >= 3 && row[0] > 0) {
3079
- row[0]--;
3080
- if (row[0] <= 0) result.array.splice(i, 1);
3752
+ for (var j = result.array.length - 1; j >= 1; j--) {
3753
+ var row2 = result.array[j];
3754
+ if (row2.length >= 3 && row2[0] > 0) {
3755
+ row2[0]--;
3756
+ if (row2[0] <= 0) result.array.splice(j, 1);
3081
3757
  result.normalize();
3082
3758
  if (result.array.length <= 1) result.layer = 0;
3083
3759
  return result;
@@ -3091,10 +3767,10 @@
3091
3767
  return new MetaNum(x).inv_itermult(z);
3092
3768
  };
3093
3769
 
3094
- // cuboiter (ω^ω*2): x{(ω^ω)*2}y = x{ω^ω+ω^y}y
3095
- // for k <= MSI, cube(3,k)=3{ω^ω+ω^k}k
3096
- // ≈10{ω^ω+ω^k}k → layer=1, array=[[0],[1,k],[1,0,1]]
3097
- // for k > MSI, cube(3,k)≈10{ω^ω*2}MSI → layer=1, array=[[0],[2,0,1]]
3770
+ // cuboiter (ω^ω*2): (ω^ω*2)[y] = ω^ω + ω^y → x{ω^ω*2}y = x{ω^ω+ω^y}x
3771
+ // for k <= MSI, cube(3,k)=3{ω^ω+ω^k}3
3772
+ // ≈10{ω^ω+ω^k}10 → layer=1, array=[[10],[1,k],[1,0,1]] (ω^k + ω^ω)
3773
+ // for k > MSI, cube(3,k)≈10{ω^ω*2}10 → layer=1, array=[[10],[2,0,1]]
3098
3774
  P.cuboiter = P.cube = P.hwx2 = function (y) {
3099
3775
  var x = this.clone();
3100
3776
  y = new MetaNum(y);
@@ -3102,24 +3778,14 @@
3102
3778
  if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
3103
3779
  if (y.eq(MetaNum.ONE)) return x.clone();
3104
3780
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
3105
- var base = x.itermult(x);
3106
- if (y.layer === 0 && y.array.length <= 1) {
3107
- var yn = y.toNumber();
3108
- if (y.eq(2)) return base;
3109
- var result = base.clone();
3110
- result.layer = 1;
3111
- result.array = [[1]];
3112
- result.array.push([1, yn, 1]);
3113
- result.array.push([1, 0, 1]);
3114
- result.normalize();
3115
- return result;
3781
+ var yc = metaFiniteCount(y);
3782
+ if (yc <= MAX_SAFE_INTEGER) {
3783
+ var m = Math.max(2, Math.floor(yc));
3784
+ if (m > MAX_SAFE_INTEGER) m = MAX_SAFE_INTEGER;
3785
+ return Q._layerMarker([10], 1, [[1, m], [1, 0, 1]]);
3116
3786
  }
3117
- var result = y.clone();
3118
- result.layer = 1;
3119
- result.array[0] = base.array[0].slice();
3120
- result.array.push([1, 0, 1]);
3121
- result.normalize();
3122
- return result;
3787
+ // ordinal / out-of-range operand: y plus two ω^ω marker rows (ω^ω*2)
3788
+ return Q._ordinalOperandOp(y, 1, [2, 0, 1]);
3123
3789
  };
3124
3790
  Q.cuboiter = Q.cube = Q.hwx2 = function (x, y) {
3125
3791
  return new MetaNum(x).cuboiter(y);
@@ -3130,20 +3796,26 @@
3130
3796
  z = new MetaNum(z);
3131
3797
  if (x.isNaN() || z.isNaN()) return MetaNum.NaN.clone();
3132
3798
  if (x.array.length >= 2) {
3133
- // For finite y: find [1, yn, 1] with yn > 0 and return yn
3134
- // (skip [1, 0, 1] which is the cuboiter marker)
3135
- for (var i = x.array.length - 1; i >= 1; i--) {
3136
- var row = x.array[i];
3137
- if (row.length === 3 && row[0] === 1 && row[2] === 1 && row[1] > 0) {
3138
- return new MetaNum(row[1]);
3799
+ // standard marker [[…,1@y,…],[1,0,1]] = 10{ω^ω+ω^y}10: the ω^y term is
3800
+ // merged into r0 (index y) whenever y < maxCols, else it is the row [1,y]
3801
+ if (x.layer >= 1) {
3802
+ var r0 = x.array[0];
3803
+ for (var j = r0.length - 1; j >= 1; j--) {
3804
+ if ((r0[j] || 0) > 0) return new MetaNum(j);
3805
+ }
3806
+ for (var i = x.array.length - 1; i >= 1; i--) {
3807
+ var row = x.array[i];
3808
+ if (row.length === 2 && row[0] === 1 && row[1] > 0) {
3809
+ return new MetaNum(row[1]);
3810
+ }
3139
3811
  }
3140
3812
  }
3141
3813
  // For ordinal y: find [1, 0, 1] marker and return y
3142
- for (var i = x.array.length - 1; i >= 1; i--) {
3143
- var row = x.array[i];
3144
- if (row.length >= 3 && row[1] === 0 && row[2] === 1 && row[0] === 1) {
3814
+ for (var k = x.array.length - 1; k >= 1; k--) {
3815
+ var row2 = x.array[k];
3816
+ if (row2.length >= 3 && row2[1] === 0 && row2[2] === 1 && row2[0] === 1) {
3145
3817
  var result = x.clone();
3146
- result.array.splice(i, 1);
3818
+ result.array.splice(k, 1);
3147
3819
  result.normalize();
3148
3820
  if (result.array.length <= 1) result.layer = 0;
3149
3821
  return result;
@@ -3156,10 +3828,10 @@
3156
3828
  return new MetaNum(x).inv_cuboiter(z);
3157
3829
  };
3158
3830
 
3159
- // expoiter (ω^(ω+1)): x{ω^(ω+1)}y = x{ω^ω * y}y
3160
- // for k <= MSI, expo(3,k)=3{ω^ω*k}k
3161
- // ≈10{ω^ω*k}k → layer=1, array=[[0],[k,0,1]]
3162
- // for k > MSI, expo(3,k)≈10{ω^(ω+1)}MSI → layer=1, array=[[0],[1,1,1]]
3831
+ // expoiter (ω^(ω+1)): (ω^(ω+1))[y] = ω^ω*y → x{ω^(ω+1)}y = x{ω^ω*y}x
3832
+ // for k <= MSI, expo(3,k)=3{ω^ω*k}3
3833
+ // ≈10{ω^ω*k}10 → layer=1, array=[[10],[k,0,1]]
3834
+ // for k > MSI, expo(3,k)≈10{ω^(ω+1)}10 → layer=1, array=[[10],[1,1,1]]
3163
3835
  P.expoiter = P.expo = P.hwa1 = function (y) {
3164
3836
  var x = this.clone();
3165
3837
  y = new MetaNum(y);
@@ -3167,23 +3839,14 @@
3167
3839
  if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
3168
3840
  if (y.eq(MetaNum.ONE)) return x.clone();
3169
3841
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
3170
- var base = x.iter(x);
3171
- if (y.layer === 0 && y.array.length <= 1) {
3172
- var yn = y.toNumber();
3173
- if (y.eq(2)) return x.cuboiter(x);
3174
- var result = base.clone();
3175
- result.layer = 1;
3176
- result.array = [[1]];
3177
- result.array.push([yn, 0, 1]);
3178
- result.normalize();
3179
- return result;
3842
+ var yc = metaFiniteCount(y);
3843
+ if (yc <= MAX_SAFE_INTEGER) {
3844
+ var m = Math.max(2, Math.floor(yc));
3845
+ if (m > MAX_SAFE_INTEGER) m = MAX_SAFE_INTEGER;
3846
+ return Q._layerMarker([10], 1, [[m, 0, 1]]);
3180
3847
  }
3181
- var result = y.clone();
3182
- result.layer = 1;
3183
- result.array[0] = base.array[0].slice();
3184
- result.array.push([1, 0, 1]);
3185
- result.normalize();
3186
- return result;
3848
+ // ordinal / out-of-range operand: y plus one ω^(ω+1) marker row
3849
+ return Q._ordinalOperandOp(y, 1, [1, 1, 1]);
3187
3850
  };
3188
3851
  Q.expoiter = Q.expo = Q.hwa1 = function (x, y) {
3189
3852
  return new MetaNum(x).expoiter(y);
@@ -3194,24 +3857,24 @@
3194
3857
  z = new MetaNum(z);
3195
3858
  if (x.isNaN() || z.isNaN()) return MetaNum.NaN.clone();
3196
3859
  if (x.array.length >= 2) {
3197
- // For ordinal y: find [1, 0, 1] marker and return y
3860
+ // marker [y,0,1] = 10{ω^ω·y}10 → the count carries y
3198
3861
  for (var i = x.array.length - 1; i >= 1; i--) {
3199
3862
  var row = x.array[i];
3200
- if (row.length >= 3 && row[1] === 0 && row[2] === 1 && row[0] === 1) {
3863
+ if (row.length === 3 && row[1] === 0 && row[2] === 1 && row[0] > 0) {
3864
+ return new MetaNum(row[0]);
3865
+ }
3866
+ }
3867
+ // For ordinal y: find [1, 0, 1] marker and return y
3868
+ for (var k = x.array.length - 1; k >= 1; k--) {
3869
+ var row2 = x.array[k];
3870
+ if (row2.length >= 3 && row2[1] === 0 && row2[2] === 1 && row2[0] === 1) {
3201
3871
  var result = x.clone();
3202
- result.array.splice(i, 1);
3872
+ result.array.splice(k, 1);
3203
3873
  result.normalize();
3204
3874
  if (result.array.length <= 1) result.layer = 0;
3205
3875
  return result;
3206
3876
  }
3207
3877
  }
3208
- // For finite y: find [yn, 0, 1] and return yn
3209
- for (var i = x.array.length - 1; i >= 1; i--) {
3210
- var row = x.array[i];
3211
- if (row.length === 3 && row[1] === 0 && row[2] === 1 && row[0] > 0) {
3212
- return new MetaNum(row[0]);
3213
- }
3214
- }
3215
3878
  }
3216
3879
  return z;
3217
3880
  };
@@ -3219,10 +3882,10 @@
3219
3882
  return new MetaNum(x).inv_expoiter(z);
3220
3883
  };
3221
3884
 
3222
- // trioterate (ω^(ω*2)): x{ω^(ω*2)}y = x{ω^(ω+y)}y
3223
- // for k <= MSI, tria(3,k)=3{ω^(ω+k)}k
3224
- // ≈10{ω^(ω+k)}k → layer=1, array=[[0],[1,k,1]]
3225
- // for k > MSI, tria(3,k)≈10{ω^(ω*2)}MSI → layer=1, array=[[0],[1,0,2]]
3885
+ // trioterate (ω^(ω*2)): (ω^(ω*2))[y] = ω^(ω+y) → x{ω^(ω*2)}y = x{ω^(ω+y)}x
3886
+ // for k <= MSI, tria(3,k)=3{ω^(ω+k)}3
3887
+ // ≈10{ω^(ω+k)}10 → layer=1, array=[[10],[1,k,1]] (ord = ω+k)
3888
+ // for k > MSI, tria(3,k)≈10{ω^(ω*2)}10 → layer=1, array=[[10],[1,0,2]]
3226
3889
  P.trioterate = P.tria = P.hwm2 = function (y) {
3227
3890
  var x = this.clone();
3228
3891
  y = new MetaNum(y);
@@ -3230,23 +3893,14 @@
3230
3893
  if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
3231
3894
  if (y.eq(MetaNum.ONE)) return x.clone();
3232
3895
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
3233
- if (y.layer === 0 && y.array.length <= 1) {
3234
- var yn = y.toNumber();
3235
- var base = x.expoiter(x);
3236
- if (y.eq(2)) return base;
3237
- var result = base.clone();
3238
- result.layer = 1;
3239
- result.array = [[1]];
3240
- result.array.push([1, yn, 1]);
3241
- result.normalize();
3242
- return result;
3896
+ var yc = metaFiniteCount(y);
3897
+ if (yc <= MAX_SAFE_INTEGER) {
3898
+ var m = Math.max(2, Math.floor(yc));
3899
+ if (m > MAX_SAFE_INTEGER) m = MAX_SAFE_INTEGER;
3900
+ return Q._layerMarker([10], 1, [[1, m, 1]]);
3243
3901
  }
3244
- var result = y.clone();
3245
- result.layer = 1;
3246
- var base = x.iter(x);
3247
- result.array[0] = base.array[0].slice();
3248
- result.normalize();
3249
- return result;
3902
+ // ordinal / out-of-range operand: y plus one ω^(ω*2) marker row
3903
+ return Q._ordinalOperandOp(y, 1, [1, 0, 2]);
3250
3904
  };
3251
3905
  Q.trioterate = Q.tria = Q.hwm2 = function (x, y) {
3252
3906
  return new MetaNum(x).trioterate(y);
@@ -3282,10 +3936,10 @@
3282
3936
  return new MetaNum(x).inv_trioterate(z);
3283
3937
  };
3284
3938
 
3285
- // trixxate (ω^(ω^2)): x{ω^(ω^2)}y=x{ω^(ω*y)}y
3286
- // for k <= MSI, trix(3,k)=3{ω^(ω*k)}k
3287
- // ≈10{ω^(ω*k)}k → layer=1, array=[[0],[1,0,k]]
3288
- // for k > MSI, trix(3,k)≈10{ω^(ω^2)}MSI → layer=1, array=[[0],[1,0,0,1]]
3939
+ // trixxate (ω^(ω^2)): (ω^(ω^2))[y] = ω^(ω*y) → x{ω^(ω^2)}y = x{ω^(ω*y)}x
3940
+ // for k <= MSI, trix(3,k)=3{ω^(ω*k)}3
3941
+ // ≈10{ω^(ω*k)}10 → layer=2, array=[[10],[k,1]] (bracket = ω*k, ω^bracket)
3942
+ // for k > MSI, trix(3,k)≈10{ω^(ω^2)}10 → layer=2, array=[[10],[1,2]]
3289
3943
  P.trixxate = P.trix = P.hwp2 = function (y) {
3290
3944
  var x = this.clone();
3291
3945
  y = new MetaNum(y);
@@ -3293,23 +3947,14 @@
3293
3947
  if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
3294
3948
  if (y.eq(MetaNum.ONE)) return x.clone();
3295
3949
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
3296
- if (y.layer === 0 && y.array.length <= 1) {
3297
- var yn = y.toNumber();
3298
- var base = x.trioterate(x);
3299
- if (y.eq(2)) return base;
3300
- var result = base.clone();
3301
- result.layer = 2;
3302
- result.array = [[1]];
3303
- result.array.push([1, yn, 1]);
3304
- result.normalize();
3305
- return result;
3950
+ var yc = metaFiniteCount(y);
3951
+ if (yc <= MAX_SAFE_INTEGER) {
3952
+ var m = Math.max(2, Math.floor(yc));
3953
+ if (m > MAX_SAFE_INTEGER) m = MAX_SAFE_INTEGER;
3954
+ return Q._layerMarker([10], 2, [[m, 1]]);
3306
3955
  }
3307
- var result = y.clone();
3308
- result.layer = 2;
3309
- var base = x.trioterate(x);
3310
- result.array[0] = base.array[0].slice();
3311
- result.normalize();
3312
- return result;
3956
+ // ordinal / out-of-range operand: y plus one ω^(ω^2) marker row
3957
+ return Q._ordinalOperandOp(y, 2, [1, 2]);
3313
3958
  };
3314
3959
  Q.trixxate = Q.trix = Q.hwp2 = function (x, y) {
3315
3960
  return new MetaNum(x).trixxate(y);
@@ -3319,6 +3964,12 @@
3319
3964
  var x = this.clone();
3320
3965
  z = new MetaNum(z);
3321
3966
  if (x.isNaN() || z.isNaN()) return MetaNum.NaN.clone();
3967
+ // standard marker [1,10,y] = 10{ω^(ω*y+10)}10 (layer 1) or [y,1] (layer 2)
3968
+ for (var k = x.array.length - 1; k >= 1; k--) {
3969
+ var rw = x.array[k];
3970
+ if (rw.length === 2 && rw[0] > 0 && rw[1] === 1) return new MetaNum(rw[0]);
3971
+ if (rw.length === 3 && rw[0] === 1 && rw[2] >= 2) return new MetaNum(rw[2]);
3972
+ }
3322
3973
  if (x.array.length >= 2) {
3323
3974
  // For ordinal y: find [1, 0, 1] marker and return y
3324
3975
  for (var i = x.array.length - 1; i >= 1; i--) {
@@ -3345,11 +3996,11 @@
3345
3996
  return new MetaNum(x).inv_trixxate(z);
3346
3997
  };
3347
3998
 
3348
- // aperixxate (ω^(ω^ω)): x{ω^(ω^ω)}y=x{ω^(ω^y)}y, can reach layer 2
3349
- // for k < maxCol-1, apix(3,k)≈10{ω^(ω^k)}k → layer=1, array=[[0],[1,0,0,...(k zeroes)...,0,1]]
3350
- // for maxCol-1 <= k <= MSI → layer=2, array=[[0],[1,k]]
3351
- // for k > MSI, apix(3,k)≈10{ω^(ω^2)}MSI → layer=2, array=[[0],[1,0,1]]
3352
- // Repetition count negligible for layer >= 2 (defaults to 1)
3999
+ // aperixxate (ω^(ω^ω)): (ω^(ω^ω))[y] = ω^(ω^y) → x{ω^(ω^ω)}y = x{ω^(ω^y)}x
4000
+ // for k <= MSI, apix(3,k)=3{ω^(ω^k)}3
4001
+ // ≈10{ω^(ω^k)}10 → layer=3, array=[[k]] (bracket = the constant k, so the
4002
+ // ordinal reads ω^(ω^k)); layer 3 is the ω^(ω^ω) level (README).
4003
+ // for k > MSI, apix(3,k)≈10{ω^(ω^ω)}10 → layer=3, array=[[10],[1,1]]
3353
4004
  P.aperixxate = P.apix = P.hwpw = function (y) {
3354
4005
  var x = this.clone();
3355
4006
  y = new MetaNum(y);
@@ -3357,23 +4008,14 @@
3357
4008
  if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
3358
4009
  if (y.eq(MetaNum.ONE)) return x.clone();
3359
4010
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
3360
- if (y.layer === 0 && y.array.length <= 1) {
3361
- var yn = y.toNumber();
3362
- var base = x.trixxate(x);
3363
- if (y.eq(2)) return base;
3364
- var result = base.clone();
3365
- result.layer = 3;
3366
- result.array = [[1]];
3367
- result.array.push([1, yn, 1]);
3368
- result.normalize();
3369
- return result;
4011
+ var yc = metaFiniteCount(y);
4012
+ if (yc <= MAX_SAFE_INTEGER) {
4013
+ var m = Math.max(2, Math.floor(yc));
4014
+ if (m > MAX_SAFE_INTEGER) m = MAX_SAFE_INTEGER;
4015
+ return Q._layerMarker([m], 3, []);
3370
4016
  }
3371
- var result = y.clone();
3372
- result.layer = 3;
3373
- var base = x.trixxate(x);
3374
- result.array[0] = base.array[0].slice();
3375
- result.normalize();
3376
- return result;
4017
+ // ordinal / out-of-range operand: y plus one ω^(ω^ω) marker row
4018
+ return Q._ordinalOperandOp(y, 3, [1, 1]);
3377
4019
  };
3378
4020
  Q.aperixxate = Q.apix = Q.hwpw = function (x, y) {
3379
4021
  return new MetaNum(x).aperixxate(y);
@@ -3383,6 +4025,24 @@
3383
4025
  var x = this.clone();
3384
4026
  z = new MetaNum(z);
3385
4027
  if (x.isNaN() || z.isNaN()) return MetaNum.NaN.clone();
4028
+ // standard marker [[10],[1,0,…,0,1]] = 10{ω^(ω^y)}10 → y+1 zeros-and-one
4029
+ // row length (layer 1), or the layer-≥2 merged form r0 = [...,1@y]
4030
+ for (var k = x.array.length - 1; k >= 1; k--) {
4031
+ var rw = x.array[k];
4032
+ if (rw.length >= 3 && rw[0] === 1 && rw[rw.length - 1] === 1) {
4033
+ var zeros = 0;
4034
+ for (var j = 1; j < rw.length - 1; j++) {
4035
+ if ((rw[j] || 0) === 0) zeros++; else break;
4036
+ }
4037
+ if (zeros === rw.length - 2 && zeros > 0) return new MetaNum(zeros);
4038
+ }
4039
+ }
4040
+ if (x.layer >= 2 && x.array.length === 1) {
4041
+ var rr = x.array[0];
4042
+ for (var j2 = rr.length - 1; j2 >= 1; j2--) {
4043
+ if ((rr[j2] || 0) > 0) return new MetaNum(j2);
4044
+ }
4045
+ }
3386
4046
  if (x.array.length >= 2) {
3387
4047
  // For ordinal y: find [1, 0, 1] marker and return y
3388
4048
  for (var i = x.array.length - 1; i >= 1; i--) {
@@ -3409,8 +4069,11 @@
3409
4069
  return new MetaNum(x).inv_aperixxate(z);
3410
4070
  };
3411
4071
 
3412
- // epsilonate (ε₀ = ω↑↑ω): x{ε₀}y=x{ω^ω^...(y ω's)}y
3413
- // layer varies with y
4072
+ // epsilonate (ε₀ = ω↑↑ω): ε₀[y] = ω^ω^…(y ω's) → x{ε₀}y = x{ω↑↑y}x
4073
+ // layer = y (README L17: layer L holds an ω-tower of height L), so
4074
+ // epsl(3,k) ≈ 10{ω^ω^…^ω(k ω's)}10 → layer=k, array=[[10],[1,1]]
4075
+ // (bracket = ω, (k-1) ω^'s above it → a tower of k ω's).
4076
+ // k > MSI → the ε-tower cap: layer=MSI (the MetaNum limit).
3414
4077
  P.epsilonate = P.epsl = P.hepsl = function (y) {
3415
4078
  var x = this.clone();
3416
4079
  y = new MetaNum(y);
@@ -3418,23 +4081,17 @@
3418
4081
  if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
3419
4082
  if (y.eq(MetaNum.ONE)) return x.clone();
3420
4083
  if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
3421
- if (y.layer === 0 && y.array.length <= 1) {
3422
- var yn = y.toNumber();
3423
- var base = x.aperixxate(x);
3424
- if (y.eq(2)) return base;
3425
- var result = base.clone();
3426
- result.layer = yn;
3427
- result.array = [[1]];
3428
- result.array.push([1, yn, 1]);
3429
- result.normalize();
3430
- return result;
3431
- }
3432
- var result = y.clone();
3433
- result.layer = y.layer;
3434
- var base = x.aperixxate(x);
3435
- result.array[0] = base.array[0].slice();
3436
- result.normalize();
3437
- return result;
4084
+ // ε₀[2] = ω^ω, so epsilonate(x,2) = x{ω^ω}x = iterate(x,x) exactly (the
4085
+ // same value itermult(x,2) produces — x{ε₀}2 = x{ω^ω+1}2).
4086
+ if (y.eq(2)) return x.iterate(x);
4087
+ var yc = metaFiniteCount(y);
4088
+ if (yc <= MAX_SAFE_INTEGER) {
4089
+ var m = Math.max(2, Math.floor(yc));
4090
+ if (m > MAX_SAFE_INTEGER) m = MAX_SAFE_INTEGER;
4091
+ return Q._layerMarker([10], m, [[1, 1]]);
4092
+ }
4093
+ // ordinal / out-of-range operand: ε₀ caps the library → the MSI ω-tower
4094
+ return Q._layerMarker([10], MAX_SAFE_INTEGER, [[1, 1]]);
3438
4095
  };
3439
4096
  Q.epsilonate = Q.epsl = Q.hepsl = function (x, y) {
3440
4097
  return new MetaNum(x).epsilonate(y);
@@ -3444,6 +4101,15 @@
3444
4101
  var x = this.clone();
3445
4102
  z = new MetaNum(z);
3446
4103
  if (x.isNaN() || z.isNaN()) return MetaNum.NaN.clone();
4104
+ // standard marker: layer = y-1 with the de-layered tower row [1,10,1]
4105
+ if (x.layer >= 1) {
4106
+ for (var k = x.array.length - 1; k >= 1; k--) {
4107
+ var rw = x.array[k];
4108
+ if (rw.length === 3 && rw[0] === 1 && rw[2] === 1 && (rw[1] || 0) >= 2) {
4109
+ return new MetaNum(x.layer + 1);
4110
+ }
4111
+ }
4112
+ }
3447
4113
  if (x.array.length >= 2) {
3448
4114
  // For ordinal y: find [1, 0, 1] marker and return y
3449
4115
  for (var i = x.array.length - 1; i >= 1; i--) {
@@ -3867,17 +4533,19 @@
3867
4533
  var lastRow = this.array[this.array.length - 1];
3868
4534
  return lastRow[0] + "Aa" + lastRow[1];
3869
4535
  }
3870
- // Non-truncated: show all rows
4536
+ // Non-truncated: show all rows as space-separated "countAalevel"
4537
+ // tokens (count always included, so the parser can re-split them)
3871
4538
  var tokens = [];
3872
4539
  for (var i = this.array.length - 1; i >= 1; i--) {
3873
4540
  var row = this.array[i];
3874
- var tok = row[0] > 1 ? row[0] + "Aa" + row[1] : "Aa" + row[1];
3875
- tokens.push(tok);
4541
+ tokens.push(row[0] + "Aa" + row[1]);
3876
4542
  }
3877
4543
  var finOps = formatFiniteOps(this.array[0]);
3878
4544
  var hasAa = finOps && finOps.indexOf("Aa") !== -1;
3879
4545
  var baseNum = hasAa ? "" : decimalPlaces(this.array[0][0], 6);
3880
- return tokens.join("") + (finOps ? finOps : "") + baseNum;
4546
+ var tokStr = tokens.join(" ");
4547
+ if (tokStr !== "" && (finOps !== "" || baseNum !== "")) tokStr += " ";
4548
+ return tokStr + (finOps ? finOps : "") + baseNum;
3881
4549
  }
3882
4550
 
3883
4551
  var ordTokens = [];
@@ -3971,6 +4639,19 @@
3971
4639
  return this.toString();
3972
4640
  };
3973
4641
 
4642
+ // dlsdl letter-notation formatting (format-metanum.js, README "Format"
4643
+ // section). The module is resolved lazily to avoid a circular require:
4644
+ // format-metanum reads the MetaNum constructor from the global scope.
4645
+ // MetaNum("G600").format() → "1.000G600"
4646
+ // MetaNum.hardy(4166).format() → "2.397G5"
4647
+ P.format = function (precision, small) {
4648
+ var formatter = null;
4649
+ if (typeof require == 'function') {
4650
+ try { formatter = require('./format-metanum.js').format; } catch (e) { formatter = null; }
4651
+ }
4652
+ return format(this, precision, small);
4653
+ };
4654
+
3974
4655
  P.toExponential = function (places) {
3975
4656
  if (this.sign === -1 || this.sign === -2) return "-" + this.abs().toExponential(places);
3976
4657
  if (this.isNaN()) return "NaN";
@@ -4036,7 +4717,7 @@
4036
4717
  else x.sign = sign < 0 ? -1 : 1;
4037
4718
  } else x.sign = 1;
4038
4719
  if (typeof layer === "number" && isFinite(layer) && layer >= 0) x.layer = Math.floor(layer);
4039
- else x.layer = computeLayer(x.array);
4720
+ else x.layer = 0;
4040
4721
  return x.normalize();
4041
4722
  };
4042
4723
 
@@ -4626,14 +5307,16 @@
4626
5307
  cCount = parseInt(chainTokM[2], 10);
4627
5308
  for (var cli = 0; cli < cLetters.length; cli++) {
4628
5309
  var clLevel = cLetters.charCodeAt(cli) - 68; // E->1, F->2, ...
4629
- if (clLevel < 1 || clLevel >= MetaNum.maxCols - 1) { chainOk = false; break; }
5310
+ if (clLevel < 1 || clLevel > 99) { chainOk = false; break; }
4630
5311
  chainFin[clLevel] = (chainFin[clLevel] || 0) + (cli === cLetters.length - 1 ? cCount : 1);
4631
5312
  }
4632
5313
  if (!chainOk) break;
4633
5314
  } else {
4634
5315
  cLevel = parseInt(chainTokM[4], 10);
4635
5316
  cCount = parseInt(chainTokM[3], 10);
4636
- if (cLevel < 1 || cLevel >= MetaNum.maxCols - 1) { chainOk = false; break; }
5317
+ // Levels beyond maxCols are fine: normalize converts the r0
5318
+ // overflow into finite-level ordinal rows [count, level]
5319
+ if (cLevel < 1 || cLevel > 99) { chainOk = false; break; }
4637
5320
  chainFin[cLevel] = (chainFin[cLevel] || 0) + cCount;
4638
5321
  }
4639
5322
  }
@@ -4641,7 +5324,7 @@
4641
5324
  var chainCompact = chainMatch[3] || "";
4642
5325
  for (var cci = 0; cci < chainCompact.length && chainOk; cci++) {
4643
5326
  var cclLevel = chainCompact.charCodeAt(cci) - 68;
4644
- if (cclLevel >= 1 && cclLevel < MetaNum.maxCols - 1) {
5327
+ if (cclLevel >= 1 && cclLevel <= 99) {
4645
5328
  chainFin[cclLevel] = (chainFin[cclLevel] || 0) + 1;
4646
5329
  }
4647
5330
  }
@@ -4728,6 +5411,56 @@
4728
5411
  }
4729
5412
  }
4730
5413
 
5414
+ // Stacked layer symbols: peel the outermost symbol and add its layer
5415
+ // to the parsed remainder ("@!2.000Aaaa10" = parse of !form at one
5416
+ // higher layer).
5417
+ var stackedSym = rem.match(/^([!@#\$%&~<>?])([!@#\$%&~<>?]+\S*)$/);
5418
+ if (stackedSym) {
5419
+ var innerS = Q.fromString(stackedSym[2]);
5420
+ // each outer symbol is exactly one more ω^-tower layer
5421
+ innerS.layer = (innerS.layer || 0) + 1;
5422
+ if (negateIt) innerS.sign = -1;
5423
+ return innerS.normalize();
5424
+ }
5425
+
5426
+ // Canonical diagonal-letter output "mantissa LETTER β" where LETTER is
5427
+ // any multi-letter token ending in 'a' (Aa, Ba, Aaa, Aaaa, …), with the
5428
+ // dlsdl diagonal mantissa α ∈ [2,10):
5429
+ // exact anchor α=2.000 -> the plain letter application LETTER(β)
5430
+ // (2·5^0=2 adds nothing);
5431
+ // fractional α -> compact smooth row [α, β] (r0=[1]), the same
5432
+ // representation the engine emits for 10{β}(structured counts).
5433
+ var diagBinMatch = rem.match(/^([!@#\$%&~<>?]?)(\d+\.\d+)([A-Z][a-z]+)(\d[\d,]*)\s*$/);
5434
+ if (diagBinMatch) {
5435
+ var dbSym = diagBinMatch[1];
5436
+ var dbMant = Number(diagBinMatch[2]);
5437
+ var dbTok = diagBinMatch[3];
5438
+ var dbBeta = Number(String(diagBinMatch[4]).replace(/,/g, ""));
5439
+ if (isFinite(dbMant) && isFinite(dbBeta) &&
5440
+ dbTok[dbTok.length - 1] === "a" && dbMant >= 2 && dbMant < 10) {
5441
+ var dbVal;
5442
+ if (Math.abs(dbMant - 2) < 1e-9) {
5443
+ dbVal = Q.fromString(dbSym + dbTok + String(dbBeta));
5444
+ } else {
5445
+ // compact smooth form 10{β+1}(α): row [α, β] with r0=[1]
5446
+ dbVal = new MetaNum({ sign: 1, layer: 0, array: [[1], [dbMant, dbBeta]] });
5447
+ dbVal.normalize();
5448
+ if (dbSym) {
5449
+ dbVal.layer = "!@#$%&~<>?".indexOf(dbSym) + 1;
5450
+ dbVal.normalize();
5451
+ }
5452
+ }
5453
+ if (negateIt) dbVal.sign = -1;
5454
+ return dbVal;
5455
+ }
5456
+ }
5457
+
5458
+ // Binary-form α prefix with α = 1.000 exactly: Γ(β + log 1) = Γβ, so the
5459
+ // mantissa carries no information and can be stripped before matching
5460
+ // (e.g. "!1.000Aa5" ≡ "!Aa5", "1.000F300" ≡ "F300"). Non-unit α needs
5461
+ // the fractional-argument machinery and is not accepted here.
5462
+ rem = rem.replace(/^([!@#\$%&~<>?]?)1\.0+(?=[A-Z])/, '$1');
5463
+
4731
5464
  // Handle layer symbol prefix + letter pattern + optional finOps + number (e.g., !Abcd1234, !AaE16, @Bcde500)
4732
5465
  var symPrefixMatch = rem.match(/^([!@#\$%&~<>?])([A-Z][a-z]+(?:[A-Z][a-z]+)*)([A-Z]*)(\d+)\s*$/);
4733
5466
  if (symPrefixMatch) {
@@ -4737,12 +5470,17 @@
4737
5470
  rem = symPrefixMatch[2] + (symPrefixMatch[3] || '') + symPrefixMatch[4];
4738
5471
  }
4739
5472
 
4740
- var oaMatch = rem.match(/^((?:[A-Z][a-z]+)+)([A-Z]*)(\d+)/);
5473
+ // Ordinal-prefix chain with a full number argument — the argument may be
5474
+ // a plain integer ("AaG5"), a decimal ("AaG5.5"), or a sci-notation value
5475
+ // ("AaGF7.626E12", the round-trip of format() displays like "AaGF7.626E12"
5476
+ // whose letter chain carries a huge finite-arg). The old (\d+) regex ate
5477
+ // only "7" and silently dropped ".626E12".
5478
+ var oaMatch = rem.match(/^((?:[A-Z][a-z]+)+)([A-Z]*)((?:\d+(?:\.\d+)?(?:[Ee]\d+)?))$/);
4741
5479
  if (oaMatch) {
4742
5480
  var oaFullPrefix = oaMatch[1];
4743
5481
  var oaFinOps = oaMatch[2];
4744
5482
  var oaN = Number(oaMatch[3]);
4745
- if (!isNaN(oaN) && isFinite(oaN) && oaN >= 1 && oaN === Math.floor(oaN)) {
5483
+ if (!isNaN(oaN) && isFinite(oaN) && oaN >= 0) {
4746
5484
  var oaTokens = [];
4747
5485
  var oaTokenRegex = /[A-Z][a-z]+/g;
4748
5486
  var oaTm;
@@ -4925,9 +5663,9 @@
4925
5663
 
4926
5664
 
4927
5665
  // ==================== BEAF Ordinal Helpers ====================
4928
- // Build ordinal coefficient array from BEAF args (each arg contributes arg-1):
4929
- // BEAF(a,b,c,d,e,f,...) = a{...+ω^3*(f-1)+ω^2*(e-1)+ω*(d-1)+(c-1)}b
4930
- // coeffs[0] = c-1 (ω^0 = constant term)
5666
+ // Build ordinal coefficient array from BEAF args:
5667
+ // BEAF(a,b,c,d,e,f,...) = a{...+ω^3*(f-1)+ω^2*(e-1)+ω*(d-1)+c}b
5668
+ // coeffs[0] = c (ω^0 = constant term, no decrement)
4931
5669
  // coeffs[1] = d-1 (ω^1 coefficient)
4932
5670
  // coeffs[2] = e-1 (ω^2 coefficient)
4933
5671
  // coeffs[3] = f-1 (ω^3 coefficient)
@@ -4947,7 +5685,8 @@
4947
5685
  hugeArgs.push(arg.clone());
4948
5686
  coeffs.push(Infinity);
4949
5687
  } else {
4950
- coeffs.push(Math.max(0, Math.floor(eff) - 1));
5688
+ // constant term (i=2) keeps its value; ω^k coefficients (i>=3) decrement
5689
+ coeffs.push(i === 2 ? Math.max(0, Math.floor(eff)) : Math.max(0, Math.floor(eff) - 1));
4951
5690
  }
4952
5691
  }
4953
5692
  return { coeffs: coeffs, hugeArgs: hugeArgs };
@@ -4972,7 +5711,7 @@
4972
5711
  var cf = trimCoeffs(coeffs.map(function (c) { return Math.max(0, Math.floor(c)); }));
4973
5712
  if (cf.length === 0) return a.pow(b); // level 0 → a^b (b arg is the level-1 op)
4974
5713
  if (!coeffsHaveOmegaPart(cf)) return a.arrow(cf[0])(b); // finite level c
4975
- return Q._ordinalHyperop(a, b, cf);
5714
+ return Q._applyExpansionTruncation(Q._ordinalHyperop(a, b, cf));
4976
5715
  }
4977
5716
  // collapse at the highest huge coefficient: coeffs[iHuge+1] += 1, zero the rest below
4978
5717
  var cf = coeffs.slice();
@@ -4983,7 +5722,183 @@
4983
5722
  // anchor: the largest operand dominates (right-to-left composition)
4984
5723
  var anchor = a.max(b);
4985
5724
  for (var j = 0; j < (hugeArgs || []).length; j++) anchor = anchor.max(hugeArgs[j]);
4986
- return Q._applyOrdinalRows(anchor, cf, 1);
5725
+ return Q._applyExpansionTruncation(Q._applyOrdinalRows(anchor, cf, 1));
5726
+ };
5727
+
5728
+ // ==================== Hardy Hierarchy ====================
5729
+ // H_α(n) via transfinite recursion (issues.md / README):
5730
+ // H_0(n) = n
5731
+ // H_{α+1}(n) = H_α(n+1) (successor step: only +1, never iterated)
5732
+ // H_λ(n) = H_{λ[n]}(n) (limit step: CNF fundamental sequence at n)
5733
+ // where λ[n] acts on the lowest limit term: (… + ω^j·c_j)[n] = … + ω^j·(c_j−1)
5734
+ // + ω^{j−1}·n. Closed forms keep the recursion finite:
5735
+ // H_{β+c}(n) = H_β(n+c) (c successor steps)
5736
+ // H_{β+ω·c}(n) = H_β(n·2^c) (c ω-level limit steps)
5737
+ // For ω^j·c segments with c beyond the exact-iteration bound (j ≥ 2) the
5738
+ // value collapses into the hyperoperation engine, mirroring the classic
5739
+ // identity F_j = H^{ω^j} (F_2(n)=n·2^n, F_3(n)≈2↑↑n, …):
5740
+ // H_{β+ω^j·c}(n) ≈ H_β(2{c}^j) i.e. 2.arrow(j)(c)
5741
+ var HARDY_EXACT_BOUND = 50;
5742
+ // H_α(n) — ITERATIVE (the original tail recursion grew hundreds of frames
5743
+ // deep for inputs like hardy(1e10+20) where n1≈40 makes every ω^j segment
5744
+ // take the exact branch: Maximum call stack size exceeded).
5745
+ Q._hardyH = function (coeffs, nArg) {
5746
+ function MN(v) { return (v instanceof MetaNum) ? v.clone() : new MetaNum(v || 0); }
5747
+ var c = [];
5748
+ for (var i0 = 0; i0 < coeffs.length; i0++) c.push(MN(coeffs[i0]));
5749
+ var n = MN(nArg);
5750
+ var guard2 = 200000;
5751
+ // The exact limit-step expansion is only feasible while the running base n
5752
+ // stays a small plain integer; once n is structured (or the step budget is
5753
+ // exhausted) the nested expansion would take ~n^degree steps, so take the
5754
+ // same supremum collapse the engine uses above HARDY_EXACT_BOUND.
5755
+ function nIsSmallPlain() {
5756
+ if (n.layer !== 0 || n.array.length !== 1) return false;
5757
+ var nv = n.toNumber();
5758
+ return isFinite(nv) && nv === Math.floor(nv) && Math.abs(nv) <= HARDY_EXACT_BOUND;
5759
+ }
5760
+ while (--guard2 >= 0) {
5761
+ while (c.length > 0 && c[c.length - 1].eq(MetaNum.ZERO)) c.pop();
5762
+ if (c.length === 0) return n; // H_0(n) = n
5763
+ if (c.length === 1) return n.add(c[0]); // H_c(n) = n + c
5764
+ if (c[0].gt(MetaNum.ZERO)) { // successor strip
5765
+ n = n.add(c[0]);
5766
+ c[0] = MetaNum.ZERO.clone();
5767
+ continue;
5768
+ }
5769
+ var j = 1;
5770
+ while (j < c.length && !c[j].gt(MetaNum.ZERO)) j++;
5771
+ if (j === 1) { // ω-segment closed form
5772
+ // H_{β + ω·c1}(n) = H_β(n · 2^{c1}) — evaluate with the OLD c1
5773
+ var nWf = n.mul(new MetaNum(2).pow(c[1]));
5774
+ var beta = [MetaNum.ZERO.clone(), MetaNum.ZERO.clone()];
5775
+ for (var k = 2; k < c.length; k++) beta.push(c[k]);
5776
+ c = beta;
5777
+ n = nWf;
5778
+ continue;
5779
+ }
5780
+ if (c[j].gt(HARDY_EXACT_BOUND)) { // engine collapse
5781
+ // H_{β + ω^j·c}(n) ≈ H_β(2{c}j) — evaluate with the OLD c[j]
5782
+ var nCol = new MetaNum(2).arrow(j)(c[j]);
5783
+ var beta2 = [MetaNum.ZERO.clone()];
5784
+ for (var k2 = 0; k2 < j; k2++) beta2.push(MetaNum.ZERO.clone());
5785
+ for (var k3 = j + 1; k3 < c.length; k3++) beta2.push(c[k3]);
5786
+ c = beta2;
5787
+ n = nCol;
5788
+ continue;
5789
+ }
5790
+ // exact limit step on ω^j·c_j: c_j-=1, c_{j-1}=n
5791
+ c[j] = c[j].sub(MetaNum.ONE);
5792
+ c[j - 1] = n.clone();
5793
+ }
5794
+ // budget exhausted: keep whatever was accumulated (monotone)
5795
+ return n;
5796
+ };
5797
+
5798
+ // MetaNum.hardy(n): the Hardy level of n.
5799
+ // n < 10 → 10 + n; otherwise the decimal digits of n become the CNF
5800
+ // coefficients of an ordinal α (hardy(1234) = H_{ω³+ω²·2+ω·3+4}(10)) and
5801
+ // the result is H_α(10).
5802
+ Q.hardy = function (n) {
5803
+ n = new MetaNum(n);
5804
+ if (n.sign !== 1) {
5805
+ throw Error(metaNumError + 'hardy: n must be a non-negative integer');
5806
+ }
5807
+ // v2.1 (issues.md): MetaNum-object input. Values beyond double range or
5808
+ // carrying ordinal rows/layers read their STRUCTURE as the ordinal:
5809
+ // a power tower 10^^k shadows to ω^ω^…^ω (k ω's), and H there is the
5810
+ // engine diagonal 10{ω^ω^…^ω(k ω's)}10 = 10.epsilonate(k) — so
5811
+ // hardy(10^^MSI) = the MetaNum limit exactly (slog(10^^MSI) = MSI).
5812
+ // Ordinal-row / ε-layer values sit at their own Hardy position
5813
+ // (H_{ω^β}(10) = 10{β}10) and map to themselves.
5814
+ var num = (n.layer === 0 && n.array.length === 1) ? n.toNumber() : Infinity;
5815
+ if (!isFinite(num)) {
5816
+ if (n.layer === 0 && n.array.length === 1) {
5817
+ var hVal = n.slog();
5818
+ // a clean power tower shadows to ω^ω^…^ω (k ω's); slog(10^^k) = [[k]]
5819
+ // (a plain single number — NOT the structured slog of, say, G600)
5820
+ if (hVal.layer === 0 && hVal.array.length === 1 && hVal.array[0].length === 1) {
5821
+ var hNum = hVal.toNumber();
5822
+ if (isFinite(hNum) && hNum >= 2 && hNum <= Number.MAX_SAFE_INTEGER) {
5823
+ // k ≤ MSI: the tower fits the engine limit (f_ε₀); k > MSI is
5824
+ // beyond ε₀ and the Hardy hierarchy is undefined there → Infinity
5825
+ return MetaNum.TEN.epsilonate(hNum).normalize();
5826
+ }
5827
+ }
5828
+ // layer-0 value beyond a clean 10^^k with k ≤ MSI: finite
5829
+ // hyperoperations above tetration (G600, 3{9}3, …) or a tower taller
5830
+ // than 10^^MSI exceed the library's ε₀ ceiling → Infinity
5831
+ return new MetaNum(Infinity);
5832
+ }
5833
+ // ordinal-row / ε-layer / letter-chain values sit at their own Hardy
5834
+ // position (H_{ω^β}(10) = 10{β}10): map to themselves
5835
+ return n.clone().normalize();
5836
+ }
5837
+ var s = String(num);
5838
+ // > 1e20 arrives in scientific notation ('1e+21') — expand to the exact
5839
+ // decimal digits so the digit-reading stays monotone (issues.md v2.1:
5840
+ // hardy must support > 1e15 inputs)
5841
+ var eMatch = s.match(/^(\d)(?:\.(\d+))?e\+?(\d+)$/);
5842
+ if (eMatch) {
5843
+ var eFrac = eMatch[2] || '';
5844
+ var eZeros = Number(eMatch[3]) - eFrac.length;
5845
+ if (eZeros > 0) s = eMatch[1] + eFrac + '0'.repeat(eZeros);
5846
+ }
5847
+ if (s.length >= 11) {
5848
+ // n ≥ 1e10 (issues.md v2.0): the ordinal is built per definition, then
5849
+ // evaluated from below on the engine's own representation:
5850
+ // n = dk·10^kExp + rest → α = ω^ord(kExp)·dk + ord(rest)
5851
+ // H_α(10) = H_{ω^ord(kExp)·dk}(H_ord(rest)(10)) — the lower part acts
5852
+ // first: n1 = H_ord(rest)(10) (recursive, exact path for rest < 1e10).
5853
+ // n1 = H_rest(10) becomes the fundamental-sequence argument of the
5854
+ // leading term:
5855
+ // kExp = 10 (ord = ω): H_{ω^ω·dk}(n1) = H_{ω^n1}(n1) exact (first
5856
+ // segment), the remaining dk−1 ω^ω-segments each add one ω-row —
5857
+ // hardy(1e10) = H_{ω^10}(10) = [3086.036065328153, 9×8] EXACTLY,
5858
+ // strictly below 10{10}10 (issues.md);
5859
+ // kExp ≥ 11 (ord = ω+c): mirror the engine's own ordinal rows for
5860
+ // 10{ω+c}(9+dk) on the from-below base H_{ω^n1}(n1) — hardy(1e11)
5861
+ // = H_{ω^(ω+1)}(10) keeps expande(10,10)'s row structure with the
5862
+ // strictly smaller definitional base, so hardy(1e11) < 10{ω+1}10
5863
+ // (issues.md).
5864
+ var kExp = s.length - 1;
5865
+ var dk = s.charCodeAt(0) - 48;
5866
+ var restNum = Number(s.slice(1));
5867
+ var n1 = MetaNum.TEN.clone();
5868
+ if (restNum > 0) n1 = Q.hardy(restNum);
5869
+ // from-below base: H_{ω^n1}(n1) — exact for small finite n1, one
5870
+ // ω-diagonal row (engine convention) for huge n1
5871
+ var base;
5872
+ var n1Num = (n1.array.length === 1 && n1.layer === 0) ? n1.toNumber() : Infinity;
5873
+ if (isFinite(n1Num) && n1Num === Math.floor(n1Num) && n1Num >= 2 && n1Num <= 100) {
5874
+ var ec = [];
5875
+ for (var zi = 0; zi < n1Num; zi++) ec.push(0);
5876
+ ec.push(1);
5877
+ base = Q._hardyH(ec, n1);
5878
+ } else {
5879
+ base = Q._applyOrdinalRows(n1, [0, 1], 1);
5880
+ }
5881
+ if (kExp === 10) {
5882
+ return Q._applyOrdinalRows(base, [0, 1], dk - 1).normalize();
5883
+ }
5884
+ // kExp ≥ 11 (ord = ω+c): mirror the engine's own ordinal rows for
5885
+ // 10{ω+c}(9+dk) onto the from-below base — hardy(1e11) keeps
5886
+ // expande(10,10)'s row structure with the strictly smaller
5887
+ // definitional base, so hardy(1e11) < 10{ω+1}10 (issues.md)
5888
+ var ks = String(kExp);
5889
+ var ordCoeffs = [];
5890
+ for (var oi = ks.length - 1; oi >= 0; oi--) ordCoeffs.push(ks.charCodeAt(oi) - 48);
5891
+ var mir = Q._hyperopFromOrdinalRaw(MetaNum.TEN.clone(), new MetaNum(9 + dk), ordCoeffs);
5892
+ var out = base.clone();
5893
+ for (var ri = 1; ri < mir.array.length; ri++) {
5894
+ out = Q._applyOrdinalRows(out, mir.array[ri].slice(1), mir.array[ri][0]);
5895
+ }
5896
+ return out.normalize();
5897
+ }
5898
+ if (num < 10) return new MetaNum(10 + num);
5899
+ var coeffs = [];
5900
+ for (var i = s.length - 1; i >= 0; i--) coeffs.push(s.charCodeAt(i) - 48);
5901
+ return Q._hardyH(coeffs, MetaNum.TEN.clone());
4987
5902
  };
4988
5903
 
4989
5904
  // ==================== BEAF Array Notation ====================
@@ -5019,7 +5934,7 @@
5019
5934
  var cNum = c.toNumber();
5020
5935
  if (isFinite(cNum)) {
5021
5936
  // any finite integer level: arrow() covers small, compact ordinal-row
5022
- // (level ≥ maxCols) and the ≥ maxArrow approximation branches
5937
+ // (level ≥ maxCols) approximation branches
5023
5938
  return args[0].arrow(cNum)(args[1]);
5024
5939
  }
5025
5940
  }
@@ -5116,7 +6031,7 @@
5116
6031
  if (allNonNegative) {
5117
6032
  var a = decimalPlaces(x.array[0][0], 6);
5118
6033
  // Reconstruct BEAF: {a, ?, c, d, e, ...} from ordinal row [1, c, d, e, ..., 1]
5119
- // (raw coefficient convention: BEAF(a,b,c,d,...) = a{...+ω*d+c}b)
6034
+ // (issues.md convention: BEAF(a,b,c,d,...) = a{...+ω*(d-1)+c}b)
5120
6035
  var beafParts = [a, '?'];
5121
6036
  for (var i = 0; i < vals.length; i++) {
5122
6037
  beafParts.push(String(vals[i]));
@@ -5312,7 +6227,7 @@
5312
6227
 
5313
6228
  if (obj === void 0) obj = {};
5314
6229
  if (obj) {
5315
- ps = ['maxRows', 'maxCols', 'maxArrow', 'serializeMode', 'debug'];
6230
+ ps = ['maxRows', 'maxCols', 'serializeMode', 'debug'];
5316
6231
  for (i = 0; i < ps.length;) if (!obj.hasOwnProperty(p = ps[i++])) obj[p] = this[p];
5317
6232
  }
5318
6233
 
@@ -5322,6 +6237,27 @@
5322
6237
  }
5323
6238
 
5324
6239
  function defineConstants(obj) {
6240
+ // maxRows / maxCols are clamped to [10, 1000] on every write, direct or
6241
+ // through config() — outside the range the array structures lose their
6242
+ // invariants (r0 diagonal needs ≥ 2 levels, row budgets exceed the
6243
+ // ordinal-row machinery).
6244
+ if (Object.defineProperty) {
6245
+ ['maxRows', 'maxCols'].forEach(function (p) {
6246
+ var store = obj[p];
6247
+ Object.defineProperty(obj, p, {
6248
+ configurable: true,
6249
+ enumerable: true,
6250
+ get: function () { return store; },
6251
+ set: function (v) {
6252
+ var n = Math.floor(Number(v));
6253
+ if (!isFinite(n)) return;
6254
+ if (n < 10) n = 10;
6255
+ if (n > 1000) n = 1000;
6256
+ store = n;
6257
+ }
6258
+ });
6259
+ });
6260
+ }
5325
6261
  for (var prop in R) {
5326
6262
  if (R.hasOwnProperty(prop)) {
5327
6263
  var val = R[prop];
@@ -5350,7 +6286,6 @@
5350
6286
  ps = [
5351
6287
  'maxRows', 10, 1000,
5352
6288
  'maxCols', 10, 1000,
5353
- 'maxArrow', 1, Number.MAX_SAFE_INTEGER,
5354
6289
  'serializeMode', 0, 1,
5355
6290
  'debug', 0, 2
5356
6291
  ];