1
- import BN from "bn.js" ;
2
-
3
1
import { Uint32 , Uint53 , Uint64 } from "./integers" ;
4
2
5
3
// Too large values lead to massive memory usage. Limit to something sensible.
@@ -93,7 +91,10 @@ export class Decimal {
93
91
94
92
public static compare ( a : Decimal , b : Decimal ) : number {
95
93
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 ;
97
98
}
98
99
99
100
public get atomics ( ) : string {
@@ -105,7 +106,7 @@ export class Decimal {
105
106
}
106
107
107
108
private readonly data : {
108
- readonly atomics : BN ;
109
+ readonly atomics : bigint ;
109
110
readonly fractionalDigits : number ;
110
111
} ;
111
112
@@ -117,7 +118,7 @@ export class Decimal {
117
118
}
118
119
119
120
this . data = {
120
- atomics : new BN ( atomics ) ,
121
+ atomics : BigInt ( atomics ) ,
121
122
fractionalDigits : fractionalDigits ,
122
123
} ;
123
124
}
@@ -129,36 +130,36 @@ export class Decimal {
129
130
130
131
/** Returns the greatest decimal <= this which has no fractional part (rounding down) */
131
132
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 ;
135
136
136
- if ( fractional . isZero ( ) ) {
137
+ if ( fractional === 0n ) {
137
138
return this . clone ( ) ;
138
139
} else {
139
- return Decimal . fromAtomics ( whole . mul ( factor ) . toString ( ) , this . fractionalDigits ) ;
140
+ return Decimal . fromAtomics ( ( whole * factor ) . toString ( ) , this . fractionalDigits ) ;
140
141
}
141
142
}
142
143
143
144
/** Returns the smallest decimal >= this which has no fractional part (rounding up) */
144
145
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 ;
148
149
149
- if ( fractional . isZero ( ) ) {
150
+ if ( fractional === 0n ) {
150
151
return this . clone ( ) ;
151
152
} else {
152
- return Decimal . fromAtomics ( whole . addn ( 1 ) . mul ( factor ) . toString ( ) , this . fractionalDigits ) ;
153
+ return Decimal . fromAtomics ( ( ( whole + 1n ) * factor ) . toString ( ) , this . fractionalDigits ) ;
153
154
}
154
155
}
155
156
156
157
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 ;
160
161
161
- if ( fractional . isZero ( ) ) {
162
+ if ( fractional === 0n ) {
162
163
return whole . toString ( ) ;
163
164
} else {
164
165
const fullFractionalPart = fractional . toString ( ) . padStart ( this . data . fractionalDigits , "0" ) ;
@@ -184,7 +185,7 @@ export class Decimal {
184
185
*/
185
186
public plus ( b : Decimal ) : Decimal {
186
187
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 ) ;
188
189
return new Decimal ( sum . toString ( ) , this . fractionalDigits ) ;
189
190
}
190
191
@@ -196,8 +197,8 @@ export class Decimal {
196
197
*/
197
198
public minus ( b : Decimal ) : Decimal {
198
199
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" ) ;
201
202
return new Decimal ( difference . toString ( ) , this . fractionalDigits ) ;
202
203
}
203
204
@@ -207,7 +208,7 @@ export class Decimal {
207
208
* We only allow multiplication by unsigned integers to avoid rounding errors.
208
209
*/
209
210
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 ( ) ) ;
211
212
return new Decimal ( product . toString ( ) , this . fractionalDigits ) ;
212
213
}
213
214
0 commit comments