New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

exactnumber

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

exactnumber - npm Package Compare versions

Comparing version 0.11.0 to 1.0.0

.prettierignore

9

CHANGELOG.md

@@ -0,1 +1,10 @@

## 1.0.0 (November 05, 2022)
- Add modular exponentiation - `powm()`
- Do not expose `trimTrailingZeros()` anymore. Zero trimming is still available through the third parameter at toFixed(), toExponential() and toPrecision()
- Radian angles handled more precisely. Trigonometric functions now provide exact results for expressions like `sin(PI/6)=0.5`
- Not using BigInt literals anymore, because they are not compatible with some FE frameworks
- Performance improvements by memoizing common BigInt values
- Fixed bug with zeros not being trimmed corectly
## 0.11.0 (October 29, 2022)

@@ -2,0 +11,0 @@

4

dist/index.esm.min.js
/*!
* exactnumber v0.11.0 (https://www.npmjs.com/package/exactnumber)
* exactnumber v1.0.0 (https://www.npmjs.com/package/exactnumber)
* (c) Dani Biro

@@ -7,2 +7,2 @@ * @license MIT

var t,n;!function(t){t[t.NEAREST_TO_POSITIVE=201008]="NEAREST_TO_POSITIVE",t[t.NEAREST_TO_NEGATIVE=201009]="NEAREST_TO_NEGATIVE",t[t.NEAREST_TO_EVEN=201010]="NEAREST_TO_EVEN",t[t.NEAREST_TO_ZERO=201011]="NEAREST_TO_ZERO",t[t.NEAREST_AWAY_FROM_ZERO=201012]="NEAREST_AWAY_FROM_ZERO",t[t.TO_POSITIVE=201001]="TO_POSITIVE",t[t.TO_NEGATIVE=201002]="TO_NEGATIVE",t[t.TO_ZERO=201003]="TO_ZERO",t[t.AWAY_FROM_ZERO=201004]="AWAY_FROM_ZERO"}(t||(t={})),function(t){t.TRUNCATED="T",t.FLOORED="F",t.EUCLIDEAN="E"}(n||(n={}));const r=t=>{const n=t.indexOf(".");if(-1===n)return t;let r=t.length;for(;r>n&&"0"===t.charAt(r-1);)r--;const e=n===r-1?n:r;return 0===e?"0":t.slice(0,e)},e=(t,n,e,i)=>{let o=t.toString();if(0===n&&0===e)return o;const s=o.startsWith("-");if(s&&(o=o.slice(1)),n>=o.length&&(o="0".repeat(n-o.length+1)+o),n>0){const t=o.slice(0,-n),s=o.slice(-n),u=e<=n?s.slice(0,e):`${s}${"0".repeat(e-n)}`;0!==u.length?(o=`${t}.${u}`,i&&(o=r(o))):o=t}else e>0&&(o=`${o}.${"0".repeat(e)}`);return s?`-${o}`:o},i=(n,r)=>(n=n.normalize())instanceof o?n.round(r,t.NEAREST_AWAY_FROM_ZERO):n;class o{constructor(t,n=0){if(this.type="fixed","bigint"==typeof t)this.number=t,this.decimalPos=n;else{const n=this.parseConstructorParameter(t);this.number=n.number,this.decimalPos=n.decimalPos}}parseConstructorParameter(t){if(t instanceof o)return{number:t.number,decimalPos:t.decimalPos};if(t instanceof s){if(!t.isInteger())throw new Error("Cannot create FixedNumber from non-integer Fraction");return{number:t.trunc().number,decimalPos:0}}if("number"==typeof t){if(!Number.isSafeInteger(t))throw new Error("The specified number cannot be exactly represented as an integer. Please provide a string instead.");return{number:BigInt(t),decimalPos:0}}if("string"==typeof t){if(0===(t=t.trim()).length)throw new Error("Empty string is not allowed");const n=t.match(/^(-?[0-9]*)(?:\.([0-9]*))?(?:[eE]([+-]?[0-9]+))?$/);if(!n)throw new Error(`Cannot parse number "${t}"`);let r=0,e=n[1]??"0";if(void 0!==n[2]&&(e+=n[2],r+=n[2].length),void 0!==n[3]){const t=Number(n[3]);t>0?e+="0".repeat(t):r-=t}return{number:BigInt(e),decimalPos:r}}throw new Error("Unsupported parameter!")}scaleNumber(t,n){const r=Math.max(this.decimalPos,n);return{a:r===this.decimalPos?this.number:this.number*10n**BigInt(r-this.decimalPos),b:r===n?t:t*10n**BigInt(r-n),decimalPos:r}}add(t){const n=u(t);if(n instanceof s)return n.add(this);const r=n,{a:e,b:i,decimalPos:a}=this.scaleNumber(r.number,r.decimalPos);return new o(e+i,a)}sub(t){const n=u(t);return this.add(n.neg())}mul(t){const n=u(t);if(n instanceof s)return n.mul(this);const r=n,e=this.number*r.number;return new o(e,this.decimalPos+r.decimalPos)}pow(t){const n=u(t).toNumber();if(!Number.isSafeInteger(n))throw new Error("Unsupported parameter");const r=Math.abs(n),e=new o(this.number**BigInt(r),this.decimalPos*r);return n<0?e.inv():e}div(t){return this.convertToFraction().div(t)}divToInt(t){const n=u(t);if(n instanceof s)return this.convertToFraction().divToInt(n);const r=n,{a:e,b:i}=this.scaleNumber(r.number,r.decimalPos);return new o(e/i)}mod(t,r=n.TRUNCATED){const e=u(t);if(e instanceof s)return this.convertToFraction().mod(e);const i=e,{a:a,b:c,decimalPos:m}=this.scaleNumber(i.number,i.decimalPos),h=a%c,l=new o(h,m);if(r===n.TRUNCATED)return l;if(r===n.FLOORED)return Number(a<0)^Number(c<0)?l.add(c):l;if(r===n.EUCLIDEAN)return h<0?l.add(c<0?-c:c):l;throw new Error("Invalid ModType")}abs(){return new o(this.number<0?-this.number:this.number,this.decimalPos)}neg(){return this.mul(-1n)}inv(){return this.convertToFraction().inv()}floor(n){return 0===this.decimalPos?this:this.round(n,t.TO_NEGATIVE)}ceil(n){return 0===this.decimalPos?this:this.round(n,t.TO_POSITIVE)}trunc(n){return 0===this.decimalPos?this:this.round(n,t.TO_ZERO)}isTieStr(t){if("5"!==t[0])return!1;for(let n=1;n<t.length;n++)if("0"!==t[n])return!1;return!0}_round(n,r){const e=this.decimalPos-n;if(e<=0)return this;const i=10n**BigInt(e),s=this.number/i;if(r===t.TO_ZERO)return new o(s,n);const u=this.number%i;if(0n===u)return new o(s,n);if(r===t.AWAY_FROM_ZERO){const t=this.number<0n?s-1n:s+1n;return new o(t,n)}if(r===t.TO_POSITIVE){const t=this.number<0n?s:s+1n;return new o(t,n)}if(r===t.TO_NEGATIVE){const t=this.number>=0n?s:s-1n;return new o(t,n)}if(![void 0,t.NEAREST_TO_ZERO,t.NEAREST_AWAY_FROM_ZERO,t.NEAREST_TO_POSITIVE,t.NEAREST_TO_NEGATIVE,t.NEAREST_TO_EVEN].includes(r))throw new Error("Invalid rounding mode. Use the predefined values from the RoundingMode enum.");let a=(u<0n?-u:u).toString();if(a.length<e&&(a="0"),this.isTieStr(a)){if(r===t.NEAREST_TO_ZERO)return new o(s,n);if(r===t.NEAREST_AWAY_FROM_ZERO){const t=this.number<0n?s-1n:s+1n;return new o(t,n)}if(void 0===r||r===t.NEAREST_TO_POSITIVE){const t=this.number<0n?s:s+1n;return new o(t,n)}if(r===t.NEAREST_TO_NEGATIVE){const t=this.number>=0n?s:s-1n;return new o(t,n)}if(r===t.NEAREST_TO_EVEN){if(s%2n===0n)return new o(s,n);return new o(s<0n?s-1n:s+1n,n)}}if(Number(a[0])<5)return new o(s,n);const c=this.number<0?s-1n:s+1n;return new o(c,n)}round(t,n){if(t=void 0===t?0:t,!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for decimals");return this._round(t,n).normalize()}_incExponent(t){if(0===t)return this;let n=this.number,r=this.decimalPos;if(t<0)r-=t;else{const e=Math.min(t,this.decimalPos);r-=e;const i=t-e;i>0&&(n*=10n**BigInt(i))}return new o(n,r)}countDigits(){if(0n===this.number)return 1;let t=0,n=this.number<0?-this.number:this.number;for(;n>0n;)n/=10n,t++;return t}toSubZeroNum(){const t=this.countDigits();return{subZeroNum:new o(this.number,t),exponentDiff:t-this.decimalPos}}roundToDigits(t,n){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid value for digits");const{subZeroNum:r,exponentDiff:e}=this.toSubZeroNum();let i=r.round(t,n);return i=i._incExponent(e),i}intPart(){return this.trunc()}fracPart(){return this.sub(this.trunc())}sign(){return this.number<0n?-1:1}bitwiseAnd(t){if(t=a(t),!this.isInteger()||-1===this.sign()||!t.isInteger()||-1===t.sign())throw new Error("Only positive integers are supported");t instanceof s&&(t=t.trunc());const n=2n**24n;let r=this.normalize().number,e=t.trunc().normalize().number,i=0n,u=1n;for(;r>0&&e>0;){const t=BigInt.asUintN(24,r),o=BigInt.asUintN(24,e);i+=BigInt(Number(t)&Number(o))*u,u*=n,r/=n,e/=n}return new o(i)}bitwiseOr(t){if(t=a(t),!this.isInteger()||-1===this.sign()||!t.isInteger()||-1===t.sign())throw new Error("Only positive integers are supported");t instanceof s&&(t=t.trunc());const n=2n**24n;let r=this.normalize().number,e=t.trunc().normalize().number,i=0n,u=1n;for(;r>0||e>0;){const t=BigInt.asUintN(24,r),o=BigInt.asUintN(24,e);i+=BigInt(Number(t)|Number(o))*u,u*=n,r/=n,e/=n}return new o(i)}bitwiseXor(t){if(t=a(t),!this.isInteger()||-1===this.sign()||!t.isInteger()||-1===t.sign())throw new Error("Only positive integers are supported");t instanceof s&&(t=t.trunc());const n=2n**24n;let r=this.normalize().number,e=t.trunc().normalize().number,i=0n,u=1n;for(;r>0||e>0;){const t=BigInt.asUintN(24,r),o=BigInt.asUintN(24,e);i+=BigInt(Number(t)^Number(o))*u,u*=n,r/=n,e/=n}return new o(i)}shiftLeft(t){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for bitCount");const n=2n**BigInt(t);return this.mul(n)}shiftRight(t){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for bitCount");const n=2n**BigInt(t);return new o(this.normalize().number/n)}cmp(t){const n=u(t);if(n instanceof s)return-n.cmp(this);const r=n,{a:e,b:i}=this.scaleNumber(r.number,r.decimalPos);return e===i?0:e>i?1:-1}eq(t){return 0===this.cmp(t)}lt(t){return-1===this.cmp(t)}lte(t){return this.cmp(t)<=0}gt(t){return 1===this.cmp(t)}gte(t){return this.cmp(t)>=0}clamp(t,n){const r=a(t),e=a(n);if(r.gt(e))throw new Error("Min parameter has to be smaller than max");return this.lt(r)?r:this.gt(e)?e:this}isZero(){return 0n===this.number}isOne(){if(0===this.decimalPos)return 1n===this.number;const t=10n**BigInt(this.decimalPos),n=this.number/t;return 1n===n&&n*t===this.number}isInteger(){return 0===this.decimalPos||this.number%10n**BigInt(this.decimalPos)===0n}serialize(){return[this.number,this.decimalPos]}getFractionParts(t=!0){return this.convertToFraction().getFractionParts(t)}normalize(){if(0===this.decimalPos)return this;let t=this.decimalPos,n=this.number;for(;t>0&&n%10n===0n;)t--,n/=10n;return new o(n,t)}convertToFraction(){if(0===this.decimalPos)return new s(this.number,1n);const t=10n**BigInt(this.decimalPos);return new s(this.number,t)}toNumber(){return Number(this.toPrecision(20))}toFixed(n,r=t.TO_ZERO){if(!Number.isSafeInteger(n)||n<0)throw new Error("Invalid parameter");const i=this._round(n,r);return e(i.number,i.decimalPos,n,!1)}toExponential(n,r=t.TO_ZERO){if(!Number.isSafeInteger(n)||n<0)throw new Error("Invalid parameter");const e=this.roundToDigits(n+1,r).normalize(),i=-1===e.sign(),o=e.abs(),s=o.number.toString(),u=s.length<=n?`${s}${"0".repeat(n-s.length+1)}`:s.slice(0,n+1),a=u.length>1?`${u.slice(0,1)}.${u.slice(1)}`:u,c=o.decimalPos,m=s.length-1-c;return`${i?"-":""}${a}e${m>=0?"+":""}${m}`}toBase(t,n){if(!Number.isSafeInteger(t)||t<2||t>16)throw new Error("Invalid radix");if(void 0!==n&&(!Number.isSafeInteger(n)||n<0))throw new Error("Invalid parameter");const r=this.normalize();if(0===r.decimalPos)return r.number.toString(t);const e=void 0===n?Number.MAX_SAFE_INTEGER:n;let i=r.intPart(),o=r.sub(i);const s=-1===r.sign();s&&(i=i.neg(),o=o.neg());const u=new Map;let a=[];for(;!o.isZero();){const n=o.mul(t),r=n.toString(),i=u.get(r);if(void 0!==i){a=[...a.slice(0,i-1),"(",...a.slice(i-1),")"];break}if(a.length===e)break;const s=Math.abs(n.intPart().toNumber());a.push(s.toString(t)),o=n.fracPart(),u.set(r,a.length)}return[s?"-":"",i.number.toString(t),a.length?".":"",...a].join("")}toFraction(){return this.convertToFraction().toFraction()}toString(t,n){if(void 0===t||10===t){const t=void 0!==n?this.trunc(n):this;return e(t.number,t.decimalPos,t.decimalPos,!0)}return this.toBase(t,n)}toPrecision(n,r=t.TO_ZERO){if(!Number.isSafeInteger(n)||n<1)throw new Error("Invalid parameter");const i=this.roundToDigits(n,r),{subZeroNum:o,exponentDiff:s}=i.toSubZeroNum(),u=-1===o.sign();let a=e(o.number,o.decimalPos,o.decimalPos,!1);a=a.slice(u?3:2),a=a.slice(0,Math.max(n,s));const c=a.slice(0,Math.max(0,s)),m=a.slice(Math.max(0,s)),h=Math.max(0,n-c.length-m.length),l="0".repeat(h),d="0".repeat(s<0?-s:0);let f=c||"0";return m.length+d.length+h>0&&(f+=`.${d}${m}${l}`),u?`-${f}`:f}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}class s{constructor(t,n){if(this.type="fraction","bigint"==typeof t&&"bigint"==typeof n)this.numerator=t,this.denominator=n;else{const r=this.parseParameter(t),e=this.parseParameter(n),i=r.div(e),s=i instanceof o?i.convertToFraction():i;this.numerator=s.numerator,this.denominator=s.denominator}if(0n===this.denominator)throw new Error("Division by zero")}parseRepeatingDecimal(t){if(!t.includes("("))return new o(t).convertToFraction();const n=(t=t.trim()).match(/^(-?[0-9]*)\.([0-9]+)?\(([0-9]+)\)(?:[eE]([+-]?[0-9]+))?$/);if(!n)throw new Error(`Cannot parse string "${t}"`);const r="-"===n[1]?"-0":n[1],e=n[2]??"",i=n[3],u=n[4],a=BigInt(r+e+i)-BigInt(r+e),c=BigInt("9".repeat(i.length)+"0".repeat(e.length)),m=new s(a,c);if(void 0!==u){const t=u.startsWith("-"),n=10n**BigInt(t?u.slice(1):u);return t?m.div(n).normalize():m.mul(n).normalize()}return m.simplify()}parseParameter(t){if(t instanceof s)return t;if(t instanceof o)return t.convertToFraction();if("number"==typeof t){if(!Number.isSafeInteger(t))throw new Error("Floating point values as numbers are unsafe. Please provide them as a string.");return new s(BigInt(t),1n)}if("bigint"==typeof t)return new s(t,1n);if("string"==typeof t){const n=t.split("/");if(n.length>2)throw new Error(`Cannot parse string '${t}'`);const r=this.parseRepeatingDecimal(n[0]),e=n[1]?this.parseRepeatingDecimal(n[1]):new s(1n,1n);return r.div(e).convertToFraction()}throw new Error("Unsupported parameter!")}add(t){const{numerator:n,denominator:r}=this.parseParameter(t);return this.denominator===r?new s(this.numerator+n,this.denominator):new s(this.numerator*r+n*this.denominator,r*this.denominator)}sub(t){const{numerator:n,denominator:r}=this.parseParameter(t);return this.add(new s(-n,r))}mul(t){const{numerator:n,denominator:r}=this.parseParameter(t);return new s(this.numerator*n,this.denominator*r)}div(t){const{numerator:n,denominator:r}=this.parseParameter(t);return this.mul(new s(r,n))}divToInt(t){return this.div(t).trunc()}mod(t,r=n.TRUNCATED){const e=this.parseParameter(t),i=e.denominator*this.numerator%(e.numerator*this.denominator),o=this.denominator*e.denominator,u=new s(i,o);if(r===n.TRUNCATED)return u;if(r===n.FLOORED)return Number(-1===this.sign())^Number(-1===e.sign())?u.add(e):u;if(r===n.EUCLIDEAN)return u.sign()<0?u.add(e.sign()<0?e.neg():e):u;throw new Error("Invalid ModType")}pow(t){const n=this.parseParameter(t);if(!n.isInteger())throw new Error("Unsupported parameter");const r=n.numerator/n.denominator,e=r<0?-r:r,i=new s(this.numerator**e,this.denominator**e);return r<0?i.inv():i}inv(){return new s(this.denominator,this.numerator)}floor(n){return 1n===this.denominator?new o(this.numerator):this.round(n,t.TO_NEGATIVE)}ceil(n){return 1n===this.denominator?new o(this.numerator):this.round(n,t.TO_POSITIVE)}trunc(n){return 1n===this.denominator?new o(this.numerator):this.round(n,t.TO_ZERO)}round(t,n){if(t=void 0===t?0:t,!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for decimals");const r=this.toFixedNumber(t+1);if(this.sub(r).isZero())return r.round(t,n);return new o(`${r.toFixed(t+1)}1`).round(t,n)}roundToDigits(t,n){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid value for digits");if(this.isZero())return new o(0n);let r=this.abs(),e=0;for(;r.gte(1n);)r=r.div(10n),e++;const i=new s(1n,10n);for(;r.lt(i);)r=r.mul(10n),e--;let u=r.round(t,n);return u=u._incExponent(e),-1===this.sign()?u.neg():u}gcd(t,n){let r=t<0?-t:t,e=n<0?-n:n;if(e>r){const t=r;r=e,e=t}for(;;){if(0n===e)return r;if(r%=e,0n===r)return e;e%=r}}simplify(){let{numerator:t,denominator:n}=this;const r=this.gcd(t,n);return r>1n&&(t/=r,n/=r),n<0n&&(t=-t,n=-n),new s(t,n)}normalize(){const{numerator:n,denominator:r}=this.simplify();if(1n===r)return new o(n,0);const e=new s(n,r),{cycleLen:i,cycleStart:u}=e.getDecimalFormat(0);return 0!==i?e:e.round(u,t.TO_ZERO)}getFractionParts(t=!0){const n=t?this.simplify():this;return{numerator:new o(n.numerator),denominator:new o(n.denominator)}}sign(){return(this.numerator<0n?-1:1)*(this.denominator<0n?-1:1)}abs(){return new s(this.numerator<0n?-this.numerator:this.numerator,this.denominator<0n?-this.denominator:this.denominator)}neg(){return this.mul(-1n)}intPart(){return this.trunc()}fracPart(){return this.sub(this.trunc())}cmp(t){const n=this.parseParameter(t),r=this.denominator===n.denominator,e=r?this.numerator:this.numerator*n.denominator,i=r?n.numerator:n.numerator*this.denominator;return e===i?0:e>i?1:-1}eq(t){return 0===this.cmp(t)}lt(t){return-1===this.cmp(t)}lte(t){return this.cmp(t)<=0}gt(t){return 1===this.cmp(t)}gte(t){return this.cmp(t)>=0}clamp(t,n){const r=a(t),e=a(n);if(r.gt(e))throw new Error("Min parameter has to be smaller than max");return this.lt(r)?r:this.gt(e)?e:this}isZero(){return 0n===this.numerator}isOne(){return this.numerator===this.denominator}isInteger(){return this.numerator%this.denominator===0n}serialize(){return[this.numerator,this.denominator]}toNumber(){return Number(this.toPrecision(20))}convertToFraction(){return this}getNumberForBitwiseOp(){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");return this.intPart()}bitwiseAnd(t){return this.getNumberForBitwiseOp().bitwiseAnd(t)}bitwiseOr(t){return this.getNumberForBitwiseOp().bitwiseOr(t)}bitwiseXor(t){return this.getNumberForBitwiseOp().bitwiseXor(t)}shiftLeft(t){return this.getNumberForBitwiseOp().shiftLeft(t)}shiftRight(t){return this.getNumberForBitwiseOp().shiftRight(t)}getDecimalFormat(t){t=void 0===t?Number.MAX_SAFE_INTEGER:t;let n=this.denominator<0?-this.denominator:this.denominator,r=0;for(;n%2n===0n;)n/=2n,r++;let e=0;for(;n%5n===0n;)n/=5n,e++;const i=Math.max(r,e);if(1n===n)return{cycleLen:0,cycleStart:i};const o=Math.max(1,t-i);let s=10n%n,u=1;for(;1n!==s;){if(u===o)return{cycleLen:null,cycleStart:i};s=10n*s%n,u++}return{cycleLen:u,cycleStart:i}}toFixed(n,r=t.TO_ZERO){if(!Number.isSafeInteger(n)||n<0)throw new Error("Invalid parameter");return this.round(n,r).toFixed(n)}toRepeatingParts(t){if(this.isZero())return["0","",""];const{cycleLen:n,cycleStart:e}=this.simplify().getDecimalFormat(t);if(null===n||0===n){const n=t??e,i=this.toFixed(n),o=r(i).split(".");return[o[0],o[1]??"",""]}const i=e+n,o=this.toFixed(i).split(".");return[o[0],o[1].slice(0,e),o[1].slice(e)]}toRepeatingDigits(t){const n=this.toRepeatingParts(t);let r=n[0];return(n[1]||n[2])&&(r+=`.${n[1]}`),n[2]&&(r+=`(${n[2]})`),r}toExponential(n,r=t.TO_ZERO){if(!Number.isSafeInteger(n)||n<0)throw new Error("Invalid parameters");return this.toFixedNumber(n).toExponential(n,r)}toFraction(){const{numerator:t,denominator:n}=this.getFractionParts(!0);return`${t.toString()}/${n.toString()}`}toFixedNumber(t){const n=this.numerator*10n**BigInt(t);return new o(n/this.denominator,t)}toBase(t,n){if(!Number.isSafeInteger(t)||t<2||t>16)throw new Error("Invalid radix");if(void 0!==n&&(!Number.isSafeInteger(n)||n<0))throw new Error("Invalid parameter");if(10===t)return void 0===n?this.toRepeatingDigits(n):r(this.toFixed(n));const e=this.normalize(),i=void 0===n?Number.MAX_SAFE_INTEGER:n+1;let o=e.intPart(),s=e.sub(o);const u=-1===e.sign();u&&(o=o.neg(),s=s.neg());const a=new Map;let c=[];for(;!s.isZero()&&c.length!==i;){const n=s.mul(t),r=n.normalize().toFraction(),e=a.get(r);if(void 0!==e){c=[...c.slice(0,e-1),"(",...c.slice(e-1),")"];break}const i=Math.abs(n.intPart().toNumber());c.push(i.toString(t)),s=n.fracPart(),a.set(r,c.length)}return c.length===i&&c.pop(),[u?"-":"",o.toString(t),c.length?".":"",...c].join("")}toString(t,n){return void 0===t||10===t?this.toRepeatingDigits(n):this.toBase(t,n)}toPrecision(n,r=t.TO_ZERO){if(!Number.isSafeInteger(n)||n<1)throw new Error("Invalid parameter");return this.roundToDigits(n,r).toPrecision(n)}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}function u(t){if(t instanceof o||t instanceof s)return t;if("bigint"==typeof t)return new o(t);if("number"==typeof t){if(!Number.isSafeInteger(t))throw new Error("Floating point values as numbers are unsafe. Please provide them as a string.");return new o(t)}if("string"==typeof t)return t.includes("/")||t.includes("(")?new s(t,1n):new o(t);throw new Error("Unsupported parameter type")}const a=(t,n)=>{if(void 0===t)throw new Error("First parameter cannot be undefined");const r=u(t);if(void 0===n)return r;const e=u(n);return new s(r,1n).div(new s(e,1n))};a.min=(...t)=>{if(0===t.length)throw new Error("Got empty array");let n=a(t[0]);for(let r=1;r<t.length;r++){const e=a(t[r]);e.lt(n)&&(n=e)}return n},a.max=(...t)=>{if(0===t.length)throw new Error("Got empty array");let n=a(t[0]);for(let r=1;r<t.length;r++){const e=a(t[r]);e.gt(n)&&(n=e)}return n};const c=(t,n)=>{let r=0n;for(let e=0;e<t.length;e++){const i=t.charAt(e),o=parseInt(i,n);if(Number.isNaN(o))throw new Error(`Invalid digit "${i}"`);r*=BigInt(n),r+=BigInt(o)}return r};a.fromBase=(t,n)=>{if("string"!=typeof t)throw new Error("First parameter must be string");if(!Number.isSafeInteger(n)||n<2||n>16)throw new Error("Invalid radix");if(10===n)return a(t);if(0===(t=t.trim()).length)throw new Error("Empty string is not allowed");const r=t.startsWith("-");r&&(t=t.slice(1));const e=t.match(/^([0-9a-f]*)(?:\.([0-9a-f]*)(?:\(([0-9a-f]+)\))?)?$/i);if(!e)throw new Error(`Cannot parse number "${t}"`);const i=e[1]??"",o=e[2]??"",u=e[3]??"";if(u.length>0){const t=c([i,o,u].join(""),n)-c([i,o].join(""),n),e=c((n-1).toString(n).repeat(u.length)+"0".repeat(o.length),n),a=new s(t,e).normalize();return r?a.neg():a}const m=c(i,n),h=c(o,n),l=new s(h,BigInt(n)**BigInt(o.length)),d=new s(m,1n).add(l).normalize();return r?d.neg():d},a.range=function*(t,n,r){const e=a(n),i=a(r??1);let o=a(t);for(;o.lt(e);)yield o,o=o.add(i)},a.gcd=(t,n)=>{const r=a(t).abs(),e=a(n).abs();let i=e.gt(r)?e:r,o=i.eq(r)?e:r;for(;;){if(o.isZero())return i;if(i=i.mod(o),i.isZero())return o;o=o.mod(i)}},a.lcm=(t,n)=>{const r=a(t).abs(),e=a(n).abs(),i=r.mul(e);if(i.isZero())throw new Error("LCM of zero is undefined");const o=a.gcd(r,e);return i.div(o)};const m=(t,n,r)=>{const e=((t,n)=>{let r=n.toNumber();if(Number.isFinite(r)){const n=r<0;n&&(r=-r);let e=r**(1/t);return n&&(e=-e),e.toString()}const e=n.abs().toFixed(0).length,i=Math.ceil(e/t);return`${1===n.sign()?"":"-"}5e${i}`})(t,n);let i=new o("0"!==e?e:"1");const u=new s(t-1,t),a=new s(n,t),c=BigInt(t-1);let m=i.trunc(r+5);for(;i=u.mul(i).add(a.mul(i.pow(c).inv())),i=i.trunc(r+5),!i.isZero()&&!m.eq(i);)m=i;return i.trunc(r)},h=(t,n,r)=>{if(!Number.isSafeInteger(t))throw new Error("Integer is expected for N");if(t<0)throw new Error("Negative N is not supported");if(0===t)throw new Error("N cannot be zero");const e=i(a(n),r);if(1===t)return e.trunc(r);if(t%2==0&&-1===e.sign())throw new Error("Complex numbers are not supported");if(e.isZero())return new o(0n).trunc(r);if(e.isOne())return new o(1n).trunc(r);return m(t,e,r)},l=(t,n)=>h(2,t,n),d=(t,n)=>h(3,t,n);class f{constructor(t,n){this.cachedDecimals=0,this.fn=t,this.max=n}get(t){if(t<=this.cachedDecimals)return this.cache.trunc(t);const n=new o(this.fn(t)),r=Math.min(this.max,t);return this.cachedDecimals!==r&&(this.cache=n.trunc(r),this.cachedDecimals=r),n}}const g=(t,n)=>{let r=i(a(t),n);if(r.isOne())return new o(0).trunc(n);if(r.lte(0n))throw new Error("Invalid parameter");let e=0;const s=a("0.1");for(;r.sub(1n).abs().gt(s);)r=new o(l(r,n+10)),e++;const u=function*(t,n){const r=t.pow(2n).normalize();let e=t,i=1n,o=a(t);for(;;){e=e.mul(r),i+=2n;const t=e.div(i).trunc(n+10);o=o.add(t),yield{term:t,sum:o}}}(r.sub(1n).div(r.add(1n)),n);for(const{term:t,sum:r}of u)if(t.isZero()){return r.mul(2n**BigInt(e+1)).trunc(n)}return a(0)},w=(t,n,r)=>{if(!Number.isSafeInteger(t)||t<2)throw new Error("Invalid parameter for N");const e=g(n,r+10),i=g(t,r+10);return new o(e).div(i).trunc(r)},b=new f((t=>g(2n,t)),200),E=(t,n)=>new o(g(t,n+10)).div(b.get(n+10)).trunc(n),p=new f((t=>g(10n,t)),200),N=(t,n)=>new o(g(t,n+10)).div(p.get(n+10)).trunc(n);const I=(t,n)=>{const r=i(a(t),n),e=a(`1e-${n+5}`),o=function*(t,n){let r=t.add(1n),e=6n,i=4n;const o=t.pow(2n);let s=o;for(;;){const u=s.mul(t.add(i-1n)).div(e);e*=i*(i+1n),i+=2n,s=s.mul(o),r=r.add(u).trunc(n+5),yield{term:u,sum:r}}}(r,n);for(const{term:t,sum:r}of o)if(t.abs().lt(e))return r.trunc(n);return a(0)},v=(t,n,r)=>{const e=i(a(t),r),o=i(a(n),r);if(o.isInteger()&&Number.isSafeInteger(o.toNumber()))return e.pow(o).trunc(r);if(-1===e.sign()&&!o.isInteger())throw new Error("Complex numbers are not supported");const s=g(e,r+5),u=o.mul(s);return I(u,r+5).trunc(r)},O=new f((t=>{if(0===t)return a(3n);let n=1n,r=3n*10n**BigInt(t+20),e=r;for(;0n!==r;)r=r*n/(4n*(n+1n)),n+=2n,e+=r/n;return a(`3.${e.toString().slice(1,t+1)}`)}),1e3),T=t=>0===t?a(3):O.get(t).trunc(t),P=(n,r)=>{const e=new o(T(r+5)),i=e.mul(2n);let s=n.round(r+5,t.NEAREST_AWAY_FROM_ZERO).div(i).fracPart();s.lt(0n)&&(s=s.add(1n)),s=s.round(r+5);const u=s.div("0.25").floor().toNumber()+1;let c=i.mul(s),m=s.mul(360n);return 4===u?(c=i.sub(c),m=a(360).sub(m)):3===u?(c=c.sub(e),m=m.sub(180)):2===u&&(c=e.sub(c),m=a(180).sub(m)),{quadrantDegrees:m.round(r),quadrant:u,subHalfPiAngle:c}};const _=(t,n,r)=>{let e=a(t);return n&&(e=e.neg()),e.trunc(r)},S=(n,r)=>{const e=r+10,o=i(a(n),r+5),{quadrantDegrees:s,subHalfPiAngle:u,quadrant:c}=P(o,r),m=2===c||3===c;if(s.isZero())return _("1",m,r);if(s.eq(30n))return _(a(l(3n,r+5)).div(2n),m,r);if(s.eq(45n))return _(a(l(2n,r+5)).div(2n),m,r);if(s.eq(60n))return _("0.5",m,r);if(s.eq(90n))return _("0",m,r);const h=a(`1e-${e}`),d=function*(n,r){const e=n.round(r+10,t.NEAREST_AWAY_FROM_ZERO).pow(2n);let i=e,o=2n,s=a(1n).sub(i.div(o).trunc(r+10)),u=3n;for(;;){o*=u*(u+1n),u+=2n;const t=u*(u+1n);u+=2n,i=i.mul(e),o*=t;let n=i.mul(t);i=i.mul(e),n=n.sub(i);const a=n.div(o).trunc(r+10);s=s.add(a),yield{term:a,sum:s}}}(u,r);for(const{term:t,sum:n}of d)if(t.lt(h))return _(n,m,r);return a(0)},R=(t,n)=>{const r=new o(T(n+10)),e=i(a(t),n+5);return S(r.div(2n).sub(e),n+5).trunc(n)},A=(t,n)=>{const r=i(a(t),n+5),{quadrantDegrees:e,quadrant:o,subHalfPiAngle:s}=P(r,n+5),u=1===o||3===o;if(e.isZero())return _("0",u,n);if(e.eq(30n))return _(a(1n).div(l(3n,n+5)),u,n);if(e.eq(45n))return _("1",u,n);if(e.eq(60n))return _(l(3n,n+5),u,n);if(e.eq(90n))throw new Error("Out of range");const c=a(S(s.mul(2n),n+5)),m=a(1n).sub(c).div(a(1n).add(c)).round(n+5),h=l(m,n+5).trunc(n);return u?h:h.neg()};const F=(t,n)=>{let r=i(a(t),n);if(r.isZero())return a(0);if(r.abs().isOne())return a(T(n)).div(4*r.sign()).trunc(n);let e=0;const o=a("0.42");for(;r.abs().gt(o);){const t=a(l(r.pow(2n).add(1n),n+10));r=r.div(t.add(1n)),e++}const s=a(`1e-${n+10}`),u=function*(t,n){const r=t.pow(2n).normalize(),e=r.pow(2n).normalize();let i=3n,o=t.sub(t.mul(r).div(i)),s=t.mul(e);for(;;){i+=2n;const t=i+2n,u=s.mul(r.mul(-i).add(t)).div(i*t);i=t,s=s.mul(e),o=o.add(u).trunc(n+10),yield{term:u,sum:o}}}(r,n);for(const{term:t,sum:r}of u)if(t.abs().lt(s)){return r.mul(2n**BigInt(e)).trunc(n)}return a(0)},y=(t,n)=>{const r=i(a(t),n);if(r.isZero())return a(0);if(r.abs().isOne())return a(T(n)).mul(r.sign()).div(2n).trunc(n);if(r.abs().eq("1/2"))return a(T(n)).mul(r.sign()).div(6n).trunc(n);if(r.gt(1n)||r.lt(-1n))throw new Error("Out of range");const e=a(l(r.pow(2n).neg().add(1),n+10));return a(F(r.div(e.add(1n)),n+10)).mul(2).trunc(n)},Z=(t,n)=>{const r=i(a(t),n);if(r.isZero())return a(T(n)).div(2n).trunc(n);if(r.isOne())return a(0);if(r.abs().isOne())return T(n);if(r.abs().eq("1/2")){const t=a(T(n)).div(3n);return-1===r.sign()?t.mul(2n).trunc(n):t.trunc(n)}if(r.gt(1n)||r.lt(-1n))throw new Error("Out of range");return a(T(n+10)).div(2n).sub(y(r,n+10)).trunc(n)};const B=(t,n)=>{const r=i(a(t),n),e=new o(`1e-${n+5}`),s=function*(t,n){let r=t,e=1n;const i=t.pow(2n).normalize();let o=t.trunc(n+5),s=2n;for(;;){r=r.mul(i),e*=s*(s+1n),s+=2n;const t=r.div(e);o=o.add(t).trunc(n+5),yield{term:t,sum:o}}}(r,n);for(const{term:t,sum:r}of s)if(t.abs().lt(e))return r.trunc(n);return a(0)};const x=(t,n)=>{const r=i(a(t),n),e=new o(`1e-${n+5}`),s=function*(t,n){const r=t.pow(2n).normalize();let e=r,i=2n,o=e.div(i).add(1n).trunc(n+5),s=3n;for(;;){e=e.mul(r),i*=s*(s+1n),s+=2n;const t=e.div(i);o=o.add(t).trunc(n+5),yield{term:t,sum:o}}}(r,n);for(const{term:t,sum:r}of s)if(t.abs().lt(e))return r.trunc(n);return a(0)},$=(t,n)=>{const r=i(a(t),n);if(r.isZero())return a(0);const e=x(r,n+10).abs();return l(e.pow(2).sub(1),n+10).div(e).mul(r.sign()).trunc(n)},D=(t,n)=>{const r=i(a(t),n);if(r.isZero())return a(0);const e=l(r.pow(2).add(1n),n+5);return g(r.add(e),n+5).trunc(n)},M=(t,n)=>{const r=i(a(t),n);if(r.isOne())return a(0);if(r.lt(1n))throw new Error("Out of range");const e=l(r.pow(2).sub(1n),n+5);return g(r.add(e),n+5).trunc(n)},z=(t,n)=>{const r=i(a(t),n);if(r.abs().gte(1n))throw new Error("Out of range");if(r.isZero())return a(0);const e=g(r.add(1n).div(r.neg().add(1n)),n+5);return a(e).div(2n).trunc(n)};export{a as ExactNumber,n as ModType,T as PI,t as RoundingMode,Z as acos,M as acosh,y as asin,D as asinh,F as atan,z as atanh,d as cbrt,S as cos,x as cosh,I as exp,g as log,N as log10,E as log2,w as logn,h as nthroot,v as pow,R as sin,B as sinh,l as sqrt,A as tan,$ as tanh,r as trimTrailingZeros};
var t,r;!function(t){t[t.NEAREST_TO_POSITIVE=201008]="NEAREST_TO_POSITIVE",t[t.NEAREST_TO_NEGATIVE=201009]="NEAREST_TO_NEGATIVE",t[t.NEAREST_TO_EVEN=201010]="NEAREST_TO_EVEN",t[t.NEAREST_TO_ZERO=201011]="NEAREST_TO_ZERO",t[t.NEAREST_AWAY_FROM_ZERO=201012]="NEAREST_AWAY_FROM_ZERO",t[t.TO_POSITIVE=201001]="TO_POSITIVE",t[t.TO_NEGATIVE=201002]="TO_NEGATIVE",t[t.TO_ZERO=201003]="TO_ZERO",t[t.AWAY_FROM_ZERO=201004]="AWAY_FROM_ZERO"}(t||(t={})),function(t){t.TRUNCATED="T",t.FLOORED="F",t.EUCLIDEAN="E"}(r||(r={}));const e=t=>{const r=t.indexOf(".");if(-1===r)return t;let e=t.length;for(;e>r&&"0"===t.charAt(e-1);)e--;const n=r===e-1?r:e;return 0===n?"0":t.slice(0,n)},n=(t,r,n,i)=>{let o=t.toString();if(0===r&&0===n)return o;const s=o.startsWith("-");if(s&&(o=o.slice(1)),r>=o.length&&(o="0".repeat(r-o.length+1)+o),r>0){const t=o.slice(0,-r),s=o.slice(-r),u=n<=r?s.slice(0,n):`${s}${"0".repeat(n-r)}`;0!==u.length?(o=`${t}.${u}`,i&&(o=e(o))):o=t}else n>0&&!i&&(o=`${o}.${"0".repeat(n)}`);return s?`-${o}`:o},i=(r,e)=>(r=r.normalize())instanceof d?r.round(e,t.NEAREST_AWAY_FROM_ZERO):r,o=BigInt(0),s=BigInt(1),u=BigInt(2),a=BigInt(3),c=BigInt(4),m=BigInt(5),h=BigInt(10),l=BigInt(24);class d{constructor(t,r=0){if(this.type="fixed","bigint"==typeof t)this.number=t,this.decimalPos=r;else{const r=this.parseConstructorParameter(t);this.number=r.number,this.decimalPos=r.decimalPos}}parseConstructorParameter(t){if(t instanceof d)return{number:t.number,decimalPos:t.decimalPos};if(t instanceof f){if(!t.isInteger())throw new Error("Cannot create FixedNumber from non-integer Fraction");return{number:t.trunc().number,decimalPos:0}}if("number"==typeof t){if(!Number.isSafeInteger(t))throw new Error("The specified number cannot be exactly represented as an integer. Please provide a string instead.");return{number:BigInt(t),decimalPos:0}}if("string"==typeof t){if(0===(t=t.trim()).length)throw new Error("Empty string is not allowed");const r=t.match(/^(-?[0-9]*)(?:\.([0-9]*))?(?:[eE]([+-]?[0-9]+))?$/);if(!r)throw new Error(`Cannot parse number "${t}"`);let e=0,n=r[1]??"0";if(void 0!==r[2]&&(n+=r[2],e+=r[2].length),void 0!==r[3]){const t=Number(r[3]);t>0?n+="0".repeat(t):e-=t}return{number:BigInt(n),decimalPos:e}}throw new Error("Unsupported parameter!")}scaleNumber(t,r){const e=Math.max(this.decimalPos,r);return{a:e===this.decimalPos?this.number:this.number*h**BigInt(e-this.decimalPos),b:e===r?t:t*h**BigInt(e-r),decimalPos:e}}add(t){const r=g(t);if(r instanceof f)return r.add(this);const e=r,{a:n,b:i,decimalPos:o}=this.scaleNumber(e.number,e.decimalPos);return new d(n+i,o)}sub(t){const r=g(t);return this.add(r.neg())}mul(t){const r=g(t);if(r instanceof f)return r.mul(this);const e=r,n=this.number*e.number;return new d(n,this.decimalPos+e.decimalPos)}pow(t){const r=g(t).toNumber();if(!Number.isSafeInteger(r))throw new Error("Unsupported parameter");const e=Math.abs(r),n=new d(this.number**BigInt(e),this.decimalPos*e);return r<0?n.inv():n}powm(t,r,e){let n=g(t).toNumber();if(!Number.isSafeInteger(n))throw new Error("Unsupported parameter");const i=g(r);let o=this,a=new d(s);for(;0!==n;)n%2!=0&&(a=a.mul(o).mod(i,e)),o=o.pow(u).mod(i,e),n=Math.floor(n/2);return a}div(t){return this.convertToFraction().div(t)}divToInt(t){const r=g(t);if(r instanceof f)return this.convertToFraction().divToInt(r);const e=r,{a:n,b:i}=this.scaleNumber(e.number,e.decimalPos);return new d(n/i)}mod(t,e=r.TRUNCATED){const n=g(t);if(n instanceof f)return this.convertToFraction().mod(n);const i=n,{a:s,b:u,decimalPos:a}=this.scaleNumber(i.number,i.decimalPos),c=s%u,m=new d(c,a);if(e===r.TRUNCATED)return m;if(e===r.FLOORED)return Number(s<o)^Number(u<o)?m.add(u):m;if(e===r.EUCLIDEAN)return c<o?m.add(u<o?-u:u):m;throw new Error("Invalid ModType")}abs(){return new d(this.number<o?-this.number:this.number,this.decimalPos)}neg(){return this.mul(-s)}inv(){return this.convertToFraction().inv()}floor(r){return 0===this.decimalPos?this:this.round(r,t.TO_NEGATIVE)}ceil(r){return 0===this.decimalPos?this:this.round(r,t.TO_POSITIVE)}trunc(r){return 0===this.decimalPos?this:this.round(r,t.TO_ZERO)}isTieStr(t){if("5"!==t[0])return!1;for(let r=1;r<t.length;r++)if("0"!==t[r])return!1;return!0}_round(r,e){const n=this.decimalPos-r;if(n<=0)return this;const i=h**BigInt(n),a=this.number/i;if(e===t.TO_ZERO)return new d(a,r);const c=this.number%i;if(c===o)return new d(a,r);if(e===t.AWAY_FROM_ZERO){const t=this.number<o?a-s:a+s;return new d(t,r)}if(e===t.TO_POSITIVE){const t=this.number<o?a:a+s;return new d(t,r)}if(e===t.TO_NEGATIVE){const t=this.number>=o?a:a-s;return new d(t,r)}if(![void 0,t.NEAREST_TO_ZERO,t.NEAREST_AWAY_FROM_ZERO,t.NEAREST_TO_POSITIVE,t.NEAREST_TO_NEGATIVE,t.NEAREST_TO_EVEN].includes(e))throw new Error("Invalid rounding mode. Use the predefined values from the RoundingMode enum.");let m=(c<o?-c:c).toString();if(m.length<n&&(m="0"),this.isTieStr(m)){if(e===t.NEAREST_TO_ZERO)return new d(a,r);if(e===t.NEAREST_AWAY_FROM_ZERO){const t=this.number<o?a-s:a+s;return new d(t,r)}if(void 0===e||e===t.NEAREST_TO_POSITIVE){const t=this.number<o?a:a+s;return new d(t,r)}if(e===t.NEAREST_TO_NEGATIVE){const t=this.number>=o?a:a-s;return new d(t,r)}if(e===t.NEAREST_TO_EVEN){if(a%u===o)return new d(a,r);return new d(a<o?a-s:a+s,r)}}if(Number(m[0])<5)return new d(a,r);const l=this.number<o?a-s:a+s;return new d(l,r)}round(t,r){if(t=void 0===t?0:t,!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for decimals");return this._round(t,r).normalize()}_incExponent(t){if(0===t)return this;let r=this.number,e=this.decimalPos;if(t<0)e-=t;else{const n=Math.min(t,this.decimalPos);e-=n;const i=t-n;i>0&&(r*=h**BigInt(i))}return new d(r,e)}countDigits(){if(this.number===o)return 1;let t=0,r=this.number<o?-this.number:this.number;for(;r>o;)r/=h,t++;return t}toSubZeroNum(){const t=this.countDigits();return{subZeroNum:new d(this.number,t),exponentDiff:t-this.decimalPos}}roundToDigits(t,r){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid value for digits");const{subZeroNum:e,exponentDiff:n}=this.toSubZeroNum();let i=e.round(t,r);return i=i._incExponent(n),i}intPart(){return this.trunc()}fracPart(){return this.sub(this.trunc())}sign(){return this.number<o?-1:1}bitwiseAnd(t){if(t=w(t),!this.isInteger()||-1===this.sign()||!t.isInteger()||-1===t.sign())throw new Error("Only positive integers are supported");t instanceof f&&(t=t.trunc());const r=u**l;let e=this.normalize().number,n=t.trunc().normalize().number,i=o,a=s;for(;e>o&&n>o;){const t=BigInt.asUintN(24,e),o=BigInt.asUintN(24,n);i+=BigInt(Number(t)&Number(o))*a,a*=r,e/=r,n/=r}return new d(i)}bitwiseOr(t){if(t=w(t),!this.isInteger()||-1===this.sign()||!t.isInteger()||-1===t.sign())throw new Error("Only positive integers are supported");t instanceof f&&(t=t.trunc());const r=u**l;let e=this.normalize().number,n=t.trunc().normalize().number,i=o,a=s;for(;e>o||n>o;){const t=BigInt.asUintN(24,e),o=BigInt.asUintN(24,n);i+=BigInt(Number(t)|Number(o))*a,a*=r,e/=r,n/=r}return new d(i)}bitwiseXor(t){if(t=w(t),!this.isInteger()||-1===this.sign()||!t.isInteger()||-1===t.sign())throw new Error("Only positive integers are supported");t instanceof f&&(t=t.trunc());const r=u**l;let e=this.normalize().number,n=t.trunc().normalize().number,i=o,a=s;for(;e>o||n>o;){const t=BigInt.asUintN(24,e),o=BigInt.asUintN(24,n);i+=BigInt(Number(t)^Number(o))*a,a*=r,e/=r,n/=r}return new d(i)}shiftLeft(t){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for bitCount");const r=u**BigInt(t);return this.mul(r)}shiftRight(t){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for bitCount");const r=u**BigInt(t);return new d(this.normalize().number/r)}cmp(t){const r=g(t);if(r instanceof f)return-r.cmp(this);const e=r,{a:n,b:i}=this.scaleNumber(e.number,e.decimalPos);return n===i?0:n>i?1:-1}eq(t){return 0===this.cmp(t)}lt(t){return-1===this.cmp(t)}lte(t){return this.cmp(t)<=0}gt(t){return 1===this.cmp(t)}gte(t){return this.cmp(t)>=0}clamp(t,r){const e=w(t),n=w(r);if(e.gt(n))throw new Error("Min parameter has to be smaller than max");return this.lt(e)?e:this.gt(n)?n:this}isZero(){return this.number===o}isOne(){if(0===this.decimalPos)return this.number===s;const t=h**BigInt(this.decimalPos),r=this.number/t;return r===s&&r*t===this.number}isInteger(){return 0===this.decimalPos||this.number%h**BigInt(this.decimalPos)===o}serialize(){return[this.number,this.decimalPos]}getFractionParts(t=!0){return this.convertToFraction().getFractionParts(t)}normalize(){if(0===this.decimalPos)return this;let t=this.decimalPos,r=this.number;for(;t>0&&r%h===o;)t--,r/=h;return new d(r,t)}convertToFraction(){if(0===this.decimalPos)return new f(this.number,s);const t=h**BigInt(this.decimalPos);return new f(this.number,t)}toNumber(){return Number(this.toPrecision(20))}toFixed(r,e=t.TO_ZERO,i=!1){if(!Number.isSafeInteger(r)||r<0)throw new Error("Invalid parameter");const o=this._round(r,e);return n(o.number,o.decimalPos,r,i)}toExponential(r,n=t.TO_ZERO,i=!1){if(!Number.isSafeInteger(r)||r<0)throw new Error("Invalid parameter");const o=this.roundToDigits(r+1,n).normalize(),s=-1===o.sign(),u=o.abs(),a=u.number.toString(),c=a.length<=r?`${a}${"0".repeat(r-a.length+1)}`:a.slice(0,r+1);let m=c;c.length>1&&(m=`${c.slice(0,1)}.${c.slice(1)}`,i&&(m=e(m)));const h=u.decimalPos,l=a.length-1-h;return`${s?"-":""}${m}e${l>=0?"+":""}${l}`}toBase(t,r){if(!Number.isSafeInteger(t)||t<2||t>16)throw new Error("Invalid radix");if(void 0!==r&&(!Number.isSafeInteger(r)||r<0))throw new Error("Invalid parameter");const e=this.normalize();if(0===e.decimalPos)return e.number.toString(t);const n=void 0===r?Number.MAX_SAFE_INTEGER:r;let i=e.intPart(),o=e.sub(i);const s=-1===e.sign();s&&(i=i.neg(),o=o.neg());const u=new Map;let a=[];for(;!o.isZero();){const r=o.mul(t),e=r.toString(),i=u.get(e);if(void 0!==i){a=[...a.slice(0,i-1),"(",...a.slice(i-1),")"];break}if(a.length===n)break;const s=Math.abs(r.intPart().toNumber());a.push(s.toString(t)),o=r.fracPart(),u.set(e,a.length)}const c=a.join("");return`${s?"-":""}${i.number.toString(t)}${a.length?".":""}${c}`}toFraction(){return this.convertToFraction().toFraction()}toString(t,r){if(void 0===t||10===t){const t=void 0!==r?this.trunc(r):this;return n(t.number,t.decimalPos,t.decimalPos,!0)}return this.toBase(t,r)}toPrecision(r,i=t.TO_ZERO,o=!1){if(!Number.isSafeInteger(r)||r<1)throw new Error("Invalid parameter");const s=this.roundToDigits(r,i),{subZeroNum:u,exponentDiff:a}=s.toSubZeroNum(),c=-1===u.sign();let m=n(u.number,u.decimalPos,u.decimalPos,!1);m=m.slice(c?3:2),m=m.slice(0,Math.max(r,a));const h=m.slice(0,Math.max(0,a)),l=m.slice(Math.max(0,a)),d=Math.max(0,r-h.length-l.length),f="0".repeat(a<0?-a:0);let g=h||"0";if(l.length+f.length+d>0){g+=`.${f}${l}${"0".repeat(d)}`,o&&(g=e(g))}return c?`-${g}`:g}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}class f{constructor(t,r){if(this.type="fraction","bigint"==typeof t&&"bigint"==typeof r)this.numerator=t,this.denominator=r;else{const e=this.parseParameter(t),n=this.parseParameter(r),i=e.div(n),o=i instanceof d?i.convertToFraction():i;this.numerator=o.numerator,this.denominator=o.denominator}if(this.denominator===o)throw new Error("Division by zero")}parseRepeatingDecimal(t){if(!t.includes("("))return new d(t).convertToFraction();const r=(t=t.trim()).match(/^(-?[0-9]*)\.([0-9]+)?\(([0-9]+)\)(?:[eE]([+-]?[0-9]+))?$/);if(!r)throw new Error(`Cannot parse string "${t}"`);const e="-"===r[1]?"-0":r[1],n=r[2]??"",i=r[3],o=r[4],s=BigInt(e+n+i)-BigInt(e+n),u=BigInt("9".repeat(i.length)+"0".repeat(n.length)),a=new f(s,u);if(void 0!==o){const t=o.startsWith("-"),r=h**BigInt(t?o.slice(1):o);return t?a.div(r).normalize():a.mul(r).normalize()}return a.simplify()}parseParameter(t){if(t instanceof f)return t;if(t instanceof d)return t.convertToFraction();if("number"==typeof t){if(!Number.isSafeInteger(t))throw new Error("Floating point values as numbers are unsafe. Please provide them as a string.");return new f(BigInt(t),s)}if("bigint"==typeof t)return new f(t,s);if("string"==typeof t){const r=t.split("/");if(r.length>2)throw new Error(`Cannot parse string '${t}'`);const e=this.parseRepeatingDecimal(r[0]),n=r[1]?this.parseRepeatingDecimal(r[1]):new f(s,s);return e.div(n).convertToFraction()}throw new Error("Unsupported parameter!")}add(t){const{numerator:r,denominator:e}=this.parseParameter(t);return this.denominator===e?new f(this.numerator+r,this.denominator):new f(this.numerator*e+r*this.denominator,e*this.denominator)}sub(t){const{numerator:r,denominator:e}=this.parseParameter(t);return this.add(new f(-r,e))}mul(t){const{numerator:r,denominator:e}=this.parseParameter(t);return new f(this.numerator*r,this.denominator*e)}div(t){const{numerator:r,denominator:e}=this.parseParameter(t);return this.mul(new f(e,r))}divToInt(t){return this.div(t).trunc()}mod(t,e=r.TRUNCATED){const n=this.parseParameter(t),i=n.denominator*this.numerator%(n.numerator*this.denominator),o=this.denominator*n.denominator,s=new f(i,o);if(e===r.TRUNCATED)return s;if(e===r.FLOORED)return Number(-1===this.sign())^Number(-1===n.sign())?s.add(n):s;if(e===r.EUCLIDEAN)return-1===s.sign()?s.add(-1===n.sign()?n.neg():n):s;throw new Error("Invalid ModType")}pow(t){const r=this.parseParameter(t);if(!r.isInteger())throw new Error("Unsupported parameter");const e=r.numerator/r.denominator,n=e<o?-e:e,i=new f(this.numerator**n,this.denominator**n);return e<o?i.inv():i}powm(t,r,e){const n=this.parseParameter(t);if(!n.isInteger())throw new Error("Unsupported parameter");let i=n.toNumber();const o=this.parseParameter(r);let a=this,c=new f(s,s);for(;0!==i;)i%2!=0&&(c=c.mul(a).mod(o,e)),a=a.pow(u).mod(o,e),i=Math.floor(i/2);return c}inv(){return new f(this.denominator,this.numerator)}floor(r){return this.denominator===s?new d(this.numerator):this.round(r,t.TO_NEGATIVE)}ceil(r){return this.denominator===s?new d(this.numerator):this.round(r,t.TO_POSITIVE)}trunc(r){return this.denominator===s?new d(this.numerator):this.round(r,t.TO_ZERO)}round(t,r){if(t=void 0===t?0:t,!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for decimals");const e=this.toFixedNumber(t+1);if(this.sub(e).isZero())return e.round(t,r);return new d(`${e.toFixed(t+1)}1`).round(t,r)}roundToDigits(t,r){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid value for digits");if(this.isZero())return new d(o);let e=this.abs(),n=0;for(;e.gte(s);)e=e.div(h),n++;const i=new f(s,h);for(;e.lt(i);)e=e.mul(h),n--;let u=e.round(t,r);return u=u._incExponent(n),-1===this.sign()?u.neg():u}gcd(t,r){let e=t<o?-t:t,n=r<o?-r:r;if(n>e){const t=e;e=n,n=t}for(;;){if(n===o)return e;if(e%=n,e===o)return n;n%=e}}simplify(){let{numerator:t,denominator:r}=this;const e=this.gcd(t,r);return e>s&&(t/=e,r/=e),r<o&&(t=-t,r=-r),new f(t,r)}normalize(){const{numerator:r,denominator:e}=this.simplify();if(e===s)return new d(r,0);const n=new f(r,e),{cycleLen:i,cycleStart:o}=n.getDecimalFormat(0);return 0!==i?n:n.round(o,t.TO_ZERO)}getFractionParts(t=!0){const r=t?this.simplify():this;return{numerator:new d(r.numerator),denominator:new d(r.denominator)}}sign(){return(this.numerator<o?-1:1)*(this.denominator<o?-1:1)}abs(){return new f(this.numerator<o?-this.numerator:this.numerator,this.denominator<o?-this.denominator:this.denominator)}neg(){return this.mul(-s)}intPart(){return this.trunc()}fracPart(){return this.sub(this.trunc())}cmp(t){const r=this.parseParameter(t),e=this.denominator===r.denominator,n=e?this.numerator:this.numerator*r.denominator,i=e?r.numerator:r.numerator*this.denominator;return n===i?0:n>i?1:-1}eq(t){return 0===this.cmp(t)}lt(t){return-1===this.cmp(t)}lte(t){return this.cmp(t)<=0}gt(t){return 1===this.cmp(t)}gte(t){return this.cmp(t)>=0}clamp(t,r){const e=w(t),n=w(r);if(e.gt(n))throw new Error("Min parameter has to be smaller than max");return this.lt(e)?e:this.gt(n)?n:this}isZero(){return this.numerator===o}isOne(){return this.numerator===this.denominator}isInteger(){return this.numerator%this.denominator===o}serialize(){return[this.numerator,this.denominator]}toNumber(){return Number(this.toPrecision(20))}convertToFraction(){return this}getNumberForBitwiseOp(){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");return this.intPart()}bitwiseAnd(t){return this.getNumberForBitwiseOp().bitwiseAnd(t)}bitwiseOr(t){return this.getNumberForBitwiseOp().bitwiseOr(t)}bitwiseXor(t){return this.getNumberForBitwiseOp().bitwiseXor(t)}shiftLeft(t){return this.getNumberForBitwiseOp().shiftLeft(t)}shiftRight(t){return this.getNumberForBitwiseOp().shiftRight(t)}getDecimalFormat(t){t=void 0===t?Number.MAX_SAFE_INTEGER:t;let r=this.denominator<o?-this.denominator:this.denominator,e=0;for(;r%u===o;)r/=u,e++;let n=0;for(;r%m===o;)r/=m,n++;const i=Math.max(e,n);if(r===s)return{cycleLen:0,cycleStart:i};const a=Math.max(1,t-i);let c=h%r,l=1;for(;c!==s;){if(l===a)return{cycleLen:null,cycleStart:i};c=c*h%r,l++}return{cycleLen:l,cycleStart:i}}toFixed(r,e=t.TO_ZERO,n=!1){if(!Number.isSafeInteger(r)||r<0)throw new Error("Invalid parameter");return this.round(r,e).toFixed(r,t.TO_ZERO,n)}toRepeatingParts(t){if(this.isZero())return["0","",""];const{cycleLen:r,cycleStart:n}=this.simplify().getDecimalFormat(t);if(null===r||0===r){const r=t??n,i=this.toFixed(r),o=e(i).split(".");return[o[0],o[1]??"",""]}const i=n+r,o=this.toFixed(i).split(".");return[o[0],o[1].slice(0,n),o[1].slice(n)]}toRepeatingDigits(t){const r=this.toRepeatingParts(t);let e=r[0];return(r[1]||r[2])&&(e+=`.${r[1]}`),r[2]&&(e+=`(${r[2]})`),e}toExponential(r,e=t.TO_ZERO,n=!1){if(!Number.isSafeInteger(r)||r<0)throw new Error("Invalid parameters");return this.toFixedNumber(r).toExponential(r,e,n)}toFraction(){const{numerator:t,denominator:r}=this.getFractionParts(!0);return`${t.toString()}/${r.toString()}`}toFixedNumber(t){const r=this.numerator*h**BigInt(t);return new d(r/this.denominator,t)}toBase(t,r){if(!Number.isSafeInteger(t)||t<2||t>16)throw new Error("Invalid radix");if(void 0!==r&&(!Number.isSafeInteger(r)||r<0))throw new Error("Invalid parameter");if(10===t)return void 0===r?this.toRepeatingDigits(r):e(this.toFixed(r));const n=this.normalize(),i=void 0===r?Number.MAX_SAFE_INTEGER:r+1;let o=n.intPart(),s=n.sub(o);const u=-1===n.sign();u&&(o=o.neg(),s=s.neg());const a=new Map;let c=[];for(;!s.isZero()&&c.length!==i;){const r=s.mul(t),e=r.normalize().toFraction(),n=a.get(e);if(void 0!==n){c=[...c.slice(0,n-1),"(",...c.slice(n-1),")"];break}const i=Math.abs(r.intPart().toNumber());c.push(i.toString(t)),s=r.fracPart(),a.set(e,c.length)}c.length===i&&c.pop();const m=c.join("");return`${u?"-":""}${o.toString(t)}${c.length?".":""}${m}`}toString(t,r){return void 0===t||10===t?this.toRepeatingDigits(r):this.toBase(t,r)}toPrecision(r,e=t.TO_ZERO,n=!1){if(!Number.isSafeInteger(r)||r<1)throw new Error("Invalid parameter");return this.roundToDigits(r,e).toPrecision(r,t.TO_ZERO,n)}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}function g(t){if(t instanceof d||t instanceof f)return t;if("bigint"==typeof t)return new d(t);if("number"==typeof t){if(!Number.isSafeInteger(t))throw new Error("Floating point values as numbers are unsafe. Please provide them as a string.");return new d(t)}if("string"==typeof t)return t.includes("/")||t.includes("(")?new f(t,s):new d(t);throw new Error("Unsupported parameter type")}const w=(t,r)=>{if(void 0===t)throw new Error("First parameter cannot be undefined");const e=g(t);if(void 0===r)return e;const n=g(r);return new f(e,s).div(new f(n,s))};w.min=(...t)=>{if(0===t.length)throw new Error("Got empty array");let r=w(t[0]);for(let e=1;e<t.length;e++){const n=w(t[e]);n.lt(r)&&(r=n)}return r},w.max=(...t)=>{if(0===t.length)throw new Error("Got empty array");let r=w(t[0]);for(let e=1;e<t.length;e++){const n=w(t[e]);n.gt(r)&&(r=n)}return r};const b=(t,r)=>{let e=o;for(let n=0;n<t.length;n++){const i=t.charAt(n),o=parseInt(i,r);if(Number.isNaN(o))throw new Error(`Invalid digit "${i}"`);e*=BigInt(r),e+=BigInt(o)}return e};w.fromBase=(t,r)=>{if("string"!=typeof t)throw new Error("First parameter must be string");if(!Number.isSafeInteger(r)||r<2||r>16)throw new Error("Invalid radix");if(10===r)return w(t);if(0===(t=t.trim()).length)throw new Error("Empty string is not allowed");const e=t.startsWith("-");e&&(t=t.slice(1));const n=t.match(/^([0-9a-f]*)(?:\.([0-9a-f]*)(?:\(([0-9a-f]+)\))?)?$/i);if(!n)throw new Error(`Cannot parse number "${t}"`);const i=n[1]??"",o=n[2]??"",u=n[3]??"";if(u.length>0){const t=b(`${i}${o}${u}`,r)-b(`${i}${o}`,r),n=b((r-1).toString(r).repeat(u.length)+"0".repeat(o.length),r),s=new f(t,n).normalize();return e?s.neg():s}const a=b(i,r),c=b(o,r),m=new f(c,BigInt(r)**BigInt(o.length)),h=new f(a,s).add(m).normalize();return e?h.neg():h},w.range=function*(t,r,e){const n=w(r),i=w(e??1);let o=w(t);for(;o.lt(n);)yield o,o=o.add(i)},w.gcd=(t,r)=>{const e=w(t).abs(),n=w(r).abs();let i=n.gt(e)?n:e,o=i.eq(e)?n:e;for(;;){if(o.isZero())return i;if(i=i.mod(o),i.isZero())return o;o=o.mod(i)}},w.lcm=(t,r)=>{const e=w(t).abs(),n=w(r).abs(),i=e.mul(n);if(i.isZero())throw new Error("LCM of zero is undefined");const o=w.gcd(e,n);return i.div(o)};const E=(t,r,e)=>{const n=((t,r)=>{let e=r.toNumber();if(Number.isFinite(e)){const r=e<0;r&&(e=-e);let n=e**(1/t);return r&&(n=-n),n.toString()}const n=r.abs().toFixed(0).length,i=Math.ceil(n/t);return`${1===r.sign()?"":"-"}5e${i}`})(t,r);let i=new d("0"!==n?n:"1");const o=new f(t-1,t),s=new f(r,t),u=BigInt(t-1);let a=i.trunc(e+5);for(;i=o.mul(i).add(s.mul(i.pow(u).inv())),i=i.trunc(e+5),!i.isZero()&&!a.eq(i);)a=i;return i.trunc(e)},p=(t,r,e)=>{if(!Number.isSafeInteger(t))throw new Error("Integer is expected for N");if(t<0)throw new Error("Negative N is not supported");if(0===t)throw new Error("N cannot be zero");const n=i(w(r),e);if(1===t)return n.trunc(e);if(t%2==0&&-1===n.sign())throw new Error("Complex numbers are not supported");if(n.isZero())return new d(o).trunc(e);if(n.isOne())return new d(s).trunc(e);return E(t,n,e)},I=(t,r)=>p(2,t,r),N=(t,r)=>p(3,t,r);class v{constructor(t,r){this.cachedDecimals=0,this.fn=t,this.max=r}get(t){if(t<=this.cachedDecimals)return this.cache.trunc(t);const r=new d(this.fn(t)),e=Math.min(this.max,t);return this.cachedDecimals!==e&&(this.cache=r.trunc(e),this.cachedDecimals=e),r}}const O=(t,r)=>{let e=i(w(t),r);if(e.isOne())return new d(0).trunc(r);if(e.lte(0))throw new Error("Invalid parameter");let n=0;const a=w("0.1");for(;e.sub(s).abs().gt(a);)e=new d(I(e,r+10)),n++;const c=function*(t,r){const e=t.pow(u).normalize();let n=t,i=s,o=w(t);for(;;){n=n.mul(e),i+=u;const t=n.div(i).trunc(r+10);o=o.add(t),yield{term:t,sum:o}}}(e.sub(s).div(e.add(s)),r);for(const{term:t,sum:e}of c)if(t.isZero()){return e.mul(u**BigInt(n+1)).trunc(r)}return w(o)},T=(t,r,e)=>{if(!Number.isSafeInteger(t)||t<2)throw new Error("Invalid parameter for N");const n=O(r,e+10),i=O(t,e+10);return new d(n).div(i).trunc(e)},P=new v((t=>O(u,t)),200),_=(t,r)=>new d(O(t,r+10)).div(P.get(r+10)).trunc(r),S=new v((t=>O(h,t)),200),R=(t,r)=>new d(O(t,r+10)).div(S.get(r+10)).trunc(r);const A=(t,r)=>{const e=i(w(t),r),n=w(`1e-${r+5}`),a=function*(t,r){let e=t.add(1),n=BigInt(6),i=c;const o=t.pow(u);let a=o;for(;;){const c=a.mul(t.add(i-s)).div(n);n*=i*(i+s),i+=u,a=a.mul(o),e=e.add(c).trunc(r+5),yield{term:c,sum:e}}}(e,r);for(const{term:t,sum:e}of a)if(t.abs().lt(n))return e.trunc(r);return w(o)},F=(t,r,e)=>{const n=i(w(t),e),o=i(w(r),e);if(o.isInteger()&&Number.isSafeInteger(o.toNumber()))return n.pow(o).trunc(e);if(-1===n.sign()&&!o.isInteger())throw new Error("Complex numbers are not supported");const s=O(n,e+5),u=o.mul(s);return A(u,e+5).trunc(e)},y=new v((t=>{if(0===t)return w(a);let r=s,e=a*h**BigInt(t+20),n=e;for(;e!==o;)e=e*r/((r+s)*c),r+=u,n+=e/r;return w(`3.${n.toString().slice(1,t+1)}`)}),1e3),B=t=>0===t?w(a):y.get(t).trunc(t),Z=(r,e)=>{let n=r.round(e+5,t.NEAREST_AWAY_FROM_ZERO);const i=B(e+5),o=((t,r,e)=>{const n=Math.max(3,e),i=t.trunc(n),o=i.div(r).round();return r.mul(o).trunc(n).eq(i)?o:null})(n,i.div(12),e);if(null!==o)return(t=>{let r=t.mod(l).toNumber();r<0&&(r+=24);const e=Math.floor(r/6)+1;let n=15*r;return 4===e?n=360-n:3===e?n-=180:2===e&&(n=180-n),{specialCaseDeg:n,quadrant:e,subHalfPiAngle:null}})(o);const s=i.mul(u);n=n.mod(s),-1===n.sign()&&(n=n.add(s));const a=n.mul(u).div(i).floor().toNumber()+1;let c=n;return 4===a?c=s.sub(c):3===a?c=c.sub(i):2===a&&(c=i.sub(c)),{specialCaseDeg:null,quadrant:a,subHalfPiAngle:c}};const $=(t,r,e)=>{let n=w(t);return r&&(n=n.neg()),n.trunc(e)},x=(r,e)=>{const n=e+10,c=i(w(r),e+5),{specialCaseDeg:m,subHalfPiAngle:h,quadrant:l}=Z(c,e),d=2===l||3===l;if(null!==m){if(0===m)return $(s,d,e);if(30===m)return $(w(I(a,e+5)).div(u),d,e);if(45===m)return $(w(I(u,e+5)).div(u),d,e);if(60===m)return $("0.5",d,e);if(90===m)return $(o,d,e);throw new Error}const f=w(`1e-${n}`),g=function*(r,e){const n=r.round(e+10,t.NEAREST_AWAY_FROM_ZERO).pow(u);let i=n,o=u,c=w(s).sub(i.div(o).trunc(e+10)),m=a;for(;;){o*=m*(m+s),m+=u;const t=m*(m+s);m+=u,i=i.mul(n),o*=t;let r=i.mul(t);i=i.mul(n),r=r.sub(i);const a=r.div(o).trunc(e+10);c=c.add(a),yield{term:a,sum:c}}}(h,e);for(const{term:t,sum:r}of g)if(t.lt(f))return $(r,d,e);return w(0)},D=(t,r)=>{const e=new d(B(r+10)),n=i(w(t),r+5);return x(e.div(u).sub(n),r+5).trunc(r)},M=(t,r)=>{const e=i(w(t),r+5),{specialCaseDeg:n,quadrant:o,subHalfPiAngle:c}=Z(e,r),m=1===o||3===o;if(null!==n){if(0===n)return $("0",m,r);if(30===n)return $(w(s).div(I(a,r+5)),m,r);if(4===n)return $("1",m,r);if(60===n)return $(I(a,r+5),m,r);if(90===n)throw new Error("Out of range");throw new Error}const h=w(x(c.mul(u),r+5)),l=w(s).sub(h).div(w(s).add(h)).round(r+5),d=I(l,r+5).trunc(r);return m?d:d.neg()};const z=(t,r)=>{let e=i(w(t),r);if(e.isZero())return w(0);if(e.abs().isOne())return w(B(r)).div(4*e.sign()).trunc(r);let n=0;const o=w("0.42");for(;e.abs().gt(o);){const t=w(I(e.pow(u).add(s),r+10));e=e.div(t.add(s)),n++}const c=w(`1e-${r+10}`),m=function*(t,r){const e=t.pow(u).normalize(),n=e.pow(u).normalize();let i=a,o=t.sub(t.mul(e).div(i)),s=t.mul(n);for(;;){i+=u;const t=i+u,a=s.mul(e.mul(-i).add(t)).div(i*t);i=t,s=s.mul(n),o=o.add(a).trunc(r+10),yield{term:a,sum:o}}}(e,r);for(const{term:t,sum:e}of m)if(t.abs().lt(c)){return e.mul(u**BigInt(n)).trunc(r)}return w(0)},U=(t,r)=>{const e=i(w(t),r);if(e.isZero())return w(o);if(e.abs().isOne())return w(B(r)).mul(e.sign()).div(u).trunc(r);if(e.abs().eq("1/2"))return w(B(r)).mul(e.sign()).div(6).trunc(r);if(e.gt(s)||e.lt(-s))throw new Error("Out of range");const n=w(I(e.pow(u).neg().add(s),r+10));return w(z(e.div(n.add(s)),r+10)).mul(u).trunc(r)},C=(t,r)=>{const e=i(w(t),r);if(e.isZero())return w(B(r)).div(u).trunc(r);if(e.isOne())return w(o);if(e.abs().isOne())return B(r);if(e.abs().eq("1/2")){const t=w(B(r)).div(a);return-1===e.sign()?t.mul(u).trunc(r):t.trunc(r)}if(e.gt(s)||e.lt(-s))throw new Error("Out of range");return w(B(r+10)).div(u).sub(U(e,r+10)).trunc(r)};const V=(t,r)=>{const e=i(w(t),r),n=new d(`1e-${r+5}`),a=function*(t,r){let e=t,n=s;const i=t.pow(u).normalize();let o=t.trunc(r+5),a=u;for(;;){e=e.mul(i),n*=a*(a+s),a+=u;const t=e.div(n);o=o.add(t).trunc(r+5),yield{term:t,sum:o}}}(e,r);for(const{term:t,sum:e}of a)if(t.abs().lt(n))return e.trunc(r);return w(o)};const L=(t,r)=>{const e=i(w(t),r),n=new d(`1e-${r+5}`),c=function*(t,r){const e=t.pow(u).normalize();let n=e,i=u,o=n.div(i).add(s).trunc(r+5),c=a;for(;;){n=n.mul(e),i*=c*(c+s),c+=u;const t=n.div(i);o=o.add(t).trunc(r+5),yield{term:t,sum:o}}}(e,r);for(const{term:t,sum:e}of c)if(t.abs().lt(n))return e.trunc(r);return w(o)},G=(t,r)=>{const e=i(w(t),r);if(e.isZero())return w(o);const n=L(e,r+10).abs();return I(n.pow(u).sub(s),r+10).div(n).mul(e.sign()).trunc(r)},W=(t,r)=>{const e=i(w(t),r);if(e.isZero())return w(o);const n=I(e.pow(u).add(s),r+5);return O(e.add(n),r+5).trunc(r)},q=(t,r)=>{const e=i(w(t),r);if(e.isOne())return w(o);if(e.lt(s))throw new Error("Out of range");const n=I(e.pow(u).sub(s),r+5);return O(e.add(n),r+5).trunc(r)},Y=(t,r)=>{const e=i(w(t),r);if(e.abs().gte(s))throw new Error("Out of range");if(e.isZero())return w(o);const n=O(e.add(s).div(e.neg().add(s)),r+5);return w(n).div(u).trunc(r)};export{w as ExactNumber,r as ModType,B as PI,t as RoundingMode,C as acos,q as acosh,U as asin,W as asinh,z as atan,Y as atanh,N as cbrt,x as cos,L as cosh,A as exp,O as log,R as log10,_ as log2,T as logn,p as nthroot,F as pow,D as sin,V as sinh,I as sqrt,M as tan,G as tanh};
/*!
* exactnumber v0.11.0 (https://www.npmjs.com/package/exactnumber)
* exactnumber v1.0.0 (https://www.npmjs.com/package/exactnumber)
* (c) Dani Biro

@@ -7,2 +7,2 @@ * @license MIT

!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((n="undefined"!=typeof globalThis?globalThis:n||self).exactnumber={})}(this,(function(n){"use strict";var t,r;n.RoundingMode=void 0,(t=n.RoundingMode||(n.RoundingMode={}))[t.NEAREST_TO_POSITIVE=201008]="NEAREST_TO_POSITIVE",t[t.NEAREST_TO_NEGATIVE=201009]="NEAREST_TO_NEGATIVE",t[t.NEAREST_TO_EVEN=201010]="NEAREST_TO_EVEN",t[t.NEAREST_TO_ZERO=201011]="NEAREST_TO_ZERO",t[t.NEAREST_AWAY_FROM_ZERO=201012]="NEAREST_AWAY_FROM_ZERO",t[t.TO_POSITIVE=201001]="TO_POSITIVE",t[t.TO_NEGATIVE=201002]="TO_NEGATIVE",t[t.TO_ZERO=201003]="TO_ZERO",t[t.AWAY_FROM_ZERO=201004]="AWAY_FROM_ZERO",n.ModType=void 0,(r=n.ModType||(n.ModType={})).TRUNCATED="T",r.FLOORED="F",r.EUCLIDEAN="E";const e=n=>{const t=n.indexOf(".");if(-1===t)return n;let r=n.length;for(;r>t&&"0"===n.charAt(r-1);)r--;const e=t===r-1?t:r;return 0===e?"0":n.slice(0,e)},i=(n,t,r,i)=>{let o=n.toString();if(0===t&&0===r)return o;const s=o.startsWith("-");if(s&&(o=o.slice(1)),t>=o.length&&(o="0".repeat(t-o.length+1)+o),t>0){const n=o.slice(0,-t),s=o.slice(-t),u=r<=t?s.slice(0,r):`${s}${"0".repeat(r-t)}`;0!==u.length?(o=`${n}.${u}`,i&&(o=e(o))):o=n}else r>0&&(o=`${o}.${"0".repeat(r)}`);return s?`-${o}`:o},o=(t,r)=>(t=t.normalize())instanceof s?t.round(r,n.RoundingMode.NEAREST_AWAY_FROM_ZERO):t;class s{constructor(n,t=0){if(this.type="fixed","bigint"==typeof n)this.number=n,this.decimalPos=t;else{const t=this.parseConstructorParameter(n);this.number=t.number,this.decimalPos=t.decimalPos}}parseConstructorParameter(n){if(n instanceof s)return{number:n.number,decimalPos:n.decimalPos};if(n instanceof u){if(!n.isInteger())throw new Error("Cannot create FixedNumber from non-integer Fraction");return{number:n.trunc().number,decimalPos:0}}if("number"==typeof n){if(!Number.isSafeInteger(n))throw new Error("The specified number cannot be exactly represented as an integer. Please provide a string instead.");return{number:BigInt(n),decimalPos:0}}if("string"==typeof n){if(0===(n=n.trim()).length)throw new Error("Empty string is not allowed");const t=n.match(/^(-?[0-9]*)(?:\.([0-9]*))?(?:[eE]([+-]?[0-9]+))?$/);if(!t)throw new Error(`Cannot parse number "${n}"`);let r=0,e=t[1]??"0";if(void 0!==t[2]&&(e+=t[2],r+=t[2].length),void 0!==t[3]){const n=Number(t[3]);n>0?e+="0".repeat(n):r-=n}return{number:BigInt(e),decimalPos:r}}throw new Error("Unsupported parameter!")}scaleNumber(n,t){const r=Math.max(this.decimalPos,t);return{a:r===this.decimalPos?this.number:this.number*10n**BigInt(r-this.decimalPos),b:r===t?n:n*10n**BigInt(r-t),decimalPos:r}}add(n){const t=a(n);if(t instanceof u)return t.add(this);const r=t,{a:e,b:i,decimalPos:o}=this.scaleNumber(r.number,r.decimalPos);return new s(e+i,o)}sub(n){const t=a(n);return this.add(t.neg())}mul(n){const t=a(n);if(t instanceof u)return t.mul(this);const r=t,e=this.number*r.number;return new s(e,this.decimalPos+r.decimalPos)}pow(n){const t=a(n).toNumber();if(!Number.isSafeInteger(t))throw new Error("Unsupported parameter");const r=Math.abs(t),e=new s(this.number**BigInt(r),this.decimalPos*r);return t<0?e.inv():e}div(n){return this.convertToFraction().div(n)}divToInt(n){const t=a(n);if(t instanceof u)return this.convertToFraction().divToInt(t);const r=t,{a:e,b:i}=this.scaleNumber(r.number,r.decimalPos);return new s(e/i)}mod(t,r=n.ModType.TRUNCATED){const e=a(t);if(e instanceof u)return this.convertToFraction().mod(e);const i=e,{a:o,b:c,decimalPos:m}=this.scaleNumber(i.number,i.decimalPos),d=o%c,h=new s(d,m);if(r===n.ModType.TRUNCATED)return h;if(r===n.ModType.FLOORED)return Number(o<0)^Number(c<0)?h.add(c):h;if(r===n.ModType.EUCLIDEAN)return d<0?h.add(c<0?-c:c):h;throw new Error("Invalid ModType")}abs(){return new s(this.number<0?-this.number:this.number,this.decimalPos)}neg(){return this.mul(-1n)}inv(){return this.convertToFraction().inv()}floor(t){return 0===this.decimalPos?this:this.round(t,n.RoundingMode.TO_NEGATIVE)}ceil(t){return 0===this.decimalPos?this:this.round(t,n.RoundingMode.TO_POSITIVE)}trunc(t){return 0===this.decimalPos?this:this.round(t,n.RoundingMode.TO_ZERO)}isTieStr(n){if("5"!==n[0])return!1;for(let t=1;t<n.length;t++)if("0"!==n[t])return!1;return!0}_round(t,r){const e=this.decimalPos-t;if(e<=0)return this;const i=10n**BigInt(e),o=this.number/i;if(r===n.RoundingMode.TO_ZERO)return new s(o,t);const u=this.number%i;if(0n===u)return new s(o,t);if(r===n.RoundingMode.AWAY_FROM_ZERO){const n=this.number<0n?o-1n:o+1n;return new s(n,t)}if(r===n.RoundingMode.TO_POSITIVE){const n=this.number<0n?o:o+1n;return new s(n,t)}if(r===n.RoundingMode.TO_NEGATIVE){const n=this.number>=0n?o:o-1n;return new s(n,t)}if(![void 0,n.RoundingMode.NEAREST_TO_ZERO,n.RoundingMode.NEAREST_AWAY_FROM_ZERO,n.RoundingMode.NEAREST_TO_POSITIVE,n.RoundingMode.NEAREST_TO_NEGATIVE,n.RoundingMode.NEAREST_TO_EVEN].includes(r))throw new Error("Invalid rounding mode. Use the predefined values from the RoundingMode enum.");let a=(u<0n?-u:u).toString();if(a.length<e&&(a="0"),this.isTieStr(a)){if(r===n.RoundingMode.NEAREST_TO_ZERO)return new s(o,t);if(r===n.RoundingMode.NEAREST_AWAY_FROM_ZERO){const n=this.number<0n?o-1n:o+1n;return new s(n,t)}if(void 0===r||r===n.RoundingMode.NEAREST_TO_POSITIVE){const n=this.number<0n?o:o+1n;return new s(n,t)}if(r===n.RoundingMode.NEAREST_TO_NEGATIVE){const n=this.number>=0n?o:o-1n;return new s(n,t)}if(r===n.RoundingMode.NEAREST_TO_EVEN){if(o%2n===0n)return new s(o,t);return new s(o<0n?o-1n:o+1n,t)}}if(Number(a[0])<5)return new s(o,t);const c=this.number<0?o-1n:o+1n;return new s(c,t)}round(n,t){if(n=void 0===n?0:n,!Number.isSafeInteger(n)||n<0)throw new Error("Invalid value for decimals");return this._round(n,t).normalize()}_incExponent(n){if(0===n)return this;let t=this.number,r=this.decimalPos;if(n<0)r-=n;else{const e=Math.min(n,this.decimalPos);r-=e;const i=n-e;i>0&&(t*=10n**BigInt(i))}return new s(t,r)}countDigits(){if(0n===this.number)return 1;let n=0,t=this.number<0?-this.number:this.number;for(;t>0n;)t/=10n,n++;return n}toSubZeroNum(){const n=this.countDigits();return{subZeroNum:new s(this.number,n),exponentDiff:n-this.decimalPos}}roundToDigits(n,t){if(!Number.isSafeInteger(n)||n<1)throw new Error("Invalid value for digits");const{subZeroNum:r,exponentDiff:e}=this.toSubZeroNum();let i=r.round(n,t);return i=i._incExponent(e),i}intPart(){return this.trunc()}fracPart(){return this.sub(this.trunc())}sign(){return this.number<0n?-1:1}bitwiseAnd(n){if(n=c(n),!this.isInteger()||-1===this.sign()||!n.isInteger()||-1===n.sign())throw new Error("Only positive integers are supported");n instanceof u&&(n=n.trunc());const t=2n**24n;let r=this.normalize().number,e=n.trunc().normalize().number,i=0n,o=1n;for(;r>0&&e>0;){const n=BigInt.asUintN(24,r),s=BigInt.asUintN(24,e);i+=BigInt(Number(n)&Number(s))*o,o*=t,r/=t,e/=t}return new s(i)}bitwiseOr(n){if(n=c(n),!this.isInteger()||-1===this.sign()||!n.isInteger()||-1===n.sign())throw new Error("Only positive integers are supported");n instanceof u&&(n=n.trunc());const t=2n**24n;let r=this.normalize().number,e=n.trunc().normalize().number,i=0n,o=1n;for(;r>0||e>0;){const n=BigInt.asUintN(24,r),s=BigInt.asUintN(24,e);i+=BigInt(Number(n)|Number(s))*o,o*=t,r/=t,e/=t}return new s(i)}bitwiseXor(n){if(n=c(n),!this.isInteger()||-1===this.sign()||!n.isInteger()||-1===n.sign())throw new Error("Only positive integers are supported");n instanceof u&&(n=n.trunc());const t=2n**24n;let r=this.normalize().number,e=n.trunc().normalize().number,i=0n,o=1n;for(;r>0||e>0;){const n=BigInt.asUintN(24,r),s=BigInt.asUintN(24,e);i+=BigInt(Number(n)^Number(s))*o,o*=t,r/=t,e/=t}return new s(i)}shiftLeft(n){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(n)||n<0)throw new Error("Invalid value for bitCount");const t=2n**BigInt(n);return this.mul(t)}shiftRight(n){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(n)||n<0)throw new Error("Invalid value for bitCount");const t=2n**BigInt(n);return new s(this.normalize().number/t)}cmp(n){const t=a(n);if(t instanceof u)return-t.cmp(this);const r=t,{a:e,b:i}=this.scaleNumber(r.number,r.decimalPos);return e===i?0:e>i?1:-1}eq(n){return 0===this.cmp(n)}lt(n){return-1===this.cmp(n)}lte(n){return this.cmp(n)<=0}gt(n){return 1===this.cmp(n)}gte(n){return this.cmp(n)>=0}clamp(n,t){const r=c(n),e=c(t);if(r.gt(e))throw new Error("Min parameter has to be smaller than max");return this.lt(r)?r:this.gt(e)?e:this}isZero(){return 0n===this.number}isOne(){if(0===this.decimalPos)return 1n===this.number;const n=10n**BigInt(this.decimalPos),t=this.number/n;return 1n===t&&t*n===this.number}isInteger(){return 0===this.decimalPos||this.number%10n**BigInt(this.decimalPos)===0n}serialize(){return[this.number,this.decimalPos]}getFractionParts(n=!0){return this.convertToFraction().getFractionParts(n)}normalize(){if(0===this.decimalPos)return this;let n=this.decimalPos,t=this.number;for(;n>0&&t%10n===0n;)n--,t/=10n;return new s(t,n)}convertToFraction(){if(0===this.decimalPos)return new u(this.number,1n);const n=10n**BigInt(this.decimalPos);return new u(this.number,n)}toNumber(){return Number(this.toPrecision(20))}toFixed(t,r=n.RoundingMode.TO_ZERO){if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid parameter");const e=this._round(t,r);return i(e.number,e.decimalPos,t,!1)}toExponential(t,r=n.RoundingMode.TO_ZERO){if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid parameter");const e=this.roundToDigits(t+1,r).normalize(),i=-1===e.sign(),o=e.abs(),s=o.number.toString(),u=s.length<=t?`${s}${"0".repeat(t-s.length+1)}`:s.slice(0,t+1),a=u.length>1?`${u.slice(0,1)}.${u.slice(1)}`:u,c=o.decimalPos,m=s.length-1-c;return`${i?"-":""}${a}e${m>=0?"+":""}${m}`}toBase(n,t){if(!Number.isSafeInteger(n)||n<2||n>16)throw new Error("Invalid radix");if(void 0!==t&&(!Number.isSafeInteger(t)||t<0))throw new Error("Invalid parameter");const r=this.normalize();if(0===r.decimalPos)return r.number.toString(n);const e=void 0===t?Number.MAX_SAFE_INTEGER:t;let i=r.intPart(),o=r.sub(i);const s=-1===r.sign();s&&(i=i.neg(),o=o.neg());const u=new Map;let a=[];for(;!o.isZero();){const t=o.mul(n),r=t.toString(),i=u.get(r);if(void 0!==i){a=[...a.slice(0,i-1),"(",...a.slice(i-1),")"];break}if(a.length===e)break;const s=Math.abs(t.intPart().toNumber());a.push(s.toString(n)),o=t.fracPart(),u.set(r,a.length)}return[s?"-":"",i.number.toString(n),a.length?".":"",...a].join("")}toFraction(){return this.convertToFraction().toFraction()}toString(n,t){if(void 0===n||10===n){const n=void 0!==t?this.trunc(t):this;return i(n.number,n.decimalPos,n.decimalPos,!0)}return this.toBase(n,t)}toPrecision(t,r=n.RoundingMode.TO_ZERO){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid parameter");const e=this.roundToDigits(t,r),{subZeroNum:o,exponentDiff:s}=e.toSubZeroNum(),u=-1===o.sign();let a=i(o.number,o.decimalPos,o.decimalPos,!1);a=a.slice(u?3:2),a=a.slice(0,Math.max(t,s));const c=a.slice(0,Math.max(0,s)),m=a.slice(Math.max(0,s)),d=Math.max(0,t-c.length-m.length),h="0".repeat(d),l="0".repeat(s<0?-s:0);let f=c||"0";return m.length+l.length+d>0&&(f+=`.${l}${m}${h}`),u?`-${f}`:f}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}class u{constructor(n,t){if(this.type="fraction","bigint"==typeof n&&"bigint"==typeof t)this.numerator=n,this.denominator=t;else{const r=this.parseParameter(n),e=this.parseParameter(t),i=r.div(e),o=i instanceof s?i.convertToFraction():i;this.numerator=o.numerator,this.denominator=o.denominator}if(0n===this.denominator)throw new Error("Division by zero")}parseRepeatingDecimal(n){if(!n.includes("("))return new s(n).convertToFraction();const t=(n=n.trim()).match(/^(-?[0-9]*)\.([0-9]+)?\(([0-9]+)\)(?:[eE]([+-]?[0-9]+))?$/);if(!t)throw new Error(`Cannot parse string "${n}"`);const r="-"===t[1]?"-0":t[1],e=t[2]??"",i=t[3],o=t[4],a=BigInt(r+e+i)-BigInt(r+e),c=BigInt("9".repeat(i.length)+"0".repeat(e.length)),m=new u(a,c);if(void 0!==o){const n=o.startsWith("-"),t=10n**BigInt(n?o.slice(1):o);return n?m.div(t).normalize():m.mul(t).normalize()}return m.simplify()}parseParameter(n){if(n instanceof u)return n;if(n instanceof s)return n.convertToFraction();if("number"==typeof n){if(!Number.isSafeInteger(n))throw new Error("Floating point values as numbers are unsafe. Please provide them as a string.");return new u(BigInt(n),1n)}if("bigint"==typeof n)return new u(n,1n);if("string"==typeof n){const t=n.split("/");if(t.length>2)throw new Error(`Cannot parse string '${n}'`);const r=this.parseRepeatingDecimal(t[0]),e=t[1]?this.parseRepeatingDecimal(t[1]):new u(1n,1n);return r.div(e).convertToFraction()}throw new Error("Unsupported parameter!")}add(n){const{numerator:t,denominator:r}=this.parseParameter(n);return this.denominator===r?new u(this.numerator+t,this.denominator):new u(this.numerator*r+t*this.denominator,r*this.denominator)}sub(n){const{numerator:t,denominator:r}=this.parseParameter(n);return this.add(new u(-t,r))}mul(n){const{numerator:t,denominator:r}=this.parseParameter(n);return new u(this.numerator*t,this.denominator*r)}div(n){const{numerator:t,denominator:r}=this.parseParameter(n);return this.mul(new u(r,t))}divToInt(n){return this.div(n).trunc()}mod(t,r=n.ModType.TRUNCATED){const e=this.parseParameter(t),i=e.denominator*this.numerator%(e.numerator*this.denominator),o=this.denominator*e.denominator,s=new u(i,o);if(r===n.ModType.TRUNCATED)return s;if(r===n.ModType.FLOORED)return Number(-1===this.sign())^Number(-1===e.sign())?s.add(e):s;if(r===n.ModType.EUCLIDEAN)return s.sign()<0?s.add(e.sign()<0?e.neg():e):s;throw new Error("Invalid ModType")}pow(n){const t=this.parseParameter(n);if(!t.isInteger())throw new Error("Unsupported parameter");const r=t.numerator/t.denominator,e=r<0?-r:r,i=new u(this.numerator**e,this.denominator**e);return r<0?i.inv():i}inv(){return new u(this.denominator,this.numerator)}floor(t){return 1n===this.denominator?new s(this.numerator):this.round(t,n.RoundingMode.TO_NEGATIVE)}ceil(t){return 1n===this.denominator?new s(this.numerator):this.round(t,n.RoundingMode.TO_POSITIVE)}trunc(t){return 1n===this.denominator?new s(this.numerator):this.round(t,n.RoundingMode.TO_ZERO)}round(n,t){if(n=void 0===n?0:n,!Number.isSafeInteger(n)||n<0)throw new Error("Invalid value for decimals");const r=this.toFixedNumber(n+1);if(this.sub(r).isZero())return r.round(n,t);return new s(`${r.toFixed(n+1)}1`).round(n,t)}roundToDigits(n,t){if(!Number.isSafeInteger(n)||n<1)throw new Error("Invalid value for digits");if(this.isZero())return new s(0n);let r=this.abs(),e=0;for(;r.gte(1n);)r=r.div(10n),e++;const i=new u(1n,10n);for(;r.lt(i);)r=r.mul(10n),e--;let o=r.round(n,t);return o=o._incExponent(e),-1===this.sign()?o.neg():o}gcd(n,t){let r=n<0?-n:n,e=t<0?-t:t;if(e>r){const n=r;r=e,e=n}for(;;){if(0n===e)return r;if(r%=e,0n===r)return e;e%=r}}simplify(){let{numerator:n,denominator:t}=this;const r=this.gcd(n,t);return r>1n&&(n/=r,t/=r),t<0n&&(n=-n,t=-t),new u(n,t)}normalize(){const{numerator:t,denominator:r}=this.simplify();if(1n===r)return new s(t,0);const e=new u(t,r),{cycleLen:i,cycleStart:o}=e.getDecimalFormat(0);return 0!==i?e:e.round(o,n.RoundingMode.TO_ZERO)}getFractionParts(n=!0){const t=n?this.simplify():this;return{numerator:new s(t.numerator),denominator:new s(t.denominator)}}sign(){return(this.numerator<0n?-1:1)*(this.denominator<0n?-1:1)}abs(){return new u(this.numerator<0n?-this.numerator:this.numerator,this.denominator<0n?-this.denominator:this.denominator)}neg(){return this.mul(-1n)}intPart(){return this.trunc()}fracPart(){return this.sub(this.trunc())}cmp(n){const t=this.parseParameter(n),r=this.denominator===t.denominator,e=r?this.numerator:this.numerator*t.denominator,i=r?t.numerator:t.numerator*this.denominator;return e===i?0:e>i?1:-1}eq(n){return 0===this.cmp(n)}lt(n){return-1===this.cmp(n)}lte(n){return this.cmp(n)<=0}gt(n){return 1===this.cmp(n)}gte(n){return this.cmp(n)>=0}clamp(n,t){const r=c(n),e=c(t);if(r.gt(e))throw new Error("Min parameter has to be smaller than max");return this.lt(r)?r:this.gt(e)?e:this}isZero(){return 0n===this.numerator}isOne(){return this.numerator===this.denominator}isInteger(){return this.numerator%this.denominator===0n}serialize(){return[this.numerator,this.denominator]}toNumber(){return Number(this.toPrecision(20))}convertToFraction(){return this}getNumberForBitwiseOp(){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");return this.intPart()}bitwiseAnd(n){return this.getNumberForBitwiseOp().bitwiseAnd(n)}bitwiseOr(n){return this.getNumberForBitwiseOp().bitwiseOr(n)}bitwiseXor(n){return this.getNumberForBitwiseOp().bitwiseXor(n)}shiftLeft(n){return this.getNumberForBitwiseOp().shiftLeft(n)}shiftRight(n){return this.getNumberForBitwiseOp().shiftRight(n)}getDecimalFormat(n){n=void 0===n?Number.MAX_SAFE_INTEGER:n;let t=this.denominator<0?-this.denominator:this.denominator,r=0;for(;t%2n===0n;)t/=2n,r++;let e=0;for(;t%5n===0n;)t/=5n,e++;const i=Math.max(r,e);if(1n===t)return{cycleLen:0,cycleStart:i};const o=Math.max(1,n-i);let s=10n%t,u=1;for(;1n!==s;){if(u===o)return{cycleLen:null,cycleStart:i};s=10n*s%t,u++}return{cycleLen:u,cycleStart:i}}toFixed(t,r=n.RoundingMode.TO_ZERO){if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid parameter");return this.round(t,r).toFixed(t)}toRepeatingParts(n){if(this.isZero())return["0","",""];const{cycleLen:t,cycleStart:r}=this.simplify().getDecimalFormat(n);if(null===t||0===t){const t=n??r,i=this.toFixed(t),o=e(i).split(".");return[o[0],o[1]??"",""]}const i=r+t,o=this.toFixed(i).split(".");return[o[0],o[1].slice(0,r),o[1].slice(r)]}toRepeatingDigits(n){const t=this.toRepeatingParts(n);let r=t[0];return(t[1]||t[2])&&(r+=`.${t[1]}`),t[2]&&(r+=`(${t[2]})`),r}toExponential(t,r=n.RoundingMode.TO_ZERO){if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid parameters");return this.toFixedNumber(t).toExponential(t,r)}toFraction(){const{numerator:n,denominator:t}=this.getFractionParts(!0);return`${n.toString()}/${t.toString()}`}toFixedNumber(n){const t=this.numerator*10n**BigInt(n);return new s(t/this.denominator,n)}toBase(n,t){if(!Number.isSafeInteger(n)||n<2||n>16)throw new Error("Invalid radix");if(void 0!==t&&(!Number.isSafeInteger(t)||t<0))throw new Error("Invalid parameter");if(10===n)return void 0===t?this.toRepeatingDigits(t):e(this.toFixed(t));const r=this.normalize(),i=void 0===t?Number.MAX_SAFE_INTEGER:t+1;let o=r.intPart(),s=r.sub(o);const u=-1===r.sign();u&&(o=o.neg(),s=s.neg());const a=new Map;let c=[];for(;!s.isZero()&&c.length!==i;){const t=s.mul(n),r=t.normalize().toFraction(),e=a.get(r);if(void 0!==e){c=[...c.slice(0,e-1),"(",...c.slice(e-1),")"];break}const i=Math.abs(t.intPart().toNumber());c.push(i.toString(n)),s=t.fracPart(),a.set(r,c.length)}return c.length===i&&c.pop(),[u?"-":"",o.toString(n),c.length?".":"",...c].join("")}toString(n,t){return void 0===n||10===n?this.toRepeatingDigits(t):this.toBase(n,t)}toPrecision(t,r=n.RoundingMode.TO_ZERO){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid parameter");return this.roundToDigits(t,r).toPrecision(t)}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}function a(n){if(n instanceof s||n instanceof u)return n;if("bigint"==typeof n)return new s(n);if("number"==typeof n){if(!Number.isSafeInteger(n))throw new Error("Floating point values as numbers are unsafe. Please provide them as a string.");return new s(n)}if("string"==typeof n)return n.includes("/")||n.includes("(")?new u(n,1n):new s(n);throw new Error("Unsupported parameter type")}const c=(n,t)=>{if(void 0===n)throw new Error("First parameter cannot be undefined");const r=a(n);if(void 0===t)return r;const e=a(t);return new u(r,1n).div(new u(e,1n))};c.min=(...n)=>{if(0===n.length)throw new Error("Got empty array");let t=c(n[0]);for(let r=1;r<n.length;r++){const e=c(n[r]);e.lt(t)&&(t=e)}return t},c.max=(...n)=>{if(0===n.length)throw new Error("Got empty array");let t=c(n[0]);for(let r=1;r<n.length;r++){const e=c(n[r]);e.gt(t)&&(t=e)}return t};const m=(n,t)=>{let r=0n;for(let e=0;e<n.length;e++){const i=n.charAt(e),o=parseInt(i,t);if(Number.isNaN(o))throw new Error(`Invalid digit "${i}"`);r*=BigInt(t),r+=BigInt(o)}return r};c.fromBase=(n,t)=>{if("string"!=typeof n)throw new Error("First parameter must be string");if(!Number.isSafeInteger(t)||t<2||t>16)throw new Error("Invalid radix");if(10===t)return c(n);if(0===(n=n.trim()).length)throw new Error("Empty string is not allowed");const r=n.startsWith("-");r&&(n=n.slice(1));const e=n.match(/^([0-9a-f]*)(?:\.([0-9a-f]*)(?:\(([0-9a-f]+)\))?)?$/i);if(!e)throw new Error(`Cannot parse number "${n}"`);const i=e[1]??"",o=e[2]??"",s=e[3]??"";if(s.length>0){const n=m([i,o,s].join(""),t)-m([i,o].join(""),t),e=m((t-1).toString(t).repeat(s.length)+"0".repeat(o.length),t),a=new u(n,e).normalize();return r?a.neg():a}const a=m(i,t),d=m(o,t),h=new u(d,BigInt(t)**BigInt(o.length)),l=new u(a,1n).add(h).normalize();return r?l.neg():l},c.range=function*(n,t,r){const e=c(t),i=c(r??1);let o=c(n);for(;o.lt(e);)yield o,o=o.add(i)},c.gcd=(n,t)=>{const r=c(n).abs(),e=c(t).abs();let i=e.gt(r)?e:r,o=i.eq(r)?e:r;for(;;){if(o.isZero())return i;if(i=i.mod(o),i.isZero())return o;o=o.mod(i)}},c.lcm=(n,t)=>{const r=c(n).abs(),e=c(t).abs(),i=r.mul(e);if(i.isZero())throw new Error("LCM of zero is undefined");const o=c.gcd(r,e);return i.div(o)};const d=(n,t,r)=>{const e=((n,t)=>{let r=t.toNumber();if(Number.isFinite(r)){const t=r<0;t&&(r=-r);let e=r**(1/n);return t&&(e=-e),e.toString()}const e=t.abs().toFixed(0).length,i=Math.ceil(e/n);return`${1===t.sign()?"":"-"}5e${i}`})(n,t);let i=new s("0"!==e?e:"1");const o=new u(n-1,n),a=new u(t,n),c=BigInt(n-1);let m=i.trunc(r+5);for(;i=o.mul(i).add(a.mul(i.pow(c).inv())),i=i.trunc(r+5),!i.isZero()&&!m.eq(i);)m=i;return i.trunc(r)},h=(n,t,r)=>{if(!Number.isSafeInteger(n))throw new Error("Integer is expected for N");if(n<0)throw new Error("Negative N is not supported");if(0===n)throw new Error("N cannot be zero");const e=o(c(t),r);if(1===n)return e.trunc(r);if(n%2==0&&-1===e.sign())throw new Error("Complex numbers are not supported");if(e.isZero())return new s(0n).trunc(r);if(e.isOne())return new s(1n).trunc(r);return d(n,e,r)},l=(n,t)=>h(2,n,t);class f{constructor(n,t){this.cachedDecimals=0,this.fn=n,this.max=t}get(n){if(n<=this.cachedDecimals)return this.cache.trunc(n);const t=new s(this.fn(n)),r=Math.min(this.max,n);return this.cachedDecimals!==r&&(this.cache=t.trunc(r),this.cachedDecimals=r),t}}const g=(n,t)=>{let r=o(c(n),t);if(r.isOne())return new s(0).trunc(t);if(r.lte(0n))throw new Error("Invalid parameter");let e=0;const i=c("0.1");for(;r.sub(1n).abs().gt(i);)r=new s(l(r,t+10)),e++;const u=function*(n,t){const r=n.pow(2n).normalize();let e=n,i=1n,o=c(n);for(;;){e=e.mul(r),i+=2n;const n=e.div(i).trunc(t+10);o=o.add(n),yield{term:n,sum:o}}}(r.sub(1n).div(r.add(1n)),t);for(const{term:n,sum:r}of u)if(n.isZero()){return r.mul(2n**BigInt(e+1)).trunc(t)}return c(0)},w=new f((n=>g(2n,n)),200),b=new f((n=>g(10n,n)),200);const p=(n,t)=>{const r=o(c(n),t),e=c(`1e-${t+5}`),i=function*(n,t){let r=n.add(1n),e=6n,i=4n;const o=n.pow(2n);let s=o;for(;;){const u=s.mul(n.add(i-1n)).div(e);e*=i*(i+1n),i+=2n,s=s.mul(o),r=r.add(u).trunc(t+5),yield{term:u,sum:r}}}(r,t);for(const{term:n,sum:r}of i)if(n.abs().lt(e))return r.trunc(t);return c(0)},E=new f((n=>{if(0===n)return c(3n);let t=1n,r=3n*10n**BigInt(n+20),e=r;for(;0n!==r;)r=r*t/(4n*(t+1n)),t+=2n,e+=r/t;return c(`3.${e.toString().slice(1,n+1)}`)}),1e3),N=n=>0===n?c(3):E.get(n).trunc(n),I=(t,r)=>{const e=new s(N(r+5)),i=e.mul(2n);let o=t.round(r+5,n.RoundingMode.NEAREST_AWAY_FROM_ZERO).div(i).fracPart();o.lt(0n)&&(o=o.add(1n)),o=o.round(r+5);const u=o.div("0.25").floor().toNumber()+1;let a=i.mul(o),m=o.mul(360n);return 4===u?(a=i.sub(a),m=c(360).sub(m)):3===u?(a=a.sub(e),m=m.sub(180)):2===u&&(a=e.sub(a),m=c(180).sub(m)),{quadrantDegrees:m.round(r),quadrant:u,subHalfPiAngle:a}};const v=(n,t,r)=>{let e=c(n);return t&&(e=e.neg()),e.trunc(r)},T=(t,r)=>{const e=r+10,i=o(c(t),r+5),{quadrantDegrees:s,subHalfPiAngle:u,quadrant:a}=I(i,r),m=2===a||3===a;if(s.isZero())return v("1",m,r);if(s.eq(30n))return v(c(l(3n,r+5)).div(2n),m,r);if(s.eq(45n))return v(c(l(2n,r+5)).div(2n),m,r);if(s.eq(60n))return v("0.5",m,r);if(s.eq(90n))return v("0",m,r);const d=c(`1e-${e}`),h=function*(t,r){const e=t.round(r+10,n.RoundingMode.NEAREST_AWAY_FROM_ZERO).pow(2n);let i=e,o=2n,s=c(1n).sub(i.div(o).trunc(r+10)),u=3n;for(;;){o*=u*(u+1n),u+=2n;const n=u*(u+1n);u+=2n,i=i.mul(e),o*=n;let t=i.mul(n);i=i.mul(e),t=t.sub(i);const a=t.div(o).trunc(r+10);s=s.add(a),yield{term:a,sum:s}}}(u,r);for(const{term:n,sum:t}of h)if(n.lt(d))return v(t,m,r);return c(0)};const O=(n,t)=>{let r=o(c(n),t);if(r.isZero())return c(0);if(r.abs().isOne())return c(N(t)).div(4*r.sign()).trunc(t);let e=0;const i=c("0.42");for(;r.abs().gt(i);){const n=c(l(r.pow(2n).add(1n),t+10));r=r.div(n.add(1n)),e++}const s=c(`1e-${t+10}`),u=function*(n,t){const r=n.pow(2n).normalize(),e=r.pow(2n).normalize();let i=3n,o=n.sub(n.mul(r).div(i)),s=n.mul(e);for(;;){i+=2n;const n=i+2n,u=s.mul(r.mul(-i).add(n)).div(i*n);i=n,s=s.mul(e),o=o.add(u).trunc(t+10),yield{term:u,sum:o}}}(r,t);for(const{term:n,sum:r}of u)if(n.abs().lt(s)){return r.mul(2n**BigInt(e)).trunc(t)}return c(0)},R=(n,t)=>{const r=o(c(n),t);if(r.isZero())return c(0);if(r.abs().isOne())return c(N(t)).mul(r.sign()).div(2n).trunc(t);if(r.abs().eq("1/2"))return c(N(t)).mul(r.sign()).div(6n).trunc(t);if(r.gt(1n)||r.lt(-1n))throw new Error("Out of range");const e=c(l(r.pow(2n).neg().add(1),t+10));return c(O(r.div(e.add(1n)),t+10)).mul(2).trunc(t)};const P=(n,t)=>{const r=o(c(n),t),e=new s(`1e-${t+5}`),i=function*(n,t){const r=n.pow(2n).normalize();let e=r,i=2n,o=e.div(i).add(1n).trunc(t+5),s=3n;for(;;){e=e.mul(r),i*=s*(s+1n),s+=2n;const n=e.div(i);o=o.add(n).trunc(t+5),yield{term:n,sum:o}}}(r,t);for(const{term:n,sum:r}of i)if(n.abs().lt(e))return r.trunc(t);return c(0)};n.ExactNumber=c,n.PI=N,n.acos=(n,t)=>{const r=o(c(n),t);if(r.isZero())return c(N(t)).div(2n).trunc(t);if(r.isOne())return c(0);if(r.abs().isOne())return N(t);if(r.abs().eq("1/2")){const n=c(N(t)).div(3n);return-1===r.sign()?n.mul(2n).trunc(t):n.trunc(t)}if(r.gt(1n)||r.lt(-1n))throw new Error("Out of range");return c(N(t+10)).div(2n).sub(R(r,t+10)).trunc(t)},n.acosh=(n,t)=>{const r=o(c(n),t);if(r.isOne())return c(0);if(r.lt(1n))throw new Error("Out of range");const e=l(r.pow(2).sub(1n),t+5);return g(r.add(e),t+5).trunc(t)},n.asin=R,n.asinh=(n,t)=>{const r=o(c(n),t);if(r.isZero())return c(0);const e=l(r.pow(2).add(1n),t+5);return g(r.add(e),t+5).trunc(t)},n.atan=O,n.atanh=(n,t)=>{const r=o(c(n),t);if(r.abs().gte(1n))throw new Error("Out of range");if(r.isZero())return c(0);const e=g(r.add(1n).div(r.neg().add(1n)),t+5);return c(e).div(2n).trunc(t)},n.cbrt=(n,t)=>h(3,n,t),n.cos=T,n.cosh=P,n.exp=p,n.log=g,n.log10=(n,t)=>new s(g(n,t+10)).div(b.get(t+10)).trunc(t),n.log2=(n,t)=>new s(g(n,t+10)).div(w.get(t+10)).trunc(t),n.logn=(n,t,r)=>{if(!Number.isSafeInteger(n)||n<2)throw new Error("Invalid parameter for N");const e=g(t,r+10),i=g(n,r+10);return new s(e).div(i).trunc(r)},n.nthroot=h,n.pow=(n,t,r)=>{const e=o(c(n),r),i=o(c(t),r);if(i.isInteger()&&Number.isSafeInteger(i.toNumber()))return e.pow(i).trunc(r);if(-1===e.sign()&&!i.isInteger())throw new Error("Complex numbers are not supported");const s=g(e,r+5),u=i.mul(s);return p(u,r+5).trunc(r)},n.sin=(n,t)=>{const r=new s(N(t+10)),e=o(c(n),t+5);return T(r.div(2n).sub(e),t+5).trunc(t)},n.sinh=(n,t)=>{const r=o(c(n),t),e=new s(`1e-${t+5}`),i=function*(n,t){let r=n,e=1n;const i=n.pow(2n).normalize();let o=n.trunc(t+5),s=2n;for(;;){r=r.mul(i),e*=s*(s+1n),s+=2n;const n=r.div(e);o=o.add(n).trunc(t+5),yield{term:n,sum:o}}}(r,t);for(const{term:n,sum:r}of i)if(n.abs().lt(e))return r.trunc(t);return c(0)},n.sqrt=l,n.tan=(n,t)=>{const r=o(c(n),t+5),{quadrantDegrees:e,quadrant:i,subHalfPiAngle:s}=I(r,t+5),u=1===i||3===i;if(e.isZero())return v("0",u,t);if(e.eq(30n))return v(c(1n).div(l(3n,t+5)),u,t);if(e.eq(45n))return v("1",u,t);if(e.eq(60n))return v(l(3n,t+5),u,t);if(e.eq(90n))throw new Error("Out of range");const a=c(T(s.mul(2n),t+5)),m=c(1n).sub(a).div(c(1n).add(a)).round(t+5),d=l(m,t+5).trunc(t);return u?d:d.neg()},n.tanh=(n,t)=>{const r=o(c(n),t);if(r.isZero())return c(0);const e=P(r,t+10).abs();return l(e.pow(2).sub(1),t+10).div(e).mul(r.sign()).trunc(t)},n.trimTrailingZeros=e,Object.defineProperty(n,"__esModule",{value:!0})}));
!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t="undefined"!=typeof globalThis?globalThis:t||self).exactnumber={})}(this,(function(t){"use strict";var r,e;t.RoundingMode=void 0,(r=t.RoundingMode||(t.RoundingMode={}))[r.NEAREST_TO_POSITIVE=201008]="NEAREST_TO_POSITIVE",r[r.NEAREST_TO_NEGATIVE=201009]="NEAREST_TO_NEGATIVE",r[r.NEAREST_TO_EVEN=201010]="NEAREST_TO_EVEN",r[r.NEAREST_TO_ZERO=201011]="NEAREST_TO_ZERO",r[r.NEAREST_AWAY_FROM_ZERO=201012]="NEAREST_AWAY_FROM_ZERO",r[r.TO_POSITIVE=201001]="TO_POSITIVE",r[r.TO_NEGATIVE=201002]="TO_NEGATIVE",r[r.TO_ZERO=201003]="TO_ZERO",r[r.AWAY_FROM_ZERO=201004]="AWAY_FROM_ZERO",t.ModType=void 0,(e=t.ModType||(t.ModType={})).TRUNCATED="T",e.FLOORED="F",e.EUCLIDEAN="E";const n=t=>{const r=t.indexOf(".");if(-1===r)return t;let e=t.length;for(;e>r&&"0"===t.charAt(e-1);)e--;const n=r===e-1?r:e;return 0===n?"0":t.slice(0,n)},i=(t,r,e,i)=>{let o=t.toString();if(0===r&&0===e)return o;const s=o.startsWith("-");if(s&&(o=o.slice(1)),r>=o.length&&(o="0".repeat(r-o.length+1)+o),r>0){const t=o.slice(0,-r),s=o.slice(-r),u=e<=r?s.slice(0,e):`${s}${"0".repeat(e-r)}`;0!==u.length?(o=`${t}.${u}`,i&&(o=n(o))):o=t}else e>0&&!i&&(o=`${o}.${"0".repeat(e)}`);return s?`-${o}`:o},o=(r,e)=>(r=r.normalize())instanceof f?r.round(e,t.RoundingMode.NEAREST_AWAY_FROM_ZERO):r,s=BigInt(0),u=BigInt(1),a=BigInt(2),c=BigInt(3),m=BigInt(4),d=BigInt(5),h=BigInt(10),l=BigInt(24);class f{constructor(t,r=0){if(this.type="fixed","bigint"==typeof t)this.number=t,this.decimalPos=r;else{const r=this.parseConstructorParameter(t);this.number=r.number,this.decimalPos=r.decimalPos}}parseConstructorParameter(t){if(t instanceof f)return{number:t.number,decimalPos:t.decimalPos};if(t instanceof g){if(!t.isInteger())throw new Error("Cannot create FixedNumber from non-integer Fraction");return{number:t.trunc().number,decimalPos:0}}if("number"==typeof t){if(!Number.isSafeInteger(t))throw new Error("The specified number cannot be exactly represented as an integer. Please provide a string instead.");return{number:BigInt(t),decimalPos:0}}if("string"==typeof t){if(0===(t=t.trim()).length)throw new Error("Empty string is not allowed");const r=t.match(/^(-?[0-9]*)(?:\.([0-9]*))?(?:[eE]([+-]?[0-9]+))?$/);if(!r)throw new Error(`Cannot parse number "${t}"`);let e=0,n=r[1]??"0";if(void 0!==r[2]&&(n+=r[2],e+=r[2].length),void 0!==r[3]){const t=Number(r[3]);t>0?n+="0".repeat(t):e-=t}return{number:BigInt(n),decimalPos:e}}throw new Error("Unsupported parameter!")}scaleNumber(t,r){const e=Math.max(this.decimalPos,r);return{a:e===this.decimalPos?this.number:this.number*h**BigInt(e-this.decimalPos),b:e===r?t:t*h**BigInt(e-r),decimalPos:e}}add(t){const r=w(t);if(r instanceof g)return r.add(this);const e=r,{a:n,b:i,decimalPos:o}=this.scaleNumber(e.number,e.decimalPos);return new f(n+i,o)}sub(t){const r=w(t);return this.add(r.neg())}mul(t){const r=w(t);if(r instanceof g)return r.mul(this);const e=r,n=this.number*e.number;return new f(n,this.decimalPos+e.decimalPos)}pow(t){const r=w(t).toNumber();if(!Number.isSafeInteger(r))throw new Error("Unsupported parameter");const e=Math.abs(r),n=new f(this.number**BigInt(e),this.decimalPos*e);return r<0?n.inv():n}powm(t,r,e){let n=w(t).toNumber();if(!Number.isSafeInteger(n))throw new Error("Unsupported parameter");const i=w(r);let o=this,s=new f(u);for(;0!==n;)n%2!=0&&(s=s.mul(o).mod(i,e)),o=o.pow(a).mod(i,e),n=Math.floor(n/2);return s}div(t){return this.convertToFraction().div(t)}divToInt(t){const r=w(t);if(r instanceof g)return this.convertToFraction().divToInt(r);const e=r,{a:n,b:i}=this.scaleNumber(e.number,e.decimalPos);return new f(n/i)}mod(r,e=t.ModType.TRUNCATED){const n=w(r);if(n instanceof g)return this.convertToFraction().mod(n);const i=n,{a:o,b:u,decimalPos:a}=this.scaleNumber(i.number,i.decimalPos),c=o%u,m=new f(c,a);if(e===t.ModType.TRUNCATED)return m;if(e===t.ModType.FLOORED)return Number(o<s)^Number(u<s)?m.add(u):m;if(e===t.ModType.EUCLIDEAN)return c<s?m.add(u<s?-u:u):m;throw new Error("Invalid ModType")}abs(){return new f(this.number<s?-this.number:this.number,this.decimalPos)}neg(){return this.mul(-u)}inv(){return this.convertToFraction().inv()}floor(r){return 0===this.decimalPos?this:this.round(r,t.RoundingMode.TO_NEGATIVE)}ceil(r){return 0===this.decimalPos?this:this.round(r,t.RoundingMode.TO_POSITIVE)}trunc(r){return 0===this.decimalPos?this:this.round(r,t.RoundingMode.TO_ZERO)}isTieStr(t){if("5"!==t[0])return!1;for(let r=1;r<t.length;r++)if("0"!==t[r])return!1;return!0}_round(r,e){const n=this.decimalPos-r;if(n<=0)return this;const i=h**BigInt(n),o=this.number/i;if(e===t.RoundingMode.TO_ZERO)return new f(o,r);const c=this.number%i;if(c===s)return new f(o,r);if(e===t.RoundingMode.AWAY_FROM_ZERO){const t=this.number<s?o-u:o+u;return new f(t,r)}if(e===t.RoundingMode.TO_POSITIVE){const t=this.number<s?o:o+u;return new f(t,r)}if(e===t.RoundingMode.TO_NEGATIVE){const t=this.number>=s?o:o-u;return new f(t,r)}if(![void 0,t.RoundingMode.NEAREST_TO_ZERO,t.RoundingMode.NEAREST_AWAY_FROM_ZERO,t.RoundingMode.NEAREST_TO_POSITIVE,t.RoundingMode.NEAREST_TO_NEGATIVE,t.RoundingMode.NEAREST_TO_EVEN].includes(e))throw new Error("Invalid rounding mode. Use the predefined values from the RoundingMode enum.");let m=(c<s?-c:c).toString();if(m.length<n&&(m="0"),this.isTieStr(m)){if(e===t.RoundingMode.NEAREST_TO_ZERO)return new f(o,r);if(e===t.RoundingMode.NEAREST_AWAY_FROM_ZERO){const t=this.number<s?o-u:o+u;return new f(t,r)}if(void 0===e||e===t.RoundingMode.NEAREST_TO_POSITIVE){const t=this.number<s?o:o+u;return new f(t,r)}if(e===t.RoundingMode.NEAREST_TO_NEGATIVE){const t=this.number>=s?o:o-u;return new f(t,r)}if(e===t.RoundingMode.NEAREST_TO_EVEN){if(o%a===s)return new f(o,r);return new f(o<s?o-u:o+u,r)}}if(Number(m[0])<5)return new f(o,r);const d=this.number<s?o-u:o+u;return new f(d,r)}round(t,r){if(t=void 0===t?0:t,!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for decimals");return this._round(t,r).normalize()}_incExponent(t){if(0===t)return this;let r=this.number,e=this.decimalPos;if(t<0)e-=t;else{const n=Math.min(t,this.decimalPos);e-=n;const i=t-n;i>0&&(r*=h**BigInt(i))}return new f(r,e)}countDigits(){if(this.number===s)return 1;let t=0,r=this.number<s?-this.number:this.number;for(;r>s;)r/=h,t++;return t}toSubZeroNum(){const t=this.countDigits();return{subZeroNum:new f(this.number,t),exponentDiff:t-this.decimalPos}}roundToDigits(t,r){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid value for digits");const{subZeroNum:e,exponentDiff:n}=this.toSubZeroNum();let i=e.round(t,r);return i=i._incExponent(n),i}intPart(){return this.trunc()}fracPart(){return this.sub(this.trunc())}sign(){return this.number<s?-1:1}bitwiseAnd(t){if(t=b(t),!this.isInteger()||-1===this.sign()||!t.isInteger()||-1===t.sign())throw new Error("Only positive integers are supported");t instanceof g&&(t=t.trunc());const r=a**l;let e=this.normalize().number,n=t.trunc().normalize().number,i=s,o=u;for(;e>s&&n>s;){const t=BigInt.asUintN(24,e),s=BigInt.asUintN(24,n);i+=BigInt(Number(t)&Number(s))*o,o*=r,e/=r,n/=r}return new f(i)}bitwiseOr(t){if(t=b(t),!this.isInteger()||-1===this.sign()||!t.isInteger()||-1===t.sign())throw new Error("Only positive integers are supported");t instanceof g&&(t=t.trunc());const r=a**l;let e=this.normalize().number,n=t.trunc().normalize().number,i=s,o=u;for(;e>s||n>s;){const t=BigInt.asUintN(24,e),s=BigInt.asUintN(24,n);i+=BigInt(Number(t)|Number(s))*o,o*=r,e/=r,n/=r}return new f(i)}bitwiseXor(t){if(t=b(t),!this.isInteger()||-1===this.sign()||!t.isInteger()||-1===t.sign())throw new Error("Only positive integers are supported");t instanceof g&&(t=t.trunc());const r=a**l;let e=this.normalize().number,n=t.trunc().normalize().number,i=s,o=u;for(;e>s||n>s;){const t=BigInt.asUintN(24,e),s=BigInt.asUintN(24,n);i+=BigInt(Number(t)^Number(s))*o,o*=r,e/=r,n/=r}return new f(i)}shiftLeft(t){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for bitCount");const r=a**BigInt(t);return this.mul(r)}shiftRight(t){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for bitCount");const r=a**BigInt(t);return new f(this.normalize().number/r)}cmp(t){const r=w(t);if(r instanceof g)return-r.cmp(this);const e=r,{a:n,b:i}=this.scaleNumber(e.number,e.decimalPos);return n===i?0:n>i?1:-1}eq(t){return 0===this.cmp(t)}lt(t){return-1===this.cmp(t)}lte(t){return this.cmp(t)<=0}gt(t){return 1===this.cmp(t)}gte(t){return this.cmp(t)>=0}clamp(t,r){const e=b(t),n=b(r);if(e.gt(n))throw new Error("Min parameter has to be smaller than max");return this.lt(e)?e:this.gt(n)?n:this}isZero(){return this.number===s}isOne(){if(0===this.decimalPos)return this.number===u;const t=h**BigInt(this.decimalPos),r=this.number/t;return r===u&&r*t===this.number}isInteger(){return 0===this.decimalPos||this.number%h**BigInt(this.decimalPos)===s}serialize(){return[this.number,this.decimalPos]}getFractionParts(t=!0){return this.convertToFraction().getFractionParts(t)}normalize(){if(0===this.decimalPos)return this;let t=this.decimalPos,r=this.number;for(;t>0&&r%h===s;)t--,r/=h;return new f(r,t)}convertToFraction(){if(0===this.decimalPos)return new g(this.number,u);const t=h**BigInt(this.decimalPos);return new g(this.number,t)}toNumber(){return Number(this.toPrecision(20))}toFixed(r,e=t.RoundingMode.TO_ZERO,n=!1){if(!Number.isSafeInteger(r)||r<0)throw new Error("Invalid parameter");const o=this._round(r,e);return i(o.number,o.decimalPos,r,n)}toExponential(r,e=t.RoundingMode.TO_ZERO,i=!1){if(!Number.isSafeInteger(r)||r<0)throw new Error("Invalid parameter");const o=this.roundToDigits(r+1,e).normalize(),s=-1===o.sign(),u=o.abs(),a=u.number.toString(),c=a.length<=r?`${a}${"0".repeat(r-a.length+1)}`:a.slice(0,r+1);let m=c;c.length>1&&(m=`${c.slice(0,1)}.${c.slice(1)}`,i&&(m=n(m)));const d=u.decimalPos,h=a.length-1-d;return`${s?"-":""}${m}e${h>=0?"+":""}${h}`}toBase(t,r){if(!Number.isSafeInteger(t)||t<2||t>16)throw new Error("Invalid radix");if(void 0!==r&&(!Number.isSafeInteger(r)||r<0))throw new Error("Invalid parameter");const e=this.normalize();if(0===e.decimalPos)return e.number.toString(t);const n=void 0===r?Number.MAX_SAFE_INTEGER:r;let i=e.intPart(),o=e.sub(i);const s=-1===e.sign();s&&(i=i.neg(),o=o.neg());const u=new Map;let a=[];for(;!o.isZero();){const r=o.mul(t),e=r.toString(),i=u.get(e);if(void 0!==i){a=[...a.slice(0,i-1),"(",...a.slice(i-1),")"];break}if(a.length===n)break;const s=Math.abs(r.intPart().toNumber());a.push(s.toString(t)),o=r.fracPart(),u.set(e,a.length)}const c=a.join("");return`${s?"-":""}${i.number.toString(t)}${a.length?".":""}${c}`}toFraction(){return this.convertToFraction().toFraction()}toString(t,r){if(void 0===t||10===t){const t=void 0!==r?this.trunc(r):this;return i(t.number,t.decimalPos,t.decimalPos,!0)}return this.toBase(t,r)}toPrecision(r,e=t.RoundingMode.TO_ZERO,o=!1){if(!Number.isSafeInteger(r)||r<1)throw new Error("Invalid parameter");const s=this.roundToDigits(r,e),{subZeroNum:u,exponentDiff:a}=s.toSubZeroNum(),c=-1===u.sign();let m=i(u.number,u.decimalPos,u.decimalPos,!1);m=m.slice(c?3:2),m=m.slice(0,Math.max(r,a));const d=m.slice(0,Math.max(0,a)),h=m.slice(Math.max(0,a)),l=Math.max(0,r-d.length-h.length),f="0".repeat(a<0?-a:0);let g=d||"0";if(h.length+f.length+l>0){g+=`.${f}${h}${"0".repeat(l)}`,o&&(g=n(g))}return c?`-${g}`:g}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}class g{constructor(t,r){if(this.type="fraction","bigint"==typeof t&&"bigint"==typeof r)this.numerator=t,this.denominator=r;else{const e=this.parseParameter(t),n=this.parseParameter(r),i=e.div(n),o=i instanceof f?i.convertToFraction():i;this.numerator=o.numerator,this.denominator=o.denominator}if(this.denominator===s)throw new Error("Division by zero")}parseRepeatingDecimal(t){if(!t.includes("("))return new f(t).convertToFraction();const r=(t=t.trim()).match(/^(-?[0-9]*)\.([0-9]+)?\(([0-9]+)\)(?:[eE]([+-]?[0-9]+))?$/);if(!r)throw new Error(`Cannot parse string "${t}"`);const e="-"===r[1]?"-0":r[1],n=r[2]??"",i=r[3],o=r[4],s=BigInt(e+n+i)-BigInt(e+n),u=BigInt("9".repeat(i.length)+"0".repeat(n.length)),a=new g(s,u);if(void 0!==o){const t=o.startsWith("-"),r=h**BigInt(t?o.slice(1):o);return t?a.div(r).normalize():a.mul(r).normalize()}return a.simplify()}parseParameter(t){if(t instanceof g)return t;if(t instanceof f)return t.convertToFraction();if("number"==typeof t){if(!Number.isSafeInteger(t))throw new Error("Floating point values as numbers are unsafe. Please provide them as a string.");return new g(BigInt(t),u)}if("bigint"==typeof t)return new g(t,u);if("string"==typeof t){const r=t.split("/");if(r.length>2)throw new Error(`Cannot parse string '${t}'`);const e=this.parseRepeatingDecimal(r[0]),n=r[1]?this.parseRepeatingDecimal(r[1]):new g(u,u);return e.div(n).convertToFraction()}throw new Error("Unsupported parameter!")}add(t){const{numerator:r,denominator:e}=this.parseParameter(t);return this.denominator===e?new g(this.numerator+r,this.denominator):new g(this.numerator*e+r*this.denominator,e*this.denominator)}sub(t){const{numerator:r,denominator:e}=this.parseParameter(t);return this.add(new g(-r,e))}mul(t){const{numerator:r,denominator:e}=this.parseParameter(t);return new g(this.numerator*r,this.denominator*e)}div(t){const{numerator:r,denominator:e}=this.parseParameter(t);return this.mul(new g(e,r))}divToInt(t){return this.div(t).trunc()}mod(r,e=t.ModType.TRUNCATED){const n=this.parseParameter(r),i=n.denominator*this.numerator%(n.numerator*this.denominator),o=this.denominator*n.denominator,s=new g(i,o);if(e===t.ModType.TRUNCATED)return s;if(e===t.ModType.FLOORED)return Number(-1===this.sign())^Number(-1===n.sign())?s.add(n):s;if(e===t.ModType.EUCLIDEAN)return-1===s.sign()?s.add(-1===n.sign()?n.neg():n):s;throw new Error("Invalid ModType")}pow(t){const r=this.parseParameter(t);if(!r.isInteger())throw new Error("Unsupported parameter");const e=r.numerator/r.denominator,n=e<s?-e:e,i=new g(this.numerator**n,this.denominator**n);return e<s?i.inv():i}powm(t,r,e){const n=this.parseParameter(t);if(!n.isInteger())throw new Error("Unsupported parameter");let i=n.toNumber();const o=this.parseParameter(r);let s=this,c=new g(u,u);for(;0!==i;)i%2!=0&&(c=c.mul(s).mod(o,e)),s=s.pow(a).mod(o,e),i=Math.floor(i/2);return c}inv(){return new g(this.denominator,this.numerator)}floor(r){return this.denominator===u?new f(this.numerator):this.round(r,t.RoundingMode.TO_NEGATIVE)}ceil(r){return this.denominator===u?new f(this.numerator):this.round(r,t.RoundingMode.TO_POSITIVE)}trunc(r){return this.denominator===u?new f(this.numerator):this.round(r,t.RoundingMode.TO_ZERO)}round(t,r){if(t=void 0===t?0:t,!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for decimals");const e=this.toFixedNumber(t+1);if(this.sub(e).isZero())return e.round(t,r);return new f(`${e.toFixed(t+1)}1`).round(t,r)}roundToDigits(t,r){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid value for digits");if(this.isZero())return new f(s);let e=this.abs(),n=0;for(;e.gte(u);)e=e.div(h),n++;const i=new g(u,h);for(;e.lt(i);)e=e.mul(h),n--;let o=e.round(t,r);return o=o._incExponent(n),-1===this.sign()?o.neg():o}gcd(t,r){let e=t<s?-t:t,n=r<s?-r:r;if(n>e){const t=e;e=n,n=t}for(;;){if(n===s)return e;if(e%=n,e===s)return n;n%=e}}simplify(){let{numerator:t,denominator:r}=this;const e=this.gcd(t,r);return e>u&&(t/=e,r/=e),r<s&&(t=-t,r=-r),new g(t,r)}normalize(){const{numerator:r,denominator:e}=this.simplify();if(e===u)return new f(r,0);const n=new g(r,e),{cycleLen:i,cycleStart:o}=n.getDecimalFormat(0);return 0!==i?n:n.round(o,t.RoundingMode.TO_ZERO)}getFractionParts(t=!0){const r=t?this.simplify():this;return{numerator:new f(r.numerator),denominator:new f(r.denominator)}}sign(){return(this.numerator<s?-1:1)*(this.denominator<s?-1:1)}abs(){return new g(this.numerator<s?-this.numerator:this.numerator,this.denominator<s?-this.denominator:this.denominator)}neg(){return this.mul(-u)}intPart(){return this.trunc()}fracPart(){return this.sub(this.trunc())}cmp(t){const r=this.parseParameter(t),e=this.denominator===r.denominator,n=e?this.numerator:this.numerator*r.denominator,i=e?r.numerator:r.numerator*this.denominator;return n===i?0:n>i?1:-1}eq(t){return 0===this.cmp(t)}lt(t){return-1===this.cmp(t)}lte(t){return this.cmp(t)<=0}gt(t){return 1===this.cmp(t)}gte(t){return this.cmp(t)>=0}clamp(t,r){const e=b(t),n=b(r);if(e.gt(n))throw new Error("Min parameter has to be smaller than max");return this.lt(e)?e:this.gt(n)?n:this}isZero(){return this.numerator===s}isOne(){return this.numerator===this.denominator}isInteger(){return this.numerator%this.denominator===s}serialize(){return[this.numerator,this.denominator]}toNumber(){return Number(this.toPrecision(20))}convertToFraction(){return this}getNumberForBitwiseOp(){if(!this.isInteger()||-1===this.sign())throw new Error("Only positive integers are supported");return this.intPart()}bitwiseAnd(t){return this.getNumberForBitwiseOp().bitwiseAnd(t)}bitwiseOr(t){return this.getNumberForBitwiseOp().bitwiseOr(t)}bitwiseXor(t){return this.getNumberForBitwiseOp().bitwiseXor(t)}shiftLeft(t){return this.getNumberForBitwiseOp().shiftLeft(t)}shiftRight(t){return this.getNumberForBitwiseOp().shiftRight(t)}getDecimalFormat(t){t=void 0===t?Number.MAX_SAFE_INTEGER:t;let r=this.denominator<s?-this.denominator:this.denominator,e=0;for(;r%a===s;)r/=a,e++;let n=0;for(;r%d===s;)r/=d,n++;const i=Math.max(e,n);if(r===u)return{cycleLen:0,cycleStart:i};const o=Math.max(1,t-i);let c=h%r,m=1;for(;c!==u;){if(m===o)return{cycleLen:null,cycleStart:i};c=c*h%r,m++}return{cycleLen:m,cycleStart:i}}toFixed(r,e=t.RoundingMode.TO_ZERO,n=!1){if(!Number.isSafeInteger(r)||r<0)throw new Error("Invalid parameter");return this.round(r,e).toFixed(r,t.RoundingMode.TO_ZERO,n)}toRepeatingParts(t){if(this.isZero())return["0","",""];const{cycleLen:r,cycleStart:e}=this.simplify().getDecimalFormat(t);if(null===r||0===r){const r=t??e,i=this.toFixed(r),o=n(i).split(".");return[o[0],o[1]??"",""]}const i=e+r,o=this.toFixed(i).split(".");return[o[0],o[1].slice(0,e),o[1].slice(e)]}toRepeatingDigits(t){const r=this.toRepeatingParts(t);let e=r[0];return(r[1]||r[2])&&(e+=`.${r[1]}`),r[2]&&(e+=`(${r[2]})`),e}toExponential(r,e=t.RoundingMode.TO_ZERO,n=!1){if(!Number.isSafeInteger(r)||r<0)throw new Error("Invalid parameters");return this.toFixedNumber(r).toExponential(r,e,n)}toFraction(){const{numerator:t,denominator:r}=this.getFractionParts(!0);return`${t.toString()}/${r.toString()}`}toFixedNumber(t){const r=this.numerator*h**BigInt(t);return new f(r/this.denominator,t)}toBase(t,r){if(!Number.isSafeInteger(t)||t<2||t>16)throw new Error("Invalid radix");if(void 0!==r&&(!Number.isSafeInteger(r)||r<0))throw new Error("Invalid parameter");if(10===t)return void 0===r?this.toRepeatingDigits(r):n(this.toFixed(r));const e=this.normalize(),i=void 0===r?Number.MAX_SAFE_INTEGER:r+1;let o=e.intPart(),s=e.sub(o);const u=-1===e.sign();u&&(o=o.neg(),s=s.neg());const a=new Map;let c=[];for(;!s.isZero()&&c.length!==i;){const r=s.mul(t),e=r.normalize().toFraction(),n=a.get(e);if(void 0!==n){c=[...c.slice(0,n-1),"(",...c.slice(n-1),")"];break}const i=Math.abs(r.intPart().toNumber());c.push(i.toString(t)),s=r.fracPart(),a.set(e,c.length)}c.length===i&&c.pop();const m=c.join("");return`${u?"-":""}${o.toString(t)}${c.length?".":""}${m}`}toString(t,r){return void 0===t||10===t?this.toRepeatingDigits(r):this.toBase(t,r)}toPrecision(r,e=t.RoundingMode.TO_ZERO,n=!1){if(!Number.isSafeInteger(r)||r<1)throw new Error("Invalid parameter");return this.roundToDigits(r,e).toPrecision(r,t.RoundingMode.TO_ZERO,n)}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}function w(t){if(t instanceof f||t instanceof g)return t;if("bigint"==typeof t)return new f(t);if("number"==typeof t){if(!Number.isSafeInteger(t))throw new Error("Floating point values as numbers are unsafe. Please provide them as a string.");return new f(t)}if("string"==typeof t)return t.includes("/")||t.includes("(")?new g(t,u):new f(t);throw new Error("Unsupported parameter type")}const b=(t,r)=>{if(void 0===t)throw new Error("First parameter cannot be undefined");const e=w(t);if(void 0===r)return e;const n=w(r);return new g(e,u).div(new g(n,u))};b.min=(...t)=>{if(0===t.length)throw new Error("Got empty array");let r=b(t[0]);for(let e=1;e<t.length;e++){const n=b(t[e]);n.lt(r)&&(r=n)}return r},b.max=(...t)=>{if(0===t.length)throw new Error("Got empty array");let r=b(t[0]);for(let e=1;e<t.length;e++){const n=b(t[e]);n.gt(r)&&(r=n)}return r};const p=(t,r)=>{let e=s;for(let n=0;n<t.length;n++){const i=t.charAt(n),o=parseInt(i,r);if(Number.isNaN(o))throw new Error(`Invalid digit "${i}"`);e*=BigInt(r),e+=BigInt(o)}return e};b.fromBase=(t,r)=>{if("string"!=typeof t)throw new Error("First parameter must be string");if(!Number.isSafeInteger(r)||r<2||r>16)throw new Error("Invalid radix");if(10===r)return b(t);if(0===(t=t.trim()).length)throw new Error("Empty string is not allowed");const e=t.startsWith("-");e&&(t=t.slice(1));const n=t.match(/^([0-9a-f]*)(?:\.([0-9a-f]*)(?:\(([0-9a-f]+)\))?)?$/i);if(!n)throw new Error(`Cannot parse number "${t}"`);const i=n[1]??"",o=n[2]??"",s=n[3]??"";if(s.length>0){const t=p(`${i}${o}${s}`,r)-p(`${i}${o}`,r),n=p((r-1).toString(r).repeat(s.length)+"0".repeat(o.length),r),u=new g(t,n).normalize();return e?u.neg():u}const a=p(i,r),c=p(o,r),m=new g(c,BigInt(r)**BigInt(o.length)),d=new g(a,u).add(m).normalize();return e?d.neg():d},b.range=function*(t,r,e){const n=b(r),i=b(e??1);let o=b(t);for(;o.lt(n);)yield o,o=o.add(i)},b.gcd=(t,r)=>{const e=b(t).abs(),n=b(r).abs();let i=n.gt(e)?n:e,o=i.eq(e)?n:e;for(;;){if(o.isZero())return i;if(i=i.mod(o),i.isZero())return o;o=o.mod(i)}},b.lcm=(t,r)=>{const e=b(t).abs(),n=b(r).abs(),i=e.mul(n);if(i.isZero())throw new Error("LCM of zero is undefined");const o=b.gcd(e,n);return i.div(o)};const E=(t,r,e)=>{const n=((t,r)=>{let e=r.toNumber();if(Number.isFinite(e)){const r=e<0;r&&(e=-e);let n=e**(1/t);return r&&(n=-n),n.toString()}const n=r.abs().toFixed(0).length,i=Math.ceil(n/t);return`${1===r.sign()?"":"-"}5e${i}`})(t,r);let i=new f("0"!==n?n:"1");const o=new g(t-1,t),s=new g(r,t),u=BigInt(t-1);let a=i.trunc(e+5);for(;i=o.mul(i).add(s.mul(i.pow(u).inv())),i=i.trunc(e+5),!i.isZero()&&!a.eq(i);)a=i;return i.trunc(e)},I=(t,r,e)=>{if(!Number.isSafeInteger(t))throw new Error("Integer is expected for N");if(t<0)throw new Error("Negative N is not supported");if(0===t)throw new Error("N cannot be zero");const n=o(b(r),e);if(1===t)return n.trunc(e);if(t%2==0&&-1===n.sign())throw new Error("Complex numbers are not supported");if(n.isZero())return new f(s).trunc(e);if(n.isOne())return new f(u).trunc(e);return E(t,n,e)},N=(t,r)=>I(2,t,r);class v{constructor(t,r){this.cachedDecimals=0,this.fn=t,this.max=r}get(t){if(t<=this.cachedDecimals)return this.cache.trunc(t);const r=new f(this.fn(t)),e=Math.min(this.max,t);return this.cachedDecimals!==e&&(this.cache=r.trunc(e),this.cachedDecimals=e),r}}const T=(t,r)=>{let e=o(b(t),r);if(e.isOne())return new f(0).trunc(r);if(e.lte(0))throw new Error("Invalid parameter");let n=0;const i=b("0.1");for(;e.sub(u).abs().gt(i);)e=new f(N(e,r+10)),n++;const c=function*(t,r){const e=t.pow(a).normalize();let n=t,i=u,o=b(t);for(;;){n=n.mul(e),i+=a;const t=n.div(i).trunc(r+10);o=o.add(t),yield{term:t,sum:o}}}(e.sub(u).div(e.add(u)),r);for(const{term:t,sum:e}of c)if(t.isZero()){return e.mul(a**BigInt(n+1)).trunc(r)}return b(s)},O=new v((t=>T(a,t)),200),R=new v((t=>T(h,t)),200);const P=(t,r)=>{const e=o(b(t),r),n=b(`1e-${r+5}`),i=function*(t,r){let e=t.add(1),n=BigInt(6),i=m;const o=t.pow(a);let s=o;for(;;){const c=s.mul(t.add(i-u)).div(n);n*=i*(i+u),i+=a,s=s.mul(o),e=e.add(c).trunc(r+5),yield{term:c,sum:e}}}(e,r);for(const{term:t,sum:e}of i)if(t.abs().lt(n))return e.trunc(r);return b(s)},_=new v((t=>{if(0===t)return b(c);let r=u,e=c*h**BigInt(t+20),n=e;for(;e!==s;)e=e*r/((r+u)*m),r+=a,n+=e/r;return b(`3.${n.toString().slice(1,t+1)}`)}),1e3),S=t=>0===t?b(c):_.get(t).trunc(t),M=(r,e)=>{let n=r.round(e+5,t.RoundingMode.NEAREST_AWAY_FROM_ZERO);const i=S(e+5),o=((t,r,e)=>{const n=Math.max(3,e),i=t.trunc(n),o=i.div(r).round();return r.mul(o).trunc(n).eq(i)?o:null})(n,i.div(12),e);if(null!==o)return(t=>{let r=t.mod(l).toNumber();r<0&&(r+=24);const e=Math.floor(r/6)+1;let n=15*r;return 4===e?n=360-n:3===e?n-=180:2===e&&(n=180-n),{specialCaseDeg:n,quadrant:e,subHalfPiAngle:null}})(o);const s=i.mul(a);n=n.mod(s),-1===n.sign()&&(n=n.add(s));const u=n.mul(a).div(i).floor().toNumber()+1;let c=n;return 4===u?c=s.sub(c):3===u?c=c.sub(i):2===u&&(c=i.sub(c)),{specialCaseDeg:null,quadrant:u,subHalfPiAngle:c}};const A=(t,r,e)=>{let n=b(t);return r&&(n=n.neg()),n.trunc(e)},y=(r,e)=>{const n=e+10,i=o(b(r),e+5),{specialCaseDeg:m,subHalfPiAngle:d,quadrant:h}=M(i,e),l=2===h||3===h;if(null!==m){if(0===m)return A(u,l,e);if(30===m)return A(b(N(c,e+5)).div(a),l,e);if(45===m)return A(b(N(a,e+5)).div(a),l,e);if(60===m)return A("0.5",l,e);if(90===m)return A(s,l,e);throw new Error}const f=b(`1e-${n}`),g=function*(r,e){const n=r.round(e+10,t.RoundingMode.NEAREST_AWAY_FROM_ZERO).pow(a);let i=n,o=a,s=b(u).sub(i.div(o).trunc(e+10)),m=c;for(;;){o*=m*(m+u),m+=a;const t=m*(m+u);m+=a,i=i.mul(n),o*=t;let r=i.mul(t);i=i.mul(n),r=r.sub(i);const c=r.div(o).trunc(e+10);s=s.add(c),yield{term:c,sum:s}}}(d,e);for(const{term:t,sum:r}of g)if(t.lt(f))return A(r,l,e);return b(0)};const F=(t,r)=>{let e=o(b(t),r);if(e.isZero())return b(0);if(e.abs().isOne())return b(S(r)).div(4*e.sign()).trunc(r);let n=0;const i=b("0.42");for(;e.abs().gt(i);){const t=b(N(e.pow(a).add(u),r+10));e=e.div(t.add(u)),n++}const s=b(`1e-${r+10}`),m=function*(t,r){const e=t.pow(a).normalize(),n=e.pow(a).normalize();let i=c,o=t.sub(t.mul(e).div(i)),s=t.mul(n);for(;;){i+=a;const t=i+a,u=s.mul(e.mul(-i).add(t)).div(i*t);i=t,s=s.mul(n),o=o.add(u).trunc(r+10),yield{term:u,sum:o}}}(e,r);for(const{term:t,sum:e}of m)if(t.abs().lt(s)){return e.mul(a**BigInt(n)).trunc(r)}return b(0)},B=(t,r)=>{const e=o(b(t),r);if(e.isZero())return b(s);if(e.abs().isOne())return b(S(r)).mul(e.sign()).div(a).trunc(r);if(e.abs().eq("1/2"))return b(S(r)).mul(e.sign()).div(6).trunc(r);if(e.gt(u)||e.lt(-u))throw new Error("Out of range");const n=b(N(e.pow(a).neg().add(u),r+10));return b(F(e.div(n.add(u)),r+10)).mul(a).trunc(r)};const Z=(t,r)=>{const e=o(b(t),r),n=new f(`1e-${r+5}`),i=function*(t,r){const e=t.pow(a).normalize();let n=e,i=a,o=n.div(i).add(u).trunc(r+5),s=c;for(;;){n=n.mul(e),i*=s*(s+u),s+=a;const t=n.div(i);o=o.add(t).trunc(r+5),yield{term:t,sum:o}}}(e,r);for(const{term:t,sum:e}of i)if(t.abs().lt(n))return e.trunc(r);return b(s)};t.ExactNumber=b,t.PI=S,t.acos=(t,r)=>{const e=o(b(t),r);if(e.isZero())return b(S(r)).div(a).trunc(r);if(e.isOne())return b(s);if(e.abs().isOne())return S(r);if(e.abs().eq("1/2")){const t=b(S(r)).div(c);return-1===e.sign()?t.mul(a).trunc(r):t.trunc(r)}if(e.gt(u)||e.lt(-u))throw new Error("Out of range");return b(S(r+10)).div(a).sub(B(e,r+10)).trunc(r)},t.acosh=(t,r)=>{const e=o(b(t),r);if(e.isOne())return b(s);if(e.lt(u))throw new Error("Out of range");const n=N(e.pow(a).sub(u),r+5);return T(e.add(n),r+5).trunc(r)},t.asin=B,t.asinh=(t,r)=>{const e=o(b(t),r);if(e.isZero())return b(s);const n=N(e.pow(a).add(u),r+5);return T(e.add(n),r+5).trunc(r)},t.atan=F,t.atanh=(t,r)=>{const e=o(b(t),r);if(e.abs().gte(u))throw new Error("Out of range");if(e.isZero())return b(s);const n=T(e.add(u).div(e.neg().add(u)),r+5);return b(n).div(a).trunc(r)},t.cbrt=(t,r)=>I(3,t,r),t.cos=y,t.cosh=Z,t.exp=P,t.log=T,t.log10=(t,r)=>new f(T(t,r+10)).div(R.get(r+10)).trunc(r),t.log2=(t,r)=>new f(T(t,r+10)).div(O.get(r+10)).trunc(r),t.logn=(t,r,e)=>{if(!Number.isSafeInteger(t)||t<2)throw new Error("Invalid parameter for N");const n=T(r,e+10),i=T(t,e+10);return new f(n).div(i).trunc(e)},t.nthroot=I,t.pow=(t,r,e)=>{const n=o(b(t),e),i=o(b(r),e);if(i.isInteger()&&Number.isSafeInteger(i.toNumber()))return n.pow(i).trunc(e);if(-1===n.sign()&&!i.isInteger())throw new Error("Complex numbers are not supported");const s=T(n,e+5),u=i.mul(s);return P(u,e+5).trunc(e)},t.sin=(t,r)=>{const e=new f(S(r+10)),n=o(b(t),r+5);return y(e.div(a).sub(n),r+5).trunc(r)},t.sinh=(t,r)=>{const e=o(b(t),r),n=new f(`1e-${r+5}`),i=function*(t,r){let e=t,n=u;const i=t.pow(a).normalize();let o=t.trunc(r+5),s=a;for(;;){e=e.mul(i),n*=s*(s+u),s+=a;const t=e.div(n);o=o.add(t).trunc(r+5),yield{term:t,sum:o}}}(e,r);for(const{term:t,sum:e}of i)if(t.abs().lt(n))return e.trunc(r);return b(s)},t.sqrt=N,t.tan=(t,r)=>{const e=o(b(t),r+5),{specialCaseDeg:n,quadrant:i,subHalfPiAngle:s}=M(e,r),m=1===i||3===i;if(null!==n){if(0===n)return A("0",m,r);if(30===n)return A(b(u).div(N(c,r+5)),m,r);if(4===n)return A("1",m,r);if(60===n)return A(N(c,r+5),m,r);if(90===n)throw new Error("Out of range");throw new Error}const d=b(y(s.mul(a),r+5)),h=b(u).sub(d).div(b(u).add(d)).round(r+5),l=N(h,r+5).trunc(r);return m?l:l.neg()},t.tanh=(t,r)=>{const e=o(b(t),r);if(e.isZero())return b(s);const n=Z(e,r+10).abs();return N(n.pow(a).sub(u),r+10).div(n).mul(e.sign()).trunc(r)}}));
import { ExactNumberType } from '../types';
export declare const PI: (decimals: number) => ExactNumberType;
declare type EvaluationRes = {
specialCaseDeg: number | null;
quadrant: number;
subHalfPiAngle: ExactNumberType | null;
};
export declare const evaluateAngle: (x: ExactNumberType, decimals: number) => EvaluationRes;
export declare const cos: (_angle: number | bigint | string | ExactNumberType, decimals: number) => ExactNumberType;
export declare const sin: (angle: number | bigint | string | ExactNumberType, decimals: number) => ExactNumberType;
export declare const tan: (angle: number | bigint | string | ExactNumberType, decimals: number) => ExactNumberType;
export {};

@@ -14,2 +14,3 @@ import { Fraction } from './Fraction';

pow(x: number | bigint | string | ExactNumberType): ExactNumberType;
powm(_exp: number | bigint | string | ExactNumberType, _mod: number | bigint | string | ExactNumberType, modType?: ModType): FixedNumber;
div(x: number | bigint | string | ExactNumberType): ExactNumberType;

@@ -57,9 +58,9 @@ divToInt(x: number | bigint | string | ExactNumberType): ExactNumberType;

toNumber(): number;
toFixed(decimals: number, roundingMode?: RoundingMode): string;
toExponential(digits: number, roundingMode?: RoundingMode): string;
toFixed(decimals: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;
toExponential(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;
private toBase;
toFraction(): string;
toString(radix?: number, maxDigits?: number): string;
toPrecision(digits: number, roundingMode?: RoundingMode): string;
toPrecision(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;
valueOf(): number;
}

@@ -17,2 +17,3 @@ import { ExactNumberType, ModType, RoundingMode } from './types';

pow(x: number | bigint | string | ExactNumberType): ExactNumberType;
powm(_exp: number | bigint | string | ExactNumberType, _mod: number | bigint | string | ExactNumberType, modType?: ModType): ExactNumberType;
inv(): ExactNumberType;

@@ -56,6 +57,6 @@ floor(decimals?: number): FixedNumber;

private getDecimalFormat;
toFixed(decimals: number, roundingMode?: RoundingMode): string;
toFixed(decimals: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;
private toRepeatingParts;
toRepeatingDigits(maxDigits: number | undefined): string;
toExponential(digits: number, roundingMode?: RoundingMode): string;
toExponential(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;
toFraction(): string;

@@ -65,4 +66,4 @@ private toFixedNumber;

toString(radix?: number, maxDigits?: number): string;
toPrecision(digits: number, roundingMode?: RoundingMode): string;
toPrecision(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;
valueOf(): number;
}
export { ExactNumber } from './ExactNumber';
export { RoundingMode, ModType, ExactNumberType, ExactNumberParameter } from './types';
export { trimTrailingZeros } from './util';
export * from './approx';
export { nthroot, sqrt, cbrt } from './approx/roots';
export { pow, exp } from './approx/exponential';
export { log, logn, log10, log2 } from './approx/logarithm';
export { PI, sin, cos, tan } from './approx/trigonometry';
export { asin, acos, atan } from './approx/inverse_trigonometry';
export { sinh, cosh, tanh } from './approx/hyperbolic';
export { asinh, acosh, atanh } from './approx/inverse_hyperbolic';

@@ -38,3 +38,4 @@ import { Fraction } from './Fraction';

pow(x: number | bigint | string | ExactNumberType): ExactNumberType;
/** Returns b^e mod m (modular exponentiation) */
/** Returns modulo of this number exponentiated to the given value (modular exponentiation) */
powm(exponent: number | bigint | string | ExactNumberType, modulus: number | bigint | string | ExactNumberType, type?: ModType): ExactNumberType;
/** Returns the result of the division of this number by the given one. */

