Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit 726774b

Browse files
committed
Add constructor and arithmetic options
1 parent 06554d9 commit 726774b

File tree

1 file changed

+63
-17
lines changed

1 file changed

+63
-17
lines changed

src/decimal128.mts

+63-17
Original file line numberDiff line numberDiff line change
@@ -865,10 +865,24 @@ interface FullySpecifiedConstructorOptions {
865865
normalize: boolean;
866866
}
867867

868-
const DEFAULT_CONSTRUCTOR_OPTIONS: FullySpecifiedConstructorOptions = {
869-
roundingMode: ROUNDING_MODE_DEFAULT,
870-
normalize: CONSTRUCTOR_SHOULD_NORMALIZE,
871-
};
868+
const DEFAULT_CONSTRUCTOR_OPTIONS: FullySpecifiedConstructorOptions =
869+
Object.freeze({
870+
roundingMode: ROUNDING_MODE_DEFAULT,
871+
normalize: CONSTRUCTOR_SHOULD_NORMALIZE,
872+
});
873+
874+
interface ArithmeticOperationOptions {
875+
roundingMode?: RoundingMode;
876+
}
877+
878+
interface FullySpecifiedArithmeticOperationOptions {
879+
roundingMode: RoundingMode;
880+
}
881+
882+
const DEFAULT_ARITHMETIC_OPERATION_OPTIONS: FullySpecifiedArithmeticOperationOptions =
883+
Object.freeze({
884+
roundingMode: ROUNDING_MODE_DEFAULT,
885+
});
872886

873887
type ToStringFormat = "decimal" | "exponential";
874888
const TOSTRING_FORMATS: string[] = ["decimal", "exponential"];
@@ -883,10 +897,10 @@ interface FullySpecifiedToStringOptions {
883897
numDecimalDigits: number | undefined;
884898
}
885899

886-
const DEFAULT_TOSTRING_OPTIONS: FullySpecifiedToStringOptions = {
900+
const DEFAULT_TOSTRING_OPTIONS: FullySpecifiedToStringOptions = Object.freeze({
887901
format: "decimal",
888902
numDecimalDigits: undefined,
889-
};
903+
});
890904

