UNPKG

exactnumber

Version:

Arbitrary-precision decimals. Enables making math calculations with rational numbers, without precision loss.

8 lines (6 loc) 22.7 kB
/*! * exactnumber v2.0.1 (https://www.npmjs.com/package/exactnumber) * (c) Dani Biro * @license MIT */ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).exactnumber={})}(this,function(t){"use strict";var e,r;t.RoundingMode=void 0,(e=t.RoundingMode||(t.RoundingMode={}))[e.NEAREST_TO_POSITIVE=201008]="NEAREST_TO_POSITIVE",e[e.NEAREST_TO_NEGATIVE=201009]="NEAREST_TO_NEGATIVE",e[e.NEAREST_TO_EVEN=201010]="NEAREST_TO_EVEN",e[e.NEAREST_TO_ZERO=201011]="NEAREST_TO_ZERO",e[e.NEAREST_AWAY_FROM_ZERO=201012]="NEAREST_AWAY_FROM_ZERO",e[e.TO_POSITIVE=201001]="TO_POSITIVE",e[e.TO_NEGATIVE=201002]="TO_NEGATIVE",e[e.TO_ZERO=201003]="TO_ZERO",e[e.AWAY_FROM_ZERO=201004]="AWAY_FROM_ZERO",t.ModType=void 0,(r=t.ModType||(t.ModType={})).TRUNCATED="T",r.FLOORED="F",r.EUCLIDEAN="E";const n=t=>{const e=t.indexOf(".");if(-1===e)return t;let r=t.length;for(;r>e&&"0"===t.charAt(r-1);)r--;const n=e===r-1?e:r;return 0===n?"0":t.slice(0,n)},i=(t,e,r,i)=>{let o=t.toString();if(0===e&&0===r)return o;const s=o.startsWith("-");if(s&&(o=o.slice(1)),e>=o.length&&(o="0".repeat(e-o.length+1)+o),e>0){const t=o.slice(0,-e),s=o.slice(-e),a=r<=e?s.slice(0,r):`${s}${"0".repeat(r-e)}`;0!==a.length?(o=`${t}.${a}`,i&&(o=n(o))):o=t}else r>0&&!i&&(o=`${o}.${"0".repeat(r)}`);return s?`-${o}`:o},o=BigInt(0),s=BigInt(1),a=BigInt(2);BigInt(3),BigInt(4);const u=BigInt(5),m=BigInt(10),h=BigInt(24);class c{parseConstructorParameter(t){if(t instanceof c)return{number:t.number,decimalPos:t.decimalPos};if(t instanceof d){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 e=t.match(/^(-?[0-9]*)(?:\.([0-9]*))?(?:[eE]([+-]?[0-9]+))?$/);if(!e)throw new Error(`Cannot parse number "${t}"`);let r=0,n=e[1]??"0";if(void 0!==e[2]&&(n+=e[2],r+=e[2].length),void 0!==e[3]){const t=Number(e[3]);t>0?n+="0".repeat(t):r-=t}return{number:BigInt(n),decimalPos:r}}throw new Error("Unsupported parameter!")}constructor(t,e=0){if(this.type="fixed","bigint"==typeof t)this.number=t,this.decimalPos=e;else{const e=this.parseConstructorParameter(t);this.number=e.number,this.decimalPos=e.decimalPos}}scaleNumber(t,e){const r=Math.max(this.decimalPos,e);return{a:r===this.decimalPos?this.number:this.number*m**BigInt(r-this.decimalPos),b:r===e?t:t*m**BigInt(r-e),decimalPos:r}}add(t){const e=l(t);if(e instanceof d)return e.add(this);const r=e,{a:n,b:i,decimalPos:o}=this.scaleNumber(r.number,r.decimalPos);return new c(n+i,o)}sub(t){const e=l(t);return this.add(e.neg())}mul(t){const e=l(t);if(e instanceof d)return e.mul(this);const r=e,n=this.number*r.number;return new c(n,this.decimalPos+r.decimalPos)}pow(t){const e=l(t).toNumber();if(!Number.isSafeInteger(e))throw new Error("Unsupported parameter");const r=Math.abs(e),n=new c(this.number**BigInt(r),this.decimalPos*r);return e<0?n.inv():n}powm(t,e,r){let n=l(t).toNumber();if(!Number.isSafeInteger(n))throw new Error("Unsupported parameter");const i=l(e);let o=this,u=new c(s);for(;0!==n;)n%2!=0&&(u=u.mul(o).mod(i,r)),o=o.pow(a).mod(i,r),n=Math.floor(n/2);return u}div(t){return this.convertToFraction().div(t)}divToInt(t){const e=l(t);if(e instanceof d)return this.convertToFraction().divToInt(e);const r=e,{a:n,b:i}=this.scaleNumber(r.number,r.decimalPos);return new c(n/i)}mod(e,r=t.ModType.TRUNCATED){const n=l(e);if(n instanceof d)return this.convertToFraction().mod(n);const i=n,{a:s,b:a,decimalPos:u}=this.scaleNumber(i.number,i.decimalPos),m=s%a,h=new c(m,u);if(r===t.ModType.TRUNCATED)return h;if(r===t.ModType.FLOORED)return Number(s<o)^Number(a<o)?h.add(a):h;if(r===t.ModType.EUCLIDEAN)return m<o?h.add(a<o?-a:a):h;throw new Error("Invalid ModType")}abs(){return new c(this.number<o?-this.number:this.number,this.decimalPos)}neg(){return this.mul(-s)}inv(){return this.convertToFraction().inv()}floor(e){return 0===this.decimalPos?this:this.round(e,t.RoundingMode.TO_NEGATIVE)}ceil(e){return 0===this.decimalPos?this:this.round(e,t.RoundingMode.TO_POSITIVE)}trunc(e){return 0===this.decimalPos?this:this.round(e,t.RoundingMode.TO_ZERO)}isTieStr(t){if("5"!==t[0])return!1;for(let e=1;e<t.length;e++)if("0"!==t[e])return!1;return!0}_round(e,r){const n=this.decimalPos-e;if(n<=0)return this;const i=m**BigInt(n),u=this.number/i;if(r===t.RoundingMode.TO_ZERO)return new c(u,e);const h=this.number%i;if(h===o)return new c(u,e);if(r===t.RoundingMode.AWAY_FROM_ZERO){const t=this.number<o?u-s:u+s;return new c(t,e)}if(r===t.RoundingMode.TO_POSITIVE){const t=this.number<o?u:u+s;return new c(t,e)}if(r===t.RoundingMode.TO_NEGATIVE){const t=this.number>=o?u:u-s;return new c(t,e)}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(r))throw new Error("Invalid rounding mode. Use the predefined values from the RoundingMode enum.");let d=(h<o?-h:h).toString();if(d.length<n&&(d="0"),this.isTieStr(d)){if(r===t.RoundingMode.NEAREST_TO_ZERO)return new c(u,e);if(r===t.RoundingMode.NEAREST_AWAY_FROM_ZERO){const t=this.number<o?u-s:u+s;return new c(t,e)}if(void 0===r||r===t.RoundingMode.NEAREST_TO_POSITIVE){const t=this.number<o?u:u+s;return new c(t,e)}if(r===t.RoundingMode.NEAREST_TO_NEGATIVE){const t=this.number>=o?u:u-s;return new c(t,e)}if(r===t.RoundingMode.NEAREST_TO_EVEN){if(u%a===o)return new c(u,e);return new c(u<o?u-s:u+s,e)}}if(Number(d[0])<5)return new c(u,e);const l=this.number<o?u-s:u+s;return new c(l,e)}round(t,e){if(t=void 0===t?0:t,!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for decimals");return this._round(t,e).normalize()}limitDecimals(t,e){return this.round(t,e)}_incExponent(t){if(0===t)return this;let e=this.number,r=this.decimalPos;if(t<0)r-=t;else{const n=Math.min(t,this.decimalPos);r-=n;const i=t-n;i>0&&(e*=m**BigInt(i))}return new c(e,r)}countDigits(){if(this.number===o)return 1;let t=0,e=this.number<o?-this.number:this.number;for(;e>o;)e/=m,t++;return t}toSubZeroNum(){const t=this.countDigits();return{subZeroNum:new c(this.number,t),exponentDiff:t-this.decimalPos}}roundToDigits(t,e){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid value for digits");const{subZeroNum:r,exponentDiff:n}=this.toSubZeroNum();let i=r.round(t,e);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=g(t),!this.isInteger()||this.isNegative()||!t.isInteger()||t.isNegative())throw new Error("Only positive integers are supported");t instanceof d&&(t=t.trunc());const e=a**h;let r=this.normalize().number,n=t.trunc().normalize().number,i=o,u=s;for(;r>o&&n>o;){const t=BigInt.asUintN(24,r),o=BigInt.asUintN(24,n);i+=BigInt(Number(t)&Number(o))*u,u*=e,r/=e,n/=e}return new c(i)}bitwiseOr(t){if(t=g(t),!this.isInteger()||this.isNegative()||!t.isInteger()||t.isNegative())throw new Error("Only positive integers are supported");t instanceof d&&(t=t.trunc());const e=a**h;let r=this.normalize().number,n=t.trunc().normalize().number,i=o,u=s;for(;r>o||n>o;){const t=BigInt.asUintN(24,r),o=BigInt.asUintN(24,n);i+=BigInt(Number(t)|Number(o))*u,u*=e,r/=e,n/=e}return new c(i)}bitwiseXor(t){if(t=g(t),!this.isInteger()||this.isNegative()||!t.isInteger()||t.isNegative())throw new Error("Only positive integers are supported");t instanceof d&&(t=t.trunc());const e=a**h;let r=this.normalize().number,n=t.trunc().normalize().number,i=o,u=s;for(;r>o||n>o;){const t=BigInt.asUintN(24,r),o=BigInt.asUintN(24,n);i+=BigInt(Number(t)^Number(o))*u,u*=e,r/=e,n/=e}return new c(i)}shiftLeft(t){if(!this.isInteger()||this.isNegative())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for bitCount");const e=a**BigInt(t);return this.mul(e)}shiftRight(t){if(!this.isInteger()||this.isNegative())throw new Error("Only positive integers are supported");if(!Number.isSafeInteger(t)||t<0)throw new Error("Invalid value for bitCount");const e=a**BigInt(t);return new c(this.normalize().number/e)}cmp(t){const e=l(t);if(e instanceof d)return-e.cmp(this);const r=e,{a:n,b:i}=this.scaleNumber(r.number,r.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,e){const r=g(t),n=g(e);if(r.gt(n))throw new Error("Min parameter has to be smaller than max");return this.lt(r)?r:this.gt(n)?n:this}isZero(){return this.number===o}isOne(){if(0===this.decimalPos)return this.number===s;const t=m**BigInt(this.decimalPos),e=this.number/t;return e===s&&e*t===this.number}isInteger(){return 0===this.decimalPos||this.number%m**BigInt(this.decimalPos)===o}isNegative(){return-1===this.sign()}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,e=this.number;for(;t>0&&e%m===o;)t--,e/=m;return new c(e,t)}convertToFraction(){if(0===this.decimalPos)return new d(this.number,s);const t=m**BigInt(this.decimalPos);return new d(this.number,t)}toNumber(){return Number(this.toPrecision(20))}toFixed(e,r=t.RoundingMode.TO_ZERO,n=!1){if(!Number.isSafeInteger(e)||e<0)throw new Error("Invalid parameter");const o=this._round(e,r);return i(o.number,o.decimalPos,e,n)}toExponential(e,r=t.RoundingMode.TO_ZERO,i=!1){if(!Number.isSafeInteger(e)||e<0)throw new Error("Invalid parameter");const o=this.roundToDigits(e+1,r).normalize(),s=o.isNegative(),a=o.abs(),u=a.number.toString(),m=u.length<=e?`${u}${"0".repeat(e-u.length+1)}`:u.slice(0,e+1);let h=m;m.length>1&&(h=`${m.slice(0,1)}.${m.slice(1)}`,i&&(h=n(h)));const c=a.decimalPos,d=u.length-1-c;return`${s?"-":""}${h}e${d>=0?"+":""}${d}`}toBase(t,e){if(!Number.isSafeInteger(t)||t<2||t>16)throw new Error("Invalid radix");if(void 0!==e&&(!Number.isSafeInteger(e)||e<0))throw new Error("Invalid parameter");const r=this.normalize();if(0===r.decimalPos)return r.number.toString(t);const n=void 0===e?Number.MAX_SAFE_INTEGER:e;let i=r.intPart(),o=r.sub(i);const s=r.isNegative();s&&(i=i.neg(),o=o.neg());const a=new Map;let u=[];for(;!o.isZero();){const e=o.mul(t),r=e.toString(),i=a.get(r);if(void 0!==i){u=[...u.slice(0,i-1),"(",...u.slice(i-1),")"];break}if(u.length===n)break;const s=Math.abs(e.intPart().toNumber());u.push(s.toString(t)),o=e.fracPart(),a.set(r,u.length)}const m=u.join("");return`${s?"-":""}${i.number.toString(t)}${u.length?".":""}${m}`}toFraction(){return this.convertToFraction().toFraction()}toString(t,e){if(void 0===t||10===t){const t=void 0!==e?this.trunc(e):this;return i(t.number,t.decimalPos,t.decimalPos,!0)}return this.toBase(t,e)}toPrecision(e,r=t.RoundingMode.TO_ZERO,o=!1){if(!Number.isSafeInteger(e)||e<1)throw new Error("Invalid parameter");const s=this.roundToDigits(e,r),{subZeroNum:a,exponentDiff:u}=s.toSubZeroNum(),m=a.isNegative();let h=i(a.number,a.decimalPos,a.decimalPos,!1);h=h.slice(m?3:2),h=h.slice(0,Math.max(e,u));const c=h.slice(0,Math.max(0,u)),d=h.slice(Math.max(0,u)),l=Math.max(0,e-c.length-d.length),g="0".repeat(u<0?-u:0);let f=c||"0";if(d.length+g.length+l>0){f+=`.${g}${d}${"0".repeat(l)}`,o&&(f=n(f))}return m?`-${f}`:f}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}class d{parseRepeatingDecimal(t){if(!t.includes("("))return new c(t).convertToFraction();const e=(t=t.trim()).match(/^(-?[0-9]*)\.([0-9]+)?\(([0-9]+)\)(?:[eE]([+-]?[0-9]+))?$/);if(!e)throw new Error(`Cannot parse string "${t}"`);const r="-"===e[1]?"-0":e[1],n=e[2]??"",i=e[3],o=e[4],s=BigInt(r+n+i)-BigInt(r+n),a=BigInt("9".repeat(i.length)+"0".repeat(n.length)),u=new d(s,a);if(void 0!==o){const t=o.startsWith("-"),e=m**BigInt(t?o.slice(1):o);return t?u.div(e).normalize():u.mul(e).normalize()}return u.simplify()}parseParameter(t){if(t instanceof d)return t;if(t instanceof c)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 d(BigInt(t),s)}if("bigint"==typeof t)return new d(t,s);if("string"==typeof t){const e=t.split("/");if(e.length>2)throw new Error(`Cannot parse string '${t}'`);const r=this.parseRepeatingDecimal(e[0]),n=e[1]?this.parseRepeatingDecimal(e[1]):new d(s,s);return r.div(n).convertToFraction()}throw new Error("Unsupported parameter!")}constructor(t,e){if(this.type="fraction","bigint"==typeof t&&"bigint"==typeof e)this.numerator=t,this.denominator=e;else{const r=this.parseParameter(t),n=this.parseParameter(e),i=r.div(n),o=i instanceof c?i.convertToFraction():i;this.numerator=o.numerator,this.denominator=o.denominator}if(this.denominator===o)throw new Error("Division by zero")}add(t){const{numerator:e,denominator:r}=this.parseParameter(t);return this.denominator===r?new d(this.numerator+e,this.denominator):new d(this.numerator*r+e*this.denominator,r*this.denominator)}sub(t){const{numerator:e,denominator:r}=this.parseParameter(t);return this.add(new d(-e,r))}mul(t){const{numerator:e,denominator:r}=this.parseParameter(t);return new d(this.numerator*e,this.denominator*r)}div(t){const{numerator:e,denominator:r}=this.parseParameter(t);return this.mul(new d(r,e))}divToInt(t){return this.div(t).trunc()}mod(e,r=t.ModType.TRUNCATED){const n=this.parseParameter(e),i=n.denominator*this.numerator%(n.numerator*this.denominator),o=this.denominator*n.denominator,s=new d(i,o);if(r===t.ModType.TRUNCATED)return s;if(r===t.ModType.FLOORED)return Number(this.isNegative())^Number(n.isNegative())?s.add(n):s;if(r===t.ModType.EUCLIDEAN)return s.isNegative()?s.add(n.isNegative()?n.neg():n):s;throw new Error("Invalid ModType")}pow(t){const e=this.parseParameter(t);if(!e.isInteger())throw new Error("Unsupported parameter");const r=e.numerator/e.denominator,n=r<o?-r:r,i=new d(this.numerator**n,this.denominator**n);return r<o?i.inv():i}powm(t,e,r){const n=this.parseParameter(t);if(!n.isInteger())throw new Error("Unsupported parameter");let i=n.toNumber();const o=this.parseParameter(e);let u=this,m=new d(s,s);for(;0!==i;)i%2!=0&&(m=m.mul(u).mod(o,r)),u=u.pow(a).mod(o,r),i=Math.floor(i/2);return m}inv(){return new d(this.denominator,this.numerator)}floor(e){return this.denominator===s?new c(this.numerator):this.round(e,t.RoundingMode.TO_NEGATIVE)}ceil(e){return this.denominator===s?new c(this.numerator):this.round(e,t.RoundingMode.TO_POSITIVE)}trunc(e){return this.denominator===s?new c(this.numerator):this.round(e,t.RoundingMode.TO_ZERO)}round(t,e){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,e);let n=new c(`${r.toFixed(t+1)}1`);r.isNegative()&&!n.isNegative()&&(n=n.neg());return n.round(t,e)}roundToDigits(t,e){if(!Number.isSafeInteger(t)||t<1)throw new Error("Invalid value for digits");if(this.isZero())return new c(o);let r=this.abs(),n=0;for(;r.gte(s);)r=r.div(m),n++;const i=new d(s,m);for(;r.lt(i);)r=r.mul(m),n--;let a=r.round(t,e);return a=a._incExponent(n),this.isNegative()?a.neg():a}limitDecimals(t,e){if(this.denominator===s)return new c(this.numerator,0);const{cycleLen:r,cycleStart:n}=this.getDecimalFormat(t);if(null!==r&&n+r<=t)return this;return this.round(t,e)}gcd(t,e){let r=t<o?-t:t,n=e<o?-e:e;if(n>r){const t=r;r=n,n=t}for(;;){if(n===o)return r;if(r%=n,r===o)return n;n%=r}}simplify(){let{numerator:t,denominator:e}=this;const r=this.gcd(t,e);return r>s&&(t/=r,e/=r),e<o&&(t=-t,e=-e),new d(t,e)}normalize(){const{numerator:e,denominator:r}=this.simplify();if(r===s)return new c(e,0);const n=new d(e,r),{cycleLen:i,cycleStart:o}=n.getDecimalFormat(0);return 0!==i?n:n.round(o,t.RoundingMode.TO_ZERO)}getFractionParts(t=!0){const e=t?this.simplify():this;return{numerator:new c(e.numerator),denominator:new c(e.denominator)}}sign(){return(this.numerator<o?-1:1)*(this.denominator<o?-1:1)}abs(){return new d(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 e=this.parseParameter(t),r=this.denominator===e.denominator,n=r?this.numerator:this.numerator*e.denominator,i=r?e.numerator:e.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,e){const r=g(t),n=g(e);if(r.gt(n))throw new Error("Min parameter has to be smaller than max");return this.lt(r)?r:this.gt(n)?n:this}isZero(){return this.numerator===o}isOne(){return this.numerator===this.denominator}isInteger(){return this.numerator%this.denominator===o}isNegative(){return-1===this.sign()}serialize(){return[this.numerator,this.denominator]}toNumber(){return Number(this.toPrecision(20))}convertToFraction(){return this}getNumberForBitwiseOp(){if(!this.isInteger()||this.isNegative())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=t??Number.MAX_SAFE_INTEGER;let e=this.denominator<o?-this.denominator:this.denominator,r=0;for(;e%a===o;)e/=a,r++;let n=0;for(;e%u===o;)e/=u,n++;const i=Math.max(r,n);if(e===s)return{cycleLen:0,cycleStart:i};const h=Math.max(1,t-i);let c=m%e,d=1;for(;c!==s;){if(d===h)return{cycleLen:null,cycleStart:i};c=c*m%e,d++}return{cycleLen:d,cycleStart:i}}toFixed(e,r=t.RoundingMode.TO_ZERO,n=!1){if(!Number.isSafeInteger(e)||e<0)throw new Error("Invalid parameter");return this.round(e,r).toFixed(e,t.RoundingMode.TO_ZERO,n)}toRepeatingParts(t){if(this.isZero())return["0","",""];const{cycleLen:e,cycleStart:r}=this.simplify().getDecimalFormat(t);if(null===e||0===e){const e=t??r,i=this.toFixed(e),o=n(i).split(".");return[o[0],o[1]??"",""]}const i=r+e,o=this.toFixed(i).split(".");return[o[0],o[1].slice(0,r),o[1].slice(r)]}toRepeatingDigits(t){const e=this.toRepeatingParts(t);let r=e[0];return(e[1]||e[2])&&(r+=`.${e[1]}`),e[2]&&(r+=`(${e[2]})`),r}toExponential(e,r=t.RoundingMode.TO_ZERO,n=!1){if(!Number.isSafeInteger(e)||e<0)throw new Error("Invalid parameters");return this.toFixedNumber(e).toExponential(e,r,n)}toFraction(){const{numerator:t,denominator:e}=this.getFractionParts(!0);return`${t.toString()}/${e.toString()}`}toFixedNumber(t){if(this.numerator===o)return new c(0,0);if(this.denominator===s)return new c(this.numerator,0);let e=t,r=this.numerator<0?-this.numerator:this.numerator;for(;r<this.denominator;)r*=m,e++;const n=m**BigInt(e),i=this.numerator*n/this.denominator;return new c(i,e)}toBase(t,e){if(!Number.isSafeInteger(t)||t<2||t>16)throw new Error("Invalid radix");if(void 0!==e&&(!Number.isSafeInteger(e)||e<0))throw new Error("Invalid parameter");if(10===t)return void 0===e?this.toRepeatingDigits(e):n(this.toFixed(e));const r=this.normalize(),i=void 0===e?Number.MAX_SAFE_INTEGER:e+1;let o=r.intPart(),s=r.sub(o);const a=r.isNegative();a&&(o=o.neg(),s=s.neg());const u=new Map;let m=[];for(;!s.isZero()&&m.length!==i;){const e=s.mul(t),r=e.normalize().toFraction(),n=u.get(r);if(void 0!==n){m=[...m.slice(0,n-1),"(",...m.slice(n-1),")"];break}const i=Math.abs(e.intPart().toNumber());m.push(i.toString(t)),s=e.fracPart(),u.set(r,m.length)}m.length===i&&m.pop();const h=m.join("");return`${a?"-":""}${o.toString(t)}${m.length?".":""}${h}`}toString(t,e){return void 0===t||10===t?this.toRepeatingDigits(e):this.toBase(t,e)}toPrecision(e,r=t.RoundingMode.TO_ZERO,n=!1){if(!Number.isSafeInteger(e)||e<1)throw new Error("Invalid parameter");return this.roundToDigits(e,r).toPrecision(e,t.RoundingMode.TO_ZERO,n)}valueOf(){throw new Error("Unsafe conversion to Number type! Use toNumber() instead.")}}function l(t){if(t instanceof c||t instanceof d)return t;if("bigint"==typeof t)return new c(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 c(t)}if("string"==typeof t)return t.includes("/")||t.includes("(")?new d(t,s):new c(t);throw new Error("Unsupported parameter type")}const g=(t,e)=>{if(void 0===t)throw new Error("First parameter cannot be undefined");const r=l(t);if(void 0===e)return r;const n=l(e);return new d(r,s).div(new d(n,s))};g.min=(...t)=>{if(0===t.length)throw new Error("Got empty array");let e=g(t[0]);for(let r=1;r<t.length;r++){const n=g(t[r]);n.lt(e)&&(e=n)}return e},g.max=(...t)=>{if(0===t.length)throw new Error("Got empty array");let e=g(t[0]);for(let r=1;r<t.length;r++){const n=g(t[r]);n.gt(e)&&(e=n)}return e};const f=(t,e)=>{let r=o;for(let n=0;n<t.length;n++){const i=t.charAt(n),o=parseInt(i,e);if(Number.isNaN(o))throw new Error(`Invalid digit "${i}"`);r*=BigInt(e),r+=BigInt(o)}return r};g.fromBase=(t,e)=>{if("string"!=typeof t)throw new Error("First parameter must be string");if(!Number.isSafeInteger(e)||e<2||e>16)throw new Error("Invalid radix");if(10===e)return g(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 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]??"",a=n[3]??"";if(a.length>0){const t=f(`${i}${o}${a}`,e)-f(`${i}${o}`,e),n=f((e-1).toString(e).repeat(a.length)+"0".repeat(o.length),e),s=new d(t,n).normalize();return r?s.neg():s}const u=f(i,e),m=f(o,e),h=new d(m,BigInt(e)**BigInt(o.length)),c=new d(u,s).add(h).normalize();return r?c.neg():c},g.range=function*(t,e,r){const n=g(e),i=g(r??1);let o=g(t);for(;o.lt(n);)yield o,o=o.add(i)},g.isExactNumber=t=>t instanceof c||t instanceof d,g.gcd=(t,e)=>{const r=g(t).abs(),n=g(e).abs();let i=n.gt(r)?n:r,o=i.eq(r)?n:r;for(;;){if(o.isZero())return i;if(i=i.mod(o),i.isZero())return o;o=o.mod(i)}},g.lcm=(t,e)=>{const r=g(t).abs(),n=g(e).abs(),i=r.mul(n);if(i.isZero())throw new Error("LCM of zero is undefined");const o=g.gcd(r,n);return i.div(o)},t.ExactNumber=g});