@@ -117,7 +118,7 @@ div(x: number | bigint | string | ExactNumberType): ExactNumberType;

*/
toFixed(decimals: number, roundingMode?: RoundingMode): string;
toFixed(decimals: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;
/** Returns a string representing the number in exponential notation.
* Defaults to RoundingMode.TO_ZERO
*/
toExponential(digits: number, roundingMode?: RoundingMode): string;
toExponential(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;
/** Returns a string representing the number using fixed-point notation, rounded to the specified number of significant digits.

@@ -127,3 +128,3 @@ * In contrary to JS Number.toPrecision(), this function never returns exponential notation.

*/
toPrecision(digits: number, roundingMode?: RoundingMode): string;
toPrecision(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;
/** Converts current value to a JavaScript Number */

@@ -130,0 +131,0 @@ toNumber(): number;

import { FixedNumber } from './FixedNumber';
import { ExactNumberType } from './types';
/** Trims trailing zeros from numbers in fixed-point format (1.23000 -> 1.23) */
export declare const trimTrailingZeros: (num: string) => string;
export declare const trimTrailingZerosFromFixed: (num: string) => string;
export declare const bigIntToStr: (num: bigint, inputDecimals: number, outputDecimals: number, trimZeros: boolean) => string;
export declare const limitDecimals: (x: ExactNumberType, decimals: number) => ExactNumberType | FixedNumber;
export declare const _0N: bigint;
export declare const _1N: bigint;
export declare const _2N: bigint;
export declare const _3N: bigint;
export declare const _4N: bigint;
export declare const _5N: bigint;
export declare const _10N: bigint;
export declare const _24N: bigint;
{
"name": "exactnumber",
"description": "Arbitrary-precision decimals. Enables making precise math calculations with rational numbers, without precision loss.",
"version": "0.11.0",
"description": "Arbitrary-precision decimals. Enables making math calculations with rational numbers, without precision loss.",
"version": "1.0.0",
"main": "dist/index.umd.js",

@@ -47,2 +47,3 @@ "module": "dist/index.esm.js",

},
"sideEffects": false,
"license": "MIT",

@@ -55,7 +56,6 @@ "devDependencies": {

"@types/estree": "^1.0.0",
"@types/jest": "^29.2.0",
"@types/node": "^18.11.3",
"@typescript-eslint/eslint-plugin": "^5.40.1",
"@typescript-eslint/parser": "^5.40.1",
"decimal.js": "^10.4.2",
"@types/jest": "^29.2.2",
"@types/node": "^18.11.9",
"@typescript-eslint/eslint-plugin": "^5.42.0",
"@typescript-eslint/parser": "^5.42.0",
"eslint": "^8.26.0",

@@ -65,13 +65,13 @@ "eslint-config-airbnb": "^19.0.4",

"eslint-config-prettier": "^8.5.0",
"jest": "29.2.1",
"jest": "^29.2.2",
"prettier": "^2.7.1",
"rollup": "^2.79.1",
"rollup": "^3.2.5",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-license": "^2.8.2",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-license": "^3.0.1",
"@rollup/plugin-terser": "^0.1.0",
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1",
"typescript": "^4.8.4",
"typedoc": "^0.23.17"
"typedoc": "^0.23.20"
}
}

@@ -10,48 +10,40 @@ # ExactNumber

## Quick comparision with JS floating-point arithmetic
```js
console.log(1 + 0.36);
// returns 1.3599999999999999
console.log(ExactNumber(1).add('0.36').toString());
// returns 1.36
console.log(1 / 3);
// returns 0.3333333333333333
console.log(ExactNumber(1).div(3).toString());
// returns 0.(3)
console.log((1 / 49) * 49);
// returns 0.9999999999999999
console.log(ExactNumber(1).div(49).mul(49).toString());
// returns 1
console.log(10e16 + 5);
// returns 100000000000000000
console.log(ExactNumber('10e16').add(5).toString());
// returns 100000000000000005
```
## Features
- Works with arbitrary large numbers without precision loss
- There is **no automatic rounding** or truncation. Rounding can be archived by **explicit calls** to rounding functions
- All fractions can be represented as repeating decimals like `1.23(45)`
- This repeating decimal format (`1.23(45)`) can also be parsed back
- Works with all number bases between `2` and `16`
- There are no special values like `NaN`, `Infinity` or `-0`.
- No silent errors: it throws errors immediatelly when a confusing parameter is received.
- All fractions can be represented as repeating decimals like `1.23(45)`
- Repeating decimal format can also be parsed back
- **No special values** like `NaN`, `Infinity` or `-0`.
- **No silent errors**: it throws errors immediatelly when a confusing parameter is received (e.g. 0/0)
- Supports bitwise operators (`and`, `or`, `xor`, `shiftLeft`, `shiftRight`)
- Approximation algorithms for irrational numbers (_experimental_)
- Includes approximation algorithms for irrational numbers like `PI`, `sin(1)`.
- Supports all modern browsers, web workers, Node.js and Deno
- Includes TypeScript type definitions: [documentation](https://daninet.github.io/exactnumber)
- Zero external dependencies
- Uses `BigInt` type under the hood. It automatically switches back and forth between fixed-precision and fractional representations.
- Under the hood, it relies on the `BigInt` type. It automatically switches back and forth between fixed-precision and fractional representations.
- Tries to deliver the best possible performance
- 100% open source + MIT license
## Comparision with built-in numbers
```js
import { ExactNumber as N } from 'exactnumber';
1 + 0.36 // 1.3599999999999999
N(1).add('0.36').toString() // 1.36
(1 / 49) * 49 // 0.9999999999999999
N(1).div(49).mul(49).toString() // 1
10e16 + 5 // 100000000000000000
N('10e16').add(5).toString() // 100000000000000005
1 / 3 // 0.3333333333333333
N(1).div(3).toString() // 0.(3)
2**32 >> 32 // 0
N(2).pow(32).shiftRight(32).toString() // 1
```
## Installation

@@ -83,2 +75,3 @@

N('1/7').toString(); // 0.(142857)
N('1/7').toString(6); // 0.(05)
N('1/7').toFixed(3); // 0.142

@@ -93,11 +86,64 @@ N('1/7').trunc(3).toString(); // 0.142

import { PI, sin } from 'exactnumber';
PI(10); // 3.1415926535
// approximations
const PI_OVER_2 = N(PI(10)).div(2);
sin(PI_OVER_2, 5); // 1.00000
import { PI, sin, pow } from 'exactnumber';
PI(10).toString(); // 3.1415926535
const PI_OVER_2 = PI(10).div(2);
sin(PI_OVER_2, 5).toString(); // 1.00000
// 0.1232323 raised to the power of 2.193333, approximated with 10 decimals
pow('0.1(23)', '2.19(3)', 10).toString(); // 0.0101310867
```
## Supported approximations
## Functions
- Addition / subtraction: `add()`, `sub()`
- Multiplication / division: `mul()`, `div()`, `divToInt()`
- Exponentiation: `pow()`
- Modular arithmetic: `mod()`, `powm()`
- Getting the sign / absolute value: `sign()`, `abs()`
- Negation / inversion: `neg()`, `inv()`
- Integer and fractional parts: `intPart()`, `fracPart()`
- Comparisons: `cmp()`, `eq()`, `lt()`, `lte()`, `gt()`, `gte()`
- Special comparisons: `isZero()`, `isOne()`
- Type testing: `isInteger()`
- Rounding: `round()`, `roundToDigits()`, `floor()`, `ceil()`, `trunc()`
- Bitwise operators: `bitwiseAnd()`, `bitwiseOr()`, `bitwiseXor()`, `shiftLeft()`, `shiftRight()`
- Clamping: `clamp()`
- Fraction helper: `getFractionParts()`
- Normalization / simplifying fractions: `normalize()`
- String output: `toFixed()`, `toExponential()`, `toPrecision()`, `toString()`, `toFraction()`
- Number output: `toNumber()`
- GCD, LCM: `ExactNumber.gcd()`, `ExactNumber.lcm()`
- Minimum, maximum: `ExactNumber.min()`, `ExactNumber.max()`
- Parsing numbers in different bases: `ExactNumber.fromBase()`
- Range generator: `ExactNumber.range()`
## Rounding modes
- `NEAREST_TO_POSITIVE` - Rounds to nearest number, with ties rounded towards +Infinity. Similar to Math.round().
- `NEAREST_TO_NEGATIVE` - Rounds to nearest number, with ties rounded towards -Infinity.
- `NEAREST_TO_EVEN` - Rounds to nearest number, with ties rounded towards the nearest even number.
- `NEAREST_TO_ZERO` - Rounds to nearest number, with ties rounded towards zero.
- `NEAREST_AWAY_FROM_ZERO` - Rounds to nearest number, with ties rounded away from zero.
- `TO_POSITIVE` - Rounds towards +Infinity. Similar to Math.ceil().
- `TO_NEGATIVE` - Rounds towards -Infinity. Similar to Math.floor().
- `TO_ZERO` - Rounds towards zero. Similar to Math.trunc().
- `AWAY_FROM_ZERO` - Rounds away from zero
## Modulo variants
- `TRUNCATED`
- `FLOORED`
- `EUCLIDEAN`
Read more about them [here](https://en.wikipedia.org/wiki/Modulo_operation).
## Approximation algorithms
These functions approximate irrational numbers with arbitrary number of decimals.
The last parameter is always used to specify the number of correct decimals in the result.
- Roots: `sqrt()`, `cbrt()`, `nthroot()`

@@ -104,0 +150,0 @@ - Exponentials: `pow()`, `exp()`

@@ -1,2 +0,2 @@

import { limitDecimals } from '../util';
import { limitDecimals, _0N, _1N, _2N, _4N } from '../util';
import { ExactNumber } from '../ExactNumber';

@@ -8,8 +8,8 @@ import { ExactNumberType } from '../types';

function* expGenerator(x: ExactNumberType, decimals: number) {
let sum = x.add(1n);
let sum = x.add(1);
let denominator = 6n;
let i = 4n;
let denominator = BigInt(6);
let i = _4N;
const xPow2 = x.pow(2n);
const xPow2 = x.pow(_2N);

@@ -22,5 +22,5 @@ let xPow = xPow2;

const term = xPow.mul(x.add(i - 1n)).div(denominator);
denominator *= i * (i + 1n);
i += 2n;
const term = xPow.mul(x.add(i - _1N)).div(denominator);
denominator *= i * (i + _1N);
i += _2N;
xPow = xPow.mul(xPow2);

@@ -46,3 +46,3 @@ sum = sum.add(term).trunc(decimals + 5);

return ExactNumber(0);
return ExactNumber(_0N);
};

@@ -49,0 +49,0 @@

@@ -5,3 +5,3 @@ import { FixedNumber } from '../FixedNumber';

import { sqrt } from './roots';
import { limitDecimals } from '../util';
import { limitDecimals, _0N, _1N, _2N, _3N } from '../util';

@@ -11,10 +11,10 @@ // sinh x = x + x^3/3! + x^5/5! + ...

let numerator = x;
let denominator = 1n;
const x2 = x.pow(2n).normalize();
let denominator = _1N;
const x2 = x.pow(_2N).normalize();
let sum = x.trunc(decimals + 5);
let i = 2n;
let i = _2N;
while (true) {
numerator = numerator.mul(x2);
denominator *= i * (i + 1n);
i += 2n;
denominator *= i * (i + _1N);
i += _2N;
const term = numerator.div(denominator);

@@ -38,3 +38,3 @@ sum = sum.add(term).trunc(decimals + 5);

return ExactNumber(0);
return ExactNumber(_0N);
};

@@ -44,15 +44,15 @@

function* coshGenerator(x: ExactNumberType, decimals: number) {
const x2 = x.pow(2n).normalize();
const x2 = x.pow(_2N).normalize();
let numerator = x2;
let denominator = 2n;
let denominator = _2N;
let sum = numerator
.div(denominator)
.add(1n)
.add(_1N)
.trunc(decimals + 5);
let i = 3n;
let i = _3N;
while (true) {
numerator = numerator.mul(x2);
denominator *= i * (i + 1n);
i += 2n;
denominator *= i * (i + _1N);
i += _2N;
const term = numerator.div(denominator);

@@ -76,3 +76,3 @@ sum = sum.add(term).trunc(decimals + 5);

return ExactNumber(0);
return ExactNumber(_0N);
};

@@ -82,3 +82,3 @@

const angleNum = limitDecimals(ExactNumber(angle), decimals);
if (angleNum.isZero()) return ExactNumber(0);
if (angleNum.isZero()) return ExactNumber(_0N);

@@ -89,3 +89,3 @@ // tanh x = sinh x / cosh x;

const coshRes = cosh(angleNum, decimals + 10).abs();
const sinhRes = sqrt(coshRes.pow(2).sub(1), decimals + 10);
const sinhRes = sqrt(coshRes.pow(_2N).sub(_1N), decimals + 10);

@@ -92,0 +92,0 @@ const res = sinhRes.div(coshRes).mul(angleNum.sign());

@@ -1,2 +0,2 @@

import { limitDecimals } from '../util';
import { limitDecimals, _0N, _1N, _2N } from '../util';
import { ExactNumber } from '../ExactNumber';

@@ -9,7 +9,7 @@ import { ExactNumberType } from '../types';

const input = limitDecimals(ExactNumber(x), decimals);
if (input.isZero()) return ExactNumber(0);
if (input.isZero()) return ExactNumber(_0N);
// asinh(x) = ln(x + sqrt(x^2 + 1))
const root = sqrt(input.pow(2).add(1n), decimals + 5);
const root = sqrt(input.pow(_2N).add(_1N), decimals + 5);
const res = log(input.add(root), decimals + 5);

@@ -22,8 +22,8 @@

const input = limitDecimals(ExactNumber(x), decimals);
if (input.isOne()) return ExactNumber(0);
if (input.lt(1n)) throw new Error('Out of range');
if (input.isOne()) return ExactNumber(_0N);
if (input.lt(_1N)) throw new Error('Out of range');
// acosh(x) = ln(x + sqrt(x^2 - 1))
const root = sqrt(input.pow(2).sub(1n), decimals + 5);
const root = sqrt(input.pow(_2N).sub(_1N), decimals + 5);
const res = log(input.add(root), decimals + 5);

@@ -36,10 +36,10 @@

const input = limitDecimals(ExactNumber(x), decimals);
if (input.abs().gte(1n)) throw new Error('Out of range');
if (input.isZero()) return ExactNumber(0);
if (input.abs().gte(_1N)) throw new Error('Out of range');
if (input.isZero()) return ExactNumber(_0N);
// atanh(x) = 0.5 * ln((1 + x) / (1 - x))
const res = log(input.add(1n).div(input.neg().add(1n)), decimals + 5);
const res = log(input.add(_1N).div(input.neg().add(_1N)), decimals + 5);
return ExactNumber(res).div(2n).trunc(decimals);
return ExactNumber(res).div(_2N).trunc(decimals);
};

@@ -1,2 +0,2 @@

import { limitDecimals } from '../util';
import { limitDecimals, _0N, _1N, _2N, _3N } from '../util';
import { ExactNumber } from '../ExactNumber';

@@ -9,5 +9,5 @@ import { ExactNumberType } from '../types';

function* atanGenerator(x: ExactNumberType, decimals: number) {
const x2 = x.pow(2n).normalize();
const x4 = x2.pow(2n).normalize();
let denominator = 3n;
const x2 = x.pow(_2N).normalize();
const x4 = x2.pow(_2N).normalize();
let denominator = _3N;

@@ -21,4 +21,4 @@ let sum = x.sub(x.mul(x2).div(denominator));

// = x^5 * (-ax^2 + (a + 2)) / (a * (a + 2))
denominator += 2n;
const denominator2 = denominator + 2n;
denominator += _2N;
const denominator2 = denominator + _2N;
const numerator = xPow.mul(x2.mul(-denominator).add(denominator2));

@@ -50,4 +50,4 @@ const term = numerator.div(denominator * denominator2);

while (x.abs().gt(reductionLimit)) {
const root = ExactNumber(sqrt(x.pow(2n).add(1n), decimals + 10));
x = x.div(root.add(1n));
const root = ExactNumber(sqrt(x.pow(_2N).add(_1N), decimals + 10));
x = x.div(root.add(_1N));
reductionSteps++;

@@ -62,3 +62,3 @@ }

// undo argument reduction
const res = sum.mul(2n ** BigInt(reductionSteps));
const res = sum.mul(_2N ** BigInt(reductionSteps));
return res.trunc(decimals);

@@ -74,10 +74,10 @@ }

if (x.isZero()) return ExactNumber(0);
if (x.isZero()) return ExactNumber(_0N);
if (x.abs().isOne()) {
return ExactNumber(PI(decimals)).mul(x.sign()).div(2n).trunc(decimals);
return ExactNumber(PI(decimals)).mul(x.sign()).div(_2N).trunc(decimals);
}
if (x.abs().eq('1/2')) {
return ExactNumber(PI(decimals)).mul(x.sign()).div(6n).trunc(decimals);
return ExactNumber(PI(decimals)).mul(x.sign()).div(6).trunc(decimals);
}
if (x.gt(1n) || x.lt(-1n)) {
if (x.gt(_1N) || x.lt(-_1N)) {
throw new Error('Out of range');

@@ -88,5 +88,5 @@ }

const root = ExactNumber(sqrt(x.pow(2n).neg().add(1), decimals + 10));
const atangent = ExactNumber(atan(x.div(root.add(1n)), decimals + 10));
return atangent.mul(2).trunc(decimals);
const root = ExactNumber(sqrt(x.pow(_2N).neg().add(_1N), decimals + 10));
const atangent = ExactNumber(atan(x.div(root.add(_1N)), decimals + 10));
return atangent.mul(_2N).trunc(decimals);
};

@@ -97,6 +97,6 @@

if (x.isZero()) return ExactNumber(PI(decimals)).div(2n).trunc(decimals);
if (x.isZero()) return ExactNumber(PI(decimals)).div(_2N).trunc(decimals);
if (x.isOne()) {
return ExactNumber(0);
return ExactNumber(_0N);
}

@@ -109,7 +109,7 @@

if (x.abs().eq('1/2')) {
const PI_OVER_3 = ExactNumber(PI(decimals)).div(3n);
return x.sign() === -1 ? PI_OVER_3.mul(2n).trunc(decimals) : PI_OVER_3.trunc(decimals);
const PI_OVER_3 = ExactNumber(PI(decimals)).div(_3N);
return x.sign() === -1 ? PI_OVER_3.mul(_2N).trunc(decimals) : PI_OVER_3.trunc(decimals);
}
if (x.gt(1n) || x.lt(-1n)) {
if (x.gt(_1N) || x.lt(-_1N)) {
throw new Error('Out of range');

@@ -120,5 +120,5 @@ }

return ExactNumber(PI(decimals + 10))
.div(2n)
.div(_2N)
.sub(asin(x, decimals + 10))
.trunc(decimals);
};

@@ -1,2 +0,2 @@

import { limitDecimals } from '../util';
import { limitDecimals, _0N, _10N, _1N, _2N } from '../util';
import { ExactNumber } from '../ExactNumber';

@@ -11,6 +11,6 @@ import { FixedNumber } from '../FixedNumber';

function* logGenerator(y: ExactNumberType, decimals: number) {
const y2 = y.pow(2n).normalize();
const y2 = y.pow(_2N).normalize();
let numerator = y;
let denominator = 1n;
let denominator = _1N;

@@ -21,3 +21,3 @@ let sum = ExactNumber(y);

numerator = numerator.mul(y2);
denominator += 2n;
denominator += _2N;
const term = numerator.div(denominator).trunc(decimals + 10);

@@ -35,3 +35,3 @@ sum = sum.add(term);

if (input.lte(0n)) {
if (input.lte(0)) {
throw new Error('Invalid parameter');

@@ -44,3 +44,3 @@ }

const reductionLimit = ExactNumber('0.1');
while (input.sub(1n).abs().gt(reductionLimit)) {
while (input.sub(_1N).abs().gt(reductionLimit)) {
input = new FixedNumber(sqrt(input, decimals + 10));

@@ -52,3 +52,3 @@ reductions++;

// y = (x - 1)/(x + 1) (|y| < 1)
const y = input.sub(1n).div(input.add(1n));
const y = input.sub(_1N).div(input.add(_1N));

@@ -59,3 +59,3 @@ const gen = logGenerator(y, decimals);

// undo reductions
const res = sum.mul(2n ** BigInt(reductions + 1));
const res = sum.mul(_2N ** BigInt(reductions + 1));
return res.trunc(decimals);

@@ -65,3 +65,3 @@ }

return ExactNumber(0);
return ExactNumber(_0N);
};

@@ -80,3 +80,3 @@

const LOG_2 = new ConstantCache(decimals => log(2n, decimals), 200);
const LOG_2 = new ConstantCache(decimals => log(_2N, decimals), 200);

@@ -89,3 +89,3 @@ export const log2 = (x: number | bigint | string | ExactNumberType, decimals: number): ExactNumberType => {

const LOG_10 = new ConstantCache(decimals => log(10n, decimals), 200);
const LOG_10 = new ConstantCache(decimals => log(_10N, decimals), 200);

@@ -92,0 +92,0 @@ export const log10 = (x: number | bigint | string | ExactNumberType, decimals: number): ExactNumberType => {

@@ -5,3 +5,3 @@ import { FixedNumber } from '../FixedNumber';

import { ExactNumber } from '../ExactNumber';
import { limitDecimals } from '../util';
import { limitDecimals, _0N, _1N } from '../util';

@@ -73,4 +73,4 @@ const approximateNthRoot = (n: number, x: ExactNumberType): string => {

if (n % 2 === 0 && xNum.sign() === -1) throw new Error('Complex numbers are not supported');
if (xNum.isZero()) return new FixedNumber(0n).trunc(decimals);
if (xNum.isOne()) return new FixedNumber(1n).trunc(decimals);
if (xNum.isZero()) return new FixedNumber(_0N).trunc(decimals);
if (xNum.isOne()) return new FixedNumber(_1N).trunc(decimals);

@@ -77,0 +77,0 @@ const res = nthrootWithNewton(n, xNum, decimals);

@@ -0,3 +1,4 @@

import { ExactNumberType } from '../types';
import { ExactNumber } from '../ExactNumber';
import { cos, PI, sin, tan } from './trigonometry';
import { cos, evaluateAngle, PI, sin, tan } from './trigonometry';
import { compareError, testStability } from '../testHelper.test';

@@ -24,4 +25,54 @@

it('evaluates angles', () => {
const precision = 10;
const pi = PI(15);
const toRad = (x: ExactNumberType) => ExactNumber(x).div(180).mul(pi).trunc(precision);
const normalizeAngle = (x: ExactNumberType) => {
let ref = ExactNumber(x).mod(360);
if (ref.sign() === -1) ref = ref.add(360);
return ref;
};
for (let deg = -3600; deg <= 3600; deg++) {
const rad = toRad(ExactNumber(deg));
const ref = normalizeAngle(ExactNumber(deg));
const quadrant = ref.div(90).floor().toNumber() + 1;
const res = evaluateAngle(rad, precision);
expect(res.quadrant).toBe(quadrant);
if (deg % 15 === 0) {
expect(res.specialCaseDeg).not.toBe(null);
expect(res.specialCaseDeg).toBeGreaterThanOrEqual(0);
expect(res.specialCaseDeg).toBeLessThanOrEqual(90);
expect(res.subHalfPiAngle).toBe(null);
} else {
expect(res.specialCaseDeg).toBe(null);
expect(res.subHalfPiAngle.gte(0)).toBe(true);
expect(res.subHalfPiAngle.lte('1.571')).toBe(true);
}
}
});
it('reduces angles correctly', () => {
const precision = 10;
const pi = PI(100);
const piOver2 = pi.div(2);
const seq = [ExactNumber(0), pi.div(6), pi.div(4), pi.div(3)];
for (let base = ExactNumber(0); base.lt(200); base = base.add(pi.mul(2))) {
for (let quadrant = 1; quadrant <= 4; quadrant++) {
const basePlusQuadrant = base.add(piOver2.mul(quadrant - 1));
for (const angle of seq) {
const x = basePlusQuadrant.add(angle).trunc(precision);
const res = evaluateAngle(x, precision);
expect(res.quadrant).toBe(quadrant);
}
}
}
});
it('cos reduce to half pi', () => {
const pi = ExactNumber(PI(100));
const pi = PI(100);
const piOverTwo = pi.div(2);

@@ -53,2 +104,4 @@

it('tan', () => {
// expect(tan(PI(12).div(2), 10).toFixed(10)).toBe('3.1415926535');
const range = [Math.floor(Math.PI * -4), Math.ceil(Math.PI * 4)];

@@ -55,0 +108,0 @@ for (let i = range[0]; i <= range[1]; i += 0.01) {

@@ -6,3 +6,3 @@ import { FixedNumber } from '../FixedNumber';

import { sqrt } from './roots';
import { limitDecimals } from '../util';
import { limitDecimals, _0N, _1N, _2N, _3N, _4N, _10N, _24N } from '../util';

@@ -14,11 +14,12 @@ // TODO: https://en.wikipedia.org/wiki/Niven%27s_theorem

const PIcalc = (decimals: number): ExactNumberType => {
if (decimals === 0) return ExactNumber(3n);
if (decimals === 0) return ExactNumber(_3N);
// PI = 3 + 3(1/2)(1/3)(1/4) + 3((1/2)(3/4))(1/5)(1/4^2) + 3((1/2)(3/4)(5/6))(1/7)(1/4^3) + ...
let i = 1n;
let x = 3n * 10n ** BigInt(decimals + 20);
let i = _1N;
let x = _3N * _10N ** BigInt(decimals + 20);
let res = x;
while (x !== 0n) {
x = (x * i) / ((i + 1n) * 4n);
i += 2n;
while (x !== _0N) {
x = (x * i) / ((i + _1N) * _4N);
i += _2N;
res += x / i;

@@ -33,37 +34,77 @@ }

export const PI = (decimals: number): ExactNumberType => {
if (decimals === 0) return ExactNumber(3);
if (decimals === 0) return ExactNumber(_3N);
return PI_CACHE.get(decimals).trunc(decimals);
};
const evaluateAngle = (x: ExactNumberType, decimals: number) => {
const pi = new FixedNumber(PI(decimals + 5));
const twoPi = pi.mul(2n);
const roundedX = x.round(decimals + 5, RoundingMode.NEAREST_AWAY_FROM_ZERO);
// a number between (-1, 1)
let turns = roundedX.div(twoPi).fracPart();
const getMultiplierOf = (x: ExactNumberType, y: ExactNumberType, decimals: number) => {
const precision = Math.max(3, decimals);
const input = x.trunc(precision);
const closestQuotient = input.div(y).round();
const ref = y.mul(closestQuotient).trunc(precision);
// normalize into the [0, 1) interval
if (turns.lt(0n)) {
turns = turns.add(1n);
if (ref.eq(input)) {
return closestQuotient;
}
// limit precision
turns = turns.round(decimals + 5);
return null;
};
const quadrant = turns.div('0.25').floor().toNumber() + 1;
type EvaluationRes = { specialCaseDeg: number | null; quadrant: number; subHalfPiAngle: ExactNumberType | null };
let subHalfPiAngle = twoPi.mul(turns);
let quadrantDegrees = turns.mul(360n);
const evaluateSpecialAngle = (angleMultiplier: ExactNumberType): EvaluationRes => {
let multiplier = angleMultiplier.mod(_24N).toNumber();
if (multiplier < 0) {
multiplier += 24;
}
const quadrant = Math.floor(multiplier / 6) + 1;
let specialCaseDeg = multiplier * 15;
if (quadrant === 4) {
specialCaseDeg = 360 - specialCaseDeg;
} else if (quadrant === 3) {
specialCaseDeg -= 180;
} else if (quadrant === 2) {
specialCaseDeg = 180 - specialCaseDeg;
}
return {
specialCaseDeg,
quadrant,
subHalfPiAngle: null,
};
};
export const evaluateAngle = (x: ExactNumberType, decimals: number): EvaluationRes => {
let angle = x.round(decimals + 5, RoundingMode.NEAREST_AWAY_FROM_ZERO);
const pi = PI(decimals + 5);
const angleMultiplier = getMultiplierOf(angle, pi.div(12), decimals);
if (angleMultiplier !== null) {
return evaluateSpecialAngle(angleMultiplier);
}
const twoPi = pi.mul(_2N);
angle = angle.mod(twoPi);
if (angle.sign() === -1) {
angle = angle.add(twoPi);
}
const quadrant = angle.mul(_2N).div(pi).floor().toNumber() + 1;
let subHalfPiAngle = angle;
if (quadrant === 4) {
subHalfPiAngle = twoPi.sub(subHalfPiAngle);
quadrantDegrees = ExactNumber(360).sub(quadrantDegrees);
} else if (quadrant === 3) {
subHalfPiAngle = subHalfPiAngle.sub(pi);
quadrantDegrees = quadrantDegrees.sub(180);
} else if (quadrant === 2) {
subHalfPiAngle = pi.sub(subHalfPiAngle);
quadrantDegrees = ExactNumber(180).sub(quadrantDegrees);
}
return { quadrantDegrees: quadrantDegrees.round(decimals), quadrant, subHalfPiAngle };
return {
specialCaseDeg: null,
quadrant,
subHalfPiAngle,
};
};

@@ -73,10 +114,9 @@

function* cosGenerator(x: ExactNumberType, decimals: number) {
const x2 = x.round(decimals + 10, RoundingMode.NEAREST_AWAY_FROM_ZERO).pow(2n);
const x2 = x.round(decimals + 10, RoundingMode.NEAREST_AWAY_FROM_ZERO).pow(_2N);
let xPow = x2;
let termDenominator = 2n;
let sum = ExactNumber(1n).sub(xPow.div(termDenominator).trunc(decimals + 10));
let i = 3n;
// let rndErrors = 1;
let termDenominator = _2N;
let sum = ExactNumber(_1N).sub(xPow.div(termDenominator).trunc(decimals + 10));
let i = _3N;

@@ -86,6 +126,6 @@ while (true) {

// = (5*6*x^4 - x^6)/6!
termDenominator *= i * (i + 1n);
i += 2n;
const multiplier = i * (i + 1n);
i += 2n;
termDenominator *= i * (i + _1N);
i += _2N;
const multiplier = i * (i + _1N);
i += _2N;
xPow = xPow.mul(x2);

@@ -98,7 +138,5 @@ termDenominator *= multiplier;

const term = termNumerator.div(termDenominator).trunc(decimals + 10);
// rndErrors++;
sum = sum.add(term);
// max lagrange error = x^(k+1)/(k+1)!
// const le = xPow.mul(x).div(termDenominator * i);

@@ -109,3 +147,7 @@ yield { term, sum };

const resultHandler = (value: string | ExactNumberType, shouldNegate: boolean, decimals: number): ExactNumberType => {
const resultHandler = (
value: bigint | string | ExactNumberType,
shouldNegate: boolean,
decimals: number,
): ExactNumberType => {
let convertedValue = ExactNumber(value);

@@ -122,15 +164,18 @@ if (shouldNegate) {

const angle = limitDecimals(ExactNumber(_angle), decimals + 5);
const { quadrantDegrees, subHalfPiAngle: x, quadrant } = evaluateAngle(angle, decimals);
const { specialCaseDeg, subHalfPiAngle: x, quadrant } = evaluateAngle(angle, decimals);
const shouldNegate = quadrant === 2 || quadrant === 3;
if (quadrantDegrees.isZero()) return resultHandler('1', shouldNegate, decimals);
if (quadrantDegrees.eq(30n)) {
return resultHandler(ExactNumber(sqrt(3n, decimals + 5)).div(2n), shouldNegate, decimals);
if (specialCaseDeg !== null) {
if (specialCaseDeg === 0) return resultHandler(_1N, shouldNegate, decimals);
if (specialCaseDeg === 30) {
return resultHandler(ExactNumber(sqrt(_3N, decimals + 5)).div(_2N), shouldNegate, decimals);
}
if (specialCaseDeg === 45) {
return resultHandler(ExactNumber(sqrt(_2N, decimals + 5)).div(_2N), shouldNegate, decimals);
}
if (specialCaseDeg === 60) return resultHandler('0.5', shouldNegate, decimals);
if (specialCaseDeg === 90) return resultHandler(_0N, shouldNegate, decimals);
throw new Error();
}
if (quadrantDegrees.eq(45n)) {
return resultHandler(ExactNumber(sqrt(2n, decimals + 5)).div(2n), shouldNegate, decimals);
}
if (quadrantDegrees.eq(60n)) return resultHandler('0.5', shouldNegate, decimals);
if (quadrantDegrees.eq(90n)) return resultHandler('0', shouldNegate, decimals);

@@ -152,3 +197,3 @@ const maxError = ExactNumber(`1e-${EXTRA_DECIMALS}`);

const x = limitDecimals(ExactNumber(angle), decimals + 5);
return cos(pi.div(2n).sub(x), decimals + 5).trunc(decimals);
return cos(pi.div(_2N).sub(x), decimals + 5).trunc(decimals);
};

@@ -159,24 +204,27 @@

const { quadrantDegrees, quadrant, subHalfPiAngle: x } = evaluateAngle(angleNum, decimals + 5);
const { specialCaseDeg, quadrant, subHalfPiAngle: x } = evaluateAngle(angleNum, decimals);
const shouldNegate = quadrant === 1 || quadrant === 3;
if (quadrantDegrees.isZero()) return resultHandler('0', shouldNegate, decimals);
if (quadrantDegrees.eq(30n)) {
return resultHandler(ExactNumber(1n).div(sqrt(3n, decimals + 5)), shouldNegate, decimals);
if (specialCaseDeg !== null) {
if (specialCaseDeg === 0) return resultHandler('0', shouldNegate, decimals);
if (specialCaseDeg === 30) {
return resultHandler(ExactNumber(_1N).div(sqrt(_3N, decimals + 5)), shouldNegate, decimals);
}
if (specialCaseDeg === 4) {
return resultHandler('1', shouldNegate, decimals);
}
if (specialCaseDeg === 60) return resultHandler(sqrt(_3N, decimals + 5), shouldNegate, decimals);
if (specialCaseDeg === 90) {
throw new Error('Out of range');
}
throw new Error();
}
if (quadrantDegrees.eq(45n)) {
return resultHandler('1', shouldNegate, decimals);
}
if (quadrantDegrees.eq(60n)) return resultHandler(sqrt(3n, decimals + 5), shouldNegate, decimals);
if (quadrantDegrees.eq(90n)) {
throw new Error('Out of range');
}
// tan x = sqrt((1 - cos(2x)) / 1 + cos(2x))
const cos2x = ExactNumber(cos(x.mul(2n), decimals + 5));
const cos2x = ExactNumber(cos(x.mul(_2N), decimals + 5));
const res = ExactNumber(1n)
const res = ExactNumber(_1N)
.sub(cos2x)
.div(ExactNumber(1n).add(cos2x))
.div(ExactNumber(_1N).add(cos2x))
.round(decimals + 5);

@@ -183,0 +231,0 @@

import { Fraction } from './Fraction';
import { FixedNumber } from './FixedNumber';
import { ExactNumberParameter, ExactNumberType } from './types';
import { _0N, _1N } from './util';

@@ -23,3 +24,3 @@ export function parseParameter(x: number | bigint | string | ExactNumberType): ExactNumberType {

if (x.includes('/') || x.includes('(')) {
return new Fraction(x, 1n);
return new Fraction(x, _1N);
}

@@ -66,3 +67,3 @@ return new FixedNumber(x);

const yVal = parseParameter(y);
return new Fraction(xVal, 1n).div(new Fraction(yVal, 1n));
return new Fraction(xVal, _1N).div(new Fraction(yVal, _1N));
});

@@ -103,3 +104,3 @@

const parseDigitsInBase = (str: string, radix: number) => {
let res = 0n;
let res = _0N;
for (let i = 0; i < str.length; i++) {

@@ -150,4 +151,4 @@ const c = str.charAt(i);

const numerator =
parseDigitsInBase([wholePartStr, nonRepeatingPartStr, repeatingPartStr].join(''), radix) -
parseDigitsInBase([wholePartStr, nonRepeatingPartStr].join(''), radix);
parseDigitsInBase(`${wholePartStr}${nonRepeatingPartStr}${repeatingPartStr}`, radix) -
parseDigitsInBase(`${wholePartStr}${nonRepeatingPartStr}`, radix);

@@ -168,3 +169,3 @@ const denominator = parseDigitsInBase(

const res = new Fraction(whole, 1n).add(fracPath).normalize();
const res = new Fraction(whole, _1N).add(fracPath).normalize();
return isNegative ? res.neg() : res;

@@ -171,0 +172,0 @@ });

@@ -180,2 +180,18 @@ import { FixedNumber } from './FixedNumber';

it('powm()', () => {
const run = (b: ExactNumberParameter, e: ExactNumberParameter, m: ExactNumberParameter) =>
new FixedNumber(b).powm(e, m).toString();
expect(run(3, 4, 5)).toBe('1');
expect(run(314, 23, 971)).toBe('865');
for (let b = 2; b <= 25; b++) {
for (let e = 0; e <= 10; e++) {
for (let m = 11; m <= 13; m++) {
expect(run(b, e, m)).toBe((b ** e % m).toString());
}
}
}
});
it('div()', () => {

@@ -232,2 +248,5 @@ const run = (a: ExactNumberParameter, b: ExactNumberParameter) => new FixedNumber(a).div(b).toString();

expect(run('-3.745', '-1.25')).toBe('-1.245');
expect(run('17.891', '-1.66')).toBe('1.291');
expect(run('-712.8929', '-1.79')).toBe('-0.4729');
expect(run('-2.8', '-1.789')).toBe('-1.011');

@@ -697,3 +716,4 @@ const values = [

it('toFixed()', () => {
const run = (x: string, digits: number, rndMode?: RoundingMode) => new FixedNumber(x).toFixed(digits, rndMode);
const run = (x: string, digits: number, trimZeros?: boolean) =>
new FixedNumber(x).toFixed(digits, RoundingMode.TO_ZERO, trimZeros);

@@ -708,5 +728,7 @@ expect(run('0', 0)).toBe('0');

expect(run('0.45600', 6)).toBe('0.456000');
expect(run('0.45600', 6, true)).toBe('0.456');
expect(run('-123.45600', 0)).toBe('-123');
expect(run('-123.45600', 1)).toBe('-123.4');
expect(run('-123.45600', 6)).toBe('-123.456000');
expect(run('123000', 2, true)).toBe('123000');

@@ -730,3 +752,4 @@ expect(() => run('-1.45', -1)).toThrow('Invalid parameter');

it('toPrecision()', () => {
const run = (x: string, digits: number) => new FixedNumber(x).toPrecision(digits);
const run = (x: string, digits: number, trimZeros?: boolean) =>
new FixedNumber(x).toPrecision(digits, RoundingMode.TO_ZERO, trimZeros);

@@ -744,2 +767,4 @@ expect(run('0', 1)).toBe('0');

expect(run('0.0045600', 6)).toBe('0.00456000');
expect(run('0.0045600', 6, true)).toBe('0.00456');
expect(run('123000', 2, true)).toBe('120000');

@@ -751,15 +776,21 @@ expect(() => run('-1.45', -1)).toThrow('Invalid parameter');

// it('toPrecision() rounding modes', () => {
// for (const rndMode of Object.values(RoundingMode)) {
// for (let i = 0; i < 10; i++) {
// let num = new FixedNumber('123.45600');
// expect(num.toPrecision(i, rndMode)).toBe(num.roundToDigits(rndMode, i).toPrecision(i));
// num = new FixedNumber('-123.45600');
// expect(num.toPrecision(i, rndMode)).toBe(num.roundToDigits(rndMode, i).toPrecision(i));
// }
// }
// });
it('toPrecision() rounding modes', () => {
for (const rndMode of Object.values(RoundingMode)) {
if (!Number.isInteger(rndMode)) continue;
for (let i = 1; i < 10; i++) {
let num = new FixedNumber('123.45600');
expect(num.toPrecision(i, rndMode as RoundingMode)).toBe(
num.roundToDigits(i, rndMode as RoundingMode).toPrecision(i),
);
num = num.neg();
expect(num.toPrecision(i, rndMode as RoundingMode)).toBe(
num.roundToDigits(i, rndMode as RoundingMode).toPrecision(i),
);
}
}
});
it('toExponential()', () => {
const run = (a: string, digits: number) => new FixedNumber(a).toExponential(digits);
const run = (a: string, digits: number, trimZeros?: boolean) =>
new FixedNumber(a).toExponential(digits, RoundingMode.TO_ZERO, trimZeros);

@@ -791,2 +822,7 @@ expect(run('0', 0)).toBe('0e+0');

expect(run('0.0045600', 6, true)).toBe('4.56e-3');
expect(run('123000', 2, true)).toBe('1.23e+5');
expect(run('123000', 10, false)).toBe('1.2300000000e+5');
expect(run('123000', 10, true)).toBe('1.23e+5');
expect(() => run('-1.45', -1)).toThrow('Invalid parameter');

@@ -807,3 +843,3 @@ expect(() => run('-1.45', 0.5)).toThrow('Invalid parameter');

expect(run('0.4', 3)).toBe('0.(1012)');
expect(run('0.3', 16)).toBe('0.4(c)');
expect(run('0.300', 16)).toBe('0.4(c)');
expect(run('0.013', 7)).toBe('0.(00431330261442015456)');

@@ -813,2 +849,5 @@ expect(run('0.012', 6)).toBe('0.0(0233151220401052455413443)');

expect(run('-15.012', 6)).toBe('-23.0(0233151220401052455413443)');
expect(run('-123.500', 6)).toBe('-323.3');
expect(run('1234.88', 16)).toBe('4d2.(e147a)');
expect(run('-1234.2000', 15)).toBe('-574.3');

@@ -815,0 +854,0 @@ expect(run('100', 5)).toBe('400');

@@ -1,2 +0,2 @@

import { bigIntToStr } from './util';
import { bigIntToStr, trimTrailingZerosFromFixed, _0N, _10N, _1N, _24N, _2N } from './util';
import { Fraction } from './Fraction';

@@ -80,4 +80,4 @@ import { ExactNumber, parseParameter } from './ExactNumber';

const maxPos = Math.max(this.decimalPos, decimalPos);
const a = maxPos === this.decimalPos ? this.number : this.number * 10n ** BigInt(maxPos - this.decimalPos);
const b = maxPos === decimalPos ? number : number * 10n ** BigInt(maxPos - decimalPos);
const a = maxPos === this.decimalPos ? this.number : this.number * _10N ** BigInt(maxPos - this.decimalPos);
const b = maxPos === decimalPos ? number : number * _10N ** BigInt(maxPos - decimalPos);
return { a, b, decimalPos: maxPos };

@@ -127,2 +127,27 @@ }

powm(
_exp: number | bigint | string | ExactNumberType,
_mod: number | bigint | string | ExactNumberType,
modType?: ModType,
): FixedNumber {
let exp = parseParameter(_exp).toNumber();
if (!Number.isSafeInteger(exp)) {
throw new Error('Unsupported parameter');
}
const mod = parseParameter(_mod);
let base = this as FixedNumber;
let res = new FixedNumber(_1N);
while (exp !== 0) {
if (exp % 2 !== 0) {
res = res.mul(base).mod(mod, modType) as FixedNumber;
}
base = base.pow(_2N).mod(mod, modType) as FixedNumber;
exp = Math.floor(exp / 2);
}
return res;
}
div(x: number | bigint | string | ExactNumberType): ExactNumberType {

@@ -162,7 +187,7 @@ const frac = this.convertToFraction();

if (type === ModType.FLOORED) {
return Number(a < 0) ^ Number(b < 0) ? res.add(b) : res;
return Number(a < _0N) ^ Number(b < _0N) ? res.add(b) : res;
}
if (type === ModType.EUCLIDEAN) {
return mod < 0 ? res.add(b < 0 ? -b : b) : res;
return mod < _0N ? res.add(b < _0N ? -b : b) : res;
}

@@ -174,3 +199,3 @@

abs(): FixedNumber {
const res = new FixedNumber(this.number < 0 ? -this.number : this.number, this.decimalPos);
const res = new FixedNumber(this.number < _0N ? -this.number : this.number, this.decimalPos);
return res;

@@ -180,3 +205,3 @@ }

neg() {
return this.mul(-1n) as FixedNumber;
return this.mul(-_1N) as FixedNumber;
}

@@ -222,3 +247,3 @@

const exp = 10n ** BigInt(shift);
const exp = _10N ** BigInt(shift);
const outDigits = this.number / exp;

@@ -231,3 +256,3 @@

const extraDigits = this.number % exp;
if (extraDigits === 0n) {
if (extraDigits === _0N) {
return new FixedNumber(outDigits, decimals);

@@ -237,3 +262,3 @@ }

if (roundingMode === RoundingMode.AWAY_FROM_ZERO) {
const res = this.number < 0n ? outDigits - 1n : outDigits + 1n;
const res = this.number < _0N ? outDigits - _1N : outDigits + _1N;
return new FixedNumber(res, decimals);

@@ -243,3 +268,3 @@ }

if (roundingMode === RoundingMode.TO_POSITIVE) {
const res = this.number < 0n ? outDigits : outDigits + 1n;
const res = this.number < _0N ? outDigits : outDigits + _1N;
return new FixedNumber(res, decimals);

@@ -249,3 +274,3 @@ }

if (roundingMode === RoundingMode.TO_NEGATIVE) {
const res = this.number >= 0n ? outDigits : outDigits - 1n;
const res = this.number >= _0N ? outDigits : outDigits - _1N;
return new FixedNumber(res, decimals);

@@ -267,3 +292,3 @@ }

let extraDigitsStr = (extraDigits < 0n ? -extraDigits : extraDigits).toString();
let extraDigitsStr = (extraDigits < _0N ? -extraDigits : extraDigits).toString();
// '00123' extra part will appear in extraDigitsStr as '123'

@@ -281,3 +306,3 @@ // -> in this case we can exclude the tie case by setting the extra part to zero

if (roundingMode === RoundingMode.NEAREST_AWAY_FROM_ZERO) {
const res = this.number < 0n ? outDigits - 1n : outDigits + 1n;
const res = this.number < _0N ? outDigits - _1N : outDigits + _1N;
return new FixedNumber(res, decimals);

@@ -287,3 +312,3 @@ }

if (roundingMode === undefined || roundingMode === RoundingMode.NEAREST_TO_POSITIVE) {
const res = this.number < 0n ? outDigits : outDigits + 1n;
const res = this.number < _0N ? outDigits : outDigits + _1N;
return new FixedNumber(res, decimals);

@@ -293,3 +318,3 @@ }

if (roundingMode === RoundingMode.NEAREST_TO_NEGATIVE) {
const res = this.number >= 0n ? outDigits : outDigits - 1n;
const res = this.number >= _0N ? outDigits : outDigits - _1N;
return new FixedNumber(res, decimals);

@@ -299,7 +324,7 @@ }

if (roundingMode === RoundingMode.NEAREST_TO_EVEN) {
if (outDigits % 2n === 0n) {
if (outDigits % _2N === _0N) {
return new FixedNumber(outDigits, decimals);
}
const res = outDigits < 0n ? outDigits - 1n : outDigits + 1n;
const res = outDigits < _0N ? outDigits - _1N : outDigits + _1N;
return new FixedNumber(res, decimals);

@@ -313,3 +338,3 @@ }

const res = this.number < 0 ? outDigits - 1n : outDigits + 1n;
const res = this.number < _0N ? outDigits - _1N : outDigits + _1N;
return new FixedNumber(res, decimals);

@@ -340,3 +365,3 @@ }

if (rem > 0) {
newNumber *= 10n ** BigInt(rem);
newNumber *= _10N ** BigInt(rem);
}

@@ -349,7 +374,7 @@ }

private countDigits() {
if (this.number === 0n) return 1;
if (this.number === _0N) return 1;
let digits = 0;
let x = this.number < 0 ? -this.number : this.number;
while (x > 0n) {
x /= 10n;
let x = this.number < _0N ? -this.number : this.number;
while (x > _0N) {
x /= _10N;
digits++;

@@ -389,3 +414,3 @@ }

sign(): -1 | 1 {
return this.number < 0n ? -1 : 1;
return this.number < _0N ? -1 : 1;
}

@@ -404,9 +429,9 @@

const pow = 2n ** 24n;
const pow = _2N ** _24N;
let an = this.normalize().number;
let bn = (x.trunc().normalize() as FixedNumber).number;
let res = 0n;
let shift = 1n;
let res = _0N;
let shift = _1N;
while (an > 0 && bn > 0) {
while (an > _0N && bn > _0N) {
const modA = BigInt.asUintN(24, an);

@@ -434,9 +459,9 @@ const modB = BigInt.asUintN(24, bn);

const pow = 2n ** 24n;
const pow = _2N ** _24N;
let an = this.normalize().number;
let bn = (x.trunc().normalize() as FixedNumber).number;
let res = 0n;
let shift = 1n;
let res = _0N;
let shift = _1N;
while (an > 0 || bn > 0) {
while (an > _0N || bn > _0N) {
const modA = BigInt.asUintN(24, an);

@@ -464,9 +489,9 @@ const modB = BigInt.asUintN(24, bn);

const pow = 2n ** 24n;
const pow = _2N ** _24N;
let an = this.normalize().number;
let bn = (x.trunc().normalize() as FixedNumber).number;
let res = 0n;
let shift = 1n;
let res = _0N;
let shift = _1N;
while (an > 0 || bn > 0) {
while (an > _0N || bn > _0N) {
const modA = BigInt.asUintN(24, an);

@@ -492,3 +517,3 @@ const modB = BigInt.asUintN(24, bn);

const pow = 2n ** BigInt(bitCount);
const pow = _2N ** BigInt(bitCount);
return this.mul(pow);

@@ -506,3 +531,3 @@ }

const pow = 2n ** BigInt(bitCount);
const pow = _2N ** BigInt(bitCount);
return new FixedNumber(this.normalize().number / pow);

@@ -557,3 +582,3 @@ }

isZero() {
return this.number === 0n;
return this.number === _0N;
}

@@ -563,8 +588,8 @@

if (this.decimalPos === 0) {
return this.number === 1n;
return this.number === _1N;
}
const exp = 10n ** BigInt(this.decimalPos);
const exp = _10N ** BigInt(this.decimalPos);
const q = this.number / exp;
return q === 1n && q * exp === this.number;
return q === _1N && q * exp === this.number;
}

@@ -574,3 +599,3 @@

if (this.decimalPos === 0) return true;
return this.number % 10n ** BigInt(this.decimalPos) === 0n;
return this.number % _10N ** BigInt(this.decimalPos) === _0N;
}

@@ -590,5 +615,5 @@

let n = this.number;
while (pos > 0 && n % 10n === 0n) {
while (pos > 0 && n % _10N === _0N) {
pos--;
n /= 10n;
n /= _10N;
}

@@ -600,5 +625,5 @@ return new FixedNumber(n, pos);

if (this.decimalPos === 0) {
return new Fraction(this.number, 1n);
return new Fraction(this.number, _1N);
}
const denominator = 10n ** BigInt(this.decimalPos);
const denominator = _10N ** BigInt(this.decimalPos);
return new Fraction(this.number, denominator);

@@ -611,3 +636,3 @@ }

toFixed(decimals: number, roundingMode = RoundingMode.TO_ZERO): string {
toFixed(decimals: number, roundingMode = RoundingMode.TO_ZERO, trimZeros = false): string {
if (!Number.isSafeInteger(decimals) || decimals < 0) throw new Error('Invalid parameter');

@@ -617,6 +642,6 @@

return bigIntToStr(rounded.number, rounded.decimalPos, decimals, false);
return bigIntToStr(rounded.number, rounded.decimalPos, decimals, trimZeros);
}
toExponential(digits: number, roundingMode = RoundingMode.TO_ZERO): string {
toExponential(digits: number, roundingMode = RoundingMode.TO_ZERO, trimZeros = false): string {
if (!Number.isSafeInteger(digits) || digits < 0) throw new Error('Invalid parameter');

@@ -633,5 +658,11 @@

const strWithPoint =
slicedString.length > 1 ? `${slicedString.slice(0, 1)}.${slicedString.slice(1)}` : slicedString;
let strWithPoint = slicedString;
if (slicedString.length > 1) {
strWithPoint = `${slicedString.slice(0, 1)}.${slicedString.slice(1)}`;
if (trimZeros) {
strWithPoint = trimTrailingZerosFromFixed(strWithPoint);
}
}
const fractionalDigitsBefore = absNumber.decimalPos;

@@ -689,3 +720,7 @@ const fractionalDigitsAfter = str.length - 1;

return [isNegative ? '-' : '', intPart.number.toString(radix), digits.length ? '.' : '', ...digits].join('');
const digitsStr = digits.join('');
const res = `${isNegative ? '-' : ''}${intPart.number.toString(radix)}${digits.length ? '.' : ''}${digitsStr}`;
return res;
}

@@ -706,6 +741,7 @@

toPrecision(digits: number, roundingMode = RoundingMode.TO_ZERO): string {
toPrecision(digits: number, roundingMode = RoundingMode.TO_ZERO, trimZeros = false): string {
if (!Number.isSafeInteger(digits) || digits < 1) throw new Error('Invalid parameter');
const rounded = this.roundToDigits(digits, roundingMode);
const { subZeroNum, exponentDiff } = rounded.toSubZeroNum();

@@ -724,3 +760,2 @@

const suffixLength = Math.max(0, digits - whole.length - frac.length);
const suffix = '0'.repeat(suffixLength);
const prefix = '0'.repeat(exponentDiff < 0 ? -exponentDiff : 0);

@@ -730,3 +765,7 @@

if (frac.length + prefix.length + suffixLength > 0) {
const suffix = '0'.repeat(suffixLength);
res += `.${prefix}${frac}${suffix}`;
if (trimZeros) {
res = trimTrailingZerosFromFixed(res);
}
}

@@ -733,0 +772,0 @@

@@ -213,2 +213,18 @@ import { Fraction } from './Fraction';

it('powm()', () => {
const run = (b: ExactNumberParameter, e: ExactNumberParameter, m: ExactNumberParameter) =>
new Fraction(b, 1n).powm(e, m).toString();
expect(run(3, 4, 5)).toBe('1');
expect(run(314, 23, 971)).toBe('865');
for (let b = 2; b <= 25; b++) {
for (let e = 0; e <= 10; e++) {
for (let m = 11; m <= 13; m++) {
expect(run(b, e, m)).toBe((b ** e % m).toString());
}
}
}
});
it('round()', () => {

@@ -215,0 +231,0 @@ const run = (a: string, decimals?: number, rndMode?: RoundingMode) =>

import { CommonNumberFields, ExactNumberType, ModType, RoundingMode } from './types';
import { FixedNumber } from './FixedNumber';
import { trimTrailingZeros } from './util';
import { trimTrailingZerosFromFixed, _0N, _10N, _1N, _2N, _5N } from './util';
import { ExactNumber } from './ExactNumber';

@@ -35,3 +35,3 @@

const isNegativeExp = exponent.startsWith('-');
const exp = 10n ** BigInt(isNegativeExp ? exponent.slice(1) : exponent);
const exp = _10N ** BigInt(isNegativeExp ? exponent.slice(1) : exponent);
if (isNegativeExp) {

@@ -59,7 +59,7 @@ return fraction.div(exp).normalize() as Fraction;

}
return new Fraction(BigInt(x), 1n);
return new Fraction(BigInt(x), _1N);
}
if (typeof x === 'bigint') {
return new Fraction(x, 1n);
return new Fraction(x, _1N);
}

@@ -71,3 +71,3 @@

const numerator = this.parseRepeatingDecimal(parts[0]);
const denominator = parts[1] ? this.parseRepeatingDecimal(parts[1]) : new Fraction(1n, 1n);
const denominator = parts[1] ? this.parseRepeatingDecimal(parts[1]) : new Fraction(_1N, _1N);
const res = numerator.div(denominator) as CommonNumberFields;

@@ -95,3 +95,3 @@ const fraction = res.convertToFraction();

}
if (this.denominator === 0n) {
if (this.denominator === _0N) {
throw new Error('Division by zero');

@@ -161,3 +161,3 @@ }

if (type === ModType.EUCLIDEAN) {
return res.sign() < 0 ? res.add(rFrac.sign() < 0 ? rFrac.neg() : rFrac) : res;
return res.sign() === -1 ? res.add(rFrac.sign() === -1 ? rFrac.neg() : rFrac) : res;
}

@@ -175,8 +175,35 @@

const exp = param.numerator / param.denominator;
const absExp = exp < 0 ? -exp : exp;
const absExp = exp < _0N ? -exp : exp;
const res = new Fraction(this.numerator ** absExp, this.denominator ** absExp);
return exp < 0 ? res.inv() : res;
return exp < _0N ? res.inv() : res;
}
powm(
_exp: number | bigint | string | ExactNumberType,
_mod: number | bigint | string | ExactNumberType,
modType?: ModType,
): ExactNumberType {
const exp = this.parseParameter(_exp);
if (!exp.isInteger()) {
throw new Error('Unsupported parameter');
}
let expInt = exp.toNumber();
const mod = this.parseParameter(_mod);
let base = this as Fraction;
let res = new Fraction(_1N, _1N);
while (expInt !== 0) {
if (expInt % 2 !== 0) {
res = res.mul(base).mod(mod, modType) as Fraction;
}
base = base.pow(_2N).mod(mod, modType) as Fraction;
expInt = Math.floor(expInt / 2);
}
return res;
}
inv(): ExactNumberType {

@@ -188,3 +215,3 @@ const res = new Fraction(this.denominator, this.numerator);

floor(decimals?: number) {
if (this.denominator === 1n) return new FixedNumber(this.numerator);
if (this.denominator === _1N) return new FixedNumber(this.numerator);

@@ -195,3 +222,3 @@ return this.round(decimals, RoundingMode.TO_NEGATIVE);

ceil(decimals?: number) {
if (this.denominator === 1n) return new FixedNumber(this.numerator);
if (this.denominator === _1N) return new FixedNumber(this.numerator);

@@ -202,3 +229,3 @@ return this.round(decimals, RoundingMode.TO_POSITIVE);

trunc(decimals?: number) {
if (this.denominator === 1n) return new FixedNumber(this.numerator);
if (this.denominator === _1N) return new FixedNumber(this.numerator);

@@ -240,3 +267,3 @@ return this.round(decimals, RoundingMode.TO_ZERO);

if (this.isZero()) return new FixedNumber(0n);
if (this.isZero()) return new FixedNumber(_0N);

@@ -248,10 +275,10 @@ let x = this.abs();

while (x.gte(1n)) {
x = x.div(10n);
while (x.gte(_1N)) {
x = x.div(_10N);
divisions++;
}
const zeroPointOne = new Fraction(1n, 10n);
const zeroPointOne = new Fraction(_1N, _10N);
while (x.lt(zeroPointOne)) {
x = x.mul(10n);
x = x.mul(_10N);
divisions--;

@@ -268,4 +295,4 @@ }

private gcd(numerator: bigint, denominator: bigint): bigint {
let a = numerator < 0 ? -numerator : numerator;
let b = denominator < 0 ? -denominator : denominator;
let a = numerator < _0N ? -numerator : numerator;
let b = denominator < _0N ? -denominator : denominator;

@@ -279,5 +306,5 @@ if (b > a) {

while (true) {
if (b === 0n) return a;
if (b === _0N) return a;
a %= b;
if (a === 0n) return b;
if (a === _0N) return b;
b %= a;

@@ -295,3 +322,3 @@ }

const gcd = this.gcd(numerator, denominator);
if (gcd > 1n) {
if (gcd > _1N) {
numerator /= gcd;

@@ -301,3 +328,3 @@ denominator /= gcd;

if (denominator < 0n) {
if (denominator < _0N) {
numerator = -numerator;

@@ -313,3 +340,3 @@ denominator = -denominator;

if (denominator === 1n) {
if (denominator === _1N) {
return new FixedNumber(numerator, 0);

@@ -339,4 +366,4 @@ }

sign(): -1 | 1 {
const numeratorSign = this.numerator < 0n ? -1 : 1;
const denominatorSign = this.denominator < 0n ? -1 : 1;
const numeratorSign = this.numerator < _0N ? -1 : 1;
const denominatorSign = this.denominator < _0N ? -1 : 1;
return (numeratorSign * denominatorSign) as -1 | 1;

@@ -347,4 +374,4 @@ }

const res = new Fraction(
this.numerator < 0n ? -this.numerator : this.numerator,
this.denominator < 0n ? -this.denominator : this.denominator,
this.numerator < _0N ? -this.numerator : this.numerator,
this.denominator < _0N ? -this.denominator : this.denominator,
);

@@ -355,3 +382,3 @@ return res;

neg() {
return this.mul(-1n);
return this.mul(-_1N);
}

@@ -412,3 +439,3 @@

isZero() {
return this.numerator === 0n;
return this.numerator === _0N;
}

@@ -421,3 +448,3 @@

isInteger() {
return this.numerator % this.denominator === 0n;
return this.numerator % this.denominator === _0N;
}

@@ -467,7 +494,7 @@

let d = this.denominator < 0 ? -this.denominator : this.denominator;
let d = this.denominator < _0N ? -this.denominator : this.denominator;
let twoExp = 0;
while (d % 2n === 0n) {
d /= 2n;
while (d % _2N === _0N) {
d /= _2N;
twoExp++;

@@ -477,4 +504,4 @@ }

let fiveExp = 0;
while (d % 5n === 0n) {
d /= 5n;
while (d % _5N === _0N) {
d /= _5N;
fiveExp++;

@@ -485,3 +512,3 @@ }

if (d === 1n) {
if (d === _1N) {
return { cycleLen: 0, cycleStart };

@@ -492,7 +519,7 @@ }

let rem = 10n % d;
let rem = _10N % d;
let cycleLen = 1;
// 10^l ≡ 1 (mod d)
while (rem !== 1n) {
while (rem !== _1N) {
if (cycleLen === end) {

@@ -502,3 +529,3 @@ // abort calculation

}
rem = (rem * 10n) % d;
rem = (rem * _10N) % d;
cycleLen++;

@@ -510,6 +537,6 @@ }

toFixed(decimals: number, roundingMode = RoundingMode.TO_ZERO): string {
toFixed(decimals: number, roundingMode = RoundingMode.TO_ZERO, trimZeros = false): string {
if (!Number.isSafeInteger(decimals) || decimals < 0) throw new Error('Invalid parameter');
return this.round(decimals, roundingMode).toFixed(decimals);
return this.round(decimals, roundingMode).toFixed(decimals, RoundingMode.TO_ZERO, trimZeros);
}

@@ -528,3 +555,3 @@

const str = this.toFixed(outputDigits);
const parts = trimTrailingZeros(str).split('.');
const parts = trimTrailingZerosFromFixed(str).split('.');
return [parts[0], parts[1] ?? '', ''];

@@ -555,7 +582,7 @@ }

toExponential(digits: number, roundingMode = RoundingMode.TO_ZERO): string {
toExponential(digits: number, roundingMode = RoundingMode.TO_ZERO, trimZeros = false): string {
if (!Number.isSafeInteger(digits) || digits < 0) throw new Error('Invalid parameters');
const fixedNum = this.toFixedNumber(digits);
return fixedNum.toExponential(digits, roundingMode);
return fixedNum.toExponential(digits, roundingMode, trimZeros);
}

@@ -570,3 +597,3 @@

private toFixedNumber(digits: number): FixedNumber {
const numerator = this.numerator * 10n ** BigInt(digits);
const numerator = this.numerator * _10N ** BigInt(digits);
const fixedNum = new FixedNumber(numerator / this.denominator, digits);

@@ -584,3 +611,5 @@ return fixedNum;

if (radix === 10) {
return maxDigits === undefined ? this.toRepeatingDigits(maxDigits) : trimTrailingZeros(this.toFixed(maxDigits));
return maxDigits === undefined
? this.toRepeatingDigits(maxDigits)
: trimTrailingZerosFromFixed(this.toFixed(maxDigits));
}

@@ -627,3 +656,7 @@

return [isNegative ? '-' : '', intPart.toString(radix), digits.length ? '.' : '', ...digits].join('');
const digitsStr = digits.join('');
const res = `${isNegative ? '-' : ''}${intPart.toString(radix)}${digits.length ? '.' : ''}${digitsStr}`;
return res;
}

@@ -639,6 +672,6 @@

toPrecision(digits: number, roundingMode = RoundingMode.TO_ZERO): string {
toPrecision(digits: number, roundingMode = RoundingMode.TO_ZERO, trimZeros = false): string {
if (!Number.isSafeInteger(digits) || digits < 1) throw new Error('Invalid parameter');
return this.roundToDigits(digits, roundingMode).toPrecision(digits);
return this.roundToDigits(digits, roundingMode).toPrecision(digits, RoundingMode.TO_ZERO, trimZeros);
}

@@ -645,0 +678,0 @@

@@ -9,3 +9,2 @@ import * as API from '.';

'ModType',
'trimTrailingZeros',
'nthroot',

@@ -12,0 +11,0 @@ 'sqrt',

@@ -5,4 +5,8 @@ export { ExactNumber } from './ExactNumber';

export { trimTrailingZeros } from './util';
export * from './approx';
export { nthroot, sqrt, cbrt } from './approx/roots';
export { pow, exp } from './approx/exponential';
export { log, logn, log10, log2 } from './approx/logarithm';
export { PI, sin, cos, tan } from './approx/trigonometry';
export { asin, acos, atan } from './approx/inverse_trigonometry';
export { sinh, cosh, tanh } from './approx/hyperbolic';
export { asinh, acosh, atanh } from './approx/inverse_hyperbolic';

@@ -50,8 +50,8 @@ import { Fraction } from './Fraction';

/** Returns b^e mod m (modular exponentiation) */
// modpow(
// exponent: number | bigint | string | ExactNumberType,
// modulus: number | bigint | string | ExactNumberType,
// type?: ModType,
// ): ExactNumberType;
/** Returns modulo of this number exponentiated to the given value (modular exponentiation) */
powm(
exponent: number | bigint | string | ExactNumberType,
modulus: number | bigint | string | ExactNumberType,
type?: ModType,
): ExactNumberType;

@@ -166,3 +166,3 @@ /** Returns the result of the division of this number by the given one. */

*/
toFixed(decimals: number, roundingMode?: RoundingMode): string;
toFixed(decimals: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;

@@ -172,3 +172,3 @@ /** Returns a string representing the number in exponential notation.

*/
toExponential(digits: number, roundingMode?: RoundingMode): string;
toExponential(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;

@@ -179,3 +179,3 @@ /** Returns a string representing the number using fixed-point notation, rounded to the specified number of significant digits.

*/
toPrecision(digits: number, roundingMode?: RoundingMode): string;
toPrecision(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string;

@@ -182,0 +182,0 @@ /** Converts current value to a JavaScript Number */

@@ -1,24 +0,24 @@

import { trimTrailingZeros } from './util';
import { trimTrailingZerosFromFixed } from './util';
describe('Util functions', () => {
it('trimTrailingZeros()', () => {
expect(trimTrailingZeros('0')).toBe('0');
expect(trimTrailingZeros('-0')).toBe('-0');
expect(trimTrailingZeros('00000')).toBe('00000');
expect(trimTrailingZeros('0.0000')).toBe('0');
expect(trimTrailingZeros('.0000')).toBe('0');
expect(trimTrailingZeros('.0001')).toBe('.0001');
expect(trimTrailingZeros('-.00010')).toBe('-.0001');
expect(trimTrailingZeros('-123.0000')).toBe('-123');
expect(trimTrailingZeros('-123.002')).toBe('-123.002');
expect(trimTrailingZeros('-123.0020')).toBe('-123.002');
expect(trimTrailingZeros('100.00')).toBe('100');
expect(trimTrailingZeros('1231.')).toBe('1231');
expect(trimTrailingZeros('1230.0')).toBe('1230');
expect(trimTrailingZeros('1230.2304')).toBe('1230.2304');
expect(trimTrailingZeros('001230.0')).toBe('001230');
expect(trimTrailingZeros('-001230.01')).toBe('-001230.01');
expect(trimTrailingZeros('001230.010')).toBe('001230.01');
expect(trimTrailingZeros('001230.01000000')).toBe('001230.01');
it('trimTrailingZerosFromFixed()', () => {
expect(trimTrailingZerosFromFixed('0')).toBe('0');
expect(trimTrailingZerosFromFixed('-0')).toBe('-0');
expect(trimTrailingZerosFromFixed('00000')).toBe('00000');
expect(trimTrailingZerosFromFixed('0.0000')).toBe('0');
expect(trimTrailingZerosFromFixed('.0000')).toBe('0');
expect(trimTrailingZerosFromFixed('.0001')).toBe('.0001');
expect(trimTrailingZerosFromFixed('-.00010')).toBe('-.0001');
expect(trimTrailingZerosFromFixed('-123.0000')).toBe('-123');
expect(trimTrailingZerosFromFixed('-123.002')).toBe('-123.002');
expect(trimTrailingZerosFromFixed('-123.0020')).toBe('-123.002');
expect(trimTrailingZerosFromFixed('100.00')).toBe('100');
expect(trimTrailingZerosFromFixed('1231.')).toBe('1231');
expect(trimTrailingZerosFromFixed('1230.0')).toBe('1230');
expect(trimTrailingZerosFromFixed('1230.2304')).toBe('1230.2304');
expect(trimTrailingZerosFromFixed('001230.0')).toBe('001230');
expect(trimTrailingZerosFromFixed('-001230.01')).toBe('-001230.01');
expect(trimTrailingZerosFromFixed('001230.010')).toBe('001230.01');
expect(trimTrailingZerosFromFixed('001230.01000000')).toBe('001230.01');
});
});

@@ -0,1 +1,2 @@

/* eslint-disable @typescript-eslint/naming-convention */
import { FixedNumber } from './FixedNumber';

@@ -5,3 +6,3 @@ import { ExactNumberType, RoundingMode } from './types';

/** Trims trailing zeros from numbers in fixed-point format (1.23000 -> 1.23) */
export const trimTrailingZeros = (num: string): string => {
export const trimTrailingZerosFromFixed = (num: string): string => {
const pointPos = num.indexOf('.');

@@ -43,3 +44,3 @@ if (pointPos === -1) return num;

if (trimZeros) {
str = trimTrailingZeros(str);
str = trimTrailingZerosFromFixed(str);
}

@@ -49,3 +50,3 @@ } else {

}
} else if (outputDecimals > 0) {
} else if (outputDecimals > 0 && !trimZeros) {
str = `${str}.${'0'.repeat(outputDecimals)}`;

@@ -67,12 +68,11 @@ }

// export const modpow = (base: bigint, exp: bigint, mod: bigint) => {
// let res = 1n;
// while (exp > 0n) {
// if (exp % 2n) {
// res = (res * base) % mod;
// }
// base = base ** 2n % mod;
// exp /= 2n;
// }
// return res;
// };
// BigInt literals (1n) are not supported by all parsers
// also, the BigInt() constructor is still too slow to call in a loop
export const _0N = BigInt(0);
export const _1N = BigInt(1);
export const _2N = BigInt(2);
export const _3N = BigInt(3);
export const _4N = BigInt(4);
export const _5N = BigInt(5);
export const _10N = BigInt(10);
export const _24N = BigInt(24);
/* eslint-disable no-console */
import { ExactNumberType } from 'src';
import { sin, cos, tan, sqrt, cbrt } from '../src/approx';
import { ExactNumberType, sin, cos, tan, sqrt, cbrt } from 'src';

@@ -5,0 +4,0 @@ function run(name: string, fn: (digits: number) => ExactNumberType) {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc