diff --git a/packages/math/src/decimal.spec.ts b/packages/math/src/decimal.spec.ts index b0e1803b..b59e556b 100644 --- a/packages/math/src/decimal.spec.ts +++ b/packages/math/src/decimal.spec.ts @@ -211,6 +211,47 @@ describe("Decimal", () => { }); }); + describe("multiply", () => { + it("returns correct values", () => { + const zero = Decimal.fromUserInput("0", 5); + expect(zero.multiply(Decimal.fromUserInput("0", 5)).toString()).toEqual("0"); + expect(zero.multiply(Decimal.fromUserInput("1", 5)).toString()).toEqual("0"); + expect(zero.multiply(Decimal.fromUserInput("2", 5)).toString()).toEqual("0"); + expect(zero.multiply(Decimal.fromUserInput("2.8", 5)).toString()).toEqual("0"); + expect(zero.multiply(Decimal.fromUserInput("0.12345", 5)).toString()).toEqual("0"); + + const one = Decimal.fromUserInput("1", 5); + expect(one.multiply(Decimal.fromUserInput("0", 5)).toString()).toEqual("0"); + expect(one.multiply(Decimal.fromUserInput("1", 5)).toString()).toEqual("1"); + expect(one.multiply(Decimal.fromUserInput("2", 5)).toString()).toEqual("2"); + expect(one.multiply(Decimal.fromUserInput("2.8", 5)).toString()).toEqual("2.8"); + expect(one.multiply(Decimal.fromUserInput("0.12345", 5)).toString()).toEqual("0.12345"); + + const oneDotFive = Decimal.fromUserInput("1.5", 5); + expect(oneDotFive.multiply(Decimal.fromUserInput("0", 5)).toString()).toEqual("0"); + expect(oneDotFive.multiply(Decimal.fromUserInput("1", 5)).toString()).toEqual("1.5"); + expect(oneDotFive.multiply(Decimal.fromUserInput("2", 5)).toString()).toEqual("3"); + expect(oneDotFive.multiply(Decimal.fromUserInput("2.8", 5)).toString()).toEqual("4.2"); + expect(oneDotFive.multiply(Decimal.fromUserInput("0.12345", 5)).toString()).toEqual("0.18517"); + + // original value remain unchanged + expect(zero.toString()).toEqual("0"); + expect(one.toString()).toEqual("1"); + expect(oneDotFive.toString()).toEqual("1.5"); + }); + + it("throws for different fractional digits", () => { + const zero = Decimal.fromUserInput("0", 5); + expect(() => zero.multiply(Decimal.fromUserInput("1", 1))).toThrowError(/do not match/i); + expect(() => zero.multiply(Decimal.fromUserInput("1", 2))).toThrowError(/do not match/i); + expect(() => zero.multiply(Decimal.fromUserInput("1", 3))).toThrowError(/do not match/i); + expect(() => zero.multiply(Decimal.fromUserInput("1", 4))).toThrowError(/do not match/i); + + expect(() => zero.multiply(Decimal.fromUserInput("1", 6))).toThrowError(/do not match/i); + expect(() => zero.multiply(Decimal.fromUserInput("1", 7))).toThrowError(/do not match/i); + }); + }); + describe("equals", () => { it("returns correct values", () => { const zero = Decimal.fromUserInput("0", 5); diff --git a/packages/math/src/decimal.ts b/packages/math/src/decimal.ts index ffedd0ed..969f811c 100644 --- a/packages/math/src/decimal.ts +++ b/packages/math/src/decimal.ts @@ -124,6 +124,18 @@ export class Decimal { return new Decimal(sum.toString(), this.fractionalDigits); } + /** + * a.multiply(b) returns a*b. + * + * Both values need to have the same fractional digits. + */ + public multiply(b: Decimal): Decimal { + if (this.fractionalDigits !== b.fractionalDigits) throw new Error("Fractional digits do not match"); + const factor = new BN(10).pow(new BN(this.data.fractionalDigits)); + const product = this.data.atomics.mul(new BN(b.atomics)).div(factor); + return new Decimal(product.toString(), this.fractionalDigits); + } + public equals(b: Decimal): boolean { return Decimal.compare(this, b) === 0; } diff --git a/packages/math/types/decimal.d.ts b/packages/math/types/decimal.d.ts index 0642fa07..102498d4 100644 --- a/packages/math/types/decimal.d.ts +++ b/packages/math/types/decimal.d.ts @@ -24,6 +24,12 @@ export declare class Decimal { * Both values need to have the same fractional digits. */ plus(b: Decimal): Decimal; + /** + * a.multiply(b) returns a*b. + * + * Both values need to have the same fractional digits. + */ + multiply(b: Decimal): Decimal; equals(b: Decimal): boolean; isLessThan(b: Decimal): boolean; isLessThanOrEqual(b: Decimal): boolean;