@@ -23,6 +23,8 @@ const MAX_SIGNIFICANT_DIGITS = 34;
23
23
24
24
const bigTen = BigInt ( 10 ) ;
25
25
const bigOne = BigInt ( 1 ) ;
26
+ const ratOne = new Rational ( 1n , 1n ) ;
27
+ const ratTen = new Rational ( 10n , 1n ) ;
26
28
27
29
type NaNValue = "NaN" ;
28
30
type InfiniteValue = "Infinity" | "-Infinity" ;
@@ -264,8 +266,6 @@ export class Decimal128 {
264
266
let q = this . quantum ( ) as number ;
265
267
let s = v ;
266
268
let e = q ;
267
- const ratTen = new Rational ( bigTen , bigOne ) ;
268
- const ratOne = new Rational ( bigOne , bigOne ) ;
269
269
270
270
while ( s . cmp ( ratOne ) < 0 ) {
271
271
s = s . scale10 ( 1 ) ;
@@ -281,13 +281,34 @@ export class Decimal128 {
281
281
}
282
282
283
283
public exponent ( ) : number {
284
- let [ _ , e ] = this . significandAndExponent ( ) ;
285
- return e ;
284
+ let mantissa = this . mantissa ( ) ;
285
+ let mantissaQuantum = mantissa . quantum ( ) ;
286
+ let ourQuantum = this . quantum ( ) ;
287
+ return ourQuantum - mantissaQuantum ;
286
288
}
287
289
288
290
public mantissa ( ) : Decimal128 {
289
- let [ sig , _ ] = this . significandAndExponent ( ) ;
290
- return new Decimal128 ( sig . toFixed ( MAX_SIGNIFICANT_DIGITS ) ) ;
291
+ if ( this . isZero ( ) ) {
292
+ throw new RangeError ( "Zero does not have a mantissa" ) ;
293
+ }
294
+
295
+ if ( this . isNegative ( ) ) {
296
+ return this . neg ( ) . mantissa ( ) . neg ( ) ;
297
+ }
298
+
299
+ let x : Decimal128 = this ;
300
+ let decimalOne = new Decimal128 ( "1" ) ;
301
+ let decimalTen = new Decimal128 ( "10" ) ;
302
+
303
+ while ( 0 <= x . cmp ( decimalTen ) ) {
304
+ x = x . scale10 ( - 1 ) ;
305
+ }
306
+
307
+ while ( x . cmp ( decimalOne ) === - 1 ) {
308
+ x = x . scale10 ( 1 ) ;
309
+ }
310
+
311
+ return x ;
291
312
}
292
313
293
314
public scale10 ( n : number ) : Decimal128 {
@@ -311,35 +332,37 @@ export class Decimal128 {
311
332
let q = this . quantum ( ) as number ;
312
333
313
334
return new Decimal128 (
314
- new Decimal ( { cohort : v . scale10 ( n ) , quantum : q - n } )
335
+ new Decimal ( { cohort : v . scale10 ( n ) , quantum : q + n } )
315
336
) ;
316
337
}
317
338
318
- private significand ( ) : Rational {
319
- let [ s , _ ] = this . significandAndExponent ( ) ;
320
- return s ;
339
+ private significand ( ) : bigint {
340
+ if ( this . isZero ( ) ) {
341
+ throw new RangeError ( "Zero does not have a significand" ) ;
342
+ }
343
+
344
+ let d = this . d as Decimal ;
345
+ return d . coefficient ( ) ;
321
346
}
322
347
323
348
private emitExponential ( ) : string {
324
- let prefix = this . isNegative ( ) ? "-" : "" ;
325
- let sg = this . significand ( ) . toString ( ) ;
326
- let exp = this . exponent ( ) ;
349
+ let v = this . cohort ( ) ;
350
+ let q = this . quantum ( ) ;
351
+ let p = this . _isNegative ? "-" : "" ;
327
352
328
- let adjustedExponent = exp + sg . length - 1 ;
353
+ if ( v === "0" || v === "-0" ) {
354
+ if ( q < 0 ) {
355
+ return p + v + "." + "0" . repeat ( 0 - q ) ;
356
+ }
329
357
330
- if ( sg . length === 1 ) {
331
- return prefix + sg + "e" + ( exp < 0 ? "" : "+" ) + exp ;
358
+ return v ;
332
359
}
333
360
334
- return (
335
- prefix +
336
- sg . substring ( 0 , 1 ) +
337
- "." +
338
- sg . substring ( 1 ) +
339
- "e" +
340
- ( adjustedExponent < 0 ? "" : "+" ) +
341
- adjustedExponent
342
- ) ;
361
+ let m = this . mantissa ( ) ;
362
+ let e = this . exponent ( ) ;
363
+ let mAsString = m . toFixed ( { digits : Infinity } ) ;
364
+ let expPart = ( e < 0 ? "-" : "+" ) + Math . abs ( e ) ;
365
+ return p + mAsString + "e" + expPart ;
343
366
}
344
367
345
368
private emitDecimal ( ) : string {
@@ -453,8 +476,14 @@ export class Decimal128 {
453
476
throw new RangeError ( "Argument must be greater than or equal to 0" ) ;
454
477
}
455
478
479
+ if ( n === Infinity ) {
480
+ return this . emitDecimal ( ) ;
481
+ }
482
+
456
483
if ( ! Number . isInteger ( n ) ) {
457
- throw new RangeError ( "Argument must be an integer" ) ;
484
+ throw new RangeError (
485
+ "Argument must be an integer or positive infinity"
486
+ ) ;
458
487
}
459
488
460
489
if ( this . isNaN ( ) ) {
@@ -727,13 +756,29 @@ export class Decimal128 {
727
756
return this . neg ( ) . add ( x . neg ( ) ) . neg ( ) ;
728
757
}
729
758
759
+ if ( this . isZero ( ) ) {
760
+ return x . clone ( ) ;
761
+ }
762
+
763
+ if ( x . isZero ( ) ) {
764
+ return this . clone ( ) ;
765
+ }
766
+
730
767
let ourCohort = this . cohort ( ) as Rational ;
731
768
let theirCohort = x . cohort ( ) as Rational ;
732
769
let ourQuantum = this . quantum ( ) as number ;
733
770
let theirQuantum = x . quantum ( ) as number ;
734
771
let sum = Rational . add ( ourCohort , theirCohort ) ;
735
772
let preferredQuantum = Math . min ( ourQuantum , theirQuantum ) ;
736
773
774
+ if ( sum . isZero ( ) ) {
775
+ if ( this . _isNegative ) {
776
+ return new Decimal128 ( "-0" ) ;
777
+ }
778
+
779
+ return new Decimal128 ( "0" ) ;
780
+ }
781
+
737
782
return new Decimal128 (
738
783
new Decimal ( {
739
784
cohort : sum ,
@@ -916,37 +961,34 @@ export class Decimal128 {
916
961
let dividendCoefficient = this . significand ( ) ;
917
962
let divisorCoefficient = x . significand ( ) ;
918
963
919
- if ( ! dividendCoefficient . isZero ( ) ) {
920
- while ( dividendCoefficient . cmp ( divisorCoefficient ) === - 1 ) {
921
- dividendCoefficient = dividendCoefficient . scale10 ( 1 ) ;
964
+ if ( dividendCoefficient !== 0n ) {
965
+ while ( dividendCoefficient < divisorCoefficient ) {
966
+ dividendCoefficient = dividendCoefficient * 10n ;
922
967
adjust ++ ;
923
968
}
924
969
}
925
970
926
- while ( dividendCoefficient . cmp ( divisorCoefficient . scale10 ( 1 ) ) ) {
927
- divisorCoefficient = divisorCoefficient . scale10 ( 1 ) ;
971
+ while ( dividendCoefficient > divisorCoefficient * 10n ) {
972
+ divisorCoefficient = divisorCoefficient * 10n ;
928
973
adjust -- ;
929
974
}
930
975
931
976
let resultCoefficient = 0n ;
932
977
let done = false ;
933
978
934
979
while ( ! done ) {
935
- while ( divisorCoefficient . cmp ( dividendCoefficient ) <= 0 ) {
936
- dividendCoefficient = Rational . subtract (
937
- dividendCoefficient ,
938
- divisorCoefficient
939
- ) ;
980
+ while ( divisorCoefficient <= dividendCoefficient ) {
981
+ dividendCoefficient = dividendCoefficient - divisorCoefficient ;
940
982
resultCoefficient ++ ;
941
983
}
942
984
if (
943
- ( dividendCoefficient . isZero ( ) && adjust >= 0 ) ||
985
+ ( dividendCoefficient === 0n && adjust >= 0 ) ||
944
986
resultCoefficient . toString ( ) . length > MAX_SIGNIFICANT_DIGITS
945
987
) {
946
988
done = true ;
947
989
} else {
948
990
resultCoefficient = resultCoefficient * 10n ;
949
- dividendCoefficient = dividendCoefficient . scale10 ( 1 ) ;
991
+ dividendCoefficient = dividendCoefficient * 10n ;
950
992
adjust ++ ;
951
993
}
952
994
}
0 commit comments