metanum 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -11
- package/format-metanum.js +131 -88
- package/metanum.js +240 -210
- package/package.json +1 -1
- package/test_mixed.js +273 -1
package/metanum.js
CHANGED
|
@@ -2916,7 +2916,7 @@
|
|
|
2916
2916
|
// enumeration representation (one row per ordinal below α, count = y-2)
|
|
2917
2917
|
// - everything else (any operand beyond MSI, x = 2, or enumeration too large):
|
|
2918
2918
|
// unified ordinal engine (README rules 1-4)
|
|
2919
|
-
Q._hyperopFromOrdinalRaw = function (x, y, coeffs) {
|
|
2919
|
+
Q._hyperopFromOrdinalRaw = function (x, y, coeffs, skipFrac) {
|
|
2920
2920
|
x = new MetaNum(x);
|
|
2921
2921
|
y = new MetaNum(y);
|
|
2922
2922
|
if (x.isNaN() || y.isNaN()) return MetaNum.NaN.clone();
|
|
@@ -2924,8 +2924,29 @@
|
|
|
2924
2924
|
if (y.lte(MetaNum.ZERO)) return MetaNum.NaN.clone();
|
|
2925
2925
|
if (x.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
|
|
2926
2926
|
if (y.eq(MetaNum.ONE)) return x.clone();
|
|
2927
|
+
|
|
2927
2928
|
var cf0 = trimCoeffs((coeffs || []).slice());
|
|
2928
2929
|
if (cf0.length === 0) return x.mul(y); // rule 1: x{0}y = x*y
|
|
2930
|
+
// Fractional level coefficients come from a fundamental sequence taken at a
|
|
2931
|
+
// non-integer index. On the diagonal ω = x, so ω^(k)·(c+f) = ω^(k)·c +
|
|
2932
|
+
// ω^(k-1)·(x·f) — resolve top-down until only the constant term can still be
|
|
2933
|
+
// fractional, then turn that leftover into a fractional argument one level
|
|
2934
|
+
// higher: x{γ+f}x = x{γ+1}(2·(x/2)^f) (README: 10{ω*2}2.1 = 10{ω+2.1}10 =
|
|
2935
|
+
// 10{ω+3}2·5^0.1; continuous at f=0 since x{γ+1}2 = x{γ}x).
|
|
2936
|
+
if (coeffsHaveFraction(cf0)) {
|
|
2937
|
+
var xnf = x.toNumber();
|
|
2938
|
+
if (isFinite(xnf) && xnf >= 2) {
|
|
2939
|
+
var rs = Q._resolveFracLevel(cf0, xnf);
|
|
2940
|
+
if (rs.frac > 0) {
|
|
2941
|
+
var up = rs.ord.slice();
|
|
2942
|
+
while (up.length < 1) up.push(0);
|
|
2943
|
+
up[0] = (up[0] || 0) + 1;
|
|
2944
|
+
var argF = 2 * Math.pow(xnf / 2, rs.frac);
|
|
2945
|
+
return Q._hyperopFromOrdinal(x, new MetaNum(argF), trimCoeffs(up));
|
|
2946
|
+
}
|
|
2947
|
+
cf0 = rs.ord;
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2929
2950
|
// Non-integer argument at ordinal levels (issues.md addition 3):
|
|
2930
2951
|
// successor level α (c0 > 0): x{α}(m+f) = x{α-1} applied m times to x^f
|
|
2931
2952
|
// (e.g. expa(10,2.1) = 10{ω+1}2.1 = 10{ω}10{ω}(10^0.1); continuous at
|
|
@@ -2944,13 +2965,33 @@
|
|
|
2944
2965
|
// exactly and composition identities stay stable across paths
|
|
2945
2966
|
var yf = new MetaNum(Number((yFracNum - ym).toPrecision(15)));
|
|
2946
2967
|
if ((cf0[0] || 0) > 0) {
|
|
2968
|
+
var xnfS = x.toNumber();
|
|
2969
|
+
var xOkS = isFinite(xnfS) && xnfS >= 3 && xnfS <= MAX_SAFE_INTEGER;
|
|
2970
|
+
// α-1 ≥ ω*2 only: for the ω+1/ω+2/ω+3 levels the applications after the
|
|
2971
|
+
// first still have an operand inside MSI, so the engine evaluates them by
|
|
2972
|
+
// the definition (10{ω}(10{ω}(10^0.1))) and that identity is exact.
|
|
2973
|
+
var pred = succCoeffs(cf0);
|
|
2974
|
+
var bigLevel = (pred[1] || 0) >= 2;
|
|
2975
|
+
for (var bi = 2; bi < pred.length; bi++) if ((pred[bi] || 0) > 0) bigLevel = true;
|
|
2976
|
+
if (xOkS && bigLevel && ym <= 100000) {
|
|
2977
|
+
// successor rule written in the EXPANDED form (the same generator the
|
|
2978
|
+
// integer arguments use): x{α}(m+f) = x{α-1}^m(x^f) means the α-1 row
|
|
2979
|
+
// carries m applications — ceil(y)-2 = m-1 — and the cascade below it
|
|
2980
|
+
// takes its first fundamental sequence at the fractional start value
|
|
2981
|
+
// x^f, which is what interpolates the cascade depth between the two
|
|
2982
|
+
// neighbouring integers (exactly what the finite levels do: 10{3}2.1
|
|
2983
|
+
// starts from 10^0.1). The base is x{x^f}x when that descent is the
|
|
2984
|
+
// ω one (ω+1 levels), x{x}x otherwise.
|
|
2985
|
+
return Q._expandedHyperop(x, new MetaNum(ym + 1), cf0,
|
|
2986
|
+
Math.pow(xnfS, Number((yFracNum - ym).toPrecision(15))));
|
|
2987
|
+
}
|
|
2947
2988
|
if (ym <= 100000) {
|
|
2948
2989
|
// successor rule: x{α}(m+f) = x{α-1} applied m times to x^f
|
|
2949
2990
|
var succ = cf0.slice();
|
|
2950
2991
|
succ[0] = succ[0] - 1;
|
|
2951
2992
|
succ = trimCoeffs(succ);
|
|
2952
2993
|
var v = x.pow(yf);
|
|
2953
|
-
for (var it = 0; it < ym; it++) v = Q._hyperopFromOrdinalRaw(x, v, succ);
|
|
2994
|
+
for (var it = 0; it < ym; it++) v = Q._hyperopFromOrdinalRaw(x, v, succ, true);
|
|
2954
2995
|
return v;
|
|
2955
2996
|
}
|
|
2956
2997
|
// Successor level with an iteration count beyond direct evaluation:
|
|
@@ -2959,9 +3000,16 @@
|
|
|
2959
3000
|
return Q._ordinalHyperop(x, y, cf0);
|
|
2960
3001
|
}
|
|
2961
3002
|
if (ym >= 1) {
|
|
2962
|
-
// limit level:
|
|
2963
|
-
//
|
|
2964
|
-
|
|
3003
|
+
// limit level: rule 3 with the FULL (fractional) index — x{λ}y =
|
|
3004
|
+
// x{λ[y]}x. λ[y] can carry fractional coefficients (10{ω*2}2.1 =
|
|
3005
|
+
// 10{ω+2.1}10), which the fractional-level rule above resolves, so the
|
|
3006
|
+
// fraction of y is never thrown away (flooring it would make
|
|
3007
|
+
// h20(10,2.1) = h20(10,2)).
|
|
3008
|
+
// Nested (skipFrac: the successor rule is already iterating a fractional
|
|
3009
|
+
// start value) the index is floored — otherwise every application would
|
|
3010
|
+
// take another fractional fundamental sequence and recurse forever.
|
|
3011
|
+
var fsIdx = skipFrac ? Math.floor(yFracNum) : yFracNum;
|
|
3012
|
+
return Q._hyperopFromOrdinalRaw(x, x, fsCoeffs(cf0, fsIdx), skipFrac);
|
|
2965
3013
|
}
|
|
2966
3014
|
}
|
|
2967
3015
|
var cf = cf0;
|
|
@@ -2970,9 +3018,11 @@
|
|
|
2970
3018
|
if (deg >= 1 && x.array.length === 1 && x.layer === 0
|
|
2971
3019
|
&& y.array.length === 1 && y.layer === 0) {
|
|
2972
3020
|
var xC = metaFiniteCount(x), yC = metaFiniteCount(y);
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
3021
|
+
// Finite operands in [3, MSI] always take the EXPANDED cascade form — a
|
|
3022
|
+
// limit operation keeps its fundamental-sequence rows all the way up to
|
|
3023
|
+
// MSI (100 < y ≤ MSI included), truncated to the largest maxRows-1 rows.
|
|
3024
|
+
if (xC >= 3 && xC <= MAX_SAFE_INTEGER && yC >= 3 && yC <= MAX_SAFE_INTEGER) {
|
|
3025
|
+
return Q._expandedHyperop(x, y, cf);
|
|
2976
3026
|
}
|
|
2977
3027
|
}
|
|
2978
3028
|
return Q._ordinalHyperop(x, y, cf);
|
|
@@ -2992,214 +3042,146 @@
|
|
|
2992
3042
|
return r;
|
|
2993
3043
|
};
|
|
2994
3044
|
|
|
2995
|
-
//
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3045
|
+
// ---------------------------------------------------------------------------
|
|
3046
|
+
// Expanded (cascade) form of x{α}y for FINITE operands in [3, MSI] — README
|
|
3047
|
+
// rules 1-4 written out row by row. The rows are generated TOP-DOWN so a
|
|
3048
|
+
// huge fundamental sequence (y up to MSI) costs nothing: generation stops as
|
|
3049
|
+
// soon as the array budget is filled, keeping the LARGEST rows.
|
|
3050
|
+
//
|
|
3051
|
+
// successor α = β + m (m = c0 > 0): x{α}y = x{β+m-1}^(y-2)(x{β+m-1}x),
|
|
3052
|
+
// so the row at β+m-1 carries y-2 applications and every row below it
|
|
3053
|
+
// (β+m-2 … β, then the cascade of β) comes from decomposing with the
|
|
3054
|
+
// BASE x as operand and therefore carries x-2 (h13(10,20) → [8,0,1],
|
|
3055
|
+
// [8,1,1], [18,2,1] — only the top row follows y).
|
|
3056
|
+
// limit α (c0 = 0): rule 3 gives x{α}opd = x{α[opd]}x, so the operand turns
|
|
3057
|
+
// into the base x and every row carries x-2 — including for 100 < y ≤ MSI
|
|
3058
|
+
// (h20(10,1000) stays an expanded cascade, not a one-row marker).
|
|
3059
|
+
// ---------------------------------------------------------------------------
|
|
3060
|
+
// `fsOpd` is the operand of the FIRST fundamental-sequence step. The default
|
|
3061
|
+
// is the base x; the fractional successor rule passes the fractional start
|
|
3062
|
+
// value x^f instead (x{α}(m+f) = x{α-1}^m(x^f)), which is what interpolates the
|
|
3063
|
+
// cascade depth between two integers. baseIdx (returned as `.baseIdx`) is the
|
|
3064
|
+
// index used by the last descent — the finite level the cascade bottoms out at.
|
|
3065
|
+
Q._cascadeRows = function (xn, cf, yn, budget, fsOpd) {
|
|
3066
|
+
var rows = [];
|
|
3067
|
+
if (!(budget >= 1)) return { rows: rows, baseIdx: xn };
|
|
3068
|
+
var cfs = trimCoeffs((cf || []).slice());
|
|
3069
|
+
var opd = Math.min(yn, MAX_SAFE_INTEGER);
|
|
3070
|
+
var first = (cfs[0] || 0) > 0; // successor: the outer count is y-2
|
|
3071
|
+
var fracOpd = (fsOpd === undefined) ? null : fsOpd;
|
|
3072
|
+
var baseIdx = xn;
|
|
3073
|
+
var fracRem = 0; // fractional constant carried to the base
|
|
3074
|
+
var guard = 0;
|
|
3075
|
+
while (rows.length < budget && guard++ < 10000) {
|
|
3076
|
+
if (!coeffsHaveOmegaPart(cfs)) break; // finite level: no row
|
|
3077
|
+
if ((cfs[0] || 0) > 0) {
|
|
3078
|
+
var mRaw = cfs[0];
|
|
3079
|
+
var m = Math.floor(mRaw);
|
|
3080
|
+
// a fractional constant term (from a fundamental sequence taken at a
|
|
3081
|
+
// fractional index) is not a valid CNF coefficient — keep the integer
|
|
3082
|
+
// part as rows and carry the remainder into the base's finite level
|
|
3083
|
+
// index (x{10.16}x), which is exactly how the ω level interpolates
|
|
3084
|
+
var mFr = Number((mRaw - m).toPrecision(15));
|
|
3085
|
+
if (mFr > 1e-9) fracRem = mFr;
|
|
3086
|
+
var beta = trimCoeffs(cfs.slice());
|
|
3087
|
+
beta[0] = 0;
|
|
3088
|
+
beta = trimCoeffs(beta);
|
|
3089
|
+
var steps = Math.min(m, budget - rows.length + 1);
|
|
3090
|
+
for (var s = 0; s < steps; s++) {
|
|
3091
|
+
var j = m - 1 - s; // rows β+m-1 … β
|
|
3092
|
+
var cnt = (first ? opd : xn) - 2;
|
|
3093
|
+
first = false;
|
|
3094
|
+
if (cnt < 1) continue;
|
|
3095
|
+
if (cnt > MAX_SAFE_INTEGER) cnt = MAX_SAFE_INTEGER;
|
|
3096
|
+
var ord = beta.slice();
|
|
3097
|
+
if (j > 0) ord[0] = (ord[0] || 0) + j; // β + j
|
|
3098
|
+
ord = trimCoeffs(ord);
|
|
3099
|
+
if (!coeffsHaveOmegaPart(ord)) continue; // finite: lives in r0
|
|
3100
|
+
rows.push([cnt].concat(ord));
|
|
3101
|
+
}
|
|
3102
|
+
cfs = beta; // continue below β
|
|
3103
|
+
opd = Math.min(xn, MAX_SAFE_INTEGER); // everything below the top
|
|
3104
|
+
continue; // row is base-operand
|
|
3105
|
+
}
|
|
3106
|
+
// limit: fundamental sequence at the current operand (rule 3)
|
|
3107
|
+
var idx = (fracOpd !== null) ? fracOpd : opd;
|
|
3108
|
+
fracOpd = null;
|
|
3109
|
+
baseIdx = idx;
|
|
3110
|
+
var nxt = fsCoeffs(cfs, idx);
|
|
3111
|
+
if (coeffsHaveFraction(nxt)) {
|
|
3112
|
+
// a fractional index makes the coefficients fractional (ω^k·(c+f)) —
|
|
3113
|
+
// resolve them against the base so every row coefficient stays an
|
|
3114
|
+
// integer, carrying the leftover constant fraction into the base
|
|
3115
|
+
var rs2 = Q._resolveFracLevel(nxt, xn);
|
|
3116
|
+
cfs = rs2.ord;
|
|
3117
|
+
if (rs2.frac > 0) fracRem = rs2.frac;
|
|
3118
|
+
} else {
|
|
3119
|
+
cfs = trimCoeffs(nxt);
|
|
3120
|
+
}
|
|
3121
|
+
opd = Math.min(xn, MAX_SAFE_INTEGER); // operand becomes x
|
|
3122
|
+
}
|
|
3123
|
+
rows.baseIdx = baseIdx + fracRem; // descending by ordinal
|
|
3124
|
+
return rows;
|
|
3125
|
+
};
|
|
3126
|
+
|
|
3127
|
+
Q._expandedHyperop = function (x, y, cf, fsOpd) {
|
|
3128
|
+
var maxRows = MetaNum.maxRows;
|
|
3129
|
+
var xn = Math.floor(metaFiniteCount(x));
|
|
3130
|
+
var yn = Math.floor(metaFiniteCount(y));
|
|
3131
|
+
var budget = maxRows - 1; // ordinal rows the array holds
|
|
3132
|
+
var desc = Q._cascadeRows(xn, cf, yn, budget + 1, fsOpd); // +1 detects truncation
|
|
3133
|
+
var truncated = desc.length > budget;
|
|
3134
|
+
if (truncated) desc = desc.slice(0, budget); // keep the LARGEST rows
|
|
3135
|
+
var rows = desc.reverse(); // ascending
|
|
3136
|
+
// base r0 = x{idx}x (rule 3 at the ω level: x{ω}x = x{x}x) — the finite part;
|
|
3137
|
+
// idx is the operand of the descent that bottoms out, i.e. the fractional
|
|
3138
|
+
// start value x^f when the cascade came from the fractional successor rule
|
|
3139
|
+
var baseIdx = (desc.baseIdx === undefined) ? xn : desc.baseIdx;
|
|
3140
|
+
// arrow() evaluates fractional levels too (10{10.2589}10 ≠ 10{10}10), so the
|
|
3141
|
+
// carried fraction survives into the base
|
|
3142
|
+
var baseResult = x.arrow(Math.max(baseIdx, 3))(x);
|
|
3006
3143
|
var result = baseResult.clone();
|
|
3007
|
-
|
|
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);
|
|
3144
|
+
if (truncated) {
|
|
3012
3145
|
result.array = [[10]];
|
|
3013
|
-
rows[0][0] = (rows[0][0] || 0) + 1;
|
|
3146
|
+
rows[0][0] = (rows[0][0] || 0) + 1; // truncation marker
|
|
3014
3147
|
if (rows[0][0] > MAX_SAFE_INTEGER) rows[0][0] = MAX_SAFE_INTEGER;
|
|
3015
3148
|
} else {
|
|
3016
3149
|
result.array = [baseResult.array[0].slice()];
|
|
3017
3150
|
}
|
|
3018
3151
|
for (var i = 0; i < rows.length; i++) result.array.push(rows[i]);
|
|
3019
|
-
|
|
3020
|
-
return result;
|
|
3152
|
+
result.layer = 0;
|
|
3153
|
+
return result.normalize();
|
|
3021
3154
|
};
|
|
3022
3155
|
|
|
3023
|
-
//
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
var n = cardinal;
|
|
3029
|
-
|
|
3030
|
-
function compareOrd(a, b) {
|
|
3031
|
-
var maxLen = Math.max(a.length, b.length);
|
|
3032
|
-
for (var i = maxLen - 1; i >= 0; i--) {
|
|
3033
|
-
var va = (i < a.length) ? (a[i] || 0) : 0;
|
|
3034
|
-
var vb = (i < b.length) ? (b[i] || 0) : 0;
|
|
3035
|
-
if (va < vb) return -1;
|
|
3036
|
-
if (va > vb) return 1;
|
|
3037
|
-
}
|
|
3038
|
-
return 0;
|
|
3039
|
-
}
|
|
3040
|
-
|
|
3041
|
-
function addOrd(a, b) {
|
|
3042
|
-
if (!b || b.length === 0 || (b.length === 1 && b[0] === 0)) return a.slice();
|
|
3043
|
-
if (!a || a.length === 0 || (a.length === 1 && a[0] === 0)) return b.slice();
|
|
3044
|
-
var result = a.slice();
|
|
3045
|
-
var k = 0;
|
|
3046
|
-
while (k < result.length && (result[k] || 0) === 0) k++;
|
|
3047
|
-
if (k >= result.length) {
|
|
3048
|
-
return b.slice();
|
|
3049
|
-
} else if (k === 0) {
|
|
3050
|
-
result[0] = (result[0] || 0) + (b[0] || 0);
|
|
3051
|
-
for (var i = 1; i < b.length; i++) {
|
|
3052
|
-
result[i] = (result[i] || 0) + (b[i] || 0);
|
|
3053
|
-
}
|
|
3054
|
-
} else {
|
|
3055
|
-
result[k] = 0;
|
|
3056
|
-
result = result.slice(0, k);
|
|
3057
|
-
for (var i = 0; i < b.length; i++) {
|
|
3058
|
-
result.push(b[i] || 0);
|
|
3059
|
-
}
|
|
3060
|
-
}
|
|
3061
|
-
while (result.length > 0 && result[result.length - 1] === 0) result.pop();
|
|
3062
|
-
return result;
|
|
3063
|
-
}
|
|
3064
|
-
|
|
3065
|
-
function isZero(ord) {
|
|
3066
|
-
if (!ord || ord.length === 0) return true;
|
|
3067
|
-
for (var i = 0; i < ord.length; i++) {
|
|
3068
|
-
if ((ord[i] || 0) !== 0) return false;
|
|
3069
|
-
}
|
|
3070
|
-
return true;
|
|
3071
|
-
}
|
|
3072
|
-
|
|
3073
|
-
function buildRow(ord, count) {
|
|
3074
|
-
var maxIdx = ord.length - 1;
|
|
3075
|
-
while (maxIdx >= 0 && (ord[maxIdx] || 0) === 0) maxIdx--;
|
|
3076
|
-
if (maxIdx < 0) return null;
|
|
3077
|
-
var row = [count];
|
|
3078
|
-
for (var i = 0; i <= maxIdx - 1; i++) row.push(ord[i] || 0);
|
|
3079
|
-
row.push(ord[maxIdx]);
|
|
3080
|
-
return row;
|
|
3081
|
-
}
|
|
3082
|
-
|
|
3083
|
-
// Enumerate all ordinals below ω^k with coefficients < n
|
|
3084
|
-
function enumBelowOmegaK(k, n) {
|
|
3085
|
-
if (k === 0) {
|
|
3086
|
-
return [[0]];
|
|
3087
|
-
}
|
|
3088
|
-
if (k === 1) {
|
|
3089
|
-
var result = [];
|
|
3090
|
-
for (var i = 0; i < n; i++) {
|
|
3091
|
-
result.push([i]);
|
|
3092
|
-
}
|
|
3093
|
-
return result;
|
|
3094
|
-
}
|
|
3095
|
-
var result = [];
|
|
3096
|
-
for (var a = 0; a < n; a++) {
|
|
3097
|
-
var sub = enumBelowOmegaK(k - 1, n);
|
|
3098
|
-
for (var i = 0; i < sub.length; i++) {
|
|
3099
|
-
var combined = sub[i].slice();
|
|
3100
|
-
while (combined.length < k) combined.push(0);
|
|
3101
|
-
combined[k - 1] = a;
|
|
3102
|
-
result.push(combined);
|
|
3103
|
-
}
|
|
3104
|
-
}
|
|
3105
|
-
return result;
|
|
3106
|
-
}
|
|
3107
|
-
|
|
3108
|
-
// Enumerate all ordinals below a given ordinal
|
|
3109
|
-
function enumBelow(alpha, n) {
|
|
3110
|
-
if (isZero(alpha)) return [];
|
|
3111
|
-
|
|
3112
|
-
if ((alpha[0] || 0) > 0) {
|
|
3113
|
-
var pred = alpha.slice();
|
|
3114
|
-
pred[0]--;
|
|
3115
|
-
while (pred.length > 0 && pred[pred.length - 1] === 0) pred.pop();
|
|
3116
|
-
if (pred.length === 0) pred = [0];
|
|
3117
|
-
var result = enumBelow(pred, n);
|
|
3118
|
-
result.push(pred.slice());
|
|
3119
|
-
return result;
|
|
3120
|
-
}
|
|
3121
|
-
|
|
3122
|
-
var k = alpha.length - 1;
|
|
3123
|
-
while (k >= 0 && (alpha[k] || 0) === 0) k--;
|
|
3124
|
-
if (k < 0) return [];
|
|
3125
|
-
|
|
3126
|
-
var ck = alpha[k] || 0;
|
|
3127
|
-
var rest = alpha.slice(0, k);
|
|
3128
|
-
while (rest.length > 0 && rest[rest.length - 1] === 0) rest.pop();
|
|
3129
|
-
|
|
3130
|
-
var result = [];
|
|
3131
|
-
|
|
3132
|
-
for (var j = 0; j < ck; j++) {
|
|
3133
|
-
var sub = enumBelowOmegaK(k, n);
|
|
3134
|
-
for (var i = 0; i < sub.length; i++) {
|
|
3135
|
-
var combined = sub[i].slice();
|
|
3136
|
-
while (combined.length <= k) combined.push(0);
|
|
3137
|
-
combined[k] = j;
|
|
3138
|
-
result.push(combined);
|
|
3139
|
-
}
|
|
3140
|
-
}
|
|
3141
|
-
|
|
3142
|
-
if (!isZero(rest)) {
|
|
3143
|
-
var restSub = enumBelow(rest, n);
|
|
3144
|
-
for (var i = 0; i < restSub.length; i++) {
|
|
3145
|
-
var combined = restSub[i].slice();
|
|
3146
|
-
while (combined.length <= k) combined.push(0);
|
|
3147
|
-
combined[k] = ck;
|
|
3148
|
-
result.push(combined);
|
|
3149
|
-
}
|
|
3150
|
-
}
|
|
3151
|
-
|
|
3152
|
-
return result;
|
|
3156
|
+
// Any coefficient with a non-zero fractional part?
|
|
3157
|
+
function coeffsHaveFraction(coeffs) {
|
|
3158
|
+
for (var i = 0; i < coeffs.length; i++) {
|
|
3159
|
+
var c = coeffs[i] || 0;
|
|
3160
|
+
if (c !== Math.floor(c)) return true;
|
|
3153
3161
|
}
|
|
3162
|
+
return false;
|
|
3163
|
+
}
|
|
3154
3164
|
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
var
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
var
|
|
3164
|
-
if (
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
var normalized = ord.slice();
|
|
3168
|
-
while (normalized.length > 0 && normalized[normalized.length - 1] === 0) {
|
|
3169
|
-
normalized.pop();
|
|
3165
|
+
// Resolve fractional CNF coefficients against the base x (see the comment in
|
|
3166
|
+
// _hyperopFromOrdinalRaw): ω^(k)·(c+f) = ω^(k)·c + ω^(k-1)·(x·f) top-down.
|
|
3167
|
+
// Returns the integer level plus the fractional part left in the constant term.
|
|
3168
|
+
Q._resolveFracLevel = function (cf, xn) {
|
|
3169
|
+
var r = trimCoeffs((cf || []).slice());
|
|
3170
|
+
for (var k = r.length - 1; k >= 1; k--) {
|
|
3171
|
+
var c = r[k] || 0;
|
|
3172
|
+
var fl = Math.floor(c);
|
|
3173
|
+
var fr = Number((c - fl).toPrecision(15));
|
|
3174
|
+
if (fr > 1e-9) {
|
|
3175
|
+
r[k] = fl;
|
|
3176
|
+
r[k - 1] = (r[k - 1] || 0) + xn * fr;
|
|
3170
3177
|
}
|
|
3171
|
-
|
|
3172
|
-
// Skip ordinals below ω (finite ordinals: only constant term, length <= 1)
|
|
3173
|
-
if (normalized.length <= 1) continue;
|
|
3174
|
-
|
|
3175
|
-
var key = normalized.join(',');
|
|
3176
|
-
if (seen[key]) continue;
|
|
3177
|
-
seen[key] = true;
|
|
3178
|
-
uniqueOrdinals.push(normalized);
|
|
3179
|
-
}
|
|
3180
|
-
|
|
3181
|
-
uniqueOrdinals.sort(function (a, b) {
|
|
3182
|
-
return compareOrd(a, b);
|
|
3183
|
-
});
|
|
3184
|
-
|
|
3185
|
-
var allRows = [];
|
|
3186
|
-
for (var i = 0; i < uniqueOrdinals.length; i++) {
|
|
3187
|
-
var row = buildRow(uniqueOrdinals[i], count);
|
|
3188
|
-
if (row) allRows.push(row);
|
|
3189
|
-
}
|
|
3190
|
-
|
|
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;
|
|
3195
|
-
allRows = allRows.slice(allRows.length - maxOrdinalRows);
|
|
3196
|
-
}
|
|
3197
|
-
|
|
3198
|
-
for (var i = 0; i < allRows.length; i++) {
|
|
3199
|
-
rows.push(allRows[i]);
|
|
3200
3178
|
}
|
|
3201
|
-
|
|
3202
|
-
|
|
3179
|
+
var c0 = r[0] || 0;
|
|
3180
|
+
var fl0 = Math.floor(c0);
|
|
3181
|
+
var fr0 = Number((c0 - fl0).toPrecision(15));
|
|
3182
|
+
if (!(fr0 > 1e-9)) fr0 = 0;
|
|
3183
|
+
r[0] = fl0;
|
|
3184
|
+
return { ord: trimCoeffs(r), frac: fr0 };
|
|
3203
3185
|
};
|
|
3204
3186
|
|
|
3205
3187
|
// Helper: number of leading iterate applications (of level `beta`) starting
|
|
@@ -3217,6 +3199,26 @@
|
|
|
3217
3199
|
return steps + 1;
|
|
3218
3200
|
}
|
|
3219
3201
|
|
|
3202
|
+
// Inverse of a LIMIT level taken through the expanded cascade: x{λ}y = x{λ[y]}x
|
|
3203
|
+
// makes every row depend on y only through the fundamental sequence, so instead
|
|
3204
|
+
// of reading a count row we search the (monotone) forward map.
|
|
3205
|
+
Q._invExpandedLimit = function (base, value, coeffs) {
|
|
3206
|
+
var lo = 3, hi = MAX_SAFE_INTEGER, best = 0;
|
|
3207
|
+
var v3 = Q._expandedHyperop(base, new MetaNum(3), coeffs);
|
|
3208
|
+
if (value.lt(v3)) return base.clone();
|
|
3209
|
+
while (lo <= hi) {
|
|
3210
|
+
var mid = lo + Math.floor((hi - lo) / 2);
|
|
3211
|
+
if (Q._expandedHyperop(base, new MetaNum(mid), coeffs).lte(value)) {
|
|
3212
|
+
best = mid; lo = mid + 1;
|
|
3213
|
+
} else {
|
|
3214
|
+
hi = mid - 1;
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
if (best === 0) return base.clone();
|
|
3218
|
+
var vb = Q._expandedHyperop(base, new MetaNum(best), coeffs);
|
|
3219
|
+
return vb.eq(value) ? new MetaNum(best) : base.clone();
|
|
3220
|
+
};
|
|
3221
|
+
|
|
3220
3222
|
// Helper: generic inverse hyperoperation from ordinal level.
|
|
3221
3223
|
// Forward paths and the rows they leave:
|
|
3222
3224
|
// - small x ∈ [3, MSI] & small y (enumeration path): rows for each ordinal
|
|
@@ -3249,14 +3251,29 @@
|
|
|
3249
3251
|
}
|
|
3250
3252
|
if (cf.length === 0) return z;
|
|
3251
3253
|
|
|
3252
|
-
//
|
|
3254
|
+
// expanded cascade path (base z is a small finite number ≥ 3): the forward
|
|
3255
|
+
// operation wrote the rule-1..4 cascade rows.
|
|
3256
|
+
// successor α: the row at α-1 carries exactly y-2 applications → +2
|
|
3257
|
+
// limit α: every row carries x-2 and y only appears inside the
|
|
3258
|
+
// fundamental-sequence rows, so it is recovered from the forward map
|
|
3253
3259
|
var zC = metaFiniteCount(z);
|
|
3254
3260
|
if (z.array.length === 1 && z.layer === 0 && zC >= 3 && zC <= MAX_SAFE_INTEGER) {
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3261
|
+
if ((cf[0] || 0) > 0) {
|
|
3262
|
+
var pred = succCoeffs(cf);
|
|
3263
|
+
var predRow = null;
|
|
3264
|
+
for (var pi = x.array.length - 1; pi >= 1; pi--) {
|
|
3265
|
+
var prow = x.array[pi];
|
|
3266
|
+
if (prow && prow.length >= 2 && (prow[0] || 0) > 0 &&
|
|
3267
|
+
cmpCoeffsLevel(rowToCoeffs(prow), pred) === 0) { predRow = prow; break; }
|
|
3268
|
+
}
|
|
3269
|
+
if (predRow) return new MetaNum((predRow[0] || 0) + 2);
|
|
3270
|
+
var lastRow = x.array[x.array.length - 1];
|
|
3271
|
+
if (lastRow && lastRow.length >= 2 && (lastRow[0] || 0) > 0) {
|
|
3272
|
+
return new MetaNum((lastRow[0] || 0) + 2);
|
|
3273
|
+
}
|
|
3274
|
+
return z;
|
|
3258
3275
|
}
|
|
3259
|
-
return z;
|
|
3276
|
+
return Q._invExpandedLimit(z, x, cf);
|
|
3260
3277
|
}
|
|
3261
3278
|
|
|
3262
3279
|
// engine path: count row [c | β] with β = α-1 (successor α only)
|
|
@@ -3636,8 +3653,21 @@
|
|
|
3636
3653
|
return Q._layerMarker([10], 1, [[1, m]]);
|
|
3637
3654
|
}
|
|
3638
3655
|
if (yc <= MAX_SAFE_INTEGER) {
|
|
3639
|
-
// fractional y:
|
|
3640
|
-
|
|
3656
|
+
// fractional y: (ω^ω)[y] = ω^y = ω^(m+f) = ω^m·ω^f, and on the diagonal
|
|
3657
|
+
// ω^f reads as x^f — so the level is ω^m·(x^f), whose coefficients carry
|
|
3658
|
+
// x^f at index m (README: 10{ω^ω}2.1 = 10{ω^2.1}10 = 10{ω^2*10^0.1}10).
|
|
3659
|
+
// Flooring y would lose the fraction and make iterate(10,2.1)=iterate(10,2).
|
|
3660
|
+
var mf = Math.max(2, Math.floor(yc));
|
|
3661
|
+
var ff = Number((yc - Math.floor(yc)).toPrecision(15));
|
|
3662
|
+
var xnf = x.toNumber();
|
|
3663
|
+
var cfac = (isFinite(xnf) && xnf >= 2 && ff > 0) ? Math.pow(xnf, ff) : 1;
|
|
3664
|
+
if (mf < MetaNum.maxCols) {
|
|
3665
|
+
var cfw = [];
|
|
3666
|
+
for (var cw = 0; cw < mf; cw++) cfw.push(0);
|
|
3667
|
+
cfw.push(cfac);
|
|
3668
|
+
return Q._hyperopFromOrdinal(x, x, cfw);
|
|
3669
|
+
}
|
|
3670
|
+
return Q._layerMarker([10], 1, [[cfac, mf]]);
|
|
3641
3671
|
}
|
|
3642
3672
|
// ordinal / out-of-range operand: y plus one ω^ω marker row
|
|
3643
3673
|
return Q._ordinalOperandOp(y, 1, [1, 0, 1]);
|