From cbb5b5586370c89e334ea85e54c8c7259e38795d Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Mon, 19 Aug 2024 14:18:30 -0700 Subject: [PATCH] feat: ratio.quantize() shouldn't increase precision unnecessarily --- packages/zoe/src/contractSupport/ratio.js | 4 ++ .../unitTests/contractSupport/ratio.test.js | 41 ++++++++++++++----- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/packages/zoe/src/contractSupport/ratio.js b/packages/zoe/src/contractSupport/ratio.js index 46e0281c04da..99ff95734532 100644 --- a/packages/zoe/src/contractSupport/ratio.js +++ b/packages/zoe/src/contractSupport/ratio.js @@ -352,6 +352,10 @@ export const ratiosSame = (left, right) => { export const quantize = (ratio, newDen) => { const oldDen = ratio.denominator.value; const oldNum = ratio.numerator.value; + if (oldDen < newDen) { + return ratio; + } + const newNum = newDen === oldDen ? oldNum : bankersDivide(oldNum * newDen, oldDen); return makeRatio( diff --git a/packages/zoe/test/unitTests/contractSupport/ratio.test.js b/packages/zoe/test/unitTests/contractSupport/ratio.test.js index 62b9ce9e56d6..8a4632b5fc5c 100644 --- a/packages/zoe/test/unitTests/contractSupport/ratio.test.js +++ b/packages/zoe/test/unitTests/contractSupport/ratio.test.js @@ -501,25 +501,25 @@ const { brand } = makeIssuerKit('moe'); test('ratio - quantize', t => { /** @type {Array<[numBefore: bigint, denBefore: bigint, numAfter: bigint, denAfter: bigint]>} */ - const cases = /** @type {const} */ [ + const cases = [ [1n, 1n, 1n, 1n], [10n, 10n, 10n, 10n], [2n * 10n ** 9n, 1n * 10n ** 9n, 20n, 10n], - [12345n, 12345n, 100n, 100n], - [12345n, 12345n, 100000n, 100000n], - [12345n, 12345n, 10n ** 15n, 10n ** 15n], - - [12345n, 123n, 100365854n, 10n ** 6n], - [12345n, 123n, 10036585n, 10n ** 5n], - [12345n, 123n, 1003659n, 10n ** 4n], - [12345n, 123n, 100366n, 10n ** 3n], [12345n, 123n, 10037n, 10n ** 2n], [12345n, 123n, 1004n, 10n ** 1n], [12345n, 123n, 100n, 10n ** 0n], + + [12345n, 12345n, 100n, 100n], ]; - for (const [numBefore, denBefore, numAfter, denAfter] of cases) { + for (const [ + numBefore, + denBefore, + numAfter, + target, + denAfter = target, + ] of cases) { const before = makeRatio(numBefore, brand, denBefore, brand); const after = makeRatio(numAfter, brand, denAfter, brand); t.deepEqual( @@ -530,6 +530,27 @@ test('ratio - quantize', t => { } }); +test('ratio - quantize - leave it alone', t => { + const cases = [ + [12345n, 123n, 10n ** 5n, 12345n, 123n], + [12345n, 123n, 10n ** 4n, 12345n, 123n], + [12345n, 123n, 10n ** 3n, 12345n, 123n], + + [12345n, 12345n, 100_000n, 12345n, 12345n], + [12345n, 12345n, 10n ** 15n, 12345n, 12345n], + ]; + + for (const [numPre, denPre, qTarget, numAfter, denAfter] of cases) { + const before = makeRatio(numPre, brand, denPre, brand); + const after = makeRatio(numAfter, brand, denAfter, brand); + t.deepEqual( + quantize(before, qTarget), + after, + `${numPre}/${denPre} quantized to ${qTarget} should be ${numAfter}/${denAfter}`, + ); + } +}); + test('ratio - parse', t => { const { brand: moeBrand } = makeIssuerKit('moe'); const { brand: larryBrand } = makeIssuerKit('larry');