From 0b3f3dff6087a104a0e3bc02019e8f37b4a1158d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 27 Apr 2021 20:44:09 +0100 Subject: [PATCH] Add ramanujan's pi approximation as a semantic test --- .../externalContracts/ramanujan_pi.sol | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol new file mode 100644 index 000000000..b280cfa33 --- /dev/null +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -0,0 +1,44 @@ +==== ExternalSource: _prbmath/PRBMathCommon.sol ==== +==== ExternalSource: _prbmath/PRBMathSD59x18.sol ==== +==== Source: ramanujan_pi.sol ==== +import "_prbmath/PRBMathSD59x18.sol"; + +// The goal of this test file is to implement Ramanujan's pi approximation using various libraries. + +function factorial(uint n) pure returns (uint ret) { + ret = 1; + for (; n > 1; --n) + ret *= n; +} + +contract test { + using PRBMathSD59x18 for int256; + + function prb_scale(uint n) internal pure returns (int256 ret) { + // Scale to SD59x18 + ret = int256(n * 10e17); + } + + // This dumb implementation of Ramanujan series calculates 1/pi + function prb_pi() external pure returns (int256 ret) { + uint n = 6; // More than 6 iterations results in failure + for (uint k = 0; k < n; k++) { + int256 a = prb_scale(factorial(4 * k)).div(prb_scale(factorial(k)).pow(4)); + int256 b = (prb_scale(25390).mul(prb_scale(k)) + prb_scale(1103)).div(prb_scale(396).pow(4 * k)); + ret += a.mul(b); + } + ret = ret.mul(prb_scale(2).sqrt().mul(prb_scale(2)).div(prb_scale(99).pow(2))); + ret = prb_scale(1).div(ret); + } +} +// ==== +// compileViaYul: also +// ---- +// constructor() +// gas irOptimized: 590192 +// gas legacy: 733634 +// gas legacyOptimized: 498033 +// prb_pi() -> 3141592656369545286 +// gas irOptimized: 66098 +// gas legacy: 98903 +// gas legacyOptimized: 75735