metanum 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -228
- package/format-metanum.js +269 -79
- package/metanum.js +632 -91
- package/package.json +1 -1
- package/test-interface.html +1 -0
- package/test_mixed.js +739 -42
package/metanum.js
CHANGED
|
@@ -228,6 +228,38 @@
|
|
|
228
228
|
return Math.log10(Number(str.substring(0, LONG_STRING_MIN_LENGTH))) + (str.length - LONG_STRING_MIN_LENGTH);
|
|
229
229
|
};
|
|
230
230
|
|
|
231
|
+
// Canonical form of a value with 0 < |v| < 1: the library stores it as the
|
|
232
|
+
// RECIPROCAL with sign 2 (0<v<1) / -2 (-1<v<0) — the same encoding the
|
|
233
|
+
// underflow path below already produced, now applied to the WHOLE sub-unit
|
|
234
|
+
// range so that `MetaNum(0.5).sign === 2` and every operation result in that
|
|
235
|
+
// range carries it too (README: sign 2 / -2 == 0~1 / -1~0).
|
|
236
|
+
//
|
|
237
|
+
// _skipCanon lets rec() produce the reciprocal of a sub-unit value (2 for 0.5)
|
|
238
|
+
// without this rule turning it straight back into a small value.
|
|
239
|
+
var _skipCanon = 0;
|
|
240
|
+
function canonicalizeSubUnit(x) {
|
|
241
|
+
if (_skipCanon) return x;
|
|
242
|
+
if (x.layer !== 0 || x.array.length !== 1) return x;
|
|
243
|
+
var r = x.array[0];
|
|
244
|
+
if (x.sign !== 1 && x.sign !== -1) return x; // already reciprocal-encoded
|
|
245
|
+
if (r.length === 1) {
|
|
246
|
+
var v = r[0];
|
|
247
|
+
if (!(typeof v === 'number') || !isFinite(v) || v <= 0 || v >= 1) return x;
|
|
248
|
+
r[0] = 1 / v;
|
|
249
|
+
x.sign = x.sign === -1 ? -2 : 2;
|
|
250
|
+
return x;
|
|
251
|
+
}
|
|
252
|
+
if (r.length === 2 && r[1] === 1) {
|
|
253
|
+
// 10^e with a negative exponent is sub-unit: store 10^(-e) as reciprocal
|
|
254
|
+
var e = r[0];
|
|
255
|
+
if (!(typeof e === 'number') || !isFinite(e) || e >= 0) return x;
|
|
256
|
+
r[0] = -e;
|
|
257
|
+
x.sign = x.sign === -1 ? -2 : 2;
|
|
258
|
+
return x;
|
|
259
|
+
}
|
|
260
|
+
return x;
|
|
261
|
+
}
|
|
262
|
+
|
|
231
263
|
P.normalize = function () {
|
|
232
264
|
var b;
|
|
233
265
|
var x = this;
|
|
@@ -469,6 +501,40 @@
|
|
|
469
501
|
return x;
|
|
470
502
|
};
|
|
471
503
|
|
|
504
|
+
// Apply the sub-unit canonical form to a public result (constructor input or
|
|
505
|
+
// the result of a basic arithmetic op). Deliberately NOT part of normalize():
|
|
506
|
+
// normalize runs on every internal intermediate, and the engine's own
|
|
507
|
+
// transcendentals (log10 → 0.301, slog, gamma, hyper-op levels) plus hardy's
|
|
508
|
+
// coefficient arrays read r0 structurally, so canonicalizing there broke
|
|
509
|
+
// them. See canonicalizeSubUnit above.
|
|
510
|
+
function canonicalizeResult(x) {
|
|
511
|
+
if (x instanceof MetaNum) canonicalizeSubUnit(x);
|
|
512
|
+
return x;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Constructor that never applies the sub-unit canonical form. Engine
|
|
516
|
+
// internals build values that are consumed STRUCTURALLY (r0 read as a
|
|
517
|
+
// magnitude, sign tested for -1): the transcendentals' own results
|
|
518
|
+
// (log10(2) = 0.301, slog, gamma, pent_log) and hardy's fractional
|
|
519
|
+
// coefficients. Canonicalizing those changed r0[0] from 0.301 to 3.32 and
|
|
520
|
+
// silently corrupted every consumer.
|
|
521
|
+
function rawMetaNum(v) {
|
|
522
|
+
_skipCanon++;
|
|
523
|
+
try { return new MetaNum(v); } finally { _skipCanon--; }
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Run fn with the sub-unit canonical form suppressed. Applied to the engine
|
|
527
|
+
// functions that CONSUME sub-unit magnitudes structurally (gamma's series,
|
|
528
|
+
// slog's log10 chain, the layeradd/pentate inverse paths): they read r0 as a
|
|
529
|
+
// plain magnitude, so a canonicalized intermediate (log10(2) → r0 [3.32]
|
|
530
|
+
// instead of [0.301]) silently produced garbage. The PRODUCERS (log10, ln,
|
|
531
|
+
// exp, root, the constructor, add/sub/mul/div) stay canonicalized, so the
|
|
532
|
+
// public contract the user asked for still holds.
|
|
533
|
+
function rawBody(fn, self, args) {
|
|
534
|
+
_skipCanon++;
|
|
535
|
+
try { return fn.apply(self, args || []); } finally { _skipCanon--; }
|
|
536
|
+
}
|
|
537
|
+
|
|
472
538
|
var standardizeMessageSent = false;
|
|
473
539
|
P.standardize = function () {
|
|
474
540
|
if (!standardizeMessageSent) console.warn(metaNumError + "'standardize' method is being deprecated in favor of 'normalize' and will be removed in the future!"), standardizeMessageSent = true;
|
|
@@ -501,6 +567,19 @@
|
|
|
501
567
|
if (this.array[0] && isNaN(this.array[0][0])) return NaN;
|
|
502
568
|
if (other.array[0] && isNaN(other.array[0][0])) return NaN;
|
|
503
569
|
|
|
570
|
+
// Plain finite numerics (any sign, including the sub-unit encoding 2/-2)
|
|
571
|
+
// compare as real numbers. The structural path below reads r0 as the
|
|
572
|
+
// magnitude and only inverts at the very end, so a sign-2 value like 0.2
|
|
573
|
+
// (stored as r0 = [5]) used to compare as 5 — every `lt`/`gt`/`eq` against a
|
|
574
|
+
// sub-unit value was wrong.
|
|
575
|
+
var tNum = plainNumericValue(this);
|
|
576
|
+
var oNum = plainNumericValue(other);
|
|
577
|
+
if (tNum !== null && oNum !== null) {
|
|
578
|
+
if (tNum < oNum) return -1;
|
|
579
|
+
if (tNum > oNum) return 1;
|
|
580
|
+
return 0;
|
|
581
|
+
}
|
|
582
|
+
|
|
504
583
|
var tInf = this.array[0] && this.array[0][0] === Infinity;
|
|
505
584
|
var oInf = other.array[0] && other.array[0][0] === Infinity;
|
|
506
585
|
|
|
@@ -796,6 +875,30 @@
|
|
|
796
875
|
return x.sign === 2 || x.sign === -2;
|
|
797
876
|
}
|
|
798
877
|
|
|
878
|
+
// The plain r0 magnitude as the engine's own numeric routines expect it:
|
|
879
|
+
// for a sub-unit value (sign 2/-2) r0 holds the RECIPROCAL, so unwrap it.
|
|
880
|
+
// Use this wherever a function does `isSimple(x) ? x.array[0][0] : …` to feed
|
|
881
|
+
// a float routine — otherwise 0.5 (r0 [2]) is read as 2.
|
|
882
|
+
function magnitudeOf(x) {
|
|
883
|
+
if (!isSmall(x)) return x.array[0][0];
|
|
884
|
+
return 1 / x.array[0][0];
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// Real value of a plain finite numeric MetaNum, or null when the value is
|
|
888
|
+
// structured (layer > 0, ordinal rows, E/power-tower r0) and must go through
|
|
889
|
+
// the structural comparison. sign 2/-2 is the sub-unit encoding: r0 holds
|
|
890
|
+
// the reciprocal, so the value is 1/r0 (negated for -2).
|
|
891
|
+
function plainNumericValue(x) {
|
|
892
|
+
if (x.layer !== 0 || x.array.length !== 1) return null;
|
|
893
|
+
var r0 = x.array[0];
|
|
894
|
+
if (r0.length !== 1) return null;
|
|
895
|
+
var v = r0[0];
|
|
896
|
+
if (typeof v !== 'number' || !isFinite(v) || v === 0) return null;
|
|
897
|
+
if (x.sign === 2) return 1 / v;
|
|
898
|
+
if (x.sign === -2) return -1 / v;
|
|
899
|
+
return x.sign === -1 ? -v : v;
|
|
900
|
+
}
|
|
901
|
+
|
|
799
902
|
function isNumeric(x) {
|
|
800
903
|
return x.layer === 0 && x.array.length === 1 &&
|
|
801
904
|
x.array[0].length === 1 && isFinite(x.array[0][0]);
|
|
@@ -1011,9 +1114,11 @@
|
|
|
1011
1114
|
var domMul = layerDominant(x, other);
|
|
1012
1115
|
if (domMul !== null) return domMul.clone().normalize();
|
|
1013
1116
|
|
|
1014
|
-
if (isSimple(x) && isSimple(other)
|
|
1015
|
-
|
|
1016
|
-
|
|
1117
|
+
if (isSimple(x) && isSimple(other)) {
|
|
1118
|
+
// magnitudeOf: sub-unit operands (sign 2/-2) store the reciprocal, so
|
|
1119
|
+
// read the real values — otherwise 0.5·0.5 multiplied 2·2 = 4.
|
|
1120
|
+
var nx = magnitudeOf(x);
|
|
1121
|
+
var ny = magnitudeOf(other);
|
|
1017
1122
|
var n = nx * ny;
|
|
1018
1123
|
if (isFinite(n) && n !== 0 && Math.abs(n) <= MAX_SAFE_INTEGER) {
|
|
1019
1124
|
if (Math.abs(n) < 1) return new MetaNum(1 / Math.abs(n)).rec();
|
|
@@ -1066,9 +1171,11 @@
|
|
|
1066
1171
|
}
|
|
1067
1172
|
|
|
1068
1173
|
if (x.eq(MetaNum.ZERO)) return MetaNum.ZERO.clone();
|
|
1069
|
-
if (isSimple(x) && isSimple(other)
|
|
1070
|
-
|
|
1071
|
-
|
|
1174
|
+
if (isSimple(x) && isSimple(other)) {
|
|
1175
|
+
// magnitudeOf: sub-unit operands store the reciprocal — 0.5 / 0.25 must
|
|
1176
|
+
// read 0.5 and 0.25, not 2 and 4.
|
|
1177
|
+
var nx = magnitudeOf(x);
|
|
1178
|
+
var ny = magnitudeOf(other);
|
|
1072
1179
|
var n = nx / ny;
|
|
1073
1180
|
if (isFinite(n) && n !== 0 && Math.abs(n) <= MAX_SAFE_INTEGER) {
|
|
1074
1181
|
if (Math.abs(n) < 1) return new MetaNum(1 / Math.abs(n)).rec();
|
|
@@ -1111,7 +1218,10 @@
|
|
|
1111
1218
|
var x = this.clone();
|
|
1112
1219
|
// Toggle between large and small: 1↔2, -1↔-2
|
|
1113
1220
|
x.sign = x.sign === 1 ? 2 : x.sign === 2 ? 1 : x.sign === -1 ? -2 : -1;
|
|
1114
|
-
|
|
1221
|
+
// _skipCanon: the reciprocal of a sub-unit value is a NORMAL value (rec(0.5)
|
|
1222
|
+
// = 2) — canonicalizeSubUnit would otherwise flip it straight back.
|
|
1223
|
+
_skipCanon++;
|
|
1224
|
+
try { return x.normalize(); } finally { _skipCanon--; }
|
|
1115
1225
|
};
|
|
1116
1226
|
Q.reciprocate = Q.rec = function (x) {
|
|
1117
1227
|
return new MetaNum(x).rec();
|
|
@@ -1202,7 +1312,11 @@
|
|
|
1202
1312
|
if (other.mod(2).eq(MetaNum.ONE)) return x.abs().root(other).neg();
|
|
1203
1313
|
return MetaNum.NaN.clone();
|
|
1204
1314
|
}
|
|
1205
|
-
if (isNumeric(x) && isNumeric(other))
|
|
1315
|
+
if (isNumeric(x) && isNumeric(other)) {
|
|
1316
|
+
// magnitudeOf: a sub-unit x (sign 2) stores the reciprocal in r0, so
|
|
1317
|
+
// sqrt(0.25) must read 0.25, not the stored 4 (which gave 2).
|
|
1318
|
+
return new MetaNum(Math.pow(magnitudeOf(x), 1 / magnitudeOf(other)));
|
|
1319
|
+
}
|
|
1206
1320
|
// Handle E^m format (iterated exponentiation levels)
|
|
1207
1321
|
if (x.layer === 0 && x.array.length === 1 && x.array[0].length > 1 && isNumeric(other)) {
|
|
1208
1322
|
var r0 = x.array[0];
|
|
@@ -1260,19 +1374,11 @@
|
|
|
1260
1374
|
P.generalLogarithm = P.log10 = function () {
|
|
1261
1375
|
if (this.isNaN() || this.sign === -1 || this.sign === -2) return MetaNum.NaN.clone();
|
|
1262
1376
|
if (this.isInfinite()) return this;
|
|
1263
|
-
if (isSmall(this)) {
|
|
1264
|
-
// Small value: log10 is negative of what it would be for the normal value
|
|
1265
|
-
var n = this.clone();
|
|
1266
|
-
n.sign = 1; // Convert to normal positive for computation
|
|
1267
|
-
var result = n.log10();
|
|
1268
|
-
// Result should be negative (because log10 of a small number is negative)
|
|
1269
|
-
// Need to handle this carefully - after conversion, the result is the magnitude
|
|
1270
|
-
// which we need to negate
|
|
1271
|
-
return result.neg();
|
|
1272
|
-
}
|
|
1273
1377
|
if (this.eq(MetaNum.ZERO)) return MetaNum.NEGATIVE_INFINITY.clone();
|
|
1274
1378
|
if (isNumeric(this)) {
|
|
1275
|
-
|
|
1379
|
+
// magnitudeOf: a sub-unit operand stores the reciprocal in r0, so
|
|
1380
|
+
// log10(0.5) must read 0.5, not the stored 2.
|
|
1381
|
+
var lv = Math.log10(magnitudeOf(this));
|
|
1276
1382
|
if (Number.isFinite(lv)) return new MetaNum(lv);
|
|
1277
1383
|
}
|
|
1278
1384
|
if (this.layer === 0 && this.array.length === 1 && this.array[0].length > 1) {
|
|
@@ -1298,7 +1404,7 @@
|
|
|
1298
1404
|
if (x.eq(MetaNum.ZERO)) return MetaNum.NEGATIVE_INFINITY.clone();
|
|
1299
1405
|
if (x.eq(MetaNum.ONE)) return MetaNum.ZERO.clone();
|
|
1300
1406
|
if (isNumeric(x) && isNumeric(base)) {
|
|
1301
|
-
var lv = Math.log(x
|
|
1407
|
+
var lv = Math.log(magnitudeOf(x)) / Math.log(magnitudeOf(base));
|
|
1302
1408
|
if (Number.isFinite(lv)) return new MetaNum(lv);
|
|
1303
1409
|
}
|
|
1304
1410
|
return x.log10().div(base.log10());
|
|
@@ -1308,11 +1414,14 @@
|
|
|
1308
1414
|
};
|
|
1309
1415
|
|
|
1310
1416
|
P.naturalLogarithm = P.ln = function () {
|
|
1311
|
-
if (this.
|
|
1417
|
+
if (this.sign === -1 || this.sign === -2) return MetaNum.NaN.clone();
|
|
1418
|
+
if (this.isNaN()) return MetaNum.NaN.clone();
|
|
1312
1419
|
if (this.eq(MetaNum.ZERO)) return MetaNum.NEGATIVE_INFINITY.clone();
|
|
1313
1420
|
if (this.isInfinite()) return this;
|
|
1314
1421
|
if (isNumeric(this)) {
|
|
1315
|
-
|
|
1422
|
+
// magnitudeOf: a sub-unit operand stores the reciprocal in r0, so
|
|
1423
|
+
// ln(0.5) must read 0.5, not the stored 2.
|
|
1424
|
+
var lv = Math.log(magnitudeOf(this));
|
|
1316
1425
|
if (Number.isFinite(lv)) return new MetaNum(lv);
|
|
1317
1426
|
}
|
|
1318
1427
|
return this.log10().div(new MetaNum(Math.LOG10E));
|
|
@@ -1354,7 +1463,7 @@
|
|
|
1354
1463
|
if (this.sign === -1 || this.sign === -2) return MetaNum.NaN.clone();
|
|
1355
1464
|
if (this.isNaN() || this.isInfinite()) return this.clone();
|
|
1356
1465
|
if (isSimple(this)) {
|
|
1357
|
-
var n = this
|
|
1466
|
+
var n = magnitudeOf(this); // sub-unit r0 holds the reciprocal
|
|
1358
1467
|
if (Number.isInteger(n) && n >= 0 && n <= 100) {
|
|
1359
1468
|
var f = 1;
|
|
1360
1469
|
for (var i = 2; i < n; i++) f *= i;
|
|
@@ -1377,7 +1486,7 @@
|
|
|
1377
1486
|
if (this.isNaN() || this.isInfinite()) return this;
|
|
1378
1487
|
if (this.sign === -1 || this.sign === -2) return this.abs().fact().neg();
|
|
1379
1488
|
if (isSimple(this)) {
|
|
1380
|
-
var n = this
|
|
1489
|
+
var n = magnitudeOf(this); // sub-unit r0 holds the reciprocal
|
|
1381
1490
|
if (Number.isInteger(n) && n >= 0 && n <= 20) {
|
|
1382
1491
|
var f = 1;
|
|
1383
1492
|
for (var i = 2; i <= n; i++) f *= i;
|
|
@@ -1415,7 +1524,7 @@
|
|
|
1415
1524
|
if (this.gt(MetaNum.E_MAX_SAFE_INTEGER)) return d_lambertw(this, tol, principal);
|
|
1416
1525
|
if (isNumeric(this)) {
|
|
1417
1526
|
try {
|
|
1418
|
-
return new MetaNum(f_lambertw(this
|
|
1527
|
+
return new MetaNum(f_lambertw(magnitudeOf(this), tol, principal));
|
|
1419
1528
|
} catch (e) {
|
|
1420
1529
|
return MetaNum.NaN.clone();
|
|
1421
1530
|
}
|
|
@@ -1428,7 +1537,8 @@
|
|
|
1428
1537
|
if (this.abs().gt(MetaNum.E_MAX_SAFE_INTEGER)) return d_lambertw(this, tol, principal);
|
|
1429
1538
|
if (isNumeric(this)) {
|
|
1430
1539
|
try {
|
|
1431
|
-
return new MetaNum(f_lambertw(
|
|
1540
|
+
return new MetaNum(f_lambertw(
|
|
1541
|
+
(this.sign === -2 ? -1 : this.sign) * magnitudeOf(this.abs()), tol, principal));
|
|
1432
1542
|
} catch (e) {
|
|
1433
1543
|
return MetaNum.NaN.clone();
|
|
1434
1544
|
}
|
|
@@ -1594,7 +1704,7 @@
|
|
|
1594
1704
|
if (this.eq(MetaNum.ZERO)) return MetaNum.ZERO.clone();
|
|
1595
1705
|
if (this.eq(MetaNum.ONE)) return MetaNum.ONE.clone();
|
|
1596
1706
|
if (isSimple(this)) {
|
|
1597
|
-
var v = this
|
|
1707
|
+
var v = magnitudeOf(this);
|
|
1598
1708
|
if (v > 0 && v < 1) return new MetaNum(v);
|
|
1599
1709
|
try {
|
|
1600
1710
|
var w = f_lambertw(Math.log(v));
|
|
@@ -2063,9 +2173,21 @@
|
|
|
2063
2173
|
if (other.eq(MetaNum.ONE)) return self.clone();
|
|
2064
2174
|
if (frac.eq(MetaNum.ZERO)) return self.arrow(nLev)(other);
|
|
2065
2175
|
var target = self.arrow(nLev)(other);
|
|
2066
|
-
var
|
|
2176
|
+
var lev1 = nLev.add(MetaNum.ONE);
|
|
2177
|
+
var theta0 = hyperAnchorReal(self, lev1, target);
|
|
2178
|
+
if (theta0 === null) theta0 = target.hyper_log(self)(lev1);
|
|
2179
|
+
if (theta0.isNaN() || !(theta0.gt(MetaNum.ZERO))) theta0 = MetaNum.ONE.clone();
|
|
2067
2180
|
var theta = theta0.mul(other.div(theta0).pow(frac));
|
|
2068
|
-
|
|
2181
|
+
var res = self.arrow(lev1)(theta);
|
|
2182
|
+
if (hasFractionOutsideR00(res)) {
|
|
2183
|
+
// levels that diagonalize into ordinal rows would keep the
|
|
2184
|
+
// interpolated argument as a fractional row count — fall back to the
|
|
2185
|
+
// integer argument so the "only array[0][0] is fractional" contract
|
|
2186
|
+
// holds (floor is exact again at f = 1, where θ = y)
|
|
2187
|
+
var ti = Math.max(1, Math.floor(theta.toNumber()));
|
|
2188
|
+
if (isFinite(ti)) res = self.arrow(lev1)(new MetaNum(ti));
|
|
2189
|
+
}
|
|
2190
|
+
return res;
|
|
2069
2191
|
};
|
|
2070
2192
|
}
|
|
2071
2193
|
return function () { return MetaNum.NaN.clone(); };
|
|
@@ -2393,6 +2515,29 @@
|
|
|
2393
2515
|
return hi;
|
|
2394
2516
|
}
|
|
2395
2517
|
|
|
2518
|
+
// Continuous inverse used as the interpolation ANCHOR of a fractional level:
|
|
2519
|
+
// the real c with a{b}c = d, searched by bisection on doubles (arrow()
|
|
2520
|
+
// evaluates fractional arguments). hyperBisect only searches integers and
|
|
2521
|
+
// therefore overshoots (θ0 = 2 where the true value is 1.0414), which makes
|
|
2522
|
+
// the geometric interpolation θ = θ0·(y/θ0)^f run BACKWARDS (y/θ0 < 1) and
|
|
2523
|
+
// breaks the monotonicity of x{y}y — arrow(10,1.5,1.5) came out smaller than
|
|
2524
|
+
// arrow(10,1.1,1.1). Returns null when d cannot be bracketed.
|
|
2525
|
+
function hyperAnchorReal(a, b, d) {
|
|
2526
|
+
try {
|
|
2527
|
+
var lo = 0, hi = 1, it = 0;
|
|
2528
|
+
while (it++ < 60 && a.arrow(b)(new MetaNum(hi)).lt(d)) { lo = hi; hi = hi * 2; }
|
|
2529
|
+
if (!isFinite(hi) || hi > 1e15) return null;
|
|
2530
|
+
for (var k = 0; k < 80; k++) {
|
|
2531
|
+
var mid = (lo + hi) / 2;
|
|
2532
|
+
if (a.arrow(b)(new MetaNum(mid)).lt(d)) lo = mid; else hi = mid;
|
|
2533
|
+
}
|
|
2534
|
+
var r = new MetaNum((lo + hi) / 2);
|
|
2535
|
+
return r.isNaN() ? null : r;
|
|
2536
|
+
} catch (e) {
|
|
2537
|
+
return null;
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2396
2541
|
P.hyper_log = function (a) {
|
|
2397
2542
|
var d = this.clone();
|
|
2398
2543
|
a = new MetaNum(a);
|
|
@@ -2814,6 +2959,22 @@
|
|
|
2814
2959
|
for (var j = 0; j < keep.length; j++) arr.push(keep[j]);
|
|
2815
2960
|
}
|
|
2816
2961
|
|
|
2962
|
+
// Layer marker WITHOUT the standard-form rewrites. hardy's tower rule needs
|
|
2963
|
+
// the layer to track the input's 10^ levels one-for-one — the standard
|
|
2964
|
+
// de-layer ((b) above) would fold a finite-bracket marker (e.g. the
|
|
2965
|
+
// layer-2 [[3086.036,9×8]] of eee10) down one layer and change the number
|
|
2966
|
+
// the rule is about. Same shape as _layerMarker, minus the rewrites.
|
|
2967
|
+
Q._rawLayerMarker = function (r0, layer, rows) {
|
|
2968
|
+
var v = new MetaNum(0);
|
|
2969
|
+
v.sign = 1;
|
|
2970
|
+
v.layer = layer > 0 ? layer : 0;
|
|
2971
|
+
v.array = [(r0 && r0.length) ? r0.slice() : [0]];
|
|
2972
|
+
for (var i = 0; i < (rows ? rows.length : 0); i++) {
|
|
2973
|
+
if (rows[i] && rows[i].length > 1) v.array.push(rows[i].slice());
|
|
2974
|
+
}
|
|
2975
|
+
return v;
|
|
2976
|
+
};
|
|
2977
|
+
|
|
2817
2978
|
Q._standardizeLayerValue = function (v) {
|
|
2818
2979
|
if (!v || v.layer < 1) return v.normalize();
|
|
2819
2980
|
var L = v.layer;
|
|
@@ -2895,12 +3056,16 @@
|
|
|
2895
3056
|
var V = V0.clone();
|
|
2896
3057
|
var i = 0;
|
|
2897
3058
|
var guard = 0;
|
|
2898
|
-
|
|
2899
|
-
|
|
3059
|
+
// a fractional argument (yCnt - 1) still means a whole number of
|
|
3060
|
+
// applications, and the rows must carry INTEGER counts — ceil keeps the
|
|
3061
|
+
// step consistent with the expanded path (count = ceil(y)-2)
|
|
3062
|
+
var total = Math.ceil(iters);
|
|
3063
|
+
while (i < total) {
|
|
3064
|
+
if (++guard > 200) return Q._applyOrdinalRows(V, beta, total - i);
|
|
2900
3065
|
var vCnt = metaFiniteCount(V);
|
|
2901
3066
|
if (!(vCnt <= MAX_SAFE_INTEGER)) {
|
|
2902
3067
|
// V is huge: every further application adds one β-row → fast-forward
|
|
2903
|
-
return Q._applyOrdinalRows(V, beta,
|
|
3068
|
+
return Q._applyOrdinalRows(V, beta, total - i);
|
|
2904
3069
|
}
|
|
2905
3070
|
V = Q._ordinalHyperop(x, V, beta, (depth || 0) + 1);
|
|
2906
3071
|
i++;
|
|
@@ -2975,13 +3140,12 @@
|
|
|
2975
3140
|
for (var bi = 2; bi < pred.length; bi++) if ((pred[bi] || 0) > 0) bigLevel = true;
|
|
2976
3141
|
if (xOkS && bigLevel && ym <= 100000) {
|
|
2977
3142
|
// successor rule written in the EXPANDED form (the same generator the
|
|
2978
|
-
// integer arguments use):
|
|
2979
|
-
//
|
|
2980
|
-
//
|
|
2981
|
-
// x^f
|
|
2982
|
-
//
|
|
2983
|
-
//
|
|
2984
|
-
// ω one (ω+1 levels), x{x}x otherwise.
|
|
3143
|
+
// integer arguments use): the α-1 row carries the m applications as an
|
|
3144
|
+
// integer count ceil(y)-2 = m-1, and the fraction lives in the cascade
|
|
3145
|
+
// depth — the first fundamental sequence is taken at the fractional
|
|
3146
|
+
// start value x^f (x{α}(m+f) = x{α-1}^m(x^f) — exactly what the finite
|
|
3147
|
+
// levels do: 10{3}2.1 starts from 10^0.1). Whatever fraction is left
|
|
3148
|
+
// over lands in the base, i.e. in array[0][0].
|
|
2985
3149
|
return Q._expandedHyperop(x, new MetaNum(ym + 1), cf0,
|
|
2986
3150
|
Math.pow(xnfS, Number((yFracNum - ym).toPrecision(15))));
|
|
2987
3151
|
}
|
|
@@ -3057,14 +3221,19 @@
|
|
|
3057
3221
|
// into the base x and every row carries x-2 — including for 100 < y ≤ MSI
|
|
3058
3222
|
// (h20(10,1000) stays an expanded cascade, not a one-row marker).
|
|
3059
3223
|
// ---------------------------------------------------------------------------
|
|
3060
|
-
//
|
|
3061
|
-
//
|
|
3062
|
-
//
|
|
3063
|
-
//
|
|
3064
|
-
//
|
|
3224
|
+
// Only array[0][0] (the base's value slot) may ever be non-integer — the same
|
|
3225
|
+
// contract as arrow(): every row count and every row coefficient is an integer.
|
|
3226
|
+
// A fractional argument therefore enters in two integer-safe places:
|
|
3227
|
+
// - the outer count is `yn - 2` with yn = ceil(y) (an integer);
|
|
3228
|
+
// - the rest of the fraction sits in the CASCADE DEPTH: the first
|
|
3229
|
+
// fundamental sequence is taken at the fractional start value x^f
|
|
3230
|
+
// (x{α}(m+f) = x{α-1}^m(x^f)), and any fractional constant term left over
|
|
3231
|
+
// is carried into the base's finite level index (x{10.16}x), so it ends up
|
|
3232
|
+
// as the fractional array[0][0] exactly like arrow() does.
|
|
3233
|
+
// `fsOpd` is that fractional start value; `.baseIdx` returns the base index.
|
|
3065
3234
|
Q._cascadeRows = function (xn, cf, yn, budget, fsOpd) {
|
|
3066
3235
|
var rows = [];
|
|
3067
|
-
if (!(budget >= 1)) return
|
|
3236
|
+
if (!(budget >= 1)) return rows;
|
|
3068
3237
|
var cfs = trimCoeffs((cf || []).slice());
|
|
3069
3238
|
var opd = Math.min(yn, MAX_SAFE_INTEGER);
|
|
3070
3239
|
var first = (cfs[0] || 0) > 0; // successor: the outer count is y-2
|
|
@@ -3077,10 +3246,8 @@
|
|
|
3077
3246
|
if ((cfs[0] || 0) > 0) {
|
|
3078
3247
|
var mRaw = cfs[0];
|
|
3079
3248
|
var m = Math.floor(mRaw);
|
|
3080
|
-
// a fractional constant term
|
|
3081
|
-
//
|
|
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
|
|
3249
|
+
// a fractional constant term is not a valid CNF coefficient: keep the
|
|
3250
|
+
// integer part as rows and carry the remainder to the base
|
|
3084
3251
|
var mFr = Number((mRaw - m).toPrecision(15));
|
|
3085
3252
|
if (mFr > 1e-9) fracRem = mFr;
|
|
3086
3253
|
var beta = trimCoeffs(cfs.slice());
|
|
@@ -3091,13 +3258,15 @@
|
|
|
3091
3258
|
var j = m - 1 - s; // rows β+m-1 … β
|
|
3092
3259
|
var cnt = (first ? opd : xn) - 2;
|
|
3093
3260
|
first = false;
|
|
3094
|
-
if (cnt < 1) continue;
|
|
3261
|
+
if (cnt < 1) continue; // no application to record
|
|
3095
3262
|
if (cnt > MAX_SAFE_INTEGER) cnt = MAX_SAFE_INTEGER;
|
|
3096
3263
|
var ord = beta.slice();
|
|
3097
3264
|
if (j > 0) ord[0] = (ord[0] || 0) + j; // β + j
|
|
3098
3265
|
ord = trimCoeffs(ord);
|
|
3099
3266
|
if (!coeffsHaveOmegaPart(ord)) continue; // finite: lives in r0
|
|
3100
|
-
|
|
3267
|
+
var row = [snapInt(cnt)];
|
|
3268
|
+
for (var oi = 0; oi < ord.length; oi++) row.push(snapInt(ord[oi]));
|
|
3269
|
+
rows.push(row);
|
|
3101
3270
|
}
|
|
3102
3271
|
cfs = beta; // continue below β
|
|
3103
3272
|
opd = Math.min(xn, MAX_SAFE_INTEGER); // everything below the top
|
|
@@ -3127,7 +3296,9 @@
|
|
|
3127
3296
|
Q._expandedHyperop = function (x, y, cf, fsOpd) {
|
|
3128
3297
|
var maxRows = MetaNum.maxRows;
|
|
3129
3298
|
var xn = Math.floor(metaFiniteCount(x));
|
|
3130
|
-
|
|
3299
|
+
// ceil: the outer count must stay an integer (only array[0][0] may be
|
|
3300
|
+
// fractional), so the m applications of x{α}(m+f) give ceil(y)-2 = m-1
|
|
3301
|
+
var yn = Math.ceil(metaFiniteCount(y));
|
|
3131
3302
|
var budget = maxRows - 1; // ordinal rows the array holds
|
|
3132
3303
|
var desc = Q._cascadeRows(xn, cf, yn, budget + 1, fsOpd); // +1 detects truncation
|
|
3133
3304
|
var truncated = desc.length > budget;
|
|
@@ -3153,6 +3324,28 @@
|
|
|
3153
3324
|
return result.normalize();
|
|
3154
3325
|
};
|
|
3155
3326
|
|
|
3327
|
+
// Floating-point residue: 2.1e-12 left where the exact value is an integer.
|
|
3328
|
+
// Only array[0][0] may be fractional, so snap everything else.
|
|
3329
|
+
function snapInt(v) {
|
|
3330
|
+
if (!isFinite(v)) return v;
|
|
3331
|
+
var r = Math.round(v);
|
|
3332
|
+
return Math.abs(v - r) < 1e-9 ? r : v;
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
// Does any entry outside array[0][0] carry a fractional part?
|
|
3336
|
+
function hasFractionOutsideR00(v) {
|
|
3337
|
+
if (!v || !v.array) return false;
|
|
3338
|
+
for (var i = 0; i < v.array.length; i++) {
|
|
3339
|
+
var row = v.array[i];
|
|
3340
|
+
for (var j = 0; j < row.length; j++) {
|
|
3341
|
+
if (i === 0 && j === 0) continue;
|
|
3342
|
+
var c = row[j];
|
|
3343
|
+
if (typeof c === "number" && isFinite(c) && c !== Math.floor(c)) return true;
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
return false;
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3156
3349
|
// Any coefficient with a non-zero fractional part?
|
|
3157
3350
|
function coeffsHaveFraction(coeffs) {
|
|
3158
3351
|
for (var i = 0; i < coeffs.length; i++) {
|
|
@@ -3667,6 +3860,17 @@
|
|
|
3667
3860
|
cfw.push(cfac);
|
|
3668
3861
|
return Q._hyperopFromOrdinal(x, x, cfw);
|
|
3669
3862
|
}
|
|
3863
|
+
// marker form: ω^m·(x^f) — the count must stay an integer, so write the
|
|
3864
|
+
// fractional part out one level down: ω^m·floor(c) + ω^(m-1)·(x·frac),
|
|
3865
|
+
// the same resolution the CNF levels use
|
|
3866
|
+
if (mf >= MetaNum.maxCols) {
|
|
3867
|
+
var cfFl = Math.floor(cfac), cfFr = cfac - cfFl;
|
|
3868
|
+
var mkRows = [];
|
|
3869
|
+
if (cfFl >= 1) mkRows.push([cfFl, mf]);
|
|
3870
|
+
if (cfFr > 1e-9 && mf >= 2) mkRows.push([Math.max(1, Math.round(xnf * cfFr)), mf - 1]);
|
|
3871
|
+
if (mkRows.length === 0) mkRows.push([1, mf]);
|
|
3872
|
+
return Q._layerMarker([10], 1, mkRows);
|
|
3873
|
+
}
|
|
3670
3874
|
return Q._layerMarker([10], 1, [[cfac, mf]]);
|
|
3671
3875
|
}
|
|
3672
3876
|
// ordinal / out-of-range operand: y plus one ω^ω marker row
|
|
@@ -4118,7 +4322,13 @@
|
|
|
4118
4322
|
if (yc <= MAX_SAFE_INTEGER) {
|
|
4119
4323
|
var m = Math.max(2, Math.floor(yc));
|
|
4120
4324
|
if (m > MAX_SAFE_INTEGER) m = MAX_SAFE_INTEGER;
|
|
4121
|
-
|
|
4325
|
+
// v2.0.2: a fractional height (hardy of anything between 10^^m and
|
|
4326
|
+
// 10^^(m+1)) interpolates through the base argument 10+f instead of being
|
|
4327
|
+
// flat across the whole range — and only array[0][0] stays fractional
|
|
4328
|
+
var marker = Q._layerMarker([10], m, [[1, 1]]);
|
|
4329
|
+
var mf = Number((yc - Math.floor(yc)).toPrecision(15));
|
|
4330
|
+
if (isFinite(mf) && mf > 0) marker.array[0][0] = 10 + mf; // stays in array[0][0]
|
|
4331
|
+
return marker;
|
|
4122
4332
|
}
|
|
4123
4333
|
// ordinal / out-of-range operand: ε₀ caps the library → the MSI ω-tower
|
|
4124
4334
|
return Q._layerMarker([10], MAX_SAFE_INTEGER, [[1, 1]]);
|
|
@@ -4663,7 +4873,7 @@
|
|
|
4663
4873
|
if (this.isNaN()) return "NaN";
|
|
4664
4874
|
if (this.isInfinite()) return "Infinity";
|
|
4665
4875
|
if (isSimple(this)) {
|
|
4666
|
-
var v = decimalPlaces(this
|
|
4876
|
+
var v = decimalPlaces(magnitudeOf(this), places); // sub-unit r0 = reciprocal
|
|
4667
4877
|
if (Number.isFinite(v)) return v.toString();
|
|
4668
4878
|
}
|
|
4669
4879
|
return this.toString();
|
|
@@ -4679,7 +4889,14 @@
|
|
|
4679
4889
|
if (typeof require == 'function') {
|
|
4680
4890
|
try { formatter = require('./format-metanum.js').format; } catch (e) { formatter = null; }
|
|
4681
4891
|
}
|
|
4682
|
-
|
|
4892
|
+
if (!formatter && typeof format === 'function') formatter = format; // browser bundle
|
|
4893
|
+
if (!formatter) {
|
|
4894
|
+
// No formatter available (bare browser include): fall back to the plain
|
|
4895
|
+
// decimal expansion rather than throwing ReferenceError.
|
|
4896
|
+
var plain = this.toNumber();
|
|
4897
|
+
return isFinite(plain) ? String(plain) : this.toString();
|
|
4898
|
+
}
|
|
4899
|
+
return formatter(this, precision, small);
|
|
4683
4900
|
};
|
|
4684
4901
|
|
|
4685
4902
|
P.toExponential = function (places) {
|
|
@@ -4711,7 +4928,7 @@
|
|
|
4711
4928
|
if (this.isNaN()) return "NaN";
|
|
4712
4929
|
if (this.isInfinite()) return "Infinity";
|
|
4713
4930
|
if (isSimple(this)) {
|
|
4714
|
-
var v = this
|
|
4931
|
+
var v = magnitudeOf(this); // sub-unit r0 holds the reciprocal
|
|
4715
4932
|
if (v < 10) return String(v);
|
|
4716
4933
|
return "E" + Math.log10(v).toFixed(6);
|
|
4717
4934
|
}
|
|
@@ -4937,6 +5154,24 @@
|
|
|
4937
5154
|
return x;
|
|
4938
5155
|
}
|
|
4939
5156
|
|
|
5157
|
+
// v2.0.2: "1e10+0.5" / "1e10+11" / "1e16+1e13" — the digit paths (hardy)
|
|
5158
|
+
// need the exact decimal value and the plain float parse reads 0 here.
|
|
5159
|
+
// Split the sum and add the parts exactly; the '+' must not be the e+
|
|
5160
|
+
// exponent marker ("1e+21" keeps its old parsing).
|
|
5161
|
+
if (s.indexOf('+') > 0) {
|
|
5162
|
+
var sumParts = s.split('+');
|
|
5163
|
+
if (sumParts.length === 2 && sumParts[0] !== '' && sumParts[1] !== '' &&
|
|
5164
|
+
!/[eE]$/.test(sumParts[0]) && !/[eE]$/.test(sumParts[1])) {
|
|
5165
|
+
var sumA = Q.fromString(sumParts[0].trim());
|
|
5166
|
+
var sumB = Q.fromString(sumParts[1].trim());
|
|
5167
|
+
if (!sumA.isNaN() && !sumB.isNaN()) {
|
|
5168
|
+
var sumV = sumA.add(sumB);
|
|
5169
|
+
if (negateIt) sumV.sign = -sumV.sign;
|
|
5170
|
+
return sumV;
|
|
5171
|
+
}
|
|
5172
|
+
}
|
|
5173
|
+
}
|
|
5174
|
+
|
|
4940
5175
|
var layerMatch = s.match(/^\u03C9\^(\d+)\s*/);
|
|
4941
5176
|
if (layerMatch) {
|
|
4942
5177
|
x.layer = parseInt(layerMatch[1], 10);
|
|
@@ -5773,6 +6008,12 @@
|
|
|
5773
6008
|
// deep for inputs like hardy(1e10+20) where n1≈40 makes every ω^j segment
|
|
5774
6009
|
// take the exact branch: Maximum call stack size exceeded).
|
|
5775
6010
|
Q._hardyH = function (coeffs, nArg) {
|
|
6011
|
+
// Coefficients are read/written STRUCTURALLY below (c[j] -= 1, c[j-1] = n,
|
|
6012
|
+
// c_j compared against HARDY_EXACT_BOUND) and a fractional coefficient is
|
|
6013
|
+
// the normal case once the running base is 10+f — the sub-unit canonical
|
|
6014
|
+
// form must not rewrite them into reciprocals.
|
|
6015
|
+
_skipCanon++;
|
|
6016
|
+
try {
|
|
5776
6017
|
function MN(v) { return (v instanceof MetaNum) ? v.clone() : new MetaNum(v || 0); }
|
|
5777
6018
|
var c = [];
|
|
5778
6019
|
for (var i0 = 0; i0 < coeffs.length; i0++) c.push(MN(coeffs[i0]));
|
|
@@ -5807,6 +6048,19 @@
|
|
|
5807
6048
|
n = nWf;
|
|
5808
6049
|
continue;
|
|
5809
6050
|
}
|
|
6051
|
+
if (j >= c.length) return n; // no positive term left (safety net)
|
|
6052
|
+
// A coefficient can turn FRACTIONAL because the fundamental-sequence step
|
|
6053
|
+
// writes the running base n — and n is 10+f for a fractional hardy input
|
|
6054
|
+
// (hardy(1000.5)). For 0 < c_j < 1 the "-1" step would go negative and
|
|
6055
|
+
// leave no positive term at all, so take the PARTIAL step instead:
|
|
6056
|
+
// ω^j·f contributes ω^(j-1)·(n·f) (continuous — f→1 is the full
|
|
6057
|
+
// ω^(j-1)·n step of the integer recursion, f→0 contributes nothing)
|
|
6058
|
+
var cjN = c[j].toNumber();
|
|
6059
|
+
if (isFinite(cjN) && cjN > 0 && cjN < 1 && j >= 2) {
|
|
6060
|
+
c[j] = MetaNum.ZERO.clone();
|
|
6061
|
+
c[j - 1] = n.mul(new MetaNum(Number(cjN.toPrecision(15))));
|
|
6062
|
+
continue;
|
|
6063
|
+
}
|
|
5810
6064
|
if (c[j].gt(HARDY_EXACT_BOUND)) { // engine collapse
|
|
5811
6065
|
// H_{β + ω^j·c}(n) ≈ H_β(2{c}j) — evaluate with the OLD c[j]
|
|
5812
6066
|
var nCol = new MetaNum(2).arrow(j)(c[j]);
|
|
@@ -5823,6 +6077,97 @@
|
|
|
5823
6077
|
}
|
|
5824
6078
|
// budget exhausted: keep whatever was accumulated (monotone)
|
|
5825
6079
|
return n;
|
|
6080
|
+
} finally { _skipCanon--; }
|
|
6081
|
+
};
|
|
6082
|
+
|
|
6083
|
+
// H_{ω^k}(n) for the from-below base of hardy (n ≥ 1e10).
|
|
6084
|
+
// The exact expansion writes a tower of level k-1 — H_{ω^10}(10) =
|
|
6085
|
+
// 10{9}(11…21), H_{ω^20}(20) = 10{19}(21…22) — so array[0] holds k entries
|
|
6086
|
+
// and the step-by-step expansion only fits while k ≤ maxCols. Above that
|
|
6087
|
+
// the running base turns structured, the coefficients the limit steps write
|
|
6088
|
+
// from it turn structured too, and every later comparison / collapse becomes
|
|
6089
|
+
// meaningless: hardy(1e10+11) (k = n1 = 22) collapsed to [[1],[2,20]] — a
|
|
6090
|
+
// destroyed base with a bogus row — and hardy(1e16+1e13) (k = 28) likewise.
|
|
6091
|
+
// There the from-below value is taken from the engine instead: 10{k-1}(n+1)
|
|
6092
|
+
// is exactly the lower bound the exact expansion stays strictly above, so
|
|
6093
|
+
// hardy stays monotone and keeps its "strictly below the engine" property.
|
|
6094
|
+
Q._hardyOmegaPower = function (n1) {
|
|
6095
|
+
var n1Num = (n1.layer === 0 && n1.array.length === 1 && n1.array[0].length === 1) ? n1.toNumber() : Infinity;
|
|
6096
|
+
if (isFinite(n1Num) && n1Num >= 2) {
|
|
6097
|
+
var kFit = Math.floor(n1Num);
|
|
6098
|
+
if (kFit <= MetaNum.maxCols + 1) {
|
|
6099
|
+
// exact expansion — a fractional base (hardy("1e10+0.5"), n = 10+f)
|
|
6100
|
+
// flows through the fundamental-sequence steps (the partial-step rule
|
|
6101
|
+
// keeps the coefficients sane) and collapses into ONE plain row: the
|
|
6102
|
+
// fractional hyper-operation result, between hardy(1e10) and
|
|
6103
|
+
// hardy(1e10+1)
|
|
6104
|
+
var ec = [];
|
|
6105
|
+
for (var zi = 0; zi < kFit; zi++) ec.push(0);
|
|
6106
|
+
ec.push(1);
|
|
6107
|
+
return Q._hardyH(ec, n1);
|
|
6108
|
+
}
|
|
6109
|
+
// n1 > maxCols+1: the exact tower [c0, (n1-1)×(n1-2)] no longer fits the
|
|
6110
|
+
// array (22 entries for n1 = 22, maxCols = 20). Keep the TRUNCATED
|
|
6111
|
+
// cascade instead of the engine value 10{n1-1}(n1+1): the tower level
|
|
6112
|
+
// n1-1 over the definitional base — hardy("1e10+11") =
|
|
6113
|
+
// [3086.036…, 21×19] (the user-visible [非整数, 21, 21, …, 21] shape),
|
|
6114
|
+
// strictly above hardy("1e10+10")'s exact [6313063, 19×18] (the level 21
|
|
6115
|
+
// dominates the level 19) and still far below the matching engine
|
|
6116
|
+
// ordinal op 10{ω^ω+ω+1}10.
|
|
6117
|
+
var lv = Math.floor(n1Num) - 1;
|
|
6118
|
+
var depth = Math.min(Math.floor(n1Num) - 2, MetaNum.maxCols - 1);
|
|
6119
|
+
var r0 = Q._hardyBaseR0();
|
|
6120
|
+
var arr = [r0[0]];
|
|
6121
|
+
for (var di = 0; di < depth; di++) arr.push(lv);
|
|
6122
|
+
var out = new MetaNum(0);
|
|
6123
|
+
out.array = [arr];
|
|
6124
|
+
return out.normalize();
|
|
6125
|
+
}
|
|
6126
|
+
// structured / fractional operand: one ω-diagonal row (engine convention)
|
|
6127
|
+
return Q._applyOrdinalRows(n1, [0, 1], 1);
|
|
6128
|
+
};
|
|
6129
|
+
|
|
6130
|
+
// Decimal digit string of a plain number stored as r0 = [v, 1] (= 10^v),
|
|
6131
|
+
// or null when the value is not in that form / has no finite exponent.
|
|
6132
|
+
// Only an actual POWER TOWER is excluded: 10^^k has the same r0 shape but
|
|
6133
|
+
// v ≥ 1e10, so "1e100000" (= 10^100000, v = 100000) is a plain number and
|
|
6134
|
+
// keeps the ordinary digit path — the old guard rejected exponents above
|
|
6135
|
+
// 1e5 and pushed hardy("1e100000") into the tower branch (layer 1).
|
|
6136
|
+
Q._hardyDigitsOfPowForm = function (r0) {
|
|
6137
|
+
if (!r0 || r0.length !== 2 || r0[1] !== 1 || !isFinite(r0[0])) return null;
|
|
6138
|
+
if (r0[0] >= 1e10) return null; // power tower → slog branch
|
|
6139
|
+
var exN = Math.floor(r0[0]);
|
|
6140
|
+
if (exN < 0 || exN > 1000000) return null; // digit string budget
|
|
6141
|
+
var mantN = Math.pow(10, r0[0] - exN);
|
|
6142
|
+
if (!isFinite(mantN)) return null;
|
|
6143
|
+
// the exponent is stored with ~15 significant digits, so the reconstructed
|
|
6144
|
+
// mantissa carries a rounding tail — 2e1000 is stored as 10^1000.301029995664
|
|
6145
|
+
// and 10^0.301029995664 = 1.9999999999999…, which would spell the digits
|
|
6146
|
+
// "19999…9" instead of "2000…0". Round the mantissa to the digits the
|
|
6147
|
+
// exponent can actually hold before spelling it out.
|
|
6148
|
+
if (mantN > 0) mantN = Number(mantN.toPrecision(12));
|
|
6149
|
+
if (mantN >= 10 - 1e-9) { mantN /= 10; exN += 1; }
|
|
6150
|
+
var digN = String(mantN).replace('.', '');
|
|
6151
|
+
var zeroN = exN - (digN.length - 1);
|
|
6152
|
+
if (zeroN < 0) return null;
|
|
6153
|
+
return digN + '0'.repeat(zeroN);
|
|
6154
|
+
};
|
|
6155
|
+
|
|
6156
|
+
// r0 of the definitional from-below base H_{ω^10}(10) = 10{9}(11…21) — the
|
|
6157
|
+
// base every hardy(n ≥ 1e10) value is built on.
|
|
6158
|
+
Q._hardyBaseR0 = function () {
|
|
6159
|
+
return Q._hardyOmegaPower(MetaNum.TEN.clone()).array[0].slice();
|
|
6160
|
+
};
|
|
6161
|
+
|
|
6162
|
+
// issues.md truncation marker: once the ordinal rows overflow, the engine
|
|
6163
|
+
// collapses the base to [10]. hardy keeps its definitional base instead —
|
|
6164
|
+
// every level above it is carried by the ordinal rows, so the truncation
|
|
6165
|
+
// loses nothing but the unnameable low levels, and the value stays bigger
|
|
6166
|
+
// than the marker base (hardy is monotone across the truncation point).
|
|
6167
|
+
Q._hardyKeepBase = function (v) {
|
|
6168
|
+
var r0 = v.array[0];
|
|
6169
|
+
if (r0 && r0.length === 1 && r0[0] === 10) v.array[0] = Q._hardyBaseR0();
|
|
6170
|
+
return v;
|
|
5826
6171
|
};
|
|
5827
6172
|
|
|
5828
6173
|
// MetaNum.hardy(n): the Hardy level of n.
|
|
@@ -5830,6 +6175,29 @@
|
|
|
5830
6175
|
// coefficients of an ordinal α (hardy(1234) = H_{ω³+ω²·2+ω·3+4}(10)) and
|
|
5831
6176
|
// the result is H_α(10).
|
|
5832
6177
|
Q.hardy = function (n) {
|
|
6178
|
+
// A plain JS number / numeric string keeps its own decimal expansion: from
|
|
6179
|
+
// 1e16 on the library stores the value as 10^v (r0 = [v,1]) and the way
|
|
6180
|
+
// back through the double loses the low digits — hardy(1e16+1e13) =
|
|
6181
|
+
// hardy(10010000000000000) reads back as 10010000000000014, so the digit
|
|
6182
|
+
// path would take 14 instead of 1e13 as the "rest" of the ordinal.
|
|
6183
|
+
var rawNum = (typeof n === 'number') ? n
|
|
6184
|
+
: (typeof n === 'string' ? Number(n) : null);
|
|
6185
|
+
// v2.0.2: "1e10+0.5" / "1e10+11" / "1e16+1e13" — the digit path needs the
|
|
6186
|
+
// exact decimal value, and Number('1e10+0.5') is NaN (the old path read 0 →
|
|
6187
|
+
// hardy(0) = 10 → the [10] base). Split the sum and add the parts exactly.
|
|
6188
|
+
if (typeof n === 'string' && n.indexOf('+') > 0) {
|
|
6189
|
+
var plusParts = n.split('+');
|
|
6190
|
+
if (plusParts.length === 2 && plusParts[0] !== '' && plusParts[1] !== '' &&
|
|
6191
|
+
!/[eE]$/.test(plusParts[0]) && !/[eE]$/.test(plusParts[1])) {
|
|
6192
|
+
var pvA = new MetaNum(plusParts[0].trim());
|
|
6193
|
+
var pvB = new MetaNum(plusParts[1].trim());
|
|
6194
|
+
if (!pvA.isNaN() && !pvB.isNaN()) {
|
|
6195
|
+
n = pvA.add(pvB);
|
|
6196
|
+
rawNum = null;
|
|
6197
|
+
}
|
|
6198
|
+
}
|
|
6199
|
+
}
|
|
6200
|
+
if (rawNum !== null && !isFinite(rawNum)) rawNum = null;
|
|
5833
6201
|
n = new MetaNum(n);
|
|
5834
6202
|
if (n.sign !== 1) {
|
|
5835
6203
|
throw Error(metaNumError + 'hardy: n must be a non-negative integer');
|
|
@@ -5841,9 +6209,23 @@
|
|
|
5841
6209
|
// hardy(10^^MSI) = the MetaNum limit exactly (slog(10^^MSI) = MSI).
|
|
5842
6210
|
// Ordinal-row / ε-layer values sit at their own Hardy position
|
|
5843
6211
|
// (H_{ω^β}(10) = 10{β}10) and map to themselves.
|
|
5844
|
-
var num = (
|
|
6212
|
+
var num = (rawNum !== null) ? rawNum
|
|
6213
|
+
: ((n.layer === 0 && n.array.length === 1) ? n.toNumber() : Infinity);
|
|
6214
|
+
// r0 = [v, 1] means 10^v — the plain-number form the library uses once a
|
|
6215
|
+
// value leaves the plain-integer range. Read the decimal expansion off
|
|
6216
|
+
// that mantissa/exponent pair when the double itself is unavailable
|
|
6217
|
+
// (hardy("1.8e308") — beyond Number.MAX_VALUE).
|
|
6218
|
+
var hStr = (rawNum === null && n.layer === 0 && n.array.length === 1)
|
|
6219
|
+
? Q._hardyDigitsOfPowForm(n.array[0]) : null;
|
|
5845
6220
|
if (!isFinite(num)) {
|
|
5846
6221
|
if (n.layer === 0 && n.array.length === 1) {
|
|
6222
|
+
// v2.0.2: a PLAIN number that merely exceeds the double range (hardy
|
|
6223
|
+
// ("1.8e308") — 1.8e308 > Number.MAX_VALUE) is not a power tower, so it
|
|
6224
|
+
// must not fall into the tower branch: read its decimal expansion and
|
|
6225
|
+
// keep the ordinary digit path (hardy(1.8e308) stays layer 0).
|
|
6226
|
+
// (A tower 10^^k has the same shape but v ≥ 1e10, so the size guard
|
|
6227
|
+
// below keeps towers on the slog branch.)
|
|
6228
|
+
if (hStr === null) {
|
|
5847
6229
|
var hVal = n.slog();
|
|
5848
6230
|
// a clean power tower shadows to ω^ω^…^ω (k ω's); slog(10^^k) = [[k]]
|
|
5849
6231
|
// (a plain single number — NOT the structured slog of, say, G600)
|
|
@@ -5851,20 +6233,82 @@
|
|
|
5851
6233
|
var hNum = hVal.toNumber();
|
|
5852
6234
|
if (isFinite(hNum) && hNum >= 2 && hNum <= Number.MAX_SAFE_INTEGER) {
|
|
5853
6235
|
// k ≤ MSI: the tower fits the engine limit (f_ε₀); k > MSI is
|
|
5854
|
-
// beyond ε₀ and the Hardy hierarchy is undefined there → Infinity
|
|
5855
|
-
|
|
6236
|
+
// beyond ε₀ and the Hardy hierarchy is undefined there → Infinity.
|
|
6237
|
+
// The ordinal is read off the value itself: V = 10^W gives
|
|
6238
|
+
// α = ω^ord(W), so the result is the ordinary cascade on the
|
|
6239
|
+
// from-below base while the tower height still leaves a readable
|
|
6240
|
+
// exponent (k ≤ 3 — hardy(ee10) = H_{ω^(ω^ω)}(10) = the ω^ω
|
|
6241
|
+
// cascade, layer 0 like iterate(10), not a layer-2 marker).
|
|
6242
|
+
// Above that the level no longer fits into ordinal rows and the
|
|
6243
|
+
// value becomes a layer marker whose layer is ceil(k) - 3:
|
|
6244
|
+
// ee10 < 10^(1e10+1) < ee20 … eee10 → layer 1
|
|
6245
|
+
// eee20 … eeee10 → layer 2, and so on
|
|
6246
|
+
var r0T = n.array[0];
|
|
6247
|
+
// v2.0.2 (issues): clean power towers — EVERY extra 10^ level in
|
|
6248
|
+
// the input raises hardy's layer by ONE, the ordinal rows stay
|
|
6249
|
+
// those of the innermost readable expansion:
|
|
6250
|
+
// hardy("1e308") = the layer-0 digit-path cascade (…[8,6,0,3],[8,7,0,3])
|
|
6251
|
+
// hardy("e1e308") = the same rows at layer 1
|
|
6252
|
+
// hardy("ee1e308") = the same rows at layer 2, and so on.
|
|
6253
|
+
// The stored tower r0 = [v, k] is (k-1) further 10^ levels over
|
|
6254
|
+
// 10^v; a layer-L input adds L more levels on top.
|
|
6255
|
+
if (r0T && r0T.length === 2 && r0T[1] >= 1 &&
|
|
6256
|
+
r0T[1] === Math.floor(r0T[1]) &&
|
|
6257
|
+
isFinite(r0T[0]) && r0T[0] >= 10 &&
|
|
6258
|
+
(r0T[1] >= 2 || r0T[0] >= 1e10)) {
|
|
6259
|
+
var towerInner;
|
|
6260
|
+
if (r0T[1] >= 2) {
|
|
6261
|
+
// peel (k-1) levels at once: hardy = layerUp^(k-1)(hardy(10^v))
|
|
6262
|
+
var towerBase = new MetaNum(0);
|
|
6263
|
+
towerBase.sign = 1;
|
|
6264
|
+
towerBase.layer = 0;
|
|
6265
|
+
towerBase.array = [[r0T[0], 1]];
|
|
6266
|
+
towerInner = Q.hardy(towerBase); // hardy(10^v), layer 0/1
|
|
6267
|
+
return Q._rawLayerMarker(towerInner.array[0],
|
|
6268
|
+
n.layer + (r0T[1] - 1) + towerInner.layer,
|
|
6269
|
+
towerInner.array.slice(1));
|
|
6270
|
+
}
|
|
6271
|
+
// single 10^ level over a readable exponent: hardy(10^v) =
|
|
6272
|
+
// layerUp(hardy(v))
|
|
6273
|
+
towerInner = Q.hardy(r0T[0]);
|
|
6274
|
+
return Q._rawLayerMarker(towerInner.array[0], n.layer + 1,
|
|
6275
|
+
towerInner.array.slice(1));
|
|
6276
|
+
}
|
|
6277
|
+
if (hNum <= 3 && r0T && r0T.length === 2 && r0T[1] === 1 &&
|
|
6278
|
+
isFinite(r0T[0]) && r0T[0] >= 10) {
|
|
6279
|
+
return Q._hardyLeading(r0T[0], 1, MetaNum.TEN.clone());
|
|
6280
|
+
}
|
|
6281
|
+
var kc = Math.ceil(hNum - 1e-9);
|
|
6282
|
+
// position inside the band (kc-1, kc]: monotone in the tower height,
|
|
6283
|
+
// kept just below 1 so the layer does not jump at the band edge
|
|
6284
|
+
var kFrac = Math.min(Math.max(hNum - (kc - 1), 0), 0.999999);
|
|
6285
|
+
if (kc <= 4) {
|
|
6286
|
+
// layer 1: 10{ω^y}10 = L1 [[base],[1,y,1]] with y = ω + t, t
|
|
6287
|
+
// growing with the tower height so the band stays monotone —
|
|
6288
|
+
// the base is hardy's definitional from-below base, not the
|
|
6289
|
+
// bare [10] marker (issues: a truncated base keeps
|
|
6290
|
+
// [3086.036,9×8])
|
|
6291
|
+
var tv = Math.max(1, Math.round((hNum - 3) * 1e6));
|
|
6292
|
+
return Q._layerMarker(Q._hardyBaseR0(), 1, [[1, tv, 1]]);
|
|
6293
|
+
}
|
|
6294
|
+
// layer kc-3 ≥ 2: epsilonate(layer+1) carries the fractional tower
|
|
6295
|
+
// height in its base, so the band stays monotone as well
|
|
6296
|
+
// (beyond ~1e15 the fraction is not representable in the exponent)
|
|
6297
|
+
return MetaNum.TEN.epsilonate(
|
|
6298
|
+
kc > 1e15 ? (kc - 2) : (kc - 2 + kFrac)).normalize();
|
|
5856
6299
|
}
|
|
5857
6300
|
}
|
|
5858
6301
|
// layer-0 value beyond a clean 10^^k with k ≤ MSI: finite
|
|
5859
6302
|
// hyperoperations above tetration (G600, 3{9}3, …) or a tower taller
|
|
5860
6303
|
// than 10^^MSI exceed the library's ε₀ ceiling → Infinity
|
|
5861
6304
|
return new MetaNum(Infinity);
|
|
6305
|
+
}
|
|
5862
6306
|
}
|
|
5863
6307
|
// ordinal-row / ε-layer / letter-chain values sit at their own Hardy
|
|
5864
6308
|
// position (H_{ω^β}(10) = 10{β}10): map to themselves
|
|
5865
|
-
return n.clone().normalize();
|
|
6309
|
+
if (hStr === null) return n.clone().normalize();
|
|
5866
6310
|
}
|
|
5867
|
-
var s = String(num);
|
|
6311
|
+
var s = (hStr !== null) ? hStr : String(num);
|
|
5868
6312
|
// > 1e20 arrives in scientific notation ('1e+21') — expand to the exact
|
|
5869
6313
|
// decimal digits so the digit-reading stays monotone (issues.md v2.1:
|
|
5870
6314
|
// hardy must support > 1e15 inputs)
|
|
@@ -5874,6 +6318,17 @@
|
|
|
5874
6318
|
var eZeros = Number(eMatch[3]) - eFrac.length;
|
|
5875
6319
|
if (eZeros > 0) s = eMatch[1] + eFrac + '0'.repeat(eZeros);
|
|
5876
6320
|
}
|
|
6321
|
+
// v2.0.2: fractional argument. The ordinal is read from the INTEGER part's
|
|
6322
|
+
// digits while the base argument becomes 10+f, so H stays continuous in n:
|
|
6323
|
+
// hardy(10.38) = H_ω(10.38) = 10.38·2 = 20.76
|
|
6324
|
+
// hardy(100.1) = H_{ω²}(10.1) = 10.1·2^10.1 = 11084.709858935355
|
|
6325
|
+
var hFrac = 0;
|
|
6326
|
+
var hDot = s.indexOf('.');
|
|
6327
|
+
if (hDot >= 0) {
|
|
6328
|
+
hFrac = Number('0.' + s.slice(hDot + 1));
|
|
6329
|
+
s = s.slice(0, hDot);
|
|
6330
|
+
}
|
|
6331
|
+
var hArg = hFrac > 0 ? new MetaNum(10 + hFrac) : MetaNum.TEN.clone();
|
|
5877
6332
|
if (s.length >= 11) {
|
|
5878
6333
|
// n ≥ 1e10 (issues.md v2.0): the ordinal is built per definition, then
|
|
5879
6334
|
// evaluated from below on the engine's own representation:
|
|
@@ -5894,41 +6349,62 @@
|
|
|
5894
6349
|
var kExp = s.length - 1;
|
|
5895
6350
|
var dk = s.charCodeAt(0) - 48;
|
|
5896
6351
|
var restNum = Number(s.slice(1));
|
|
5897
|
-
var n1 =
|
|
5898
|
-
|
|
5899
|
-
//
|
|
5900
|
-
//
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
6352
|
+
var n1 = hArg.clone();
|
|
6353
|
+
// the fractional part flows into the rest part too: hardy("1e10+1.5")
|
|
6354
|
+
// = H_{ω^10}(hardy(1.5)) = H_{ω^10}(11.5) — dropping the fraction here
|
|
6355
|
+
// made every 1e10+k.f input behave like 1e10+k
|
|
6356
|
+
if (restNum > 0) n1 = Q.hardy(restNum + hFrac);
|
|
6357
|
+
return Q._hardyLeading(kExp, dk, n1);
|
|
6358
|
+
}
|
|
6359
|
+
if (num < 10) return new MetaNum(10 + num);
|
|
6360
|
+
var coeffs = [];
|
|
6361
|
+
for (var i = s.length - 1; i >= 0; i--) coeffs.push(s.charCodeAt(i) - 48);
|
|
6362
|
+
return Q._hardyH(coeffs, hArg);
|
|
6363
|
+
};
|
|
6364
|
+
|
|
6365
|
+
// The leading term ω^ord(kExp)·dk of hardy's ordinal, evaluated from below
|
|
6366
|
+
// on the already-computed lower part n1 = H_ord(rest)(10).
|
|
6367
|
+
Q._hardyLeading = function (kExp, dk, n1) {
|
|
6368
|
+
// a plain operand still has a single plain number as its whole array[0]
|
|
6369
|
+
var nPlain = (n1.layer === 0 && n1.array.length === 1 && n1.array[0].length === 1);
|
|
6370
|
+
var n1Num = nPlain ? n1.toNumber() : Infinity;
|
|
5911
6371
|
if (kExp === 10) {
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
//
|
|
6372
|
+
// H_{ω^ω·dk}(n1): the first ω^ω-segment is H_{ω^n1}(n1) (from below),
|
|
6373
|
+
// every further one adds one ω-row
|
|
6374
|
+
return Q._hardyKeepBase(
|
|
6375
|
+
Q._applyOrdinalRows(Q._hardyOmegaPower(n1), [0, 1], dk - 1)).normalize();
|
|
6376
|
+
}
|
|
6377
|
+
// kExp ≥ 11 (ord = ω+c): β = ord(kExp) and the leading term ω^β·dk is dk
|
|
6378
|
+
// APPLICATIONS of H_{ω^β}, one after the other on the running value:
|
|
6379
|
+
// hardy(1.1e11) = H_{ω^(ω+1)+ω^ω}(10) = H_{ω^(ω+1)}(H_{ω^ω}(10))
|
|
6380
|
+
// = [3086.036,9×8] [1,1,1] (one row per application)
|
|
6381
|
+
// hardy(2e11) = H_{ω^(ω+1)·2}(10) = H_{ω^(ω+1)}(H_{ω^(ω+1)}(10))
|
|
6382
|
+
// = [3086.036,9×8] [8,0,1] [1,1,1]
|
|
6383
|
+
// hardy(1e16+1e13) = H_{ω^(ω+6)}(H_{ω^(ω+3)}(10)) → … [1,6,1]
|
|
6384
|
+
// so an application is a row [1, β] — never a bump of the ω-row count
|
|
6385
|
+
// ([9,0,1] / [16,0,1] conflated dk with the rest-part). The FIRST
|
|
6386
|
+
// application on a plain operand is still expanded from below: the base
|
|
6387
|
+
// H_{ω^n1}(n1) plus the cascade of 10{β}10 (hardy(1e11) = [3086.036,9×8]
|
|
6388
|
+
// [8,0,1], strictly below 10{ω+1}10 — issues.md).
|
|
5918
6389
|
var ks = String(kExp);
|
|
5919
6390
|
var ordCoeffs = [];
|
|
5920
6391
|
for (var oi = ks.length - 1; oi >= 0; oi--) ordCoeffs.push(ks.charCodeAt(oi) - 48);
|
|
5921
|
-
var
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
6392
|
+
var out, extra;
|
|
6393
|
+
if (nPlain && isFinite(n1Num) && n1Num >= 2) {
|
|
6394
|
+
out = Q._hardyOmegaPower(n1);
|
|
6395
|
+
var mir = Q._hyperopFromOrdinalRaw(MetaNum.TEN.clone(), MetaNum.TEN.clone(), ordCoeffs);
|
|
6396
|
+
for (var ri = 1; ri < mir.array.length; ri++) {
|
|
6397
|
+
out = Q._applyOrdinalRows(out, mir.array[ri].slice(1), mir.array[ri][0]);
|
|
6398
|
+
}
|
|
6399
|
+
extra = dk - 1;
|
|
6400
|
+
} else {
|
|
6401
|
+
// structured operand: H_{ω^β} has no room left to expand into, so each
|
|
6402
|
+
// application is one more row [1, β]
|
|
6403
|
+
out = n1.clone();
|
|
6404
|
+
extra = dk;
|
|
5925
6405
|
}
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
if (num < 10) return new MetaNum(10 + num);
|
|
5929
|
-
var coeffs = [];
|
|
5930
|
-
for (var i = s.length - 1; i >= 0; i--) coeffs.push(s.charCodeAt(i) - 48);
|
|
5931
|
-
return Q._hardyH(coeffs, MetaNum.TEN.clone());
|
|
6406
|
+
if (extra > 0) out = Q._applyOrdinalRows(out, ordCoeffs, extra);
|
|
6407
|
+
return Q._hardyKeepBase(out).normalize();
|
|
5932
6408
|
};
|
|
5933
6409
|
|
|
5934
6410
|
// ==================== BEAF Array Notation ====================
|
|
@@ -6118,7 +6594,12 @@
|
|
|
6118
6594
|
}
|
|
6119
6595
|
|
|
6120
6596
|
var temp;
|
|
6597
|
+
// Public primitive input: a numeric literal / decimal string in (0,1) or
|
|
6598
|
+
// (-1,0) is stored as the reciprocal with sign 2 / -2. Array/object input
|
|
6599
|
+
// (engine internals, JSON, parsers) is left exactly as given.
|
|
6600
|
+
var publicInput = false;
|
|
6121
6601
|
if (typeof input === "number" && input2 === undefined) {
|
|
6602
|
+
publicInput = true;
|
|
6122
6603
|
temp = objectCreate();
|
|
6123
6604
|
temp.array = [[Math.abs(input)]];
|
|
6124
6605
|
temp.sign = input < 0 ? -1 : 1;
|
|
@@ -6128,6 +6609,7 @@
|
|
|
6128
6609
|
} else if (parsedObject) {
|
|
6129
6610
|
temp = Q.fromObject(parsedObject);
|
|
6130
6611
|
} else if (typeof input === "string") {
|
|
6612
|
+
publicInput = true;
|
|
6131
6613
|
temp = Q.fromString(input);
|
|
6132
6614
|
} else if (Array.isArray(input)) {
|
|
6133
6615
|
temp = Q.fromArray(input, input2, input3);
|
|
@@ -6136,6 +6618,7 @@
|
|
|
6136
6618
|
} else if (typeof input === "object" && input !== null) {
|
|
6137
6619
|
temp = Q.fromObject(input);
|
|
6138
6620
|
} else {
|
|
6621
|
+
publicInput = true;
|
|
6139
6622
|
temp = objectCreate();
|
|
6140
6623
|
var num = Number(input);
|
|
6141
6624
|
if (!isNaN(num) && isFinite(num)) {
|
|
@@ -6151,6 +6634,7 @@
|
|
|
6151
6634
|
temp.sign = num < 0 ? -1 : 1;
|
|
6152
6635
|
}
|
|
6153
6636
|
}
|
|
6637
|
+
if (publicInput) canonicalizeSubUnit(temp);
|
|
6154
6638
|
|
|
6155
6639
|
x.array = deepCloneArray(temp.array);
|
|
6156
6640
|
x.sign = temp.sign;
|
|
@@ -6330,6 +6814,63 @@
|
|
|
6330
6814
|
|
|
6331
6815
|
MetaNum = clone(MetaNum);
|
|
6332
6816
|
MetaNum = defineConstants(MetaNum);
|
|
6817
|
+
|
|
6818
|
+
// Sub-unit canonical form: run the engine's structural CONSUMERS with it off.
|
|
6819
|
+
// These functions read r0 as a plain magnitude and chain through log10/exp
|
|
6820
|
+
// (whose results are now canonicalized when a user calls them directly), so
|
|
6821
|
+
// without this they saw reciprocals where they expected values — gamma(0.5)
|
|
6822
|
+
// read r0 [2] as 2, slog computed from a 3.32 instead of 0.301, and
|
|
6823
|
+
// layeradd/pentate_log returned garbage. The PRODUCERS (constructor with a
|
|
6824
|
+
// primitive, add/sub/mul/div, log10, ln, exp, root, neg) stay canonicalized,
|
|
6825
|
+
// so MetaNum(0.5).sign === 2 and arithmetic results in (0,1) carry sign 2.
|
|
6826
|
+
(function () {
|
|
6827
|
+
var rawConsumers = [
|
|
6828
|
+
'gamma', 'lambertw', 'slog', 'layeradd', 'layeradd10',
|
|
6829
|
+
'pentate', 'pentate_log', 'pentate_root', 'ssrt', 'linear_sroot',
|
|
6830
|
+
'hyper_log', 'hyper_root', 'tetrate', 'expande', 'explode',
|
|
6831
|
+
'expandainate', 'expoiter', 'slayer', 'fastest_hypergrow',
|
|
6832
|
+
'logBase', 'mod', 'arrow'
|
|
6833
|
+
];
|
|
6834
|
+
for (var ri = 0; ri < rawConsumers.length; ri++) {
|
|
6835
|
+
var name = rawConsumers[ri];
|
|
6836
|
+
var fn = P[name];
|
|
6837
|
+
if (typeof fn !== 'function') continue;
|
|
6838
|
+
P[name] = (function (orig) {
|
|
6839
|
+
return function () {
|
|
6840
|
+
_skipCanon++;
|
|
6841
|
+
var out;
|
|
6842
|
+
try { out = orig.apply(this, arguments); }
|
|
6843
|
+
finally { _skipCanon--; }
|
|
6844
|
+
// The hyper-op builders (arrow, tetrate, expande, …) return a
|
|
6845
|
+
// CLOSURE that carries out the real computation — the guard is gone
|
|
6846
|
+
// by then, so the chain ran canonicalized and drifted by an ULP
|
|
6847
|
+
// (4{25}4 → 153.906997547968 instead of …802). Re-arm around it.
|
|
6848
|
+
if (typeof out === 'function') {
|
|
6849
|
+
return function () {
|
|
6850
|
+
_skipCanon++;
|
|
6851
|
+
try { return out.apply(this, arguments); }
|
|
6852
|
+
finally { _skipCanon--; }
|
|
6853
|
+
};
|
|
6854
|
+
}
|
|
6855
|
+
return out;
|
|
6856
|
+
};
|
|
6857
|
+
})(fn);
|
|
6858
|
+
}
|
|
6859
|
+
// Q-level entry points that drive the same structural machinery
|
|
6860
|
+
var rawStatics = ['BEAF', '_beafRecursive', 'arrow', 'beaf'];
|
|
6861
|
+
for (var si = 0; si < rawStatics.length; si++) {
|
|
6862
|
+
var sfn = Q[rawStatics[si]];
|
|
6863
|
+
if (typeof sfn !== 'function') continue;
|
|
6864
|
+
Q[rawStatics[si]] = (function (orig) {
|
|
6865
|
+
return function () {
|
|
6866
|
+
_skipCanon++;
|
|
6867
|
+
try { return orig.apply(this, arguments); }
|
|
6868
|
+
finally { _skipCanon--; }
|
|
6869
|
+
};
|
|
6870
|
+
})(sfn);
|
|
6871
|
+
}
|
|
6872
|
+
})();
|
|
6873
|
+
|
|
6333
6874
|
MetaNum['default'] = MetaNum.MetaNum = MetaNum;
|
|
6334
6875
|
|
|
6335
6876
|
if (typeof define == 'function' && define.amd) {
|