Skip to content

Commit 8ec61a6

Browse files
authored
Merge pull request #94 from hyperweb-io/enhance-decimal
enhance decimal
2 parents 51ec43a + cec11b4 commit 8ec61a6

File tree

1 file changed

+24
-23
lines changed

1 file changed

+24
-23
lines changed

packages/math/src/decimal.ts

+24-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import BN from "bn.js";
2-
31
import { Uint32, Uint53, Uint64 } from "./integers";
42

53
// Too large values lead to massive memory usage. Limit to something sensible.
@@ -93,7 +91,10 @@ export class Decimal {
9391

9492
public static compare(a: Decimal, b: Decimal): number {
9593
if (a.fractionalDigits !== b.fractionalDigits) throw new Error("Fractional digits do not match");
96-
return a.data.atomics.cmp(new BN(b.atomics));
94+
const diff = a.data.atomics - BigInt(b.atomics);
95+
if (diff < 0n) return -1;
96+
if (diff > 0n) return 1;
97+
return 0;
9798
}
9899

99100
public get atomics(): string {
@@ -105,7 +106,7 @@ export class Decimal {
105106
}
106107

107108
private readonly data: {
108-
readonly atomics: BN;
109+
readonly atomics: bigint;
109110
readonly fractionalDigits: number;
110111
};
111112

@@ -117,7 +118,7 @@ export class Decimal {
117118
}
118119

119120
this.data = {
120-
atomics: new BN(atomics),
121+
atomics: BigInt(atomics),
121122
fractionalDigits: fractionalDigits,
122123
};
123124
}
@@ -129,36 +130,36 @@ export class Decimal {
129130

130131
/** Returns the greatest decimal <= this which has no fractional part (rounding down) */
131132
public floor(): Decimal {
132-
const factor = new BN(10).pow(new BN(this.data.fractionalDigits));
133-
const whole = this.data.atomics.div(factor);
134-
const fractional = this.data.atomics.mod(factor);
133+
const factor = BigInt(10) ** BigInt(this.data.fractionalDigits);
134+
const whole = this.data.atomics / factor;
135+
const fractional = this.data.atomics % factor;
135136

136-
if (fractional.isZero()) {
137+
if (fractional === 0n) {
137138
return this.clone();
138139
} else {
139-
return Decimal.fromAtomics(whole.mul(factor).toString(), this.fractionalDigits);
140+
return Decimal.fromAtomics((whole * factor).toString(), this.fractionalDigits);
140141
}
141142
}
142143

143144
/** Returns the smallest decimal >= this which has no fractional part (rounding up) */
144145
public ceil(): Decimal {
145-
const factor = new BN(10).pow(new BN(this.data.fractionalDigits));
146-
const whole = this.data.atomics.div(factor);
147-
const fractional = this.data.atomics.mod(factor);
146+
const factor = BigInt(10) ** BigInt(this.data.fractionalDigits);
147+
const whole = this.data.atomics / factor;
148+
const fractional = this.data.atomics % factor;
148149

149-
if (fractional.isZero()) {
150+
if (fractional === 0n) {
150151
return this.clone();
151152
} else {
152-
return Decimal.fromAtomics(whole.addn(1).mul(factor).toString(), this.fractionalDigits);
153+
return Decimal.fromAtomics(((whole + 1n) * factor).toString(), this.fractionalDigits);
153154
}
154155
}
155156

156157
public toString(): string {
157-
const factor = new BN(10).pow(new BN(this.data.fractionalDigits));
158-
const whole = this.data.atomics.div(factor);
159-
const fractional = this.data.atomics.mod(factor);
158+
const factor = BigInt(10) ** BigInt(this.data.fractionalDigits);
159+
const whole = this.data.atomics / factor;
160+
const fractional = this.data.atomics % factor;
160161

161-
if (fractional.isZero()) {
162+
if (fractional === 0n) {
162163
return whole.toString();
163164
} else {
164165
const fullFractionalPart = fractional.toString().padStart(this.data.fractionalDigits, "0");
@@ -184,7 +185,7 @@ export class Decimal {
184185
*/
185186
public plus(b: Decimal): Decimal {
186187
if (this.fractionalDigits !== b.fractionalDigits) throw new Error("Fractional digits do not match");
187-
const sum = this.data.atomics.add(new BN(b.atomics));
188+
const sum = this.data.atomics + BigInt(b.atomics);
188189
return new Decimal(sum.toString(), this.fractionalDigits);
189190
}
190191

@@ -196,8 +197,8 @@ export class Decimal {
196197
*/
197198
public minus(b: Decimal): Decimal {
198199
if (this.fractionalDigits !== b.fractionalDigits) throw new Error("Fractional digits do not match");
199-
const difference = this.data.atomics.sub(new BN(b.atomics));
200-
if (difference.ltn(0)) throw new Error("Difference must not be negative");
200+
const difference = this.data.atomics - BigInt(b.atomics);
201+
if (difference < 0n) throw new Error("Difference must not be negative");
201202
return new Decimal(difference.toString(), this.fractionalDigits);
202203
}
203204

@@ -207,7 +208,7 @@ export class Decimal {
207208
* We only allow multiplication by unsigned integers to avoid rounding errors.
208209
*/
209210
public multiply(b: Uint32 | Uint53 | Uint64): Decimal {
210-
const product = this.data.atomics.mul(new BN(b.toString()));
211+
const product = this.data.atomics * BigInt(b.toString());
211212
return new Decimal(product.toString(), this.fractionalDigits);
212213
}
213214

0 commit comments

Comments
 (0)