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

Commit 6e9ed93

Browse files
committed
WIP
1 parent 01608a4 commit 6e9ed93

File tree

4 files changed

+84
-38
lines changed

4 files changed

+84
-38
lines changed

src/Decimal128.mts

+59-19
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ const TEN_MAX_EXPONENT = new Rational(
4040
bigOne
4141
);
4242

43-
function pickQuantum(d: Rational, preferredQuantum: number): number {
43+
function pickQuantum(
44+
d: "0" | "-0" | Rational,
45+
preferredQuantum: number
46+
): number {
4447
return preferredQuantum;
4548
}
4649

@@ -69,15 +72,21 @@ function adjustDecimal128(v: Rational, q: number): Decimal {
6972
throw new RangeError("Integer too large");
7073
}
7174

72-
let sig = x.significand();
73-
let exp = x.exponent();
75+
let c = x.cohort as Rational;
76+
let cAsString = c.toFixed(Infinity);
77+
let [integerPart, fractionalPart] = cAsString.split(/[.]/);
7478

75-
let scaledSig = sig.scale10(MAX_SIGNIFICANT_DIGITS - 1);
79+
if (integerPart.length > MAX_SIGNIFICANT_DIGITS) {
80+
throw new RangeError("Integer part too large");
81+
}
82+
83+
let scaledSig = c.scale10(MAX_SIGNIFICANT_DIGITS - integerPart.length);
7684
let rounded = scaledSig.round(0, "halfEven");
77-
return new Decimal({
78-
cohort: rounded.scale10(0 - MAX_SIGNIFICANT_DIGITS + exp + 1),
79-
quantum: 0 - MAX_SIGNIFICANT_DIGITS + exp,
80-
});
85+
let rescaled = rounded.scale10(
86+
0 - MAX_SIGNIFICANT_DIGITS + integerPart.length
87+
);
88+
let rescaledAsString = rescaled.toFixed(Infinity);
89+
return new Decimal(rescaledAsString);
8190
}
8291

