From 21fb3272540c20951e72a5e6852aa38eeb440ebc Mon Sep 17 00:00:00 2001 From: Paul Razvan Berg Date: Fri, 25 Nov 2022 16:14:58 +0200 Subject: [PATCH] refactor: truncate instead of round up in "mulDiv18" test: update test to account for new truncating behavior --- src/Core.sol | 23 +++++++---------- test/sd59x18/fixed-point/mul/mul.t.sol | 32 ++++++++++++++++++------ test/sd59x18/fixed-point/pow/pow.t.sol | 12 ++++----- test/sd59x18/fixed-point/powu/powu.t.sol | 12 ++++----- test/ud60x18/fixed-point/mul/mul.t.sol | 2 +- test/ud60x18/fixed-point/pow/pow.t.sol | 8 +++--- test/ud60x18/fixed-point/powu/powu.t.sol | 6 ++--- 7 files changed, 53 insertions(+), 42 deletions(-) diff --git a/src/Core.sol b/src/Core.sol index 7c531b93..fc854a5b 100644 --- a/src/Core.sol +++ b/src/Core.sol @@ -105,8 +105,8 @@ function mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } - // Handle non-overflow cases, 256 by 256 division. "prod1 > 0 == false" is equivalent to "prod1 == 0" but faster. - if (prod1 > 0 == false) { + // Handle non-overflow cases, 256 by 256 division. + if (prod1 == 0) { unchecked { return prod0 / denominator; } @@ -205,28 +205,23 @@ function mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) { } uint256 remainder; - uint256 roundUpUnit; assembly { remainder := mulmod(x, y, UNIT) - roundUpUnit := gt(remainder, 499999999999999999) } - if (prod1 > 0 == false) { + if (prod1 == 0) { unchecked { - return (prod0 / UNIT) + roundUpUnit; + return prod0 / UNIT; } } assembly { - result := add( - mul( - or( - div(sub(prod0, remainder), UNIT_LPOTD), - mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1)) - ), - UNIT_INVERSE + result := mul( + or( + div(sub(prod0, remainder), UNIT_LPOTD), + mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1)) ), - roundUpUnit + UNIT_INVERSE ) } } diff --git a/test/sd59x18/fixed-point/mul/mul.t.sol b/test/sd59x18/fixed-point/mul/mul.t.sol index c3e88462..ec23c309 100644 --- a/test/sd59x18/fixed-point/mul/mul.t.sol +++ b/test/sd59x18/fixed-point/mul/mul.t.sol @@ -102,7 +102,11 @@ contract SD59x18__MulTest is SD59x18__BaseTest { set({ x: MIN_SD59x18.add(sd(0.5e18 + 1)), y: -0.000000000000000001e18, expected: MAX_SCALED_SD59x18 }) ); sets.push( - set({ x: MIN_WHOLE_SD59x18.add(sd(0.5e18)), y: -0.000000000000000001e18, expected: MAX_SCALED_SD59x18 }) + set({ + x: MIN_WHOLE_SD59x18.add(sd(0.5e18)), + y: -0.000000000000000001e18, + expected: MAX_SCALED_SD59x18.sub(sd(1)) + }) ); sets.push(set({ x: -1e24, y: -1e20, expected: 1e26 })); sets.push(set({ x: -12_983.989e18, y: -782.99e18, expected: 1_016_6333.54711e18 })); @@ -117,9 +121,9 @@ contract SD59x18__MulTest is SD59x18__BaseTest { sets.push(set({ x: -0.00001e18, y: -0.00001e18, expected: 0.0000000001e18 })); sets.push(set({ x: -0.000000001e18, y: -0.000000001e18, expected: 0.000000000000000001e18 })); sets.push(set({ x: -0.000000000000000001e18, y: -0.000000000000000001e18, expected: 0 })); - sets.push(set({ x: -0.000000000000000006e18, y: -0.1e18, expected: 0.000000000000000001e18 })); + sets.push(set({ x: -0.000000000000000006e18, y: -0.1e18, expected: 0 })); sets.push(set({ x: 0.000000000000000001e18, y: 0.000000000000000001e18, expected: 0 })); - sets.push(set({ x: 0.000000000000000006e18, y: 0.1e18, expected: 0.000000000000000001e18 })); + sets.push(set({ x: 0.000000000000000006e18, y: 0.1e18, expected: 0 })); sets.push(set({ x: 0.000000001e18, y: 0.000000001e18, expected: 0.000000000000000001e18 })); sets.push(set({ x: 0.00001e18, y: 0.00001e18, expected: 0.0000000001e18 })); sets.push(set({ x: 0.001e18, y: 0.01e18, expected: 0.00001e18 })); @@ -133,7 +137,11 @@ contract SD59x18__MulTest is SD59x18__BaseTest { sets.push(set({ x: 12_983.989e18, y: 782.99e18, expected: 1_016_6333.54711e18 })); sets.push(set({ x: 1e24, y: 1e20, expected: 1e26 })); sets.push( - set({ x: MAX_WHOLE_SD59x18.sub(sd(0.5e18)), y: 0.000000000000000001e18, expected: MAX_SCALED_SD59x18 }) + set({ + x: MAX_WHOLE_SD59x18.sub(sd(0.5e18)), + y: 0.000000000000000001e18, + expected: MAX_SCALED_SD59x18.sub(sd(1)) + }) ); sets.push(set({ x: MAX_SD59x18.sub(sd(0.5e18)), y: 0.000000000000000001e18, expected: MAX_SCALED_SD59x18 })); return sets; @@ -157,7 +165,11 @@ contract SD59x18__MulTest is SD59x18__BaseTest { set({ x: MIN_SD59x18.add(sd(0.5e18 + 1)), y: 0.000000000000000001e18, expected: MIN_SCALED_SD59x18 }) ); sets.push( - set({ x: MIN_WHOLE_SD59x18.add(sd(0.5e18)), y: 0.000000000000000001e18, expected: MIN_SCALED_SD59x18 }) + set({ + x: MIN_WHOLE_SD59x18.add(sd(0.5e18)), + y: 0.000000000000000001e18, + expected: MIN_SCALED_SD59x18.add(sd(1)) + }) ); sets.push(set({ x: -1e24, y: 1e20, expected: -1e26 })); sets.push(set({ x: -12_983.989e18, y: 782.99e18, expected: -1_016_6333.54711e18 })); @@ -172,9 +184,9 @@ contract SD59x18__MulTest is SD59x18__BaseTest { sets.push(set({ x: -0.00001e18, y: 0.00001e18, expected: -0.0000000001e18 })); sets.push(set({ x: -0.000000001e18, y: 0.000000001e18, expected: -0.000000000000000001e18 })); sets.push(set({ x: -0.000000000000000001e18, y: 0.000000000000000001e18, expected: 0 })); - sets.push(set({ x: -0.000000000000000006e18, y: 0.1e18, expected: -0.000000000000000001e18 })); + sets.push(set({ x: -0.000000000000000006e18, y: 0.1e18, expected: 0 })); sets.push(set({ x: 0.000000000000000001e18, y: -0.000000000000000001e18, expected: 0 })); - sets.push(set({ x: 0.000000000000000006e18, y: -0.1e18, expected: -0.000000000000000001e18 })); + sets.push(set({ x: 0.000000000000000006e18, y: -0.1e18, expected: 0 })); sets.push(set({ x: 0.000000001e18, y: -0.000000001e18, expected: -0.000000000000000001e18 })); sets.push(set({ x: 0.00001e18, y: -0.00001e18, expected: -0.0000000001e18 })); sets.push(set({ x: 0.001e18, y: -0.01e18, expected: -0.00001e18 })); @@ -188,7 +200,11 @@ contract SD59x18__MulTest is SD59x18__BaseTest { sets.push(set({ x: 12_983.989e18, y: -782.99e18, expected: -1_016_6333.54711e18 })); sets.push(set({ x: 1e24, y: -1e20, expected: -1e26 })); sets.push( - set({ x: MAX_WHOLE_SD59x18.sub(sd(0.5e18)), y: -0.000000000000000001e18, expected: MIN_SCALED_SD59x18 }) + set({ + x: MAX_WHOLE_SD59x18.sub(sd(0.5e18)), + y: -0.000000000000000001e18, + expected: MIN_SCALED_SD59x18.add(sd(1)) + }) ); sets.push(set({ x: MAX_SD59x18.sub(sd(0.5e18)), y: -0.000000000000000001e18, expected: MIN_SCALED_SD59x18 })); return sets; diff --git a/test/sd59x18/fixed-point/pow/pow.t.sol b/test/sd59x18/fixed-point/pow/pow.t.sol index 4be85e9a..50528cad 100644 --- a/test/sd59x18/fixed-point/pow/pow.t.sol +++ b/test/sd59x18/fixed-point/pow/pow.t.sol @@ -102,7 +102,7 @@ contract SD59x18__PowTest is SD59x18__BaseTest { function negativeExponentSets() internal returns (Set[] memory) { delete sets; - sets.push(set({ x: 0.000000000000000001e18, y: -0.000000000000000001e18, expected: 1e18 + 41 })); + sets.push(set({ x: 0.000000000000000001e18, y: -0.000000000000000001e18, expected: 1e18 + 40 })); sets.push(set({ x: 0.000000000001e18, y: -4.4e9, expected: 1_000000121576500300 })); sets.push(set({ x: 0.1e18, y: -0.8e18, expected: 6_309573444801932444 })); sets.push(set({ x: 0.24e18, y: -11e18, expected: 6571678_991286039528731186 })); @@ -139,7 +139,7 @@ contract SD59x18__PowTest is SD59x18__BaseTest { function positiveExponentSets() internal returns (Set[] memory) { delete sets; - sets.push(set({ x: 0.000000000000000001e18, y: 0.000000000000000001e18, expected: 0.999999999999999959e18 })); + sets.push(set({ x: 0.000000000000000001e18, y: 0.000000000000000001e18, expected: 0.999999999999999960e18 })); sets.push(set({ x: 1e6, y: 4.4e9, expected: 0.99999987842351448e18 })); sets.push(set({ x: 0.1e18, y: 0.8e18, expected: 0.158489319246111349e18 })); sets.push(set({ x: 0.24e18, y: 11e18, expected: 0.000000152168114316e18 })); @@ -148,10 +148,10 @@ contract SD59x18__PowTest is SD59x18__BaseTest { sets.push(set({ x: 1e18, y: 2e18, expected: 1e18 })); sets.push(set({ x: 1e18, y: PI, expected: 1e18 })); sets.push(set({ x: 2e18, y: 1.5e18, expected: 2_828427124746190097 })); - sets.push(set({ x: E, y: E, expected: 15_154262241479263804 })); - sets.push(set({ x: E, y: 1.66976e18, expected: 5_310893029888037563 })); + sets.push(set({ x: E, y: E, expected: 15_154262241479263793 })); + sets.push(set({ x: E, y: 1.66976e18, expected: 5_310893029888037560 })); sets.push(set({ x: PI, y: PI, expected: 36_462159607207910473 })); - sets.push(set({ x: 11e18, y: 28.5e18, expected: 478290249106383504726311660571_903531944106436935 })); + sets.push(set({ x: 11e18, y: 28.5e18, expected: 478290249106383504389245497918_050372801213485439 })); sets.push( set({ x: 32.15e18, y: 23.99e18, expected: 1436387590627448555101723413293079116_943375472179194989 }) ); @@ -162,7 +162,7 @@ contract SD59x18__PowTest is SD59x18__BaseTest { set({ x: 340282366920938463463374607431768211455e18, y: 1e18 + 1, - expected: 340282366920938487979097481391762860220_000000000004665573 + expected: 340282366920938487757736552507248225013_000000000004316573 }) ); sets.push( diff --git a/test/sd59x18/fixed-point/powu/powu.t.sol b/test/sd59x18/fixed-point/powu/powu.t.sol index ecc3eeda..5c09a58f 100644 --- a/test/sd59x18/fixed-point/powu/powu.t.sol +++ b/test/sd59x18/fixed-point/powu/powu.t.sol @@ -106,7 +106,7 @@ contract SD59x18__PowuTest is SD59x18__BaseTest { set({ x: -38685626227668133590.597631999999999999e18, y: 3, - expected: -57896044618658097711785492504343953922145259302939748255014_626107971862774100 + expected: -57896044618658097711785492504343953922145259302939748254975_940481744194640509 }) ); sets.push(set({ x: -1e24, y: 3, expected: -1e36 })); @@ -119,9 +119,9 @@ contract SD59x18__PowuTest is SD59x18__BaseTest { }) ); sets.push(set({ x: -100e18, y: 4, expected: 1e26 })); - sets.push(set({ x: -5.491e18, y: 19, expected: -113077820843204_476043049664958629 })); + sets.push(set({ x: -5.491e18, y: 19, expected: -113077820843204_476043049664958463 })); sets.push(set({ x: NEGATIVE_E, y: 2, expected: 7_389056098930650225 })); - sets.push(set({ x: NEGATIVE_PI, y: 3, expected: -31_006276680299820162 })); + sets.push(set({ x: NEGATIVE_PI, y: 3, expected: -31_006276680299820158 })); sets.push(set({ x: -2e18, y: 100, expected: 1267650600228_229401496703205376e18 })); sets.push(set({ x: -2e18, y: 5, expected: -32e18 })); sets.push(set({ x: -1e18, y: 1, expected: -1e18 })); @@ -150,8 +150,8 @@ contract SD59x18__PowuTest is SD59x18__BaseTest { sets.push(set({ x: 2e18, y: 5, expected: 32e18 })); sets.push(set({ x: 2e18, y: 100, expected: 1267650600228_229401496703205376e18 })); sets.push(set({ x: E, y: 2, expected: 7_389056098930650225 })); - sets.push(set({ x: PI, y: 3, expected: 31_006276680299820162 })); - sets.push(set({ x: 5.491e18, y: 19, expected: 113077820843204_476043049664958629 })); + sets.push(set({ x: PI, y: 3, expected: 31_006276680299820158 })); + sets.push(set({ x: 5.491e18, y: 19, expected: 113077820843204_476043049664958463 })); sets.push(set({ x: 100e18, y: 4, expected: 1e26 })); sets.push( set({ @@ -166,7 +166,7 @@ contract SD59x18__PowuTest is SD59x18__BaseTest { set({ x: 38685626227668133590.597631999999999999e18, y: 3, - expected: 57896044618658097711785492504343953922145259302939748255014_626107971862774100 + expected: 57896044618658097711785492504343953922145259302939748254975_940481744194640509 }) ); sets.push( diff --git a/test/ud60x18/fixed-point/mul/mul.t.sol b/test/ud60x18/fixed-point/mul/mul.t.sol index 74926382..46d16934 100644 --- a/test/ud60x18/fixed-point/mul/mul.t.sol +++ b/test/ud60x18/fixed-point/mul/mul.t.sol @@ -49,7 +49,7 @@ contract UD60x18__MulTest is UD60x18__BaseTest { function mulSets() internal returns (Set[] memory) { delete sets; sets.push(set({ x: 0.000000000000000001e18, y: 0.000000000000000001e18, expected: 0 })); - sets.push(set({ x: 0.000000000000000006e18, y: 0.1e18, expected: 0.000000000000000001e18 })); + sets.push(set({ x: 0.000000000000000006e18, y: 0.1e18, expected: 0 })); sets.push(set({ x: 0.000000001e18, y: 0.000000001e18, expected: 0.000000000000000001e18 })); sets.push(set({ x: 0.00001e18, y: 0.00001e18, expected: 0.0000000001e18 })); sets.push(set({ x: 0.001e18, y: 0.01e18, expected: 0.00001e18 })); diff --git a/test/ud60x18/fixed-point/pow/pow.t.sol b/test/ud60x18/fixed-point/pow/pow.t.sol index 27d2400e..c55b4d56 100644 --- a/test/ud60x18/fixed-point/pow/pow.t.sol +++ b/test/ud60x18/fixed-point/pow/pow.t.sol @@ -111,10 +111,10 @@ contract UD60x18__PowTest is UD60x18__BaseTest { sets.push(set({ x: 1e18, y: 2e18, expected: 1e18 })); sets.push(set({ x: 1e18, y: PI, expected: 1e18 })); sets.push(set({ x: 2e18, y: 1.5e18, expected: 2_828427124746190097 })); - sets.push(set({ x: E, y: 1.66976e18, expected: 5_310893029888037563 })); - sets.push(set({ x: E, y: E, expected: 15_154262241479263804 })); + sets.push(set({ x: E, y: 1.66976e18, expected: 5_310893029888037560 })); + sets.push(set({ x: E, y: E, expected: 15_154262241479263793 })); sets.push(set({ x: PI, y: PI, expected: 36_462159607207910473 })); - sets.push(set({ x: 11e18, y: 28.5e18, expected: 478290249106383504726311660571_903531944106436935 })); + sets.push(set({ x: 11e18, y: 28.5e18, expected: 478290249106383504389245497918_050372801213485439 })); sets.push( set({ x: 32.15e18, y: 23.99e18, expected: 1436387590627448555101723413293079116_943375472179194989 }) ); @@ -125,7 +125,7 @@ contract UD60x18__PowTest is UD60x18__BaseTest { set({ x: 340282366920938463463374607431768211455e18, y: 1e18 + 1, - expected: 340282366920938487979097481391762860220_000000000004665573 + expected: 340282366920938487757736552507248225013_000000000004316573 }) ); sets.push( diff --git a/test/ud60x18/fixed-point/powu/powu.t.sol b/test/ud60x18/fixed-point/powu/powu.t.sol index e2e7fe64..e0e7a3ef 100644 --- a/test/ud60x18/fixed-point/powu/powu.t.sol +++ b/test/ud60x18/fixed-point/powu/powu.t.sol @@ -69,8 +69,8 @@ contract UD60x18__PowuTest is UD60x18__BaseTest { sets.push(set({ x: 2e18, y: 5, expected: 32e18 })); sets.push(set({ x: 2e18, y: 100, expected: 1267650600228_229401496703205376e18 })); sets.push(set({ x: E, y: 2, expected: 7_389056098930650225 })); - sets.push(set({ x: PI, y: 3, expected: 31_006276680299820162 })); - sets.push(set({ x: 5.491e18, y: 19, expected: 113077820843204_476043049664958629 })); + sets.push(set({ x: PI, y: 3, expected: 31_006276680299820158 })); + sets.push(set({ x: 5.491e18, y: 19, expected: 113077820843204_476043049664958463 })); sets.push(set({ x: 100e18, y: 4, expected: 1e26 })); sets.push( set({ @@ -85,7 +85,7 @@ contract UD60x18__PowuTest is UD60x18__BaseTest { set({ x: 38685626227668133590.597631999999999999e18, y: 3, - expected: 57896044618658097711785492504343953922145259302939748255014_626107971862774100 + expected: 57896044618658097711785492504343953922145259302939748254975_940481744194640509 }) ); sets.push(