891905
function ensureFullySpecifiedConstructorOptions(
892906
options?: ConstructorOptions
@@ -911,6 +925,25 @@ function ensureFullySpecifiedConstructorOptions(
911925
return opts;
912926
}
913927

928+
function ensureFullySpecifiedArithmeticOperationOptions(
929+
options?: ArithmeticOperationOptions
930+
): FullySpecifiedArithmeticOperationOptions {
931+
let opts = { ...DEFAULT_ARITHMETIC_OPERATION_OPTIONS };
932+
933+
if (undefined === options) {
934+
return opts;
935+
}
936+
937+
if (
938+
"string" === typeof options.roundingMode &&
939+
ROUNDING_MODES.includes(options.roundingMode)
940+
) {
941+
opts.roundingMode = options.roundingMode;
942+
}
943+
944+
return opts;
945+
}
946+
914947
function ensureFullySpecifiedToStringOptions(
915948
options?: ToStringOptions
916949
): FullySpecifiedToStringOptions {
@@ -1144,8 +1177,9 @@ export class Decimal128 {
11441177
* Add this Decimal128 value to one or more Decimal128 values.
11451178
*
11461179
* @param x
1180+
* @param opts
11471181
*/
1148-
add(x: Decimal128): Decimal128 {
1182+
add(x: Decimal128, opts?: ArithmeticOperationOptions): Decimal128 {
11491183
if (this.isNaN() || x.isNaN()) {
11501184
return new Decimal128(NAN);
11511185
}
@@ -1167,12 +1201,14 @@ export class Decimal128 {
11671201
}
11681202

11691203
if (this.isNegative && x.isNegative) {
1170-
return this.negate().add(x.negate()).negate();
1204+
return this.negate().add(x.negate(), opts).negate();
11711205
}
11721206

11731207
let resultRat = Rational.add(this.rat, x.rat);
1208+
let options = ensureFullySpecifiedArithmeticOperationOptions(opts);
11741209
let initialResult = new Decimal128(
1175-
resultRat.toDecimalPlaces(MAX_SIGNIFICANT_DIGITS + 1)
1210+
resultRat.toDecimalPlaces(MAX_SIGNIFICANT_DIGITS + 1),
1211+
{ roundingMode: options.roundingMode }
11761212
);
11771213
let adjusted = initialResult.setExponent(
11781214
Math.min(this.exponent, x.exponent)
@@ -1185,8 +1221,9 @@ export class Decimal128 {
11851221
* Subtract another Decimal128 value from one or more Decimal128 values.
11861222
*
11871223
* @param x
1224+
* @param opts
11881225
*/
1189-
subtract(x: Decimal128): Decimal128 {
1226+
subtract(x: Decimal128, opts?: ArithmeticOperationOptions): Decimal128 {
11901227
if (this.isNaN() || x.isNaN()) {
11911228
return new Decimal128(NAN);
11921229
}
@@ -1215,7 +1252,9 @@ export class Decimal128 {
12151252
MAX_SIGNIFICANT_DIGITS + 1
12161253
);
12171254

1218-
let initialResult = new Decimal128(rendered);
1255+
let options = ensureFullySpecifiedArithmeticOperationOptions(opts);
1256+
1257+
let initialResult = new Decimal128(rendered, options);
12191258
let adjusted = initialResult.setExponent(
12201259
Math.min(this.exponent, x.exponent)
12211260
);
@@ -1228,8 +1267,9 @@ export class Decimal128 {
12281267
* If no arguments are given, return this value.
12291268
*
12301269
* @param x
1270+
* @param opts
12311271
*/
1232-
multiply(x: Decimal128): Decimal128 {
1272+
multiply(x: Decimal128, opts?: ArithmeticOperationOptions): Decimal128 {
12331273
if (this.isNaN() || x.isNaN()) {
12341274
return new Decimal128(NAN);
12351275
}
@@ -1268,7 +1308,8 @@ export class Decimal128 {
12681308

12691309
let resultRat = Rational.multiply(this.rat, x.rat);
12701310
let initialResult = new Decimal128(
1271-
resultRat.toDecimalPlaces(MAX_SIGNIFICANT_DIGITS + 1)
1311+
resultRat.toDecimalPlaces(MAX_SIGNIFICANT_DIGITS + 1),
1312+
ensureFullySpecifiedArithmeticOperationOptions(opts)
12721313
);
12731314
let adjusted = initialResult.setExponent(this.exponent + x.exponent);
12741315

@@ -1291,8 +1332,9 @@ export class Decimal128 {
12911332
* If only one argument is given, just return the first argument.
12921333
*
12931334
* @param x
1335+
* @param opts
12941336
*/
1295-
divide(x: Decimal128): Decimal128 {
1337+
divide(x: Decimal128, opts?: ArithmeticOperationOptions): Decimal128 {
12961338
if (this.isNaN() || x.isNaN()) {
12971339
return new Decimal128(NAN);
12981340
}
@@ -1375,7 +1417,10 @@ export class Decimal128 {
13751417
}
13761418

13771419
let resultExponent = this.exponent - (x.exponent + adjust);
1378-
return new Decimal128(`${resultCoefficient}E${resultExponent}`);
1420+
return new Decimal128(
1421+
`${resultCoefficient}E${resultExponent}`,
1422+
ensureFullySpecifiedArithmeticOperationOptions(opts)
1423+
);
13791424
}
13801425

13811426
/**
@@ -1453,9 +1498,10 @@ export class Decimal128 {
14531498
* Return the remainder of this Decimal128 value divided by another Decimal128 value.
14541499
*
14551500
* @param d
1501+
* @param opts
14561502
* @throws RangeError If argument is zero
14571503
*/
1458-
remainder(d: Decimal128): Decimal128 {
1504+
remainder(d: Decimal128, opts?: ArithmeticOperationOptions): Decimal128 {
14591505
if (this.isNaN() || d.isNaN()) {
14601506
return new Decimal128(NAN);
14611507
}
@@ -1481,7 +1527,7 @@ export class Decimal128 {
14811527
}
14821528

14831529
let q = this.divide(d).round(0, ROUNDING_MODE_TRUNCATE);
1484-
return this.subtract(d.multiply(q));
1530+
return this.subtract(d.multiply(q), opts);
14851531
}
14861532

14871533
normalize(): Decimal128 {

0 commit comments

Comments
 (0)