soiz1's picture
Upload 811 files
30c32c8 verified
raw
history blame
82 kB
// https://github.com/Naruyoko/ExpantaNum.js/blob/develop/ExpantaNum.js
//Code snippets and templates from Decimal.js
;(function (globalScope) {
"use strict";
// -- EDITABLE DEFAULTS -- //
var ExpantaNum = {
// The maximum number of operators stored in array.
// If the number of operations exceed the limit, then the least significant operations will be discarded.
// This is to prevent long loops and eating away of memory and processing time.
// 1000 means there are at maximum of 1000 elements in array.
// It is not recommended to make this number too big.
// `ExpantaNum.maxOps = 1000;`
maxOps: 1e3,
// Specify what format is used when serializing for JSON.stringify
//
// JSON 0 JSON object
// STRING 1 String
serializeMode: 0,
// Deprecated
// Level of debug information printed in console
//
// NONE 0 Show no information.
// NORMAL 1 Show operations.
// ALL 2 Show everything.
debug: 0
},
// -- END OF EDITABLE DEFAULTS -- //
external = true,
expantaNumError = "[ExpantaNumError] ",
invalidArgument = expantaNumError + "Invalid argument: ",
isExpantaNum = /^[-\+]*(Infinity|NaN|(J+|J\^\d+ )?(10(\^+|\{[1-9]\d*\})|\(10(\^+|\{[1-9]\d*\})\)\^[1-9]\d* )*((\d+(\.\d*)?|\d*\.\d+)?([Ee][-\+]*))*(0|\d+(\.\d*)?|\d*\.\d+))$/,
MAX_SAFE_INTEGER = 9007199254740991,
MAX_E = Math.log10(MAX_SAFE_INTEGER), //15.954589770191003
// ExpantaNum.prototype object
P={},
// ExpantaNum static object
Q={},
// ExpantaNum constants
R={};
R.ZERO=0;
R.ONE=1;
R.E=Math.E;
R.LN2=Math.LN2;
R.LN10=Math.LN10;
R.LOG2E=Math.LOG2E;
R.LOG10E=Math.LOG10E;
R.PI=Math.PI;
R.SQRT1_2=Math.SQRT1_2;
R.SQRT2=Math.SQRT2;
R.MAX_SAFE_INTEGER=MAX_SAFE_INTEGER;
R.MIN_SAFE_INTEGER=Number.MIN_SAFE_INTEGER;
R.NaN=Number.NaN;
R.NEGATIVE_INFINITY=Number.NEGATIVE_INFINITY;
R.POSITIVE_INFINITY=Number.POSITIVE_INFINITY;
R.E_MAX_SAFE_INTEGER="e"+MAX_SAFE_INTEGER;
R.EE_MAX_SAFE_INTEGER="ee"+MAX_SAFE_INTEGER;
R.TETRATED_MAX_SAFE_INTEGER="10^^"+MAX_SAFE_INTEGER;
R.GRAHAMS_NUMBER="J^63 10^^^(10^)^7625597484984 3638334640023.7783";
// ExpantaNum prototype methods
P.absoluteValue=P.abs=function(){
var x=this.clone();
x.sign=1;
return x;
};
Q.absoluteValue=Q.abs=function(x){
return new ExpantaNum(x).abs();
};
P.negate=P.neg=function (){
var x=this.clone();
x.sign=x.sign*-1;
return x;
};
Q.negate=Q.neg=function (x){
return new ExpantaNum(x).neg();
};
P.compareTo=P.cmp=function (other){
if (!(other instanceof ExpantaNum)) other=new ExpantaNum(other);
if (isNaN(this.array[0][1])||isNaN(other.array[0][1])) return NaN;
if (this.array[0][1]==Infinity&&other.array[0][1]!=Infinity) return this.sign;
if (this.array[0][1]!=Infinity&&other.array[0][1]==Infinity) return -other.sign;
if (this.array.length==1&&this.array[0][1]===0&&other.array.length==1&&other.array[0][1]===0) return 0;
if (this.sign!=other.sign) return this.sign;
var m=this.sign;
var r;
if (this.layer>other.layer) r=1;
else if (this.layer<other.layer) r=-1;
else{
var e,f;
for (var i=0,l=Math.min(this.array.length,other.array.length);i<l;++i){
e=this.array[this.array.length-1-i];
f=other.array[other.array.length-1-i];
if (e[0]>f[0]||e[0]==f[0]&&e[1]>f[1]){
r=1;
break;
}else if (e[0]<f[0]||e[0]==f[0]&&e[1]<f[1]){
r=-1;
break;
}
}
if (r===undefined){
if (this.array.length==other.array.length){
r=0;
}else if (this.array.length>other.array.length){
e=this.array[this.array.length-l];
if (e[0]>=1||e[1]>10){
r=1;
}else{
r=-1;
}
}else{
e=other.array[other.array.length-l];
if (e[0]>=1||e[1]>10){
r=-1;
}else{
r=1;
}
}
}
}
return r*m;
};
Q.compare=Q.cmp=function (x,y){
return new ExpantaNum(x).cmp(y);
};
P.greaterThan=P.gt=function (other){
return this.cmp(other)>0;
};
Q.greaterThan=Q.gt=function (x,y){
return new ExpantaNum(x).gt(y);
};
P.greaterThanOrEqualTo=P.gte=function (other){
return this.cmp(other)>=0;
};
Q.greaterThanOrEqualTo=Q.gte=function (x,y){
return new ExpantaNum(x).gte(y);
};
P.lessThan=P.lt=function (other){
return this.cmp(other)<0;
};
Q.lessThan=Q.lt=function (x,y){
return new ExpantaNum(x).lt(y);
};
P.lessThanOrEqualTo=P.lte=function (other){
return this.cmp(other)<=0;
};
Q.lessThanOrEqualTo=Q.lte=function (x,y){
return new ExpantaNum(x).lte(y);
};
P.equalsTo=P.equal=P.eq=function (other){
return this.cmp(other)===0;
};
Q.equalsTo=Q.equal=Q.eq=function (x,y){
return new ExpantaNum(x).eq(y);
};
P.notEqualsTo=P.notEqual=P.neq=function (other){
return this.cmp(other)!==0;
};
Q.notEqualsTo=Q.notEqual=Q.neq=function (x,y){
return new ExpantaNum(x).neq(y);
};
P.minimum=P.min=function (other){
return this.lt(other)?this.clone():new ExpantaNum(other);
};
Q.minimum=Q.min=function (x,y){
return new ExpantaNum(x).min(y);
};
P.maximum=P.max=function (other){
return this.gt(other)?this.clone():new ExpantaNum(other);
};
Q.maximum=Q.max=function (x,y){
return new ExpantaNum(x).max(y);
};
P.compareTo_tolerance=P.cmp_tolerance=function (other,tolerance){
if (!(other instanceof ExpantaNum)) other=new ExpantaNum(other);
return this.eq_tolerance(other,tolerance)?0:this.cmp(other);
};
Q.compare_tolerance=Q.cmp_tolerance=function (x,y,tolerance){
return new ExpantaNum(x).cmp_tolerance(y,tolerance);
};
P.greaterThan_tolerance=P.gt_tolerance=function (other,tolerance){
if (!(other instanceof ExpantaNum)) other=new ExpantaNum(other);
return !this.eq_tolerance(other,tolerance)&&this.gt(other);
};
Q.greaterThan_tolerance=Q.gt_tolerance=function (x,y,tolerance){
return new ExpantaNum(x).gt_tolerance(y,tolerance);
};
P.greaterThanOrEqualTo_tolerance=P.gte_tolerance=function (other,tolerance){
if (!(other instanceof ExpantaNum)) other=new ExpantaNum(other);
return this.eq_tolerance(other,tolerance)||this.gt(other);
};
Q.greaterThanOrEqualTo_tolerance=Q.gte_tolerance=function (x,y,tolerance){
return new ExpantaNum(x).gte_tolerance(y,tolerance);
};
P.lessThan_tolerance=P.lt_tolerance=function (other,tolerance){
if (!(other instanceof ExpantaNum)) other=new ExpantaNum(other);
return !this.eq_tolerance(other,tolerance)&&this.lt(other);
};
Q.lessThan_tolerance=Q.lt_tolerance=function (x,y,tolerance){
return new ExpantaNum(x).lt_tolerance(y,tolerance);
};
P.lessThanOrEqualTo_tolerance=P.lte_tolerance=function (other,tolerance){
if (!(other instanceof ExpantaNum)) other=new ExpantaNum(other);
return this.eq_tolerance(other,tolerance)||this.lt(other);
};
Q.lessThanOrEqualTo_tolerance=Q.lte_tolerance=function (x,y,tolerance){
return new ExpantaNum(x).lte_tolerance(y,tolerance);
};
//From break_eternity.js
//https://github.com/Patashu/break_eternity.js/blob/96901974c175cb28f66c7164a5a205cdda783872/src/index.ts#L2802
P.equalsTo_tolerance=P.equal_tolerance=P.eq_tolerance=function (other,tolerance){
if (!(other instanceof ExpantaNum)) other=new ExpantaNum(other);
if (tolerance==null) tolerance=1e-7;
if (this.isNaN()||other.isNaN()||this.isFinite()!=other.isFinite()) return false;
if (this.sign!=other.sign) return false;
if (Math.abs(this.layer-other.layer)>1) return false;
var a,b;
if (this.layer!=other.layer){
var x,y;
if (this.layer>other.layer) x=this,y=other;
else x=other,y=this;
if (!(x.array.length==2&&x.array[0][0]===0&&x.array[1][0]==1&&x.array[1][1]==1)) return false;
a=x.array[0][1];
if (y.array[y.array.length-1][1]>=10) b=Math.log10(y.array[y.array.length-1][0]+1);
else b=Math.log10(y.array[y.array.length-1][0]);
}else{
if (Math.abs(this.array[this.array.length-1][0]-other.array[other.array.length-1][0])>1) return false;
for (var i=1;Math.max(this.array.length,other.array.length)-i>=0;++i){
var c=this.array[this.array.length-i][0];
var d=other.array[other.array.length-i][0];
var x,y,e,f;
if (c!=d){
if (c>d) x=this,y=other;
else x=other,y=this,c=d;
e=x.array[x.array.length-i][1];
f=0;
}else{
x=this;
y=other;
e=x.array[x.array.length-i][1];
f=y.array[y.array.length-i][1];
if (x.array.length-i==0){
a=e;
b=f;
break;
}
}
if (Math.abs(e-f)>1) return false;
if (e!=f){
if (!(x.array.length-i<2||x.array.length-i==2&&x.array[0][0]===0&&x.array[1][0]==1&&x.array[1][1]==1)) return false;
a=x.array[0][1];
if (c==1) b=Math.log10(y.operator(0));
else if (c==2&&y.operator(0)>=1e10) b=Math.log10(y.operator(1)+2);
else if (y.operator(c-2)>=10) b=Math.log10(y.operator(c-1)+1);
else b=Math.log10(y.operator(c-1));
break;
}
}
}
return Math.abs(a-b)<=tolerance*Math.max(Math.abs(a),Math.abs(b));
};
Q.equalsTo_tolerance=Q.equal_tolerance=Q.eq_tolerance=function (x,y,tolerance){
return new ExpantaNum(x).eq_tolerance(y,tolerance);
};
P.notEqualsTo_tolerance=P.notEqual_tolerance=P.neq_tolerance=function (other,tolerance){
return !this.eq_tolerance(other,tolerance);
};
Q.notEqualsTo_tolerance=Q.notEqual_tolerance=Q.neq_tolerance=function (x,y,tolerance){
return new ExpantaNum(x).neq_tolerance(y,tolerance);
};
P.isPositive=P.ispos=function (){
return this.gt(ExpantaNum.ZERO);
};
Q.isPositive=Q.ispos=function (x){
return new ExpantaNum(x).ispos();
};
P.isNegative=P.isneg=function (){
return this.lt(ExpantaNum.ZERO);
};
Q.isNegative=Q.isneg=function (x){
return new ExpantaNum(x).isneg();
};
P.isNaN=function (){
return isNaN(this.array[0][1]);
};
Q.isNaN=function (x){
return new ExpantaNum(x).isNaN();
};
P.isFinite=function (){
return isFinite(this.array[0][1]);
};
Q.isFinite=function (x){
return new ExpantaNum(x).isFinite();
};
P.isInfinite=function (){
return this.array[0][1]==Infinity;
};
Q.isInfinite=function (x){
return new ExpantaNum(x).isInfinite();
};
P.isInteger=P.isint=function (){
if (this.sign==-1) return this.abs().isint();
if (this.gt(ExpantaNum.MAX_SAFE_INTEGER)) return true;
return Number.isInteger(this.toNumber());
};
Q.isInteger=Q.isint=function (x){
return new ExpantaNum(x).isint();
};
P.floor=function (){
if (this.isInteger()) return this.clone();
return new ExpantaNum(Math.floor(this.toNumber()));
};
Q.floor=function (x){
return new ExpantaNum(x).floor();
};
P.ceiling=P.ceil=function (){
if (this.isInteger()) return this.clone();
return new ExpantaNum(Math.ceil(this.toNumber()));
};
Q.ceiling=Q.ceil=function (x){
return new ExpantaNum(x).ceil();
};
P.round=function (){
if (this.isInteger()) return this.clone();
return new ExpantaNum(Math.round(this.toNumber()));
};
Q.round=function (x){
return new ExpantaNum(x).round();
};
var debugMessageSent=false;
P.plus=P.add=function (other){
var x=this.clone();
other=new ExpantaNum(other);
if (ExpantaNum.debug>=ExpantaNum.NORMAL){
console.log(this+"+"+other);
if (!debugMessageSent) console.warn(expantaNumError+"Debug output via 'debug' is being deprecated and will be removed in the future!"),debugMessageSent=true;
}
if (x.sign==-1) return x.neg().add(other.neg()).neg();
if (other.sign==-1) return x.sub(other.neg());
if (x.eq(ExpantaNum.ZERO)) return other;
if (other.eq(ExpantaNum.ZERO)) return x;
if (x.isNaN()||other.isNaN()||x.isInfinite()&&other.isInfinite()&&x.eq(other.neg())) return ExpantaNum.NaN.clone();
if (x.isInfinite()) return x;
if (other.isInfinite()) return other;
var p=x.min(other);
var q=x.max(other);
var op0=q.operator(0);
var op1=q.operator(1);
var t;
if (q.gt(ExpantaNum.E_MAX_SAFE_INTEGER)||q.div(p).gt(ExpantaNum.MAX_SAFE_INTEGER)){
t=q;
}else if (!op1){
t=new ExpantaNum(x.toNumber()+other.toNumber());
}else if (op1==1){
var a=p.operator(1)?p.operator(0):Math.log10(p.operator(0));
t=new ExpantaNum([a+Math.log10(Math.pow(10,op0-a)+1),1]);
}
p=q=null;
return t;
};
Q.plus=Q.add=function (x,y){
return new ExpantaNum(x).add(y);
};
P.minus=P.sub=function (other){
var x=this.clone();
other=new ExpantaNum(other);
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log(x+"-"+other);
if (x.sign==-1) return x.neg().sub(other.neg()).neg();
if (other.sign==-1) return x.add(other.neg());
if (x.eq(other)) return ExpantaNum.ZERO.clone();
if (other.eq(ExpantaNum.ZERO)) return x;
if (x.isNaN()||other.isNaN()||x.isInfinite()&&other.isInfinite()) return ExpantaNum.NaN.clone();
if (x.isInfinite()) return x;
if (other.isInfinite()) return other.neg();
var p=x.min(other);
var q=x.max(other);
var n=other.gt(x);
var op0=q.operator(0);
var op1=q.operator(1);
var t;
if (q.gt(ExpantaNum.E_MAX_SAFE_INTEGER)||q.div(p).gt(ExpantaNum.MAX_SAFE_INTEGER)){
t=q;
t=n?t.neg():t;
}else if (!op1){
t=new ExpantaNum(x.toNumber()-other.toNumber());
}else if (op1==1){
var a=p.operator(1)?p.operator(0):Math.log10(p.operator(0));
t=new ExpantaNum([a+Math.log10(Math.pow(10,op0-a)-1),1]);
t=n?t.neg():t;
}
p=q=null;
return t;
};
Q.minus=Q.sub=function (x,y){
return new ExpantaNum(x).sub(y);
};
P.times=P.mul=function (other){
var x=this.clone();
other=new ExpantaNum(other);
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log(x+"*"+other);
if (x.sign*other.sign==-1) return x.abs().mul(other.abs()).neg();
if (x.sign==-1) return x.abs().mul(other.abs());
if (x.isNaN()||other.isNaN()||x.eq(ExpantaNum.ZERO)&&other.isInfinite()||x.isInfinite()&&other.abs().eq(ExpantaNum.ZERO)) return ExpantaNum.NaN.clone();
if (other.eq(ExpantaNum.ZERO)) return ExpantaNum.ZERO.clone();
if (other.eq(ExpantaNum.ONE)) return x.clone();
if (x.isInfinite()) return x;
if (other.isInfinite()) return other;
if (x.max(other).gt(ExpantaNum.EE_MAX_SAFE_INTEGER)) return x.max(other);
var n=x.toNumber()*other.toNumber();
if (n<=MAX_SAFE_INTEGER) return new ExpantaNum(n);
return ExpantaNum.pow(10,x.log10().add(other.log10()));
};
Q.times=Q.mul=function (x,y){
return new ExpantaNum(x).mul(y);
};
P.divide=P.div=function (other){
var x=this.clone();
other=new ExpantaNum(other);
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log(x+"/"+other);
if (x.sign*other.sign==-1) return x.abs().div(other.abs()).neg();
if (x.sign==-1) return x.abs().div(other.abs());
if (x.isNaN()||other.isNaN()||x.isInfinite()&&other.isInfinite()||x.eq(ExpantaNum.ZERO)&&other.eq(ExpantaNum.ZERO)) return ExpantaNum.NaN.clone();
if (other.eq(ExpantaNum.ZERO)) return ExpantaNum.POSITIVE_INFINITY.clone();
if (other.eq(ExpantaNum.ONE)) return x.clone();
if (x.eq(other)) return ExpantaNum.ONE.clone();
if (x.isInfinite()) return x;
if (other.isInfinite()) return ExpantaNum.ZERO.clone();
if (x.max(other).gt(ExpantaNum.EE_MAX_SAFE_INTEGER)) return x.gt(other)?x.clone():ExpantaNum.ZERO.clone();
var n=x.toNumber()/other.toNumber();
if (n<=MAX_SAFE_INTEGER) return new ExpantaNum(n);
var pw=ExpantaNum.pow(10,x.log10().sub(other.log10()));
var fp=pw.floor();
if (pw.sub(fp).lt(new ExpantaNum(1e-9))) return fp;
return pw;
};
Q.divide=Q.div=function (x,y){
return new ExpantaNum(x).div(y);
};
P.reciprocate=P.rec=function (){
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log(this+"^-1");
if (this.isNaN()||this.eq(ExpantaNum.ZERO)) return ExpantaNum.NaN.clone();
if (this.abs().gt("2e323")) return ExpantaNum.ZERO.clone();
return new ExpantaNum(1/this);
};
Q.reciprocate=Q.rec=function (x){
return new ExpantaNum(x).rec();
};
P.modular=P.mod=function (other){
other=new ExpantaNum(other);
if (other.eq(ExpantaNum.ZERO)) return ExpantaNum.ZERO.clone();
if (this.sign*other.sign==-1) return this.abs().mod(other.abs()).neg();
if (this.sign==-1) return this.abs().mod(other.abs());
return this.sub(this.div(other).floor().mul(other));
};
Q.modular=Q.mod=function (x,y){
return new ExpantaNum(x).mod(y);
};
//All of these are from Patashu's break_eternity.js
//from HyperCalc source code
var f_gamma=function (n){
if (!isFinite(n)) return n;
if (n<-50){
if (n==Math.trunc(n)) return Number.NEGATIVE_INFINITY;
return 0;
}
var scal1=1;
while (n<10){
scal1=scal1*n;
++n;
}
n-=1;
var l=0.9189385332046727; //0.5*Math.log(2*Math.PI)
l+=(n+0.5)*Math.log(n);
l-=n;
var n2=n*n;
var np=n;
l+=1/(12*np);
np*=n2;
l-=1/(360*np);
np*=np*n2;
l+=1/(1260*np);
np*=n2;
l-=1/(1680*np);
np*=n2;
l+=1/(1188*np);
np*=n2;
l-=691/(360360*np);
np*=n2;
l+=7/(1092*np);
np*=n2;
l-=3617/(122400*np);
return Math.exp(l)/scal1;
};
//from HyperCalc source code
P.gamma=function (){
var x=this.clone();
if (x.gt(ExpantaNum.TETRATED_MAX_SAFE_INTEGER)) return x;
if (x.gt(ExpantaNum.E_MAX_SAFE_INTEGER)) return ExpantaNum.exp(x);
if (x.gt(ExpantaNum.MAX_SAFE_INTEGER)) return ExpantaNum.exp(ExpantaNum.mul(x,ExpantaNum.ln(x).sub(1)));
var n=x.operator(0);
if (n>1){
if (n<24) return new ExpantaNum(f_gamma(x.sign*n));
var t=n-1;
var l=0.9189385332046727; //0.5*Math.log(2*Math.PI)
l+=((t+0.5)*Math.log(t));
l-=t;
var n2=t*t;
var np=t;
var lm=12*np;
var adj=1/lm;
var l2=l+adj;
if (l2==l) return ExpantaNum.exp(l);
l=l2;
np*=n2;
lm=360*np;
adj=1/lm;
l2=l-adj;
if (l2==l) return ExpantaNum.exp(l);
l=l2;
np*=n2;
lm=1260*np;
var lt=1/lm;
l+=lt;
np*=n2;
lm=1680*np;
lt=1/lm;
l-=lt;
return ExpantaNum.exp(l);
}else return this.rec();
};
Q.gamma=function (x){
return new ExpantaNum(x).gamma();
};
//end break_eternity.js excerpt
Q.factorials=[1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800,87178291200,1307674368000,20922789888000,355687428096000,6402373705728000,121645100408832000,2432902008176640000,51090942171709440000,1.1240007277776076800e+21,2.5852016738884978213e+22,6.2044840173323941000e+23,1.5511210043330986055e+25,4.0329146112660565032e+26,1.0888869450418351940e+28,3.0488834461171387192e+29,8.8417619937397018986e+30,2.6525285981219106822e+32,8.2228386541779224302e+33,2.6313083693369351777e+35,8.6833176188118859387e+36,2.9523279903960415733e+38,1.0333147966386145431e+40,3.7199332678990125486e+41,1.3763753091226345579e+43,5.2302261746660111714e+44,2.0397882081197444123e+46,8.1591528324789768380e+47,3.3452526613163807956e+49,1.4050061177528799549e+51,6.0415263063373834074e+52,2.6582715747884488694e+54,1.1962222086548018857e+56,5.5026221598120891536e+57,2.5862324151116817767e+59,1.2413915592536072528e+61,6.0828186403426752249e+62,3.0414093201713375576e+64,1.5511187532873821895e+66,8.0658175170943876846e+67,4.2748832840600254848e+69,2.3084369733924137924e+71,1.2696403353658276447e+73,7.1099858780486348103e+74,4.0526919504877214100e+76,2.3505613312828784949e+78,1.3868311854568983861e+80,8.3209871127413898951e+81,5.0758021387722483583e+83,3.1469973260387939390e+85,1.9826083154044400850e+87,1.2688693218588416544e+89,8.2476505920824715167e+90,5.4434493907744306945e+92,3.6471110918188683221e+94,2.4800355424368305480e+96,1.7112245242814129738e+98,1.1978571669969892213e+100,8.5047858856786230047e+101,6.1234458376886084639e+103,4.4701154615126843855e+105,3.3078854415193862416e+107,2.4809140811395399745e+109,1.8854947016660503806e+111,1.4518309202828587210e+113,1.1324281178206296794e+115,8.9461821307829757136e+116,7.1569457046263805709e+118,5.7971260207473678414e+120,4.7536433370128420198e+122,3.9455239697206587884e+124,3.3142401345653531943e+126,2.8171041143805501310e+128,2.4227095383672734128e+130,2.1077572983795278544e+132,1.8548264225739843605e+134,1.6507955160908460244e+136,1.4857159644817615149e+138,1.3520015276784029158e+140,1.2438414054641308179e+142,1.1567725070816415659e+144,1.0873661566567430754e+146,1.0329978488239059305e+148,9.9167793487094964784e+149,9.6192759682482120384e+151,9.4268904488832479837e+153,9.3326215443944153252e+155,9.3326215443944150966e+157,9.4259477598383598816e+159,9.6144667150351270793e+161,9.9029007164861804721e+163,1.0299016745145628100e+166,1.0813967582402909767e+168,1.1462805637347083683e+170,1.2265202031961380050e+172,1.3246418194518290179e+174,1.4438595832024936625e+176,1.5882455415227430287e+178,1.7629525510902445874e+180,1.9745068572210740115e+182,2.2311927486598137657e+184,2.5435597334721876552e+186,2.9250936934930159967e+188,3.3931086844518980862e+190,3.9699371608087210616e+192,4.6845258497542909237e+194,5.5745857612076058231e+196,6.6895029134491271205e+198,8.0942985252734440920e+200,9.8750442008336010580e+202,1.2146304367025329301e+205,1.5061417415111409314e+207,1.8826771768889261129e+209,2.3721732428800468512e+211,3.0126600184576594309e+213,3.8562048236258040716e+215,4.9745042224772874590e+217,6.4668554892204741474e+219,8.4715806908788206314e+221,1.1182486511960043298e+224,1.4872707060906857134e+226,1.9929427461615187928e+228,2.6904727073180504073e+230,3.6590428819525488642e+232,5.0128887482749919605e+234,6.9177864726194885808e+236,9.6157231969410893532e+238,1.3462012475717525742e+241,1.8981437590761708898e+243,2.6953641378881628530e+245,3.8543707171800730787e+247,5.5502938327393044385e+249,8.0479260574719917061e+251,1.1749972043909107097e+254,1.7272458904546389230e+256,2.5563239178728653927e+258,3.8089226376305697893e+260,5.7133839564458546840e+262,8.6272097742332399855e+264,1.3113358856834524492e+267,2.0063439050956822953e+269,3.0897696138473507759e+271,4.7891429014633940780e+273,7.4710629262828942235e+275,1.1729568794264144743e+278,1.8532718694937349890e+280,2.9467022724950384028e+282,4.7147236359920616095e+284,7.5907050539472189932e+286,1.2296942187394494177e+289,2.0044015765453026266e+291,3.2872185855342959088e+293,5.4239106661315886750e+295,9.0036917057784375454e+297,1.5036165148649991456e+300,2.5260757449731984219e+302,4.2690680090047051083e+304,7.2574156153079990350e+306];
P.factorial=P.fact=function (){
var x=this.clone();
var f=ExpantaNum.factorials;
if (x.lt(ExpantaNum.ZERO)||!x.isint()) return x.add(1).gamma();
if (x.lte(170)) return new ExpantaNum(f[+x]);
var errorFixer=1;
var e=+x;
if (e<500) e+=163879/209018880*Math.pow(e,5);
if (e<1000) e+=-571/2488320*Math.pow(e,4);
if (e<50000) e+=-139/51840*Math.pow(e,3);
if (e<1e7) e+=1/288*Math.pow(e,2);
if (e<1e20) e+=1/12*e;
return x.div(ExpantaNum.E).pow(x).mul(x.mul(ExpantaNum.PI).mul(2).sqrt()).times(errorFixer);
};
Q.factorial=Q.fact=function (x){
return new ExpantaNum(x).fact();
};
P.toPower=P.pow=function (other){
other=new ExpantaNum(other);
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log(this+"^"+other);
if (other.eq(ExpantaNum.ZERO)) return ExpantaNum.ONE.clone();
if (other.eq(ExpantaNum.ONE)) return this.clone();
if (other.lt(ExpantaNum.ZERO)) return this.pow(other.neg()).rec();
if (this.lt(ExpantaNum.ZERO)&&other.isint()){
if (other.mod(2).lt(ExpantaNum.ONE)) return this.abs().pow(other);
return this.abs().pow(other).neg();
}
if (this.lt(ExpantaNum.ZERO)) return ExpantaNum.NaN.clone();
if (this.eq(ExpantaNum.ONE)) return ExpantaNum.ONE.clone();
if (this.eq(ExpantaNum.ZERO)) return ExpantaNum.ZERO.clone();
if (this.max(other).gt(ExpantaNum.TETRATED_MAX_SAFE_INTEGER)) return this.max(other);
if (this.eq(10)){
if (other.gt(ExpantaNum.ZERO)){
other.operator(1,(other.operator(1)+1)||1);
other.normalize();
return other;
}else{
return new ExpantaNum(Math.pow(10,other.toNumber()));
}
}
if (other.lt(ExpantaNum.ONE)) return this.root(other.rec());
var n=Math.pow(this.toNumber(),other.toNumber());
if (n<=MAX_SAFE_INTEGER) return new ExpantaNum(n);
return ExpantaNum.pow(10,this.log10().mul(other));
};
Q.toPower=Q.pow=function (x,y){
return new ExpantaNum(x).pow(y);
};
P.exponential=P.exp=function (){
return ExpantaNum.pow(Math.E,this);
};
Q.exponential=Q.exp=function (x){
return ExpantaNum.pow(Math.E,x);
};
P.squareRoot=P.sqrt=function (){
return this.root(2);
};
Q.squareRoot=Q.sqrt=function (x){
return new ExpantaNum(x).root(2);
};
P.cubeRoot=P.cbrt=function (){
return this.root(3);
};
Q.cubeRoot=Q.cbrt=function (x){
return new ExpantaNum(x).root(3);
};
P.root=function (other){
other=new ExpantaNum(other);
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log(this+"root"+other);
if (other.eq(ExpantaNum.ONE)) return this.clone();
if (other.lt(ExpantaNum.ZERO)) return this.root(other.neg()).rec();
if (other.lt(ExpantaNum.ONE)) return this.pow(other.rec());
if (this.lt(ExpantaNum.ZERO)&&other.isint()&&other.mod(2).eq(ExpantaNum.ONE)) return this.neg().root(other).neg();
if (this.lt(ExpantaNum.ZERO)) return ExpantaNum.NaN.clone();
if (this.eq(ExpantaNum.ONE)) return ExpantaNum.ONE.clone();
if (this.eq(ExpantaNum.ZERO)) return ExpantaNum.ZERO.clone();
if (this.max(other).gt(ExpantaNum.TETRATED_MAX_SAFE_INTEGER)) return this.gt(other)?this.clone():ExpantaNum.ZERO.clone();
return ExpantaNum.pow(10,this.log10().div(other));
};
Q.root=function (x,y){
return new ExpantaNum(x).root(y);
};
P.generalLogarithm=P.log10=function (){
var x=this.clone();
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log("log"+this);
if (x.lt(ExpantaNum.ZERO)) return ExpantaNum.NaN.clone();
if (x.eq(ExpantaNum.ZERO)) return ExpantaNum.NEGATIVE_INFINITY.clone();
if (x.lte(ExpantaNum.MAX_SAFE_INTEGER)) return new ExpantaNum(Math.log10(x.toNumber()));
if (!x.isFinite()) return x;
if (x.gt(ExpantaNum.TETRATED_MAX_SAFE_INTEGER)) return x;
x.operator(1,x.operator(1)-1);
return x.normalize();
};
Q.generalLogarithm=Q.log10=function (x){
return new ExpantaNum(x).log10();
};
P.logarithm=P.logBase=function (base){
if (base===undefined) base=Math.E;
return this.log10().div(ExpantaNum.log10(base));
};
Q.logarithm=Q.logBase=function (x,base){
return new ExpantaNum(x).logBase(base);
};
P.naturalLogarithm=P.log=P.ln=function (){
return this.logBase(Math.E);
};
Q.naturalLogarithm=Q.log=Q.ln=function (x){
return new ExpantaNum(x).ln();
};
//All of these are from Patashu's break_eternity.js
var OMEGA=0.56714329040978387299997; //W(1,0)
//from https://math.stackexchange.com/a/465183
//The evaluation can become inaccurate very close to the branch point
var f_lambertw=function (z,tol,principal){
if (tol===undefined) tol=1e-10;
if (principal===undefined) principal=true;
var w;
if (!Number.isFinite(z)) return z;
if (principal){
if (z===0) return z;
if (z===1) return OMEGA;
if (z<10) w=0;
else w=Math.log(z)-Math.log(Math.log(z));
}else{
if (z===0) return -Infinity;
if (z<=-0.1) w=-2;
else w=Math.log(-z)-Math.log(-Math.log(-z));
}
for (var i=0;i<100;++i){
var wn=(z*Math.exp(-w)+w*w)/(w+1);
if (Math.abs(wn-w)<tol*Math.abs(wn)) return wn;
w=wn;
}
throw Error("Iteration failed to converge: "+z);
};
//from https://github.com/scipy/scipy/blob/8dba340293fe20e62e173bdf2c10ae208286692f/scipy/special/lambertw.pxd
//The evaluation can become inaccurate very close to the branch point
//at ``-1/e``. In some corner cases, `lambertw` might currently
//fail to converge, or can end up on the wrong branch.
var d_lambertw=function (z,tol,principal){
if (tol===undefined) tol=1e-10;
if (principal===undefined) principal=true;
z=new ExpantaNum(z);
var w;
if (!z.isFinite()) return z;
if (principal){
if (z.eq(ExpantaNum.ZERO)) return z;
if (z.eq(ExpantaNum.ONE)) return new ExpantaNum(OMEGA);
w=ExpantaNum.ln(z);
}else{
if (z.eq(ExpantaNum.ZERO)) return ExpantaNum.NEGATIVE_INFINITY.clone();
w=ExpantaNum.ln(z.neg());
}
for (var i=0;i<100;++i){
var ew=w.neg().exp();
var wewz=w.sub(z.mul(ew));
var dd=w.add(ExpantaNum.ONE).sub(w.add(2).mul(wewz).div(ExpantaNum.mul(2,w).add(2)));
if (dd.eq(ExpantaNum.ZERO)) return w; //Escape to fix https://github.com/Naruyoko/ExpantaNum.js/issues/25
var wn=w.sub(wewz.div(dd));
if (ExpantaNum.abs(wn.sub(w)).lt(ExpantaNum.abs(wn).mul(tol))) return wn;
w = wn;
}
throw Error("Iteration failed to converge: "+z);
};
//The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x.
//https://en.wikipedia.org/wiki/Lambert_W_function
//Some special values, for testing: https://en.wikipedia.org/wiki/Lambert_W_function#Special_values
P.lambertw=function (principal){
if (principal===undefined) principal=true;
var x=this.clone();
if (x.isNaN()) return x;
if (x.lt(-0.3678794411710499)) return ExpantaNum.NaN.clone();
if (principal){
if (x.gt(ExpantaNum.TETRATED_MAX_SAFE_INTEGER)) return x;
if (x.gt(ExpantaNum.EE_MAX_SAFE_INTEGER)){
x.operator(1,x.operator(1)-1);
return x;
}
if (x.gt(ExpantaNum.MAX_SAFE_INTEGER)) return d_lambertw(x);
else return new ExpantaNum(f_lambertw(x.sign*x.operator(0)));
}else{
if (x.ispos()) return ExpantaNum.NaN.clone();
if (x.abs().gt(ExpantaNum.EE_MAX_SAFE_INTEGER)) return x.neg().rec().lambertw().neg();
if (x.abs().gt(ExpantaNum.MAX_SAFE_INTEGER)) return d_lambertw(x,1e-10,false);
else return new ExpantaNum(f_lambertw(x.sign*x.operator(0),1e-10,false));
}
};
Q.lambertw=function (x,principal){
return new ExpantaNum(x).lambertw(principal);
};
//end break_eternity.js excerpt
//Uses linear approximations for real height
P.tetrate=P.tetr=function (other,payload){
if (payload===undefined) payload=ExpantaNum.ONE;
var t=this.clone();
other=new ExpantaNum(other);
payload=new ExpantaNum(payload);
if (t.isNaN()||other.isNaN()||payload.isNaN()) return ExpantaNum.NaN.clone();
if (payload.neq(ExpantaNum.ONE)) other=other.add(payload.slog(t));
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log(t+"^^"+other);
var negln;
if (other.isInfinite()&&other.sign>0){
if (t.gte(Math.exp(1/Math.E))) return ExpantaNum.POSITIVE_INFINITY.clone();
//Formula for infinite height power tower.
negln = t.ln().neg();
return negln.lambertw().div(negln);
}
if (other.lte(-2)) return ExpantaNum.NaN.clone();
if (t.eq(ExpantaNum.ZERO)){
if (other.eq(ExpantaNum.ZERO)) return ExpantaNum.NaN.clone();
if (other.mod(2).eq(ExpantaNum.ZERO)) return ExpantaNum.ZERO.clone();
return ExpantaNum.ONE.clone();
}
if (t.eq(ExpantaNum.ONE)){
if (other.eq(ExpantaNum.ONE.neg())) return ExpantaNum.NaN.clone();
return ExpantaNum.ONE.clone();
}
if (other.eq(ExpantaNum.ONE.neg())) return ExpantaNum.ZERO.clone();
if (other.eq(ExpantaNum.ZERO)) return ExpantaNum.ONE.clone();
if (other.eq(ExpantaNum.ONE)) return t;
if (other.eq(2)) return t.pow(t);
if (t.eq(2)){
if (other.eq(3)) return new ExpantaNum(16);
if (other.eq(4)) return new ExpantaNum(65536);
}
var m=t.max(other);
if (m.gt("10^^^"+MAX_SAFE_INTEGER)) return m;
if (m.gt(ExpantaNum.TETRATED_MAX_SAFE_INTEGER)||other.gt(ExpantaNum.MAX_SAFE_INTEGER)){
if (this.lt(Math.exp(1/Math.E))){
negln = t.ln().neg();
return negln.lambertw().div(negln);
}
var j=t.slog(10).add(other);
j.operator(2,(j.operator(2)||0)+1);
j.normalize();
return j;
}
var y=other.toNumber();
var f=Math.floor(y);
var r=t.pow(y-f);
var l=ExpantaNum.NaN;
for (var i=0,w=new ExpantaNum(ExpantaNum.E_MAX_SAFE_INTEGER);f!==0&&r.lt(w)&&i<100;++i){
if (f>0){
r=t.pow(r);
if (l.eq(r)){
f=0;
break;
}
l=r;
--f;
}else{
r=r.logBase(t);
if (l.eq(r)){
f=0;
break;
}
l=r;
++f;
}
}
if (i==100||this.lt(Math.exp(1/Math.E))) f=0;
r.operator(1,(r.operator(1)+f)||f);
r.normalize();
return r;
};
Q.tetrate=Q.tetr=function (x,y,payload){
return new ExpantaNum(x).tetr(y,payload);
};
//Implementation of functions from break_eternity.js
P.iteratedexp=function (other,payload){
return this.tetr(other,payload);
};
Q.iteratedexp=function (x,y,payload){
return new ExpantaNum(x).iteratedexp(y,payload);
};
//This implementation is highly inaccurate and slow, and probably be given custom code
P.iteratedlog=function (base,other){
if (base===undefined) base=10;
if (other===undefined) other=ExpantaNum.ONE.clone();
var t=this.clone();
base=new ExpantaNum(base);
other=new ExpantaNum(other);
if (other.eq(ExpantaNum.ZERO)) return t;
if (other.eq(ExpantaNum.ONE)) return t.logBase(base);
return base.tetr(t.slog(base).sub(other));
};
Q.iteratedlog=function (x,y,z){
return new ExpantaNum(x).iteratedlog(y,z);
};
P.layeradd=function (other,base){
if (base===undefined) base=10;
if (other===undefined) other=ExpantaNum.ONE.clone();
var t=this.clone();
base=new ExpantaNum(base);
other=new ExpantaNum(other);
return base.tetr(t.slog(base).add(other));
};
Q.layeradd=function (x,y,z){
return new ExpantaNum(x).layeradd(y,z);
};
P.layeradd10=function (other){
return this.layeradd(other);
};
Q.layeradd10=function (x,y){
return new ExpantaNum(x).layeradd10(y);
};
//End implementation from break_eternity.js
//All of these are from Patashu's break_eternity.js
//The super square-root function - what number, tetrated to height 2, equals this?
//Other sroots are possible to calculate probably through guess and check methods, this one is easy though.
//https://en.wikipedia.org/wiki/Tetration#Super-root
P.ssqrt=P.ssrt=function (){
var x=this.clone();
if (x.lt(Math.exp(-1/Math.E))) return ExpantaNum.NaN.clone();
if (!x.isFinite()) return x;
if (x.gt(ExpantaNum.TETRATED_MAX_SAFE_INTEGER)) return x;
if (x.gt(ExpantaNum.EE_MAX_SAFE_INTEGER)){
x.operator(1,x.operator(1)-1);
return x;
}
var l=x.ln();
return l.div(l.lambertw());
};
Q.ssqrt=Q.ssrt=function (x){
return new ExpantaNum(x).ssqrt();
};
//Uses linear approximation
//For more information, please see the break_eternity.js source:
//https://github.com/Patashu/break_eternity.js/blob/848736e3dc37d8e7b5cc238f46e3ddb277d0dce2/src/index.ts#L4008
P.linear_sroot=function (degree){
var x=new ExpantaNum(this);
degree=new ExpantaNum(degree);
if (degree.isNaN()) return ExpantaNum.NaN.clone();
var degreeNum=Number(degree);
if (degreeNum==1) return x;
if (x.eq(ExpantaNum.POSITIVE_INFINITY)) return ExpantaNum.POSITIVE_INFINITY.clone();
if (!x.isFinite()) return ExpantaNum.NaN.clone();
if (degreeNum>0&&degreeNum<1) return x.root(degree);
if (degreeNum>-2&&degreeNum<-1) return degree.add(2).pow(x.rec());
if (degreeNum<=0) return ExpantaNum.NaN.clone();
if (degree.gt(ExpantaNum.MAX_SAFE_INTEGER)){
var xNum=Number(x);
if (xNum<Math.E&&xNum>1/Math.E) return x.pow(x.rec());
if (x.gt(ExpantaNum.TETRATED_MAX_SAFE_INTEGER)){
var nh=x.slog(10).sub(degree);
if (nh.lte(ExpantaNum.ZERO)) return new ExpantaNum(Math.exp(1/Math.E));
return ExpantaNum.tetr(10,nh);
}
return ExpantaNum.NaN.clone();
}
if (x.eq(ExpantaNum.ONE)) return ExpantaNum.ONE.clone();
if (x.lt(ExpantaNum.ZERO)) return ExpantaNum.NaN.clone();
if (x.eq(ExpantaNum.ZERO)) return ExpantaNum.ZERO.clone();
if (x.gt(ExpantaNum.ONE)){
var upperBound;
if (degreeNum<=1) upperBound=x.root(degree);
else if (x.gte(ExpantaNum.tetr(10,degree))) upperBound=x.iteratedlog(10,degreeNum-1);
else upperBound=new ExpantaNum(10);
var lower=ExpantaNum.ZERO;
var layer=upperBound.array[2]||0;
var upper=upperBound.iteratedlog(10,layer);
var guess=upper.div(2);
while (true){
if (ExpantaNum.iteratedexp(10,layer,guess).tetr(degree).gt(x)) upper=guess;
else lower=guess;
var newguess=lower.add(upper).div(2);
if (newguess.eq(guess)) break;
guess=newguess;
}
return ExpantaNum.iteratedexp(10,layer,guess);
}else{
var BIG=new ExpantaNum("10^^10");
var stage=1;
var minimum=BIG;
var maximum=BIG;
var lower=BIG
var upper=new ExpantaNum(1e-16)
var prevspan=ExpantaNum.ZERO;
var difference=BIG;
var upperBound=ExpantaNum.pow(10,upper).rec();
var distance=ExpantaNum.ZERO;
var prevPoint=upperBound;
var nextPoint=upperBound;
var evenDegree=Math.ceil(degreeNum)%2==0;
var range=0;
var lastValid=BIG;
var infLoopDetector=false;
var previousUpper=ExpantaNum.ZERO;
var decreasingFound=false;
while (stage<4){
if (stage==2){
if (evenDegree) break;
lower=BIG;
upper=minimum;
stage=3;
difference=BIG;
lastValid=BIG;
}
infLoopDetector=false;
while (upper.neq(lower)){
previousUpper=upper;
var up10r=ExpantaNum.pow(10,upper).rec();
var up10rtd=up10r.tetr(degree);
if (up10rtd.eq(ExpantaNum.ONE)&&up10r.lt(0.4)){
upperBound=up10r;
prevPoint=up10r;
nextPoint=up10r;
distance=ExpantaNum.ZERO;
range=-1;
if (stage==3) lastValid=upper;
}else if (up10rtd.eq(up10r)&&!evenDegree&&up10r.lt(0.4)){
upperBound=up10r;
prevPoint=up10r;
nextPoint=up10r;
distance=ExpantaNum.ZERO;
range=0;
}else if (up10rtd.eq(up10r.mul(2).tetr(degree))){
upperBound=up10r;
prevPoint=ExpantaNum.ZERO;
nextPoint=upperBound.mul(2);
distance=upperBound;
if (evenDegree) range=-1;
else range=0;
}else{
prevspan=upper.mul(1.2e-16);
upperBound=up10r;
prevPoint=ExpantaNum.pow(10,upper.add(prevspan)).rec();
distance=upperBound.sub(prevPoint);
nextPoint=upperBound.add(distance);
var ubtd=upperBound.tetr(degree); //upperBound does not change during lifetime
var pptd;
var nptd;
while (prevPoint.gte(upperBound)||nextPoint.lte(upperBound)||(pptd=prevPoint.tetr(degree)).eq(ubtd)||(nptd=nextPoint.tetr(degree)).eq(ubtd)){
prevspan=prevspan.mul(2);
prevPoint=ExpantaNum.pow(10,upper.add(prevspan)).rec();
distance=upperBound.sub(prevPoint);
nextPoint=upperBound.add(distance);
}
//pptd and nptd are up-to-date
if (stage==1&&nptd.gt(ubtd)&&pptd.gt(ubtd)||stage==3&&nptd.lt(ubtd)&&pptd.lt(ubtd)) lastValid=upper;
if (nptd.lt(ubtd)) range=-1;
else if (evenDegree) range=1;
else if (stage==3&&upper.gt_tolerance(minimum,1e-8)) range=0;
else{
while (prevPoint.gte(upperBound)||nextPoint.lte(upperBound)||(pptd=prevPoint.tetr(degree)).eq_tolerance(ubtd,1e-8)||(nptd=nextPoint.tetr(degree)).eq_tolerance(ubtd,1e-8)){
prevspan=prevspan.mul(2);
prevPoint=ExpantaNum.pow(10,upper.add(prevspan)).rec();
distance=upperBound.sub(prevPoint);
nextPoint=upperBound.add(distance);
}
//pptd and nptd are up-to-date
if (nptd.sub(ubtd).lt(ubtd.sub(pptd))) range=0;
else range=1;
}
}
if (range==-1) decreasingFound=true;
if (stage==1&&range==1||stage==3&&range!=0){
if (lower.eq(BIG)) upper=upper.mul(2);
else{
upper=upper.add(lower).div(2);
if (infLoopDetector&&(range==1&&stage==1||range==-1&&stage==3)) break;
}
}else{
if (lower.eq(BIG)){
lower=upper;
upper=upper.div(2);
}else{
lower=lower.sub(difference);
upper=upper.sub(difference);
if (infLoopDetector&&(range==1&&stage==1||range==-1&&stage==3)) break;
}
}
var newDifference=lower.sub(upper).div(2).abs();
if (newDifference.gt(difference.mul(1.5))) infLoopDetector=true;
difference=newDifference;
if (upper.gt(1e18)||upper.eq(previousUpper)) break;
}
if (upper.gt(1e18)) break;
if (!decreasingFound) break;
if (lastValid.eq(BIG)) break;
if (stage==1) minimum=lastValid;
else if (stage==3) maximum=lastValid;
stage++;
}
lower=minimum;
upper=new ExpantaNum(1e-18);
var previous=upper;
var guess=ExpantaNum.ZERO;
var loopGoing=true;
while (loopGoing){
if (lower.eq(BIG)) guess=upper.mul(2);
else guess=lower.add(upper).div(2);
if (ExpantaNum.pow(10,guess).rec().tetr(degree).gt(x)) upper=guess;
else lower=guess;
if (guess.eq(previous)) loopGoing=false;
else previous=guess;
if (upper.gt(1e18)) return ExpantaNum.NaN.clone();
}
if (guess.neq_tolerance(minimum,1e-15)) return ExpantaNum.pow(10,guess).rec();
else{
if (maximum.eq(BIG)) return ExpantaNum.NaN.clone();
lower=BIG;
upper=maximum;
previous=upper;
guess=ExpantaNum.ZERO;
var loopGoing=true;
while (loopGoing){
if (lower.eq(BIG)) guess=upper.mul(2);
else guess=lower.add(upper).div(2);
if (ExpantaNum.pow(10,guess).rec().tetr(degree).gt(x)) upper=guess;
else lower=guess;
if (guess.eq(previous)) loopGoing=false;
else previous=guess;
if (upper.gt(1e18)) return ExpantaNum.NaN.clone();
}
return ExpantaNum.pow(10,guess).rec();
}
}
};
Q.linear_sroot=function (x,y){
return new ExpantaNum(x).linear_sroot(y);
};
//Super-logarithm, one of tetration's inverses, tells you what size power tower you'd have to tetrate base to to get number. By definition, will never be higher than 1.8e308 in break_eternity.js, since a power tower 1.8e308 numbers tall is the largest representable number.
//Uses linear approximation
//https://en.wikipedia.org/wiki/Super-logarithm
P.slog=function (base){
if (base===undefined) base=10;
var x=this.clone();
base=new ExpantaNum(base);
if (x.isNaN()||base.isNaN()||x.isInfinite()&&base.isInfinite()) return ExpantaNum.NaN.clone();
if (x.isInfinite()) return x;
if (base.isInfinite()) return ExpantaNum.ZERO.clone();
if (x.eq(ExpantaNum.ZERO)) return ExpantaNum.ONE.neg();
if (x.eq(ExpantaNum.ONE)) return ExpantaNum.ZERO.clone();
if (x.eq(base)) return ExpantaNum.ONE.clone();
if (base.lt(Math.exp(1/Math.E))){
var a=ExpantaNum.tetr(base,Infinity);
if (x.eq(a)) return ExpantaNum.POSITIVE_INFINITY.clone();
if (x.gt(a)) return ExpantaNum.NaN.clone();
}
if (x.max(base).gt("10^^^"+MAX_SAFE_INTEGER)){
if (x.gt(base)) return x;
return ExpantaNum.ZERO.clone();
}
if (x.max(base).gt(ExpantaNum.TETRATED_MAX_SAFE_INTEGER)){
if (x.gt(base)){
x.operator(2,x.operator(2)-1);
x.normalize();
return x.sub(x.operator(1));
}
return ExpantaNum.ZERO.clone();
}
if (x.lt(ExpantaNum.ZERO)) return base.pow(x).sub(2); //Inversion of x^^y=log_x(2+y) for -2<y<=-1
var r=0;
var t=(x.operator(1)||0)-(base.operator(1)||0);
if (t>3){
var l=t-3;
r+=l;
x.operator(1,x.operator(1)-l);
}
for (var i=0;i<100;++i){
if (x.lte(ExpantaNum.ONE)) return new ExpantaNum(r+x.toNumber()-1);
++r;
x=ExpantaNum.logBase(x,base);
}
return ExpantaNum.NaN.clone(); //Failed to converge
};
Q.slog=function (x,y){
return new ExpantaNum(x).slog(y);
};
//end break_eternity.js excerpt
P.pentate=P.pent=function (other){
return this.arrow(3)(other);
};
Q.pentate=Q.pent=function (x,y){
return ExpantaNum.arrow(x,3,y);
};
P.penta_log=function (other){
return this.arrow_height_inverse(3)(other);
};
Q.penta_log=function (x,y){
return ExpantaNum.arrow_height_inverse(x,3,y);
};
//Uses linear approximations for real height
P.arrow=function (arrows){
var t=this.clone();
arrows=new ExpantaNum(arrows);
if (!arrows.isint()||arrows.lt(ExpantaNum.ZERO)) return function(other){return ExpantaNum.NaN.clone();};
if (arrows.eq(ExpantaNum.ZERO)) return function(other){return t.mul(other);};
if (arrows.eq(ExpantaNum.ONE)) return function(other){return t.pow(other);};
if (arrows.eq(2)) return function(other,payload){return t.tetr(other,payload);};
return function (other,payload,depth){
if (payload===undefined) payload=ExpantaNum.ONE;
if (depth===undefined) depth=0;
other=new ExpantaNum(other);
payload=new ExpantaNum(payload);
if (t.isNaN()||other.isNaN()||payload.isNaN()) return ExpantaNum.NaN.clone();
if (payload.neq(ExpantaNum.ONE)) other=other.add(payload.arrow_height_inverse(arrows)(t));
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log(t+"{"+arrows+"}"+other);
if (t.eq(ExpantaNum.ZERO)){
if (other.eq(ExpantaNum.ONE)) return ExpantaNum.ZERO.clone();
return ExpantaNum.NaN.clone();
}
if (t.eq(ExpantaNum.ONE)) return ExpantaNum.ONE.clone();
if (other.eq(ExpantaNum.ZERO)) return ExpantaNum.ONE.clone();
if (other.eq(ExpantaNum.ONE)) return t.clone();
//By induction: See initialization of r in the fallthrough branch
if (other.gt(ExpantaNum.ZERO)&&other.lt(ExpantaNum.ONE)) return t.pow(other);
if (other.gt(ExpantaNum.ONE)&&arrows.gt(ExpantaNum.MAX_SAFE_INTEGER)){
var r=arrows.clone();
r.layer++;
return r;
}
var arrowsNum=arrows.toNumber();
if (other.eq(2)) return t.arrow(arrowsNum-1)(t,ExpantaNum.ONE,depth+1);
if (t.max(other).gt("10{"+(arrowsNum+1)+"}"+MAX_SAFE_INTEGER)) return t.max(other);
if (t.gt("10{"+arrowsNum+"}"+MAX_SAFE_INTEGER)||other.gt(ExpantaNum.MAX_SAFE_INTEGER)){
var r;
if (t.gt("10{"+arrowsNum+"}"+MAX_SAFE_INTEGER)){
r=t.clone();
r.operator(arrowsNum,r.operator(arrowsNum)-1);
r.normalize();
}else if (t.gt("10{"+(arrowsNum-1)+"}"+MAX_SAFE_INTEGER)){
r=new ExpantaNum(t.operator(arrowsNum-1));
}else{
r=ExpantaNum.ZERO;
}
var j=r.add(other);
j.operator(arrowsNum,(j.operator(arrowsNum)||0)+1);
j.normalize();
return j;
}
if (depth>=ExpantaNum.maxOps+10){
return new ExpantaNum([[0,10],[arrowsNum,1]]);
}
var y=other.toNumber();
var f=Math.floor(y);
var arrows_m1=arrows.sub(ExpantaNum.ONE);
var r=t.arrow(arrows_m1)(y-f,ExpantaNum.ONE,depth+1);
var l=ExpantaNum.NaN;
for (var i=0,m=new ExpantaNum("10{"+(arrowsNum-1)+"}"+MAX_SAFE_INTEGER);f!==0&&r.lt(m)&&i<100;++i){
if (f>0){
r=t.arrow(arrows_m1)(r,ExpantaNum.ONE,depth+1);
if (l.eq(r)){
f=0;
break;
}
l=r;
--f;
}else{
r=r.arrow_height_inverse(arrows_m1)(t);
if (l.eq(r)){
f=0;
break;
}
l=r;
++f;
}
}
if (i==100) f=0;
r.operator(arrowsNum-1,(r.operator(arrowsNum-1)+f)||f);
r.normalize();
return r;
};
};
P.chain=function (other,arrows){
return this.arrow(arrows)(other);
};
Q.arrow=function (x,z,y,payload){
return new ExpantaNum(x).arrow(z)(y,payload);
};
Q.chain=function (x,y,z){
return new ExpantaNum(x).arrow(z)(y);
};
Q.hyper=function (z){
z=new ExpantaNum(z);
if (z.eq(ExpantaNum.ZERO)) return function(x,y){return new ExpantaNum(y).eq(ExpantaNum.ZERO)?new ExpantaNum(x):new ExpantaNum(x).add(ExpantaNum.ONE);};
if (z.eq(ExpantaNum.ONE)) return function(x,y){return ExpantaNum.add(x,y);};
return function(x,y,payload){return new ExpantaNum(x).arrow(z.sub(2))(y,payload);};
};
//arrow_height_inverse{z}_x(x{z}y)=y
//See also: https://github.com/Patashu/break_eternity.js/blob/848736e3dc37d8e7b5cc238f46e3ddb277d0dce2/src/index.ts#L4647
P.arrow_height_inverse=function (arrows){
var x=this.clone();
arrows=new ExpantaNum(arrows);
if (!arrows.isint()||arrows.lt(ExpantaNum.ONE)) return function(other){return ExpantaNum.NaN.clone();};
if (arrows.eq(ExpantaNum.ONE)) return function(base){return x.logBase(base);};
if (arrows.eq(2)) return function(base){return x.slog(base);};
return function (base,depth){
if (base===undefined) base=10;
if (depth===undefined) depth=0;
base=new ExpantaNum(base);
if (x.isNaN()||base.isNaN()||x.isInfinite()&&base.isInfinite()) return ExpantaNum.NaN.clone();
if (base.lte(ExpantaNum.ONE)) return ExpantaNum.NaN.clone();
if (x.isInfinite()) return x;
if (base.isInfinite()) return ExpantaNum.ZERO.clone();
if (x.eq(ExpantaNum.ZERO)) return ExpantaNum.ONE.neg();
if (x.eq(ExpantaNum.ONE)) return ExpantaNum.ZERO.clone();
if (x.eq(base)) return ExpantaNum.ONE.clone();
//Inverse of shortcut for 0<other<1 in arrow
if (x.gt(ExpantaNum.ONE)&&x.lt(base)) return x.logBase(base);
if (x.gt(ExpantaNum.ONE)&&arrows.gt(ExpantaNum.MAX_SAFE_INTEGER)){
var twocmp=x.cmp(base.arrow(arrows)(base));
if (twocmp==0) return new ExpantaNum(2);
if (twocmp>0) return x;
return ExpantaNum.ONE.clone(); //base{arrows}(1+epsilon) explodes
}
var arrowsNum=arrows.toNumber();
if (arrowsNum==2&&x.lt(ExpantaNum.ONE.neg())){
if (x.lt(-2)) return ExpantaNum.NaN.clone();
var infrcmp=x.cmp(base.arrow(arrows.sub(ExpantaNum.ONE))(x));
if (infrcmp==0) return ExpantaNum.NEGATIVE_INFINITY.clone();
if (infrcmp>0) return ExpantaNum.NaN.clone();
}
if (x.max(base).gt("10{"+(arrowsNum+1)+"}"+MAX_SAFE_INTEGER)){
if (x.gt(base)) return x;
return ExpantaNum.ZERO.clone();
}
if (x.max(base).gt("10{"+arrowsNum+"}"+MAX_SAFE_INTEGER)){
if (x.gt(base)){
x.operator(arrowsNum,x.operator(arrowsNum)-1);
x.normalize();
return x.sub(x.operator(arrowsNum-1));
}
return ExpantaNum.ZERO.clone();
}
var r=0;
var t=(x.operator(arrowsNum-1)||0)-(base.operator(arrowsNum-1)||0);
if (depth>=ExpantaNum.maxOps+10) return new ExpantaNum(t);
if (t>3){
var l=t-3;
r+=l;
x.operator(arrowsNum-1,x.operator(arrowsNum-1)-l);
}
var arrows_m1=arrows.sub(ExpantaNum.ONE);
for (var i=0;i<100;++i){
if (x.lt(ExpantaNum.ZERO)){
x=base.arrow(arrows_m1)(x);
--r;
}else if (x.lte(ExpantaNum.ONE)){
return new ExpantaNum(r+x.toNumber()-1);
}else{
++r;
x=x.arrow_height_inverse(arrows_m1)(base,depth+1);
}
}
return ExpantaNum.NaN.clone(); //Failed to converge
};
};
Q.arrow_height_inverse=function (x,z,y){
return new ExpantaNum(x).arrow_height_inverse(z)(y);
}
P.expansion=function (other){
var t=this.clone();
other=new ExpantaNum(other);
var r;
if (ExpantaNum.debug>=ExpantaNum.NORMAL) console.log("{"+t+","+other+",1,2}");
if (other.lte(ExpantaNum.ZERO)||!other.isint()) return ExpantaNum.NaN.clone();
if (other.eq(ExpantaNum.ONE)) return t.clone();
if (!t.isint()) return ExpantaNum.NaN.clone();
if (t.eq(2)) return new ExpantaNum(4);
if (other.gt(ExpantaNum.MAX_SAFE_INTEGER)) return ExpantaNum.POSITIVE_INFINITY.clone();
var f=other.toNumber()-1;
r=t;
for (var i=0;f!==0&&r.lt(ExpantaNum.MAX_SAFE_INTEGER)&&i<100;++i){
if (f>0){
r=t.arrow(r)(t);
--f;
}
}
if (i==100) f=0;
r.layer+=f;
r.normalize();
return r;
};
Q.expansion=function (x,y){
return new ExpantaNum(x).expansion(y);
};
// All of these are from Patashu's break_eternity.js
Q.affordGeometricSeries = function (resourcesAvailable, priceStart, priceRatio, currentOwned) {
/*
If you have resourcesAvailable, the price of something starts at
priceStart, and on each purchase it gets multiplied by priceRatio,
and you have already bought currentOwned, how many of the object
can you buy.
*/
resourcesAvailable=new ExpantaNum(resourcesAvailable);
priceStart=new ExpantaNum(priceStart);
priceRatio=new ExpantaNum(priceRatio);
var actualStart = priceStart.mul(priceRatio.pow(currentOwned));
return ExpantaNum.floor(resourcesAvailable.div(actualStart).mul(priceRatio.sub(ExpantaNum.ONE)).add(ExpantaNum.ONE).log10().div(priceRatio.log10()));
};
Q.affordArithmeticSeries = function (resourcesAvailable, priceStart, priceAdd, currentOwned) {
/*
If you have resourcesAvailable, the price of something starts at
priceStart, and on each purchase it gets increased by priceAdd,
and you have already bought currentOwned, how many of the object
can you buy.
*/
resourcesAvailable=new ExpantaNum(resourcesAvailable);
priceStart=new ExpantaNum(priceStart);
priceAdd=new ExpantaNum(priceAdd);
currentOwned=new ExpantaNum(currentOwned);
var actualStart = priceStart.add(currentOwned.mul(priceAdd));
var b = actualStart.sub(priceAdd.div(2));
var b2 = b.pow(2);
return b.neg().add(b2.add(priceAdd.mul(resourcesAvailable).mul(2)).sqrt()).div(priceAdd).floor();
};
Q.sumGeometricSeries = function (numItems, priceStart, priceRatio, currentOwned) {
/*
If you want to buy numItems of something, the price of something starts at
priceStart, and on each purchase it gets multiplied by priceRatio,
and you have already bought currentOwned, what will be the price of numItems
of something.
*/
priceStart=new ExpantaNum(priceStart);
priceRatio=new ExpantaNum(priceRatio);
return priceStart.mul(priceRatio.pow(currentOwned)).mul(ExpantaNum.sub(ExpantaNum.ONE, priceRatio.pow(numItems))).div(ExpantaNum.sub(ExpantaNum.ONE, priceRatio));
};
Q.sumArithmeticSeries = function (numItems, priceStart, priceAdd, currentOwned) {
/*
If you want to buy numItems of something, the price of something starts at
priceStart, and on each purchase it gets increased by priceAdd,
and you have already bought currentOwned, what will be the price of numItems
of something.
*/
numItems=new ExpantaNum(numItems);
priceStart=new ExpantaNum(priceStart);
currentOwned=new ExpantaNum(currentOwned);
var actualStart = priceStart.add(currentOwned.mul(priceAdd));
return numItems.div(2).mul(actualStart.mul(2).plus(numItems.sub(ExpantaNum.ONE).mul(priceAdd)));
};
// Binomial Coefficients n choose k
Q.choose = function (n, k) {
/*
If you have n items and you take k out,
how many ways could you do this?
*/
return new ExpantaNum(n).factorial().div(new ExpantaNum(k).factorial().mul(new ExpantaNum(n).sub(new ExpantaNum(k)).factorial()));
};
P.choose = function (other) {
return ExpantaNum.choose(this, other);
};
//end break_eternity.js excerpt
P.normalize=function (){
var b;
var x=this;
if (ExpantaNum.debug>=ExpantaNum.ALL) console.log(x.toString());
if (!x.array||!x.array.length) x.array=[[0,0]];
if (x.sign!=1&&x.sign!=-1){
if (typeof x.sign!="number") x.sign=Number(x.sign);
x.sign=x.sign<0?-1:1;
}
if (x.layer>MAX_SAFE_INTEGER){
x.array=[[0,Infinity]];
x.layer=0;
return x;
}
if (Number.isInteger(x.layer)) x.layer=Math.floor(x.layer);
for (var i=0;i<x.array.length;++i){
var e=x.array[i];
if (e[0]===null||e[0]===undefined){
e[0]=0;
}
if (e[0]!==0&&(e[1]===0||e[1]===null||e[1]===undefined)){
x.array.splice(i,1);
--i;
continue;
}
if (isNaN(e[0])||isNaN(e[1])){
x.array=[[0,NaN]];
return x;
}
if (!isFinite(e[0])||!isFinite(e[1])){
x.array=[[0,Infinity]];
return x;
}
if (!Number.isInteger(e[0])) e[0]=Math.floor(e[0]);
if (e[0]!==0&&!Number.isInteger(e[1])) e[1]=Math.floor(e[1]);
}
do{
if (ExpantaNum.debug>=ExpantaNum.ALL) console.log(x.toString());
b=false;
x.array.sort(function (a,b){return a[0]>b[0]?1:a[0]<b[0]?-1:0;});
if (x.array.length>ExpantaNum.maxOps) x.array.splice(0,x.array.length-ExpantaNum.maxOps);
if (!x.array.length) x.array=[[0,0]];
if (x.array[x.array.length-1][0]>MAX_SAFE_INTEGER){
x.layer++;
x.array=[[0,x.array[x.array.length-1][0]]];
b=true;
}else if (x.layer&&x.array.length==1&&x.array[0][0]===0){
x.layer--;
if (x.array[0][1]===0) x.array=[[0,10]];
else x.array=[[0,10],[Math.round(x.array[0][1]),1]];
b=true;
}
if (x.array.length<ExpantaNum.maxOps&&x.array[0][0]!==0) x.array.unshift([0,10]);
for (i=0;i<x.array.length-1;++i){
if (x.array[i][0]==x.array[i+1][0]){
x.array[i][1]+=x.array[i+1][1];
x.array.splice(i+1,1);
--i;
b=true;
}
}
if (x.array[0][0]===0&&x.array[0][1]>MAX_SAFE_INTEGER){
if (x.array.length>=2&&x.array[1][0]==1){
x.array[1][1]++;
}else{
x.array.splice(1,0,[1,1]);
}
x.array[0][1]=Math.log10(x.array[0][1]);
b=true;
}
while (x.array.length>=2&&x.array[0][0]===0&&x.array[0][1]<MAX_E&&x.array[1][0]==1&&x.array[1][1]){
x.array[0][1]=Math.pow(10,x.array[0][1]);
if (x.array[1][1]>1){
x.array[1][1]--;
}else{
x.array.splice(1,1);
}
b=true;
}
while (x.array.length>=2&&x.array[0][0]===0&&x.array[0][1]==1&&x.array[1][1]){
if (x.array[1][1]>1){
x.array[1][1]--;
}else{
x.array.splice(1,1);
}
x.array[0][1]=10;
}
if (x.array.length>=2&&x.array[0][0]===0&&x.array[1][0]!=1){
var p=1;
if (Math.floor(x.array[0][1])) x.array.splice(1,0,[x.array[1][0]-1,Math.floor(x.array[0][1])]),p++;
x.array[0][1]=Math.pow(10,x.array[0][1]-Math.floor(x.array[0][1]));
if (x.array[p][1]>1){
x.array[p][1]--;
}else{
x.array.splice(p,1);
}
b=true;
}
for (i=0;i<x.array.length;++i){
if (x.array[i][1]>MAX_SAFE_INTEGER){
if (i!=x.array.length-1&&x.array[i+1][0]==x.array[i][0]+1){
x.array[i+1][1]++;
}else{
x.array.splice(i+1,0,[x.array[i][0]+1,1]);
}
x.array.splice(0,i+1,[0,x.array[i][1]+1]);
b=true;
}
}
}while(b);
if (!x.array.length) x.array=[[0,0]];
return x;
};
var standardizeMessageSent=false;
P.standardize=function (){
if (!standardizeMessageSent) console.warn(expantaNumError+"'standardize' method is being deprecated in favor of 'normalize' and will be removed in the future!"),standardizeMessageSent=true;
return this.normalize();
}
P.toNumber=function (){
//console.log(this.array);
if (this.sign==-1) return -1*this.abs();
if (this.layer>0||this.array.length>=2&&(this.array[1][0]>=2||this.array[1][1]>=2||this.array[1][1]==1&&this.array[0][1]>Math.log10(Number.MAX_VALUE))) return Infinity;
if (this.array.length>=2&&this.array[1][1]==1) return Math.pow(10,this.array[0][1]);
return this.array[0][1];
};
P.toString=function (){
if (this.sign==-1) return "-"+this.abs();
if (isNaN(this.array[0][1])) return "NaN";
if (!isFinite(this.array[0][1])) return "Infinity";
var s="";
if (!this.layer) s+="";
else if (this.layer<3) s+="J".repeat(this.layer);
else s+="J^"+this.layer+" ";
if (this.array.length>=3||this.array.length==2&&this.array[1][0]>=2){
for (var i=this.array.length-1;i>=2;--i){
var e=this.array[i];
var q=e[0]>=5?"{"+e[0]+"}":"^".repeat(e[0]);
if (e[1]>1) s+="(10"+q+")^"+e[1]+" ";
else if (e[1]==1) s+="10"+q;
}
}
var op0=this.operator(0);
var op1=this.operator(1);
if (!op1) s+=String(op0);
else if (op1<3) s+="e".repeat(op1-1)+Math.pow(10,op0-Math.floor(op0))+"e"+Math.floor(op0);
else if (op1<8) s+="e".repeat(op1)+op0;
else s+="(10^)^"+op1+" "+op0;
return s;
};
//from break_eternity.js
var decimalPlaces=function decimalPlaces(value,places){
var len=places+1;
var numDigits=Math.ceil(Math.log10(Math.abs(value)));
if (numDigits<100) numDigits=0; //A hack-y solution to https://github.com/Naruyoko/ExpantaNum.js/issues/22
var rounded=Math.round(value*Math.pow(10,len-numDigits))*Math.pow(10,numDigits-len);
return parseFloat(rounded.toFixed(Math.max(len-numDigits,0)));
};
P.toStringWithDecimalPlaces=function (places,applyToOpNums){
if (this.sign==-1) return "-"+this.abs();
if (isNaN(this.array[0][1])) return "NaN";
if (!isFinite(this.array[0][1])) return "Infinity";
var b=0;
var s="";
var m=Math.pow(10,places);
if (!this.layer) s+="";
else if (this.layer<3) s+="J".repeat(this.layer);
else s+="J^"+this.layer+" ";
if (this.array.length>=3||this.array.length==2&&this.array[1][0]>=2){
for (var i=this.array.length-1;!b&&i>=2;--i){
var e=this.array[i];
var w=e[0];
var x=e[1];
if (applyToOpNums&&x>=m){
++w;
b=x;
x=1;
}else if (applyToOpNums&&this.array[i-1][0]==w-1&&this.array[i-1][1]>=m){
++x;
b=this.array[i-1][1];
}
var q=w>=5?"{"+w+"}":"^".repeat(w);
if (x>1) s+="(10"+q+")^"+x+" ";
else if (x==1) s+="10"+q;
}
}
var k=this.operator(0);
var l=this.operator(1);
if (k>m){
k=Math.log10(k);
++l;
}
if (b) s+=decimalPlaces(b,places);
else if (!l) s+=String(decimalPlaces(k,places));
else if (l<3) s+="e".repeat(l-1)+decimalPlaces(Math.pow(10,k-Math.floor(k)),places)+"e"+decimalPlaces(Math.floor(k),places);
else if (l<8) s+="e".repeat(l)+decimalPlaces(k,places);
else if (applyToOpNums) s+="(10^)^"+decimalPlaces(l,places)+" "+decimalPlaces(k,places);
else s+="(10^)^"+l+" "+decimalPlaces(k,places);
return s;
};
//these are from break_eternity.js as well
P.toExponential=function (places,applyToOpNums){
if (this.array.length==1) return (this.sign*this.array[0][1]).toExponential(places);
return this.toStringWithDecimalPlaces(places,applyToOpNums);
};
P.toFixed=function (places,applyToOpNums){
if (this.array.length==1) return (this.sign*this.array[0][1]).toFixed(places);
return this.toStringWithDecimalPlaces(places,applyToOpNums);
};
P.toPrecision=function (places,applyToOpNums){
if (this.array[0][1]===0) return (this.sign*this.array[0][1]).toFixed(places-1,applyToOpNums);
if (this.array.length==1&&this.array[0][1]<1e-6) return this.toExponential(places-1,applyToOpNums);
if (this.array.length==1&&places>Math.log10(this.array[0][1])) return this.toFixed(places-Math.floor(Math.log10(this.array[0][1]))-1,applyToOpNums);
return this.toExponential(places-1,applyToOpNums);
};
P.valueOf=function (){
return this.toString();
};
//Note: toArray() would be impossible without changing the layout of the array or lose the information about the sign
P.toJSON=function (){
if (ExpantaNum.serializeMode==ExpantaNum.JSON){
var a=[];
for (var i=0;i<this.array.length;++i) a.push([this.array[i][0],this.array[i][1]]);
return {
array:a,
layer:this.layer,
sign:this.sign
};
}else if (ExpantaNum.serializeMode==ExpantaNum.STRING){
return this.toString();
}
};
P.toHyperE=function (){
if (this.layer) throw Error(expantaNumError+"Sorry, but this prototype doesn't support correct Hyper-E notation for numbers larger than 10{MSI}10");
if (this.sign==-1) return "-"+this.abs().toHyperE();
if (isNaN(this.array[0][1])) return "NaN";
if (!isFinite(this.array[0][1])) return "Infinity";
if (this.lt(ExpantaNum.MAX_SAFE_INTEGER)) return String(this.array[0][1]);
if (this.lt(ExpantaNum.E_MAX_SAFE_INTEGER)) return "E"+this.array[0][1];
var r="E"+this.operator(0)+"#"+this.operator(1);
var l=1;
for (var i=Math.ceil(this.getOperatorIndex(2));i<this.array.length;++i){
if (l+1<this.array[i][0]) r+="#1".repeat(this.array[i][0]-l-1);
l=this.array[i][0];
r+="#"+(this.array[i][1]+1);
}
if (!this.layer) r=""+r;
else if (this.layer<3) r="J".repeat(this.layer)+r;
else r="J^"+this.layer+" "+r;
return r;
};
Q.fromNumber=function (input){
if (typeof input!="number") throw Error(invalidArgument+"Expected Number");
var x=new ExpantaNum();
x.array[0][1]=Math.abs(input);
x.sign=input<0?-1:1;
x.normalize();
return x;
};
var log10PosBigInt=function log10PosBigInt(input){
var exp=BigInt(64);
while (input>=BigInt(1)<<exp) exp*=BigInt(2);
var expdel=exp/BigInt(2);
while (expdel>BigInt(0)){
if (input>=BigInt(1)<<exp) exp+=expdel;
else exp-=expdel;
expdel/=BigInt(2);
}
var cutbits=exp-BigInt(54);
var firstbits=input>>cutbits;
return Math.log10(Number(firstbits))+Math.LOG10E/Math.LOG2E*Number(cutbits);
}
Q.fromBigInt=function (input){
if (typeof input!="bigint") throw Error(invalidArgument+"Expected BigInt");
var x=new ExpantaNum();
var abs=input<BigInt(0)?-input:input;
x.sign=input<BigInt(0)?-1:1;
if (abs<=MAX_SAFE_INTEGER) x.array[0][1]=Number(abs);
else x.array=[[0,log10PosBigInt(abs)],[1,1]];
x.normalize();
return x;
}
var LONG_STRING_MIN_LENGTH=17;
var log10LongString=function log10LongString(str){
return Math.log10(Number(str.substring(0,LONG_STRING_MIN_LENGTH)))+(str.length-LONG_STRING_MIN_LENGTH);
}
Q.fromString=function (input){
if (typeof input!="string") throw Error(invalidArgument+"Expected String");
var isJSON=false;
if (typeof input=="string"&&(input[0]=="["||input[0]=="{")){
try {
JSON.parse(input);
} catch {} finally {
isJSON=true;
}
}
if (isJSON){
return ExpantaNum.fromJSON(input);
}
var x=new ExpantaNum();
x.array=[[0,0]];
if (!isExpantaNum.test(input)){
console.warn(expantaNumError+"Malformed input: "+input);
x.array=[[0,NaN]];
return x;
}
var negateIt=false;
if (input[0]=="-"||input[0]=="+"){
var numSigns=input.search(/[^-\+]/);
var signs=input.substring(0,numSigns);
negateIt=signs.match(/-/g).length%2==1;
input=input.substring(numSigns);
}
if (input=="NaN") x.array=[[0,NaN]];
else if (input=="Infinity") x.array=[[0,Infinity]];
else{
var a,b,c,d,i;
if (input[0]=="J"){
if (input[1]=="^"){
a=input.substring(2).search(/[^0-9]/)+2;
x.layer=Number(input.substring(2,a));
input=input.substring(a+1);
}else{
a=input.search(/[^J]/);
x.layer=a;
input=input.substring(a);
}
}
while (input){
if (/^\(?10[\^\{]/.test(input)){
if (input[0]=="("){
input=input.substring(1);
}
var arrows;
if (input[2]=="^"){
a=input.substring(2).search(/[^\^]/);
arrows=a;
b=a+2;
}else{
a=input.indexOf("}");
arrows=Number(input.substring(3,a));
b=a+1;
}
input=input.substring(b);
if (input[0]==")"){
a=input.indexOf(" ");
c=Number(input.substring(2,a));
input=input.substring(a+1);
}else{
c=1;
}
if (arrows==1){
if (x.array.length>=2&&x.array[1][0]==1){
x.array[1][1]+=c;
}else{
x.array.splice(1,0,[1,c]);
}
}else if (arrows==2){
a=x.array.length>=2&&x.array[1][0]==1?x.array[1][1]:0;
b=x.array[0][1];
if (b>=1e10) ++a;
if (b>=10) ++a;
x.array[0][1]=a;
if (x.array.length>=2&&x.array[1][0]==1) x.array.splice(1,1);
d=x.getOperatorIndex(2);
if (Number.isInteger(d)) x.array[d][1]+=c;
else x.array.splice(Math.ceil(d),0,[2,c]);
}else{
a=x.operator(arrows-1);
b=x.operator(arrows-2);
if (b>=10) ++a;
d=x.getOperatorIndex(arrows);
x.array.splice(1,Math.ceil(d)-1);
x.array[0][1]=a;
if (Number.isInteger(d)) x.array[1][1]+=c;
else x.array.splice(1,0,[arrows,c]);
}
}else{
break;
}
}
a=input.split(/[Ee]/);
b=[x.array[0][1],0];
c=1;
for (i=a.length-1;i>=0;--i){
//The things that are already there
if (b[0]<MAX_E&&b[1]===0){
b[0]=Math.pow(10,c*b[0]);
}else if (c==-1){
if (b[1]===0){
b[0]=Math.pow(10,c*b[0]);
}else if (b[1]==1&&b[0]<=Math.log10(Number.MAX_VALUE)){
b[0]=Math.pow(10,c*Math.pow(10,b[0]));
}else{
b[0]=0;
}
b[1]=0;
}else{
b[1]++;
}
//Multiplying coefficient
var decimalPointPos=a[i].indexOf(".");
var intPartLen=decimalPointPos==-1?a[i].length:decimalPointPos;
if (b[1]===0){
if (intPartLen>=LONG_STRING_MIN_LENGTH) b[0]=Math.log10(b[0])+log10LongString(a[i].substring(0,intPartLen)),b[1]=1;
else if (a[i]) b[0]*=Number(a[i]);
}else{
d=intPartLen>=LONG_STRING_MIN_LENGTH?log10LongString(a[i].substring(0,intPartLen)):a[i]?Math.log10(Number(a[i])):0;
if (b[1]==1){
b[0]+=d;
}else if (b[1]==2&&b[0]<MAX_E+Math.log10(d)){
b[0]+=Math.log10(1+Math.pow(10,Math.log10(d)-b[0]));
}
}
//Carrying
if (b[0]<MAX_E&&b[1]){
b[0]=Math.pow(10,b[0]);
b[1]--;
}else if (b[0]>MAX_SAFE_INTEGER){
b[0]=Math.log10(b[0]);
b[1]++;
}
}
x.array[0][1]=b[0];
if (b[1]){
if (x.array.length>=2&&x.array[1][0]==1) x.array[1][1]+=b[1];
else x.array.splice(1,0,[1,b[1]]);
}
}
if (negateIt) x.sign*=-1;
x.normalize();
return x;
};
Q.fromArray=function (input1,input2,input3){
var array,layer,sign;
if (input1 instanceof Array&&(input2===undefined||typeof input2=="number")&&(input3===undefined||typeof input3=="number")){
array=input1;
sign=input2;
layer=input3||0;
}else if (typeof input1=="number"&&input2 instanceof Array&&(input3===undefined||typeof input3=="number")){
array=input2;
sign=input1;
layer=input3||0;
}else if (typeof input1=="number"&&typeof input2=="number"&&input3 instanceof Array){
array=input3;
sign=input1;
layer=input2;
}else{
throw Error(invalidArgument+"Expected an Array [and 1 or 2 Number]");
}
var x=new ExpantaNum();
var i;
if (!array.length) x.array=[[0,0]];
else if (typeof array[0]=="number"){
x.array=[];
for (i=0;i<array.length;i++){
if (typeof array[i]!="number") throw Error(invalidArgument+"Expected Array of Number");
x.array.push([i,array[i]]);
}
}else if (array[0] instanceof Array){
x.array=[];
for (i=0;i<array.length;i++){
if (!(array[i] instanceof Array)||typeof array[i][0]!="number"||typeof array[i][1]!="number") throw Error(invalidArgument+"Expected Array of pair of Number");
x.array.push([array[i][0],array[i][1]]);
}
}else throw Error(invalidArgument+"Expected Array of Number or Array of pair of Number");
if (sign) x.sign=Number(sign);
else x.sign=1;
x.normalize();
return x;
};
Q.fromObject=function (input){
if (typeof input!="object") return ExpantaNum.ZERO.clone();
if (input===null) return ExpantaNum.ZERO.clone();
if (input instanceof Array) return ExpantaNum.fromArray(input);
if (input instanceof ExpantaNum) return new ExpantaNum(input);
if (!(input.array instanceof Array)) throw Error(invalidArgument+"Expected that property 'array' exists");
if (input.sign!==undefined&&typeof input.sign!="number") throw Error(invalidArgument+"Expected that property 'sign' is Number");
if (input.layer!==undefined&&typeof input.layer!="number") throw Error(invalidArgument+"Expected that property 'layer' is Number");
return ExpantaNum.fromArray(input.array,input.sign,input.layer);
/*var x=new ExpantaNum();
x.array=[];
for (var i=0;i<input.array.length;i++) x.array.push([input.array[i][0],input.array[i][1]]);
x.sign=Number(input.sign)||1;
x.layer=Number(input.layer)||0;
x.normalize();
return x;*/
};
Q.fromJSON=function (input){
if (typeof input=="object") return ExpantaNum.fromObject(parsedObject);
if (typeof input!="string") throw Error(invalidArgument+"Expected String");
var parsedObject,x;
try{
parsedObject=JSON.parse(input);
}catch(e){
parsedObject=null;
throw e;
}finally{
x=ExpantaNum.fromObject(parsedObject);
}
parsedObject=null;
return x;
};
Q.fromHyperE=function (input){
if (typeof input!="string") throw Error(invalidArgument+"Expected String");
var x=new ExpantaNum();
x.array=[[0,0]];
if (!/^[-\+]*(0|[1-9]\d*(\.\d*)?|Infinity|NaN|E[1-9]\d*(\.\d*)?(#[1-9]\d*)*)$/.test(input)){
console.warn(expantaNumError+"Malformed input: "+input);
x.array=[[0,NaN]];
return x;
}
var negateIt=false;
if (input[0]=="-"||input[0]=="+"){
var numSigns=input.search(/[^-\+]/);
var signs=input.substring(0,numSigns);
negateIt=signs.match(/-/g).length%2===0;
input=input.substring(numSigns);
}
if (input=="NaN") x.array=[[0,NaN]];
else if (input=="Infinity") x.array=[[0,Infinity]];
else if (input[0]!="E"){
x.array[0][1]=Number(input);
}else if (input.indexOf("#")==-1){
x.array[0][1]=Number(input.substring(1));
x.array[1]=[1,1];
}else{
var array=input.substring(1).split("#");
for (var i=0;i<array.length;++i){
var t=Number(array[i]);
if (i>=2){
--t;
}
x.array[i]=[i,t];
}
}
if (negateIt) x.sign*=-1;
x.normalize();
return x;
};
P.getOperatorIndex=function (i){
if (typeof i!="number") i=Number(i);
if (!isFinite(i)) throw Error(invalidArgument+"Index out of range.");
var a=this.array;
var min=0,max=a.length-1;
if (a[max][0]<i) return max+0.5;
if (a[min][0]>i) return -0.5;
while (min!=max){
if (a[min][0]==i) return min;
if (a[max][0]==i) return max;
var mid=Math.floor((min+max)/2);
if (min==mid||a[mid][0]==i){
min=mid;
break;
}
if (a[mid][0]<i) min=mid;
if (a[mid][0]>i) max=mid;
}
return a[min][0]==i?min:min+0.5;
};
P.getOperator=function (i){
if (typeof i!="number") i=Number(i);
if (!isFinite(i)) throw Error(invalidArgument+"Index out of range.");
var ai=this.getOperatorIndex(i);
if (Number.isInteger(ai)) return this.array[ai][1];
else return i===0?10:0;
};
P.setOperator=function (i,value){
if (typeof i!="number") i=Number(i);
if (!isFinite(i)) throw Error(invalidArgument+"Index out of range.");
var ai=this.getOperatorIndex(i);
if (Number.isInteger(ai)) this.array[ai][1]=value;
else{
ai=Math.ceil(ai);
this.array.splice(ai,0,[i,value]);
}
this.normalize();
};
P.operator=function (i,value){
if (value===undefined) return this.getOperator(i);
else this.setOperator(i,value);
};
P.clone=function (){
var temp=new ExpantaNum();
var array=[];
for (var i=0;i<this.array.length;++i) array.push([this.array[i][0],this.array[i][1]]);
temp.array=array;
temp.sign=this.sign;
temp.layer=this.layer;
return temp;
};
// ExpantaNum methods
/*
* clone
* config/set
*/
/*
* Create and return a ExpantaNum constructor with the same configuration properties as this ExpantaNum constructor.
*
*/
function clone(obj) {
var i, p, ps;
function ExpantaNum(input,input2) {
var x=this;
if (!(x instanceof ExpantaNum)) return new ExpantaNum(input,input2);
x.constructor=ExpantaNum;
var parsedObject=null;
if (typeof input=="string"&&(input[0]=="["||input[0]=="{")){
try {
parsedObject=JSON.parse(input);
}catch(e){
//lol just keep going
}
}
var temp,temp2,temp3;
if (typeof input=="number"&&!(input2 instanceof Array)){
temp=ExpantaNum.fromNumber(input);
}else if (typeof input=="bigint"){
temp=ExpantaNum.fromBigInt(input);
}else if (parsedObject){
temp=ExpantaNum.fromObject(parsedObject);
}else if (typeof input=="string"&&input[0]=="E"){
temp=ExpantaNum.fromHyperE(input);
}else if (typeof input=="string"){
temp=ExpantaNum.fromString(input);
}else if (input instanceof Array||input2 instanceof Array){
temp=ExpantaNum.fromArray(input,input2);
}else if (input instanceof ExpantaNum){
temp=[];
for (var i=0;i<input.array.length;++i) temp.push([input.array[i][0],input.array[i][1]]);
temp2=input.sign;
temp3=input.layer;
}else if (typeof input=="object"){
temp=ExpantaNum.fromObject(input);
}else{
temp=[[0,NaN]];
temp2=1;
temp3=0;
}
if (typeof temp2=="undefined"){
x.array=temp.array;
x.sign=temp.sign;
x.layer=temp.layer;
}else{
x.array=temp;
x.sign=temp2;
x.layer=temp3;
}
return x;
}
ExpantaNum.prototype = P;
ExpantaNum.JSON = 0;
ExpantaNum.STRING = 1;
ExpantaNum.NONE = 0;
ExpantaNum.NORMAL = 1;
ExpantaNum.ALL = 2;
ExpantaNum.clone=clone;
ExpantaNum.config=ExpantaNum.set=config;
//ExpantaNum=Object.assign(ExpantaNum,Q);
for (var prop in Q){
if (Q.hasOwnProperty(prop)){
ExpantaNum[prop]=Q[prop];
}
}
if (obj === void 0) obj = {};
if (obj) {
ps = ['maxOps', 'serializeMode', 'debug'];
for (i = 0; i < ps.length;) if (!obj.hasOwnProperty(p = ps[i++])) obj[p] = this[p];
}
ExpantaNum.config(obj);
return ExpantaNum;
}
function defineConstants(obj){
for (var prop in R){
if (R.hasOwnProperty(prop)){
if (Object.defineProperty){
Object.defineProperty(obj,prop,{
configurable: false,
enumerable: true,
writable: false,
value: new ExpantaNum(R[prop])
});
}else{
obj[prop]=new ExpantaNum(R[prop]);
}
}
}
return obj;
}
/*
* Configure global settings for a ExpantaNum constructor.
*
* `obj` is an object with one or more of the following properties,
*
* precision {number}
* rounding {number}
* toExpNeg {number}
* toExpPos {number}
*
* E.g. ExpantaNum.config({ precision: 20, rounding: 4 })
*
*/
function config(obj){
if (!obj||typeof obj!=='object') {
throw Error(expantaNumError+'Object expected');
}
var i,p,v,
ps = [
'maxOps',1,Number.MAX_SAFE_INTEGER,
'serializeMode',0,1,
'debug',0,2
];
for (i = 0; i < ps.length; i += 3) {
if ((v = obj[p = ps[i]]) !== void 0) {
if (Math.floor(v) === v && v >= ps[i + 1] && v <= ps[i + 2]) this[p] = v;
else throw Error(invalidArgument + p + ': ' + v);
}
}
return this;
}
// Create and configure initial ExpantaNum constructor.
ExpantaNum=clone(ExpantaNum);
ExpantaNum=defineConstants(ExpantaNum);
ExpantaNum['default']=ExpantaNum.ExpantaNum=ExpantaNum;
// Export.
// AMD.
if (typeof define == 'function' && define.amd) {
define(function () {
return ExpantaNum;
});
// Node and other environments that support module.exports.
} else if (typeof module != 'undefined' && module.exports) {
module.exports = ExpantaNum;
// Browser.
} else {
if (!globalScope) {
globalScope = typeof self != 'undefined' && self && self.self == self
? self : Function('return this')();
}
globalScope.ExpantaNum = ExpantaNum;
}
})(this);