From 1146d5ab7dd4f7eb4e5fc5f8f248737c293d880a Mon Sep 17 00:00:00 2001 From: Lumi Pakkanen Date: Thu, 8 Feb 2024 02:33:29 +0200 Subject: [PATCH] Avoid IEEE simplification as a side effect of defloating --- src/__tests__/fraction.spec.ts | 15 +++++++++++++++ src/fraction.ts | 15 ++++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/__tests__/fraction.spec.ts b/src/__tests__/fraction.spec.ts index b8c14ba..16c12e1 100644 --- a/src/__tests__/fraction.spec.ts +++ b/src/__tests__/fraction.spec.ts @@ -425,4 +425,19 @@ describe('Fraction', () => { expect(lensSum.lensSub(b).equals(a)).toBe(true); expect(lensSum.lensSub(a).equals(b)).toBe(true); }); + + it.fails('blows up on repeated division', () => { + let foo = new Fraction('3/2'); + const bar = new Fraction('103/101'); + for (let i = 0; i < 10; ++i) { + foo = foo.div(bar); + } + }); + + it.fails('blows up on repeated multiplication', () => { + let foo = new Fraction('103/101'); + for (let i = 0; i < 4; ++i) { + foo = foo.mul(foo); + } + }); }); diff --git a/src/fraction.ts b/src/fraction.ts index 85e1234..4eb74bd 100644 --- a/src/fraction.ts +++ b/src/fraction.ts @@ -94,6 +94,12 @@ export class Fraction { this.s = Math.sign(numerator * denominator); this.n = Math.abs(numerator); this.d = Math.abs(denominator); + if (this.n > Number.MAX_SAFE_INTEGER) { + throw new Error('Numerator above safe limit'); + } + if (this.d > Number.MAX_SAFE_INTEGER) { + throw new Error('Denominator above safe limit'); + } if (this.d === 0) { throw new Error('Division by Zero'); } @@ -206,15 +212,6 @@ export class Fraction { if (isNaN(this.s) || isNaN(this.n) || isNaN(this.d)) { throw new Error('Cannot represent NaN as a fraction'); } - /* - if (!isFinite(this.d)) { - if (!isFinite(this.n)) { - throw new Error('Both numerator and denominator cannot be infinite'); - } - this.n = 0; - this.d = 1; - } - */ if (this.n > Number.MAX_SAFE_INTEGER) { throw new Error('Numerator above safe limit'); }