8392
function validateConstructorData(x: Decimal128Value): Decimal128Value {
@@ -829,9 +838,20 @@ export class Decimal128 {
829838
let theirCohort = x.cohort() as Rational;
830839
let ourExponent = this.quantum() as number;
831840
let theirExponent = x.quantum() as number;
832-
let difference = Rational.subtract(ourCohort, theirCohort);
841+
let difference: "0" | "-0" | Rational = Rational.subtract(
842+
ourCohort,
843+
theirCohort
844+
);
833845
let preferredQuantum = Math.min(ourExponent, theirExponent);
834846

847+
if (difference.isZero()) {
848+
if (this._isNegative) {
849+
difference = "-0";
850+
}
851+
852+
difference = "0";
853+
}
854+
835855
return new Decimal128(
836856
new Decimal({
837857
cohort: difference,
@@ -884,21 +904,37 @@ export class Decimal128 {
884904
return this.multiply(x.neg()).neg();
885905
}
886906

887-
if (this.isZero() || x.isZero()) {
888-
return this.clone();
889-
}
890-
891907
let ourCohort = this.cohort() as Rational;
892908
let theirCohort = x.cohort() as Rational;
893-
let ourExponent = this.quantum() as number;
894-
let theirExponent = x.quantum() as number;
909+
let ourQuantum = this.quantum() as number;
910+
let theirQuantum = x.quantum() as number;
911+
let preferredQuantum = ourQuantum + theirQuantum;
912+
913+
if (this.isZero()) {
914+
return new Decimal128(
915+
new Decimal({
916+
cohort: this.cohort(),
917+
quantum: preferredQuantum,
918+
})
919+
);
920+
}
921+
922+
if (x.isZero()) {
923+
return new Decimal128(
924+
new Decimal({
925+
cohort: x.cohort(),
926+
quantum: preferredQuantum,
927+
})
928+
);
929+
}
930+
895931
let product = Rational.multiply(ourCohort, theirCohort);
896-
let preferredQuantum = ourExponent + theirExponent;
932+
let actualQuantum = pickQuantum(product, preferredQuantum);
897933

898934
return new Decimal128(
899935
new Decimal({
900936
cohort: product,
901-
quantum: pickQuantum(product, preferredQuantum),
937+
quantum: actualQuantum,
902938
})
903939
);
904940
}
@@ -1039,11 +1075,15 @@ export class Decimal128 {
10391075
let v = this.cohort();
10401076

10411077
if (v === "0") {
1042-
return new Decimal128("-0");
1078+
return new Decimal128(
1079+
new Decimal({ cohort: "-0", quantum: this.quantum() })
1080+
);
10431081
}
10441082

10451083
if (v === "-0") {
1046-
return new Decimal128("0");
1084+
return new Decimal128(
1085+
new Decimal({ cohort: "0", quantum: this.quantum() })
1086+
);
10471087
}
10481088

10491089
return new Decimal128(

tests/Decimal128/multiply.test.js

+16-16
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { Decimal128 } from "../../src/Decimal128.mjs";
22

33
const examples = [
4-
["123.456", "789.789", "97504.190784"],
5-
["2", "3", "6"],
6-
["2", "3.0", "6.0"],
7-
["2.0", "3.0", "6.00"],
8-
["4", "0.5", "2.0"],
9-
["10", "100", "1000"],
10-
["0.1", "0.2", "0.02"],
11-
["0.25", "1.5", "0.375"],
12-
["0.12345", "0.67890", "0.0838102050"],
13-
["0.123456789", "0.987654321", "0.121932631112635269"],
14-
["100000.123", "99999.321", "9999944399.916483"],
15-
["123456.123456789", "987654.987654321", "121932056088.565269013112635269"],
4+
// ["123.456", "789.789", "97504.190784"],
5+
// ["2", "3", "6"],
6+
// ["2", "3.0", "6.0"],
7+
// ["2.0", "3.0", "6.00"],
8+
// ["4", "0.5", "2.0"],
9+
// ["10", "100", "1000"],
10+
// ["0.1", "0.2", "0.02"],
11+
// ["0.25", "1.5", "0.375"],
12+
// ["0.12345", "0.67890", "0.0838102050"],
13+
// ["0.123456789", "0.987654321", "0.121932631112635269"],
14+
// ["100000.123", "99999.321", "9999944399.916483"],
15+
// ["123456.123456789", "987654.987654321", "121932056088.565269013112635269"],
1616
[
1717
"123456789.987654321",
1818
"987654321.123456789",
@@ -24,7 +24,7 @@ function checkProduct(a, b, c) {
2424
expect(
2525
new Decimal128(a)
2626
.multiply(new Decimal128(b))
27-
.toString({ normalize: false })
27+
.toString({ preserveTrailingZeroes: true })
2828
).toStrictEqual(c);
2929
}
3030

@@ -166,7 +166,7 @@ describe("examples from the General Decimal Arithmetic specification", () => {
166166
expect(
167167
new Decimal128("1.20")
168168
.multiply(new Decimal128("3"))
169-
.toString({ normalize: false })
169+
.toString({ preserveTrailingZeroes: true })
170170
).toStrictEqual("3.60");
171171
});
172172
test("example two", () => {
@@ -183,15 +183,15 @@ describe("examples from the General Decimal Arithmetic specification", () => {
183183
expect(
184184
new Decimal128("0.9")
185185
.multiply(new Decimal128("-0"))
186-
.toString({ normalize: false })
186+
.toString({ preserveTrailingZeroes: true })
187187
).toStrictEqual("-0.0");
188188
});
189189
test("example five", () => {
190190
// slightly modified because we have more precision
191191
expect(
192192
new Decimal128("654321")
193193
.multiply(new Decimal128("654321"))
194-
.toString({ format: "exponential" })
194+
.toExponential()
195195
).toStrictEqual("4.28135971041e+11");
196196
});
197197
});

tests/Decimal128/subtract.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ describe("examples from the General Decimal Arithmetic specification", () => {
143143
expect(
144144
new Decimal128("1.3")
145145
.subtract(new Decimal128("1.30"))
146-
.toString({ normalize: false })
146+
.toString({ preserveTrailingZeroes: true })
147147
).toStrictEqual("0.00");
148148
});
149149
test("example three", () => {

tests/Decimal128/util.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { Decimal128 } from "../../src/Decimal128.mjs";
22

33
export function expectDecimal128(a, b) {
4-
let lhs = a instanceof Decimal128 ? a.toString({ normalize: false }) : a;
5-
let rhs = b instanceof Decimal128 ? b.toString({ normalize: false }) : b;
4+
let lhs =
5+
a instanceof Decimal128
6+
? a.toString({ preserveTrailingZeroes: true })
7+
: a;
8+
let rhs =
9+
b instanceof Decimal128
10+
? b.toString({ preserveTrailingZeroes: true })
11+
: b;
612
expect(lhs).toStrictEqual(rhs);
713
}

0 commit comments

Comments
 